1/*
2 * Copyright (C) 2008 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 android.provider;
18
19import android.content.ContentResolver;
20import android.content.ContentValues;
21import android.content.Context;
22import android.drm.mobile1.DrmRawContent;
23import android.drm.mobile1.DrmRights;
24import android.drm.mobile1.DrmRightsManager;
25import android.content.Intent;
26import android.content.pm.PackageManager;
27import android.net.Uri;
28import android.util.Log;
29
30import java.io.File;
31import java.io.FileInputStream;
32import java.io.InputStream;
33import java.io.IOException;
34import java.io.OutputStream;
35
36/**
37 * The DRM provider contains forward locked DRM content.
38 *
39 * @hide
40 */
41public final class DrmStore
42{
43    private static final String TAG = "DrmStore";
44
45    public static final String AUTHORITY = "drm";
46
47    /**
48     * This is in the Manifest class of the drm provider, but that isn't visible
49     * in the framework.
50     */
51    private static final String ACCESS_DRM_PERMISSION = "android.permission.ACCESS_DRM";
52
53    /**
54     * Fields for DRM database
55     */
56
57    public interface Columns extends BaseColumns {
58        /**
59         * The data stream for the file
60         * <P>Type: DATA STREAM</P>
61         */
62        public static final String DATA = "_data";
63
64        /**
65         * The size of the file in bytes
66         * <P>Type: INTEGER (long)</P>
67         */
68        public static final String SIZE = "_size";
69
70        /**
71         * The title of the file content
72         * <P>Type: TEXT</P>
73         */
74        public static final String TITLE = "title";
75
76        /**
77         * The MIME type of the file
78         * <P>Type: TEXT</P>
79         */
80        public static final String MIME_TYPE = "mime_type";
81
82    }
83
84    public interface Images extends Columns {
85
86        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/images");
87    }
88
89    public interface Audio extends Columns {
90
91        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/audio");
92    }
93
94    /**
95     * Utility function for inserting a file into the DRM content provider.
96     *
97     * @param cr The content resolver to use
98     * @param file The file to insert
99     * @param title The title for the content (or null)
100     * @return uri to the DRM record or null
101     */
102    public static final Intent addDrmFile(ContentResolver cr, File file, String title) {
103        FileInputStream fis = null;
104        Intent result = null;
105
106        try {
107            fis = new FileInputStream(file);
108            if (title == null) {
109                title = file.getName();
110                int lastDot = title.lastIndexOf('.');
111                if (lastDot > 0) {
112                    title = title.substring(0, lastDot);
113                }
114            }
115            result = addDrmFile(cr, fis, title);
116        } catch (Exception e) {
117            Log.e(TAG, "pushing file failed", e);
118        } finally {
119            try {
120                if (fis != null)
121                    fis.close();
122            } catch (IOException e) {
123                Log.e(TAG, "IOException in DrmStore.addDrmFile()", e);
124            }
125        }
126
127        return result;
128    }
129
130    /**
131     * Utility function for inserting a file stream into the DRM content provider.
132     *
133     * @param cr The content resolver to use
134     * @param fis The FileInputStream to insert
135     * @param title The title for the content (or null)
136     * @return uri to the DRM record or null
137     */
138    public static final Intent addDrmFile(ContentResolver cr, FileInputStream fis, String title) {
139        OutputStream os = null;
140        Intent result = null;
141
142        try {
143            DrmRawContent content = new DrmRawContent(fis, (int) fis.available(),
144                    DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING);
145            String mimeType = content.getContentType();
146            long size = fis.getChannel().size();
147
148            DrmRightsManager manager = manager = DrmRightsManager.getInstance();
149            DrmRights rights = manager.queryRights(content);
150            InputStream stream = content.getContentInputStream(rights);
151
152            Uri contentUri = null;
153            if (mimeType.startsWith("audio/")) {
154                contentUri = DrmStore.Audio.CONTENT_URI;
155            } else if (mimeType.startsWith("image/")) {
156                contentUri = DrmStore.Images.CONTENT_URI;
157            } else {
158                Log.w(TAG, "unsupported mime type " + mimeType);
159            }
160
161            if (contentUri != null) {
162                ContentValues values = new ContentValues(3);
163                values.put(DrmStore.Columns.TITLE, title);
164                values.put(DrmStore.Columns.SIZE, size);
165                values.put(DrmStore.Columns.MIME_TYPE, mimeType);
166
167                Uri uri = cr.insert(contentUri, values);
168                if (uri != null) {
169                    os = cr.openOutputStream(uri);
170
171                    byte[] buffer = new byte[1000];
172                    int count;
173
174                    while ((count = stream.read(buffer)) != -1) {
175                        os.write(buffer, 0, count);
176                    }
177                    result = new Intent();
178                    result.setDataAndType(uri, mimeType);
179
180                }
181            }
182        } catch (Exception e) {
183            Log.e(TAG, "pushing file failed", e);
184        } finally {
185            try {
186                if (fis != null)
187                    fis.close();
188                if (os != null)
189                    os.close();
190            } catch (IOException e) {
191                Log.e(TAG, "IOException in DrmStore.addDrmFile()", e);
192            }
193        }
194
195        return result;
196    }
197
198    /**
199     * Utility function to enforce any permissions required to access DRM
200     * content.
201     *
202     * @param context A context used for checking calling permission.
203     */
204    public static void enforceAccessDrmPermission(Context context) {
205        if (context.checkCallingOrSelfPermission(ACCESS_DRM_PERMISSION) !=
206                PackageManager.PERMISSION_GRANTED) {
207            throw new SecurityException("Requires DRM permission");
208        }
209    }
210
211}
212