Skip to content

Commit db20260

Browse files
Tom TaylorAndroid (Google) Code Review
authored andcommitted
Merge "Drm encode mms parts while persisting the pdu"
2 parents b104921 + ca18487 commit db20260

File tree

3 files changed

+404
-3
lines changed

3 files changed

+404
-3
lines changed

core/java/com/google/android/mms/pdu/PduPersister.java

Lines changed: 121 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import com.google.android.mms.ContentType;
2121
import com.google.android.mms.InvalidHeaderValueException;
2222
import com.google.android.mms.MmsException;
23+
import com.google.android.mms.util.DownloadDrmHelper;
24+
import com.google.android.mms.util.DrmConvertSession;
2325
import com.google.android.mms.util.PduCache;
2426
import com.google.android.mms.util.PduCacheEntry;
2527
import com.google.android.mms.util.SqliteWrapper;
@@ -30,7 +32,11 @@
3032
import android.content.Context;
3133
import android.database.Cursor;
3234
import android.database.DatabaseUtils;
35+
import android.database.sqlite.SQLiteException;
36+
import android.drm.DrmManagerClient;
3337
import android.net.Uri;
38+
import android.os.FileUtils;
39+
import android.provider.MediaStore;
3440
import android.provider.Telephony;
3541
import android.provider.Telephony.Mms;
3642
import android.provider.Telephony.MmsSms;
@@ -42,6 +48,7 @@
4248
import android.util.Log;
4349

