10a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang/* 20a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * Copyright (C) 2011 The Android Open Source Project 30a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * 40a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * Licensed under the Apache License, Version 2.0 (the "License"); 50a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * you may not use this file except in compliance with the License. 60a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * You may obtain a copy of the License at 70a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * 80a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * http://www.apache.org/licenses/LICENSE-2.0 90a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * 100a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * Unless required by applicable law or agreed to in writing, software 110a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * distributed under the License is distributed on an "AS IS" BASIS, 120a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * See the License for the specific language governing permissions and 140a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * limitations under the License. 150a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * 160a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang */ 170a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wangpackage com.android.providers.downloads; 180a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang 190a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wangimport android.content.Context; 200a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wangimport android.drm.DrmConvertedStatus; 210a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wangimport android.drm.DrmManagerClient; 220a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wangimport android.util.Log; 230a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wangimport android.provider.Downloads; 240a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang 250a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wangimport java.io.FileNotFoundException; 260a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wangimport java.io.IOException; 270a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wangimport java.io.RandomAccessFile; 280a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang 290a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang 300a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wangpublic class DrmConvertSession { 310a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang private DrmManagerClient mDrmClient; 320a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang private int mConvertSessionId; 330a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang 340a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang private DrmConvertSession(DrmManagerClient drmClient, int convertSessionId) { 350a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang mDrmClient = drmClient; 360a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang mConvertSessionId = convertSessionId; 370a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 380a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang 390a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang /** 400a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * Start of converting a file. 410a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * 420a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * @param context The context of the application running the convert session. 430a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * @param mimeType Mimetype of content that shall be converted. 440a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * @return A convert session or null in case an error occurs. 450a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang */ 460a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang public static DrmConvertSession open(Context context, String mimeType) { 470a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang DrmManagerClient drmClient = null; 480a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang int convertSessionId = -1; 490a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang if (context != null && mimeType != null && !mimeType.equals("")) { 500a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang try { 510a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang drmClient = new DrmManagerClient(context); 520a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang try { 530a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang convertSessionId = drmClient.openConvertSession(mimeType); 540a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } catch (IllegalArgumentException e) { 550a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang Log.w(Constants.TAG, "Conversion of Mimetype: " + mimeType 560a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang + " is not supported.", e); 570a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } catch (IllegalStateException e) { 580a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang Log.w(Constants.TAG, "Could not access Open DrmFramework.", e); 590a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 600a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } catch (IllegalArgumentException e) { 610a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang Log.w(Constants.TAG, 620a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang "DrmManagerClient instance could not be created, context is Illegal."); 630a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } catch (IllegalStateException e) { 640a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang Log.w(Constants.TAG, "DrmManagerClient didn't initialize properly."); 650a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 660a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 670a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang 680a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang if (drmClient == null || convertSessionId < 0) { 690a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang return null; 700a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } else { 710a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang return new DrmConvertSession(drmClient, convertSessionId); 720a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 730a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 740a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang /** 750a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * Convert a buffer of data to protected format. 760a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * 770a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * @param buffer Buffer filled with data to convert. 780a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * @param size The number of bytes that shall be converted. 790a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * @return A Buffer filled with converted data, if execution is ok, in all 800a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * other case null. 810a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang */ 820a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang public byte [] convert(byte[] inBuffer, int size) { 830a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang byte[] result = null; 840a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang if (inBuffer != null) { 850a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang DrmConvertedStatus convertedStatus = null; 860a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang try { 870a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang if (size != inBuffer.length) { 880a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang byte[] buf = new byte[size]; 890a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang System.arraycopy(inBuffer, 0, buf, 0, size); 900a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang convertedStatus = mDrmClient.convertData(mConvertSessionId, buf); 910a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } else { 920a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang convertedStatus = mDrmClient.convertData(mConvertSessionId, inBuffer); 930a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 940a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang 950a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang if (convertedStatus != null && 960a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang convertedStatus.statusCode == DrmConvertedStatus.STATUS_OK && 970a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang convertedStatus.convertedData != null) { 980a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang result = convertedStatus.convertedData; 990a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 1000a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } catch (IllegalArgumentException e) { 1010a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang Log.w(Constants.TAG, "Buffer with data to convert is illegal. Convertsession: " 1020a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang + mConvertSessionId, e); 1030a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } catch (IllegalStateException e) { 1040a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang Log.w(Constants.TAG, "Could not convert data. Convertsession: " + 1050a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang mConvertSessionId, e); 1060a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 1070a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } else { 1080a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang throw new IllegalArgumentException("Parameter inBuffer is null"); 1090a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 1100a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang return result; 1110a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 1120a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang 1130a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang /** 1140a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * Ends a conversion session of a file. 1150a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * 1160a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * @param fileName The filename of the converted file. 1170a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * @return Downloads.Impl.STATUS_SUCCESS if execution is ok. 1180a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * Downloads.Impl.STATUS_FILE_ERROR in case converted file can not 1190a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * be accessed. Downloads.Impl.STATUS_NOT_ACCEPTABLE if a problem 1200a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * occurs when accessing drm framework. 1210a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang * Downloads.Impl.STATUS_UNKNOWN_ERROR if a general error occurred. 1220a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang */ 1230a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang public int close(String filename) { 1240a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang DrmConvertedStatus convertedStatus = null; 1250a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang int result = Downloads.Impl.STATUS_UNKNOWN_ERROR; 1260a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang if (mDrmClient != null && mConvertSessionId >= 0) { 1270a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang try { 1280a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang convertedStatus = mDrmClient.closeConvertSession(mConvertSessionId); 1290a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang if (convertedStatus == null || 1300a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang convertedStatus.statusCode != DrmConvertedStatus.STATUS_OK || 1310a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang convertedStatus.convertedData == null) { 1320a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang result = Downloads.Impl.STATUS_NOT_ACCEPTABLE; 1330a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } else { 1340a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang RandomAccessFile rndAccessFile = null; 1350a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang try { 1360a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang rndAccessFile = new RandomAccessFile(filename, "rw"); 1370a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang rndAccessFile.seek(convertedStatus.offset); 1380a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang rndAccessFile.write(convertedStatus.convertedData); 1390a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang result = Downloads.Impl.STATUS_SUCCESS; 1400a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } catch (FileNotFoundException e) { 1410a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang result = Downloads.Impl.STATUS_FILE_ERROR; 1420a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang Log.w(Constants.TAG, "File: " + filename + " could not be found.", e); 1430a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } catch (IOException e) { 1440a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang result = Downloads.Impl.STATUS_FILE_ERROR; 1450a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang Log.w(Constants.TAG, "Could not access File: " + filename + " .", e); 1460a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } catch (IllegalArgumentException e) { 1470a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang result = Downloads.Impl.STATUS_FILE_ERROR; 1480a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang Log.w(Constants.TAG, "Could not open file in mode: rw", e); 1490a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } catch (SecurityException e) { 1500a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang Log.w(Constants.TAG, "Access to File: " + filename + 1510a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang " was denied denied by SecurityManager.", e); 1520a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } finally { 1530a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang if (rndAccessFile != null) { 1540a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang try { 1550a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang rndAccessFile.close(); 1560a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } catch (IOException e) { 1570a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang result = Downloads.Impl.STATUS_FILE_ERROR; 1580a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang Log.w(Constants.TAG, "Failed to close File:" + filename 1590a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang + ".", e); 1600a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 1610a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 1620a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 1630a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 1640a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } catch (IllegalStateException e) { 1650a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang Log.w(Constants.TAG, "Could not close convertsession. Convertsession: " + 1660a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang mConvertSessionId, e); 1670a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 1680a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 1690a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang return result; 1700a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang } 1710a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang} 172