1d02a064168ae5c916b977182b764580e601cb084Wink Saville/*
2d02a064168ae5c916b977182b764580e601cb084Wink Saville * Copyright (C) 2012 The Android Open Source Project
3d02a064168ae5c916b977182b764580e601cb084Wink Saville *
4d02a064168ae5c916b977182b764580e601cb084Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5d02a064168ae5c916b977182b764580e601cb084Wink Saville * you may not use this file except in compliance with the License.
6d02a064168ae5c916b977182b764580e601cb084Wink Saville * You may obtain a copy of the License at
7d02a064168ae5c916b977182b764580e601cb084Wink Saville *
8d02a064168ae5c916b977182b764580e601cb084Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
9d02a064168ae5c916b977182b764580e601cb084Wink Saville *
10d02a064168ae5c916b977182b764580e601cb084Wink Saville * Unless required by applicable law or agreed to in writing, software
11d02a064168ae5c916b977182b764580e601cb084Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12d02a064168ae5c916b977182b764580e601cb084Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d02a064168ae5c916b977182b764580e601cb084Wink Saville * See the License for the specific language governing permissions and
14d02a064168ae5c916b977182b764580e601cb084Wink Saville * limitations under the License.
15d02a064168ae5c916b977182b764580e601cb084Wink Saville *
16d02a064168ae5c916b977182b764580e601cb084Wink Saville */
17d02a064168ae5c916b977182b764580e601cb084Wink Savillepackage com.google.android.mms.util;
18d02a064168ae5c916b977182b764580e601cb084Wink Saville
19d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport android.content.Context;
20d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport android.drm.DrmConvertedStatus;
21d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport android.drm.DrmManagerClient;
22d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport android.util.Log;
23d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport android.provider.Downloads;
24d02a064168ae5c916b977182b764580e601cb084Wink Saville
25d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport java.io.FileNotFoundException;
26d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport java.io.IOException;
27d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport java.io.RandomAccessFile;
28d02a064168ae5c916b977182b764580e601cb084Wink Saville
29d02a064168ae5c916b977182b764580e601cb084Wink Saville
30d02a064168ae5c916b977182b764580e601cb084Wink Savillepublic class DrmConvertSession {
31d02a064168ae5c916b977182b764580e601cb084Wink Saville    private DrmManagerClient mDrmClient;
32d02a064168ae5c916b977182b764580e601cb084Wink Saville    private int mConvertSessionId;
33d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final String TAG = "DrmConvertSession";
34d02a064168ae5c916b977182b764580e601cb084Wink Saville
35d02a064168ae5c916b977182b764580e601cb084Wink Saville    private DrmConvertSession(DrmManagerClient drmClient, int convertSessionId) {
36d02a064168ae5c916b977182b764580e601cb084Wink Saville        mDrmClient = drmClient;
37d02a064168ae5c916b977182b764580e601cb084Wink Saville        mConvertSessionId = convertSessionId;
38d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
39d02a064168ae5c916b977182b764580e601cb084Wink Saville
40d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
41d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Start of converting a file.
42d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
43d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param context The context of the application running the convert session.
44d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param mimeType Mimetype of content that shall be converted.
45d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return A convert session or null in case an error occurs.
46d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
47d02a064168ae5c916b977182b764580e601cb084Wink Saville    public static DrmConvertSession open(Context context, String mimeType) {
48d02a064168ae5c916b977182b764580e601cb084Wink Saville        DrmManagerClient drmClient = null;
49d02a064168ae5c916b977182b764580e601cb084Wink Saville        int convertSessionId = -1;
50d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (context != null && mimeType != null && !mimeType.equals("")) {
51d02a064168ae5c916b977182b764580e601cb084Wink Saville            try {
52d02a064168ae5c916b977182b764580e601cb084Wink Saville                drmClient = new DrmManagerClient(context);
53d02a064168ae5c916b977182b764580e601cb084Wink Saville                try {
54d02a064168ae5c916b977182b764580e601cb084Wink Saville                    convertSessionId = drmClient.openConvertSession(mimeType);
55d02a064168ae5c916b977182b764580e601cb084Wink Saville                } catch (IllegalArgumentException e) {
56d02a064168ae5c916b977182b764580e601cb084Wink Saville                    Log.w(TAG, "Conversion of Mimetype: " + mimeType
57d02a064168ae5c916b977182b764580e601cb084Wink Saville                            + " is not supported.", e);
58d02a064168ae5c916b977182b764580e601cb084Wink Saville                } catch (IllegalStateException e) {
59d02a064168ae5c916b977182b764580e601cb084Wink Saville                    Log.w(TAG, "Could not access Open DrmFramework.", e);
60d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
61d02a064168ae5c916b977182b764580e601cb084Wink Saville            } catch (IllegalArgumentException e) {
62d02a064168ae5c916b977182b764580e601cb084Wink Saville                Log.w(TAG,
63d02a064168ae5c916b977182b764580e601cb084Wink Saville                        "DrmManagerClient instance could not be created, context is Illegal.");
64d02a064168ae5c916b977182b764580e601cb084Wink Saville            } catch (IllegalStateException e) {
65d02a064168ae5c916b977182b764580e601cb084Wink Saville                Log.w(TAG, "DrmManagerClient didn't initialize properly.");
66d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
67d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
68d02a064168ae5c916b977182b764580e601cb084Wink Saville
69d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (drmClient == null || convertSessionId < 0) {
70d02a064168ae5c916b977182b764580e601cb084Wink Saville            return null;
71d02a064168ae5c916b977182b764580e601cb084Wink Saville        } else {
72d02a064168ae5c916b977182b764580e601cb084Wink Saville            return new DrmConvertSession(drmClient, convertSessionId);
73d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
74d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
75d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
76d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Convert a buffer of data to protected format.
77d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
78d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param buffer Buffer filled with data to convert.
79d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param size The number of bytes that shall be converted.
80d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return A Buffer filled with converted data, if execution is ok, in all
81d02a064168ae5c916b977182b764580e601cb084Wink Saville     *         other case null.
82d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
83d02a064168ae5c916b977182b764580e601cb084Wink Saville    public byte [] convert(byte[] inBuffer, int size) {
84d02a064168ae5c916b977182b764580e601cb084Wink Saville        byte[] result = null;
85d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (inBuffer != null) {
86d02a064168ae5c916b977182b764580e601cb084Wink Saville            DrmConvertedStatus convertedStatus = null;
87d02a064168ae5c916b977182b764580e601cb084Wink Saville            try {
88d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (size != inBuffer.length) {
89d02a064168ae5c916b977182b764580e601cb084Wink Saville                    byte[] buf = new byte[size];
90d02a064168ae5c916b977182b764580e601cb084Wink Saville                    System.arraycopy(inBuffer, 0, buf, 0, size);
91d02a064168ae5c916b977182b764580e601cb084Wink Saville                    convertedStatus = mDrmClient.convertData(mConvertSessionId, buf);
92d02a064168ae5c916b977182b764580e601cb084Wink Saville                } else {
93d02a064168ae5c916b977182b764580e601cb084Wink Saville                    convertedStatus = mDrmClient.convertData(mConvertSessionId, inBuffer);
94d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
95d02a064168ae5c916b977182b764580e601cb084Wink Saville
96d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (convertedStatus != null &&
97d02a064168ae5c916b977182b764580e601cb084Wink Saville                        convertedStatus.statusCode == DrmConvertedStatus.STATUS_OK &&
98d02a064168ae5c916b977182b764580e601cb084Wink Saville                        convertedStatus.convertedData != null) {
99d02a064168ae5c916b977182b764580e601cb084Wink Saville                    result = convertedStatus.convertedData;
100d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
101d02a064168ae5c916b977182b764580e601cb084Wink Saville            } catch (IllegalArgumentException e) {
102d02a064168ae5c916b977182b764580e601cb084Wink Saville                Log.w(TAG, "Buffer with data to convert is illegal. Convertsession: "
103d02a064168ae5c916b977182b764580e601cb084Wink Saville                        + mConvertSessionId, e);
104d02a064168ae5c916b977182b764580e601cb084Wink Saville            } catch (IllegalStateException e) {
105d02a064168ae5c916b977182b764580e601cb084Wink Saville                Log.w(TAG, "Could not convert data. Convertsession: " +
106d02a064168ae5c916b977182b764580e601cb084Wink Saville                        mConvertSessionId, e);
107d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
108d02a064168ae5c916b977182b764580e601cb084Wink Saville        } else {
109d02a064168ae5c916b977182b764580e601cb084Wink Saville            throw new IllegalArgumentException("Parameter inBuffer is null");
110d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
111d02a064168ae5c916b977182b764580e601cb084Wink Saville        return result;
112d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
113d02a064168ae5c916b977182b764580e601cb084Wink Saville
114d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
115d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Ends a conversion session of a file.
116d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
117d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param fileName The filename of the converted file.
118d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return Downloads.Impl.STATUS_SUCCESS if execution is ok.
119d02a064168ae5c916b977182b764580e601cb084Wink Saville     *         Downloads.Impl.STATUS_FILE_ERROR in case converted file can not
120d02a064168ae5c916b977182b764580e601cb084Wink Saville     *         be accessed. Downloads.Impl.STATUS_NOT_ACCEPTABLE if a problem
121d02a064168ae5c916b977182b764580e601cb084Wink Saville     *         occurs when accessing drm framework.
122d02a064168ae5c916b977182b764580e601cb084Wink Saville     *         Downloads.Impl.STATUS_UNKNOWN_ERROR if a general error occurred.
123d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
124d02a064168ae5c916b977182b764580e601cb084Wink Saville    public int close(String filename) {
125d02a064168ae5c916b977182b764580e601cb084Wink Saville        DrmConvertedStatus convertedStatus = null;
126d02a064168ae5c916b977182b764580e601cb084Wink Saville        int result = Downloads.Impl.STATUS_UNKNOWN_ERROR;
127d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (mDrmClient != null && mConvertSessionId >= 0) {
128d02a064168ae5c916b977182b764580e601cb084Wink Saville            try {
129d02a064168ae5c916b977182b764580e601cb084Wink Saville                convertedStatus = mDrmClient.closeConvertSession(mConvertSessionId);
130d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (convertedStatus == null ||
131d02a064168ae5c916b977182b764580e601cb084Wink Saville                        convertedStatus.statusCode != DrmConvertedStatus.STATUS_OK ||
132d02a064168ae5c916b977182b764580e601cb084Wink Saville                        convertedStatus.convertedData == null) {
133d02a064168ae5c916b977182b764580e601cb084Wink Saville                    result = Downloads.Impl.STATUS_NOT_ACCEPTABLE;
134d02a064168ae5c916b977182b764580e601cb084Wink Saville                } else {
135d02a064168ae5c916b977182b764580e601cb084Wink Saville                    RandomAccessFile rndAccessFile = null;
136d02a064168ae5c916b977182b764580e601cb084Wink Saville                    try {
137d02a064168ae5c916b977182b764580e601cb084Wink Saville                        rndAccessFile = new RandomAccessFile(filename, "rw");
138d02a064168ae5c916b977182b764580e601cb084Wink Saville                        rndAccessFile.seek(convertedStatus.offset);
139d02a064168ae5c916b977182b764580e601cb084Wink Saville                        rndAccessFile.write(convertedStatus.convertedData);
140d02a064168ae5c916b977182b764580e601cb084Wink Saville                        result = Downloads.Impl.STATUS_SUCCESS;
141d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch (FileNotFoundException e) {
142d02a064168ae5c916b977182b764580e601cb084Wink Saville                        result = Downloads.Impl.STATUS_FILE_ERROR;
143d02a064168ae5c916b977182b764580e601cb084Wink Saville                        Log.w(TAG, "File: " + filename + " could not be found.", e);
144d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch (IOException e) {
145d02a064168ae5c916b977182b764580e601cb084Wink Saville                        result = Downloads.Impl.STATUS_FILE_ERROR;
146d02a064168ae5c916b977182b764580e601cb084Wink Saville                        Log.w(TAG, "Could not access File: " + filename + " .", e);
147d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch (IllegalArgumentException e) {
148d02a064168ae5c916b977182b764580e601cb084Wink Saville                        result = Downloads.Impl.STATUS_FILE_ERROR;
149d02a064168ae5c916b977182b764580e601cb084Wink Saville                        Log.w(TAG, "Could not open file in mode: rw", e);
150d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch (SecurityException e) {
151d02a064168ae5c916b977182b764580e601cb084Wink Saville                        Log.w(TAG, "Access to File: " + filename +
152d02a064168ae5c916b977182b764580e601cb084Wink Saville                                " was denied denied by SecurityManager.", e);
153d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } finally {
154d02a064168ae5c916b977182b764580e601cb084Wink Saville                        if (rndAccessFile != null) {
155d02a064168ae5c916b977182b764580e601cb084Wink Saville                            try {
156d02a064168ae5c916b977182b764580e601cb084Wink Saville                                rndAccessFile.close();
157d02a064168ae5c916b977182b764580e601cb084Wink Saville                            } catch (IOException e) {
158d02a064168ae5c916b977182b764580e601cb084Wink Saville                                result = Downloads.Impl.STATUS_FILE_ERROR;
159d02a064168ae5c916b977182b764580e601cb084Wink Saville                                Log.w(TAG, "Failed to close File:" + filename
160d02a064168ae5c916b977182b764580e601cb084Wink Saville                                        + ".", e);
161d02a064168ae5c916b977182b764580e601cb084Wink Saville                            }
162d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
163d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
164d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
165d02a064168ae5c916b977182b764580e601cb084Wink Saville            } catch (IllegalStateException e) {
166d02a064168ae5c916b977182b764580e601cb084Wink Saville                Log.w(TAG, "Could not close convertsession. Convertsession: " +
167d02a064168ae5c916b977182b764580e601cb084Wink Saville                        mConvertSessionId, e);
168d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
169d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
170d02a064168ae5c916b977182b764580e601cb084Wink Saville        return result;
171d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
172d02a064168ae5c916b977182b764580e601cb084Wink Saville}
173