4450
import java.io.ByteArrayOutputStream;
51+
import java.io.File;
4552
import java.io.FileNotFoundException;
4653
import java.io.IOException;
4754
import java.io.InputStream;
@@ -271,10 +278,12 @@ public class PduPersister {
271278

272279
private final Context mContext;
273280
private final ContentResolver mContentResolver;
281+
private final DrmManagerClient mDrmManagerClient;
274282

275283
private PduPersister(Context context) {
276284
mContext = context;
277285
mContentResolver = context.getContentResolver();
286+
mDrmManagerClient = new DrmManagerClient(context);
278287
}
279288

280289
/** Get(or create if not exist) an instance of PduPersister */
@@ -761,6 +770,9 @@ private void persistData(PduPart part, Uri uri,
761770
throws MmsException {
762771
OutputStream os = null;
763772
InputStream is = null;
773+
DrmConvertSession drmConvertSession = null;
774+
Uri dataUri = null;
775+
String path = null;
764776

765777
try {
766778
byte[] data = part.getData();
@@ -773,9 +785,38 @@ private void persistData(PduPart part, Uri uri,
773785
throw new MmsException("unable to update " + uri.toString());
774786
}
775787
} else {
788+
boolean isDrm = DownloadDrmHelper.isDrmConvertNeeded(contentType);
789+
if (isDrm) {
790+
if (uri != null) {
791+
try {
792+
path = convertUriToPath(mContext, uri);
793+
if (LOCAL_LOGV) {
794+
Log.v(TAG, "drm uri: " + uri + " path: " + path);
795+
}
796+
File f = new File(path);
797+
long len = f.length();
798+
if (LOCAL_LOGV) {
799+
Log.v(TAG, "drm path: " + path + " len: " + len);
800+
}
801+
if (len > 0) {
802+
// we're not going to re-persist and re-encrypt an already
803+
// converted drm file
804+
return;
805+
}
806+
} catch (Exception e) {
807+
Log.e(TAG, "Can't get file info for: " + part.getDataUri(), e);
808+
}
809+
}
810+
// We haven't converted the file yet, start the conversion
811+
drmConvertSession = DrmConvertSession.open(mContext, contentType);
812+
if (drmConvertSession == null) {
813+
throw new MmsException("Mimetype " + contentType +
814+
" can not be converted.");
815+
}
816+
}
776817
os = mContentResolver.openOutputStream(uri);
777818
if (data == null) {
778-
Uri dataUri = part.getDataUri();
819+
dataUri = part.getDataUri();
779820
if ((dataUri == null) || (dataUri == uri)) {
780821
Log.w(TAG, "Can't find data for this part.");
781822
return;
@@ -788,13 +829,32 @@ private void persistData(PduPart part, Uri uri,
788829

789830
byte[] buffer = new byte[8192];
790831
for (int len = 0; (len = is.read(buffer)) != -1; ) {
791-
os.write(buffer, 0, len);
832+
if (!isDrm) {
833+
os.write(buffer, 0, len);
834+
} else {
835+
byte[] convertedData = drmConvertSession.convert(buffer, len);
836+
if (convertedData != null) {
837+
os.write(convertedData, 0, convertedData.length);
838+
} else {
839+
throw new MmsException("Error converting drm data.");
840+
}
841+
}
792842
}
793843
} else {
794844
if (LOCAL_LOGV) {
795845
Log.v(TAG, "Saving data to: " + uri);
796846
}
797-
os.write(data);
847+
if (!isDrm) {
848+
os.write(data);
849+
} else {
850+
dataUri = uri;
851+
byte[] convertedData = drmConvertSession.convert(data, data.length);
852+
if (convertedData != null) {
853+
os.write(convertedData, 0, convertedData.length);
854+
} else {
855+
throw new MmsException("Error converting drm data.");
856+
}
857+
}
798858
}
799859
}
800860
} catch (FileNotFoundException e) {
@@ -818,7 +878,65 @@ private void persistData(PduPart part, Uri uri,
818878
Log.e(TAG, "IOException while closing: " + is, e);
819879
} // Ignore
820880
}
881+
if (drmConvertSession != null) {
882+
drmConvertSession.close(path);
883+
884+
// Reset the permissions on the encrypted part file so everyone has only read
885+
// permission.
886+
File f = new File(path);
887+
ContentValues values = new ContentValues(0);
888+
SqliteWrapper.update(mContext, mContentResolver,
889+
Uri.parse("content://mms/resetFilePerm/" + f.getName()),
890+
values, null, null);
891+
}
892+
}
893+
}
894+
895+
/**
896+
* This method expects uri in the following format
897+
* content://media/<table_name>/<row_index> (or)
898+
* file://sdcard/test.mp4
899+
* http://test.com/test.mp4
900+
*
901+
* Here <table_name> shall be "video" or "audio" or "images"
902+
* <row_index> the index of the content in given table
903+
*/
904+
static public String convertUriToPath(Context context, Uri uri) {
905+
String path = null;
906+
if (null != uri) {
907+
String scheme = uri.getScheme();
908+
if (null == scheme || scheme.equals("") ||
909+
scheme.equals(ContentResolver.SCHEME_FILE)) {
910+
path = uri.getPath();
911+
912+
} else if (scheme.equals("http")) {
913+
path = uri.toString();
914+
915+
} else if (scheme.equals(ContentResolver.SCHEME_CONTENT)) {
916+
String[] projection = new String[] {MediaStore.MediaColumns.DATA};
917+
Cursor cursor = null;
918+
try {
919+
cursor = context.getContentResolver().query(uri, projection, null,
920+
null, null);
921+
if (null == cursor || 0 == cursor.getCount() || !cursor.moveToFirst()) {
922+
throw new IllegalArgumentException("Given Uri could not be found" +
923+
" in media store");
924+
}
925+
int pathIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
926+
path = cursor.getString(pathIndex);
927+
} catch (SQLiteException e) {
928+
throw new IllegalArgumentException("Given Uri is not formatted in a way " +
929+
"so that it can be found in media store.");
930+
} finally {
931+
if (null != cursor) {
932+
cursor.close();
933+
}
934+
}
935+
} else {
936+
throw new IllegalArgumentException("Given Uri scheme is not supported");
937+
}
821938
}
939+
return path;
822940
}
823941

824942
private void updateAddress(
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright (C) 2012 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package com.google.android.mms.util;
19+
20+
import android.content.Context;
21+
import android.drm.DrmManagerClient;
22+
import android.util.Log;
23+
24+
public class DownloadDrmHelper {
25+
private static final String TAG = "DownloadDrmHelper";
26+
27+
/** The MIME type of special DRM files */
28+
public static final String MIMETYPE_DRM_MESSAGE = "application/vnd.oma.drm.message";
29+
30+
/** The extensions of special DRM files */
31+
public static final String EXTENSION_DRM_MESSAGE = ".dm";
32+
33+
public static final String EXTENSION_INTERNAL_FWDL = ".fl";
34+
35+
/**
36+
* Checks if the Media Type is a DRM Media Type
37+
*
38+
* @param drmManagerClient A DrmManagerClient
39+
* @param mimetype Media Type to check
40+
* @return True if the Media Type is DRM else false
41+
*/
42+
public static boolean isDrmMimeType(Context context, String mimetype) {
43+
boolean result = false;
44+
if (context != null) {
45+
try {
46+
DrmManagerClient drmClient = new DrmManagerClient(context);
47+
if (drmClient != null && mimetype != null && mimetype.length() > 0) {
48+
result = drmClient.canHandle("", mimetype);
49+
}
50+
} catch (IllegalArgumentException e) {
51+
Log.w(TAG,
52+
"DrmManagerClient instance could not be created, context is Illegal.");
53+
} catch (IllegalStateException e) {
54+
Log.w(TAG, "DrmManagerClient didn't initialize properly.");
55+
}
56+
}
57+
return result;
58+
}
59+
60+
/**
61+
* Checks if the Media Type needs to be DRM converted
62+
*
63+
* @param mimetype Media type of the content
64+
* @return True if convert is needed else false
65+
*/
66+
public static boolean isDrmConvertNeeded(String mimetype) {
67+
return MIMETYPE_DRM_MESSAGE.equals(mimetype);
68+
}
69+
70+
/**
71+
* Modifies the file extension for a DRM Forward Lock file NOTE: This
72+
* function shouldn't be called if the file shouldn't be DRM converted
73+
*/
74+
public static String modifyDrmFwLockFileExtension(String filename) {
75+
if (filename != null) {
76+
int extensionIndex;
77+
extensionIndex = filename.lastIndexOf(".");
78+
if (extensionIndex != -1) {
79+
filename = filename.substring(0, extensionIndex);
80+
}
81+
filename = filename.concat(EXTENSION_INTERNAL_FWDL);
82+
}
83+
return filename;
84+
}
85+
86+
/**
87+
* Gets the original mime type of DRM protected content.
88+
*
89+
* @param context The context
90+
* @param path Path to the file
91+
* @param containingMime The current mime type of of the file i.e. the
92+
* containing mime type
93+
* @return The original mime type of the file if DRM protected else the
94+
* currentMime
95+
*/
96+
public static String getOriginalMimeType(Context context, String path, String containingMime) {
97+
String result = containingMime;
98+
DrmManagerClient drmClient = new DrmManagerClient(context);
99+
try {
100+
if (drmClient.canHandle(path, null)) {
101+
result = drmClient.getOriginalMimeType(path);
102+
}
103+
} catch (IllegalArgumentException ex) {
104+
Log.w(TAG,
105+
"Can't get original mime type since path is null or empty string.");
106+
} catch (IllegalStateException ex) {
107+
Log.w(TAG, "DrmManagerClient didn't initialize properly.");
108+
}
109+
return result;
110+
}
111+
}

0 commit comments

Comments
 (0)