1526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen/*
2526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Copyright (C) 2012 The Android Open Source Project
3526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen *
4526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Licensed under the Apache License, Version 2.0 (the "License");
5526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * you may not use this file except in compliance with the License.
6526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * You may obtain a copy of the License at
7526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen *
8526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen *      http://www.apache.org/licenses/LICENSE-2.0
9526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen *
10526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Unless required by applicable law or agreed to in writing, software
11526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * distributed under the License is distributed on an "AS IS" BASIS,
12526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * See the License for the specific language governing permissions and
14526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * limitations under the License.
15526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen *
16526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen */
17526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenpackage com.google.android.mms.util;
18526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
19526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenimport android.content.Context;
20526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenimport android.drm.DrmConvertedStatus;
21526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenimport android.drm.DrmManagerClient;
22526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenimport android.util.Log;
23526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenimport android.provider.Downloads;
24526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
25526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenimport java.io.FileNotFoundException;
26526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenimport java.io.IOException;
27526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenimport java.io.RandomAccessFile;
28526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
29526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
30526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenpublic class DrmConvertSession {
31526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private DrmManagerClient mDrmClient;
32526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private int mConvertSessionId;
33526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final String TAG = "DrmConvertSession";
34526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
35526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private DrmConvertSession(DrmManagerClient drmClient, int convertSessionId) {
36526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        mDrmClient = drmClient;
37526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        mConvertSessionId = convertSessionId;
38526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
39526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
40526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
41526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Start of converting a file.
42526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
43526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param context The context of the application running the convert session.
44526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param mimeType Mimetype of content that shall be converted.
45526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return A convert session or null in case an error occurs.
46526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
47526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    public static DrmConvertSession open(Context context, String mimeType) {
48526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        DrmManagerClient drmClient = null;
49526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int convertSessionId = -1;
50526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (context != null && mimeType != null && !mimeType.equals("")) {
51526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            try {
52526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                drmClient = new DrmManagerClient(context);
53526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                try {
54526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    convertSessionId = drmClient.openConvertSession(mimeType);
55526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                } catch (IllegalArgumentException e) {
56526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    Log.w(TAG, "Conversion of Mimetype: " + mimeType
57526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            + " is not supported.", e);
58526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                } catch (IllegalStateException e) {
59526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    Log.w(TAG, "Could not access Open DrmFramework.", e);
60526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
61526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            } catch (IllegalArgumentException e) {
62526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                Log.w(TAG,
63526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        "DrmManagerClient instance could not be created, context is Illegal.");
64526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            } catch (IllegalStateException e) {
65526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                Log.w(TAG, "DrmManagerClient didn't initialize properly.");
66526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
67526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
68526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
69526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (drmClient == null || convertSessionId < 0) {
70526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return null;
71526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        } else {
72526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return new DrmConvertSession(drmClient, convertSessionId);
73526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
74526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
75526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
76526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Convert a buffer of data to protected format.
77526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
78526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param buffer Buffer filled with data to convert.
79526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param size The number of bytes that shall be converted.
80526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return A Buffer filled with converted data, if execution is ok, in all
81526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *         other case null.
82526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
83526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    public byte [] convert(byte[] inBuffer, int size) {
84526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        byte[] result = null;
85526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (inBuffer != null) {
86526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            DrmConvertedStatus convertedStatus = null;
87526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            try {
88526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (size != inBuffer.length) {
89526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    byte[] buf = new byte[size];
90526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    System.arraycopy(inBuffer, 0, buf, 0, size);
91526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    convertedStatus = mDrmClient.convertData(mConvertSessionId, buf);
92526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                } else {
93526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    convertedStatus = mDrmClient.convertData(mConvertSessionId, inBuffer);
94526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
95526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
96526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (convertedStatus != null &&
97526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        convertedStatus.statusCode == DrmConvertedStatus.STATUS_OK &&
98526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        convertedStatus.convertedData != null) {
99526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    result = convertedStatus.convertedData;
100526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
101526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            } catch (IllegalArgumentException e) {
102526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                Log.w(TAG, "Buffer with data to convert is illegal. Convertsession: "
103526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        + mConvertSessionId, e);
104526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            } catch (IllegalStateException e) {
105526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                Log.w(TAG, "Could not convert data. Convertsession: " +
106526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        mConvertSessionId, e);
107526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
108526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        } else {
109526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            throw new IllegalArgumentException("Parameter inBuffer is null");
110526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
111526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return result;
112526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
113526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
114526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
115526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Ends a conversion session of a file.
116526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
117526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param fileName The filename of the converted file.
118526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return Downloads.Impl.STATUS_SUCCESS if execution is ok.
119526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *         Downloads.Impl.STATUS_FILE_ERROR in case converted file can not
120526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *         be accessed. Downloads.Impl.STATUS_NOT_ACCEPTABLE if a problem
121526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *         occurs when accessing drm framework.
122526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *         Downloads.Impl.STATUS_UNKNOWN_ERROR if a general error occurred.
123526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
124526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    public int close(String filename) {
125526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        DrmConvertedStatus convertedStatus = null;
126526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int result = Downloads.Impl.STATUS_UNKNOWN_ERROR;
127526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (mDrmClient != null && mConvertSessionId >= 0) {
128526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            try {
129526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                convertedStatus = mDrmClient.closeConvertSession(mConvertSessionId);
130526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (convertedStatus == null ||
131526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        convertedStatus.statusCode != DrmConvertedStatus.STATUS_OK ||
132526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        convertedStatus.convertedData == null) {
133526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    result = Downloads.Impl.STATUS_NOT_ACCEPTABLE;
134526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                } else {
135526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    RandomAccessFile rndAccessFile = null;
136526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    try {
137526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        rndAccessFile = new RandomAccessFile(filename, "rw");
138526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        rndAccessFile.seek(convertedStatus.offset);
139526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        rndAccessFile.write(convertedStatus.convertedData);
140526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        result = Downloads.Impl.STATUS_SUCCESS;
141526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch (FileNotFoundException e) {
142526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        result = Downloads.Impl.STATUS_FILE_ERROR;
143526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        Log.w(TAG, "File: " + filename + " could not be found.", e);
144526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch (IOException e) {
145526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        result = Downloads.Impl.STATUS_FILE_ERROR;
146526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        Log.w(TAG, "Could not access File: " + filename + " .", e);
147526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch (IllegalArgumentException e) {
148526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        result = Downloads.Impl.STATUS_FILE_ERROR;
149526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        Log.w(TAG, "Could not open file in mode: rw", e);
150526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch (SecurityException e) {
151526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        Log.w(TAG, "Access to File: " + filename +
152526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                " was denied denied by SecurityManager.", e);
153526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } finally {
154526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (rndAccessFile != null) {
155526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            try {
156526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                rndAccessFile.close();
157526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            } catch (IOException e) {
158526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                result = Downloads.Impl.STATUS_FILE_ERROR;
159526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                Log.w(TAG, "Failed to close File:" + filename
160526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                        + ".", e);
161526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            }
162526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
163526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
164526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
165526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            } catch (IllegalStateException e) {
166526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                Log.w(TAG, "Could not close convertsession. Convertsession: " +
167526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        mConvertSessionId, e);
168526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
169526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
170526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return result;
171526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
172526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen}
173