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