blob: 046b84a89f6b451378053a3cbb5d1dab185f7bfa [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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.drm.mobile1;
18
19import java.io.*;
20
21/**
22 * This class provides interfaces to access the DRM raw content.
23 */
24public class DrmRawContent {
25 /**
26 * The "application/vnd.oma.drm.message" mime type.
27 */
28 public static final String DRM_MIMETYPE_MESSAGE_STRING = "application/vnd.oma.drm.message";
29
30 /**
31 * The "application/vnd.oma.drm.content" mime type.
32 */
33 public static final String DRM_MIMETYPE_CONTENT_STRING = "application/vnd.oma.drm.content";
34
35 /**
36 * The DRM delivery type: Forward-Lock
37 */
38 public static final int DRM_FORWARD_LOCK = 1;
39
40 /**
41 * The DRM delivery type: Combined Delivery
42 */
43 public static final int DRM_COMBINED_DELIVERY = 2;
44
45 /**
46 * The DRM delivery type: Separate Delivery
47 */
48 public static final int DRM_SEPARATE_DELIVERY = 3;
49
50 /**
51 * The DRM delivery type: Separate Delivery in DRM message
52 */
53 public static final int DRM_SEPARATE_DELIVERY_DM = 4;
54
55 /**
56 * The DRM media content length is unknown currently
57 */
58 public static final int DRM_UNKNOWN_DATA_LEN = -1;
59
60
61 /**
62 * The id of "application/vnd.oma.drm.message" mime type.
63 */
64 private static final int DRM_MIMETYPE_MESSAGE = 1;
65
66 /**
67 * The id of "application/vnd.oma.drm.content" mime type.
68 */
69 private static final int DRM_MIMETYPE_CONTENT = 2;
70
71 /**
72 * Successful operation.
73 */
74 private static final int JNI_DRM_SUCCESS = 0;
75
76 /**
77 * General failure.
78 */
79 private static final int JNI_DRM_FAILURE = -1;
80
81 /**
82 * Indicates the end of the DRM content is reached.
83 */
84 private static final int JNI_DRM_EOF = -2;
85
86 /**
87 * The media content length is unknown from native method
88 */
89 private static final int JNI_DRM_UNKNOWN_DATA_LEN = -3;
90
91 /**
92 * The member to save the original InputStream data.
93 */
94 private BufferedInputStream inData;
95
96 /**
97 * The member to save the original InputStream data length.
98 */
99 private int inDataLen;
100
101 /**
102 * The unique id to this DRM content. It will be initialized
103 * in constructor by native method. And it will not be changed
104 * after initialization.
105 */
106 private int id;
107
108 /**
109 * The rights issuer address of this DRM object.
110 */
111 private String rightsIssuer;
112
113 /**
114 * The media content type of this DRM object.
115 */
116 private String mediaType;
117
118 /**
119 * The delivery method type of this DRM object.
120 */
121 private int rawType;
122
123
124 /**
125 * Construct a DrmRawContent object.
126 *
127 * @param inRawdata object of DRM raw data stream.
128 * @param len the length of raw data can be read.
129 * @param mimeTypeStr the mime type of the DRM content.
130 */
131 public DrmRawContent(InputStream inRawdata, int len, String mimeTypeStr) throws DrmException, IOException {
132 int mimeType;
133
134 id = -1;
135 inData = new BufferedInputStream(inRawdata, 1024);
136 inDataLen = len;
137
138 if (DRM_MIMETYPE_MESSAGE_STRING.equals(mimeTypeStr))
139 mimeType = DRM_MIMETYPE_MESSAGE;
140 else if (DRM_MIMETYPE_CONTENT_STRING.equals(mimeTypeStr))
141 mimeType = DRM_MIMETYPE_CONTENT;
142 else
143 throw new IllegalArgumentException("mimeType must be DRM_MIMETYPE_MESSAGE or DRM_MIMETYPE_CONTENT");
144
145 if (len <= 0)
146 throw new IllegalArgumentException("len must be > 0");
147
148 /* call native method to initialize this DRM content */
149 id = nativeConstructDrmContent(inData, inDataLen, mimeType);
150
151 if (JNI_DRM_FAILURE == id)
152 throw new DrmException("nativeConstructDrmContent() returned JNI_DRM_FAILURE");
153
154 /* init the rights issuer field. */
155 rightsIssuer = nativeGetRightsAddress();
156
157 /* init the raw content type. */
158 rawType = nativeGetDeliveryMethod();
159 if (JNI_DRM_FAILURE == rawType)
160 throw new DrmException("nativeGetDeliveryMethod() returned JNI_DRM_FAILURE");
161
162 /* init the media content type. */
163 mediaType = nativeGetContentType();
164 if (null == mediaType)
165 throw new DrmException("nativeGetContentType() returned null");
166 }
167
168 /**
169 * Get rights address from raw Seperate Delivery content.
170 *
171 * @return the string of the rights issuer address,
172 * or null if no rights issuer.
173 */
174 public String getRightsAddress() {
175 return rightsIssuer;
176 }
177
178 /**
179 * Get the type of the raw DRM content.
180 *
181 * @return one of the following delivery type of this DRM content:
182 * #DRM_FORWARD_LOCK
183 * #DRM_COMBINED_DELIVERY
184 * #DRM_SEPARATE_DELIVERY
185 * #DRM_SEPARATE_DELIVERY_DM
186 */
187 public int getRawType() {
188 return rawType;
189 }
190
191 /**
192 * Get one InputStream object to read decrypted content.
193 *
194 * @param rights the rights object contain decrypted key.
195 *
196 * @return the InputStream object of decrypted media content.
197 */
198 public InputStream getContentInputStream(DrmRights rights) {
199 if (null == rights)
200 throw new NullPointerException();
201
202 return new DrmInputStream(rights);
203 }
204
205 /**
206 * Get the type of the decrypted media content.
207 *
208 * @return the decrypted media content type of this DRM content.
209 */
210 public String getContentType() {
211 return mediaType;
212 }
213
214 /**
215 * Get the length of the decrypted media content.
216 *
217 * @param rights the rights object contain decrypted key.
218 *
219 * @return the length of the decrypted media content.
220 * #DRM_UNKNOWN_DATA_LEN if the length is unknown currently.
221 */
222 public int getContentLength(DrmRights rights) throws DrmException {
223 /**
224 * Because currently the media object associate with rights object
225 * has been handled in native logic, so here it is not need to deal
226 * the rights. But for the apps, it is mandatory for user to get
227 * the rights object before get the media content length.
228 */
229 if (null == rights)
230 throw new NullPointerException();
231
232 int mediaLen = nativeGetContentLength();
233
234 if (JNI_DRM_FAILURE == mediaLen)
235 throw new DrmException("nativeGetContentLength() returned JNI_DRM_FAILURE");
236
237 if (JNI_DRM_UNKNOWN_DATA_LEN == mediaLen)
238 return DRM_UNKNOWN_DATA_LEN;
239
240 return mediaLen;
241 }
242
243 /**
244 * This class provide a InputStream to the DRM media content.
245 */
246 class DrmInputStream extends InputStream
247 {
248 /**
249 * The flag to indicate whether this stream is closed or not.
250 */
251 private boolean isClosed;
252
253 /**
254 * The offset of this DRM content to be reset.
255 */
256 private int offset;
257
258 /**
259 * A byte of data to be readed.
260 */
261 private byte[] b;
262
263 /**
264 * Construct a DrmInputStream instance.
265 */
266 public DrmInputStream(DrmRights rights) {
267 /**
268 * Because currently the media object associate with rights object
269 * has been handled in native logic, so here it is not need to deal
270 * the rights. But for the apps, it is mandatory for user to get
271 * the rights object before get the media content data.
272 */
273
274 isClosed = false;
275 offset = 0;
276 b = new byte[1];
277 }
278
279 /* Non-javadoc
280 * @see java.io.InputStream#available()
281 */
282 public int available() throws IOException {
283 /* call native method to get this DRM decrypted media content length */
284 int len = nativeGetContentLength();
285
286 if (JNI_DRM_FAILURE == len)
287 throw new IOException();
288
289 /* if the length is unknown, just return 0 for available value */
290 if (JNI_DRM_UNKNOWN_DATA_LEN == len)
291 return 0;
292
293 int availableLen = len - offset;
294 if (availableLen < 0)
295 throw new IOException();
296
297 return availableLen;
298 }
299
300 /* Non-javadoc
301 * @see java.io.InputStream#read()
302 */
303 public int read() throws IOException {
304 int res;
305
306 res = read(b, 0, 1);
307
308 if (-1 == res)
309 return -1;
310
311 return b[0] & 0xff;
312 }
313
314 /* Non-javadoc
315 * @see java.io.InputStream#read(byte)
316 */
317 public int read(byte[] b) throws IOException {
318 return read(b, 0, b.length);
319 }
320
321 /* Non-javadoc
322 * @see java.io.InputStream#read(byte, int, int)
323 */
324 public int read(byte[] b, int off, int len) throws IOException {
325 if (null == b)
326 throw new NullPointerException();
327 if (off < 0 || len < 0 || off + len > b.length)
328 throw new IndexOutOfBoundsException();
329 if (true == isClosed)
330 throw new IOException();
331
332 if (0 == len)
333 return 0;
334
335 len = nativeReadContent(b, off, len, offset);
336
337 if (JNI_DRM_FAILURE == len)
338 throw new IOException();
339 else if (JNI_DRM_EOF == len)
340 return -1;
341
342 offset += len;
343
344 return len;
345 }
346
347 /* Non-javadoc
348 * @see java.io.InputStream#markSupported()
349 */
350 public boolean markSupported() {
351 return false;
352 }
353
354 /* Non-javadoc
355 * @see java.io.InputStream#mark(int)
356 */
357 public void mark(int readlimit) {
358 }
359
360 /* Non-javadoc
361 * @see java.io.InputStream#reset()
362 */
363 public void reset() throws IOException {
364 throw new IOException();
365 }
366
367 /* Non-javadoc
368 * @see java.io.InputStream#skip()
369 */
370 public long skip(long n) throws IOException {
371 return 0;
372 }
373
374 /* Non-javadoc
375 * @see java.io.InputStream#close()
376 */
377 public void close() {
378 isClosed = true;
379 }
380 }
381
382 /**
383 * native method: construct a DRM content according the mime type.
384 *
385 * @param data input DRM content data to be parsed.
386 * @param len the length of the data.
387 * @param mimeType the mime type of this DRM content. the value of this field includes:
388 * #DRM_MIMETYPE_MESSAGE
389 * #DRM_MIMETYPE_CONTENT
390 *
391 * @return #the id of the DRM content if succeed.
392 * #JNI_DRM_FAILURE if fail.
393 */
394 private native int nativeConstructDrmContent(InputStream data, int len, int mimeType);
395
396 /**
397 * native method: get this DRM content rights issuer.
398 *
399 * @return the address of rights issuer if in case of separate delivery.
400 * null if not separete delivery, or otherwise.
401 */
402 private native String nativeGetRightsAddress();
403
404 /**
405 * native method: get this DRM content delivery type.
406 *
407 * @return the delivery method, the value may be one of the following:
408 * #DRM_FORWARD_LOCK
409 * #DRM_COMBINED_DELIVERY
410 * #DRM_SEPARATE_DELIVERY
411 * #DRM_SEPARATE_DELIVERY_DM
412 * #JNI_DRM_FAILURE if fail.
413 */
414 private native int nativeGetDeliveryMethod();
415
416 /**
417 * native method: get a piece of media content data.
418 *
419 * @param buf the buffer to save DRM media content data.
420 * @param bufOff the offset of the buffer to start to save data.
421 * @param len the number of byte to read.
422 * @param mediaOff the offset of the media content data to start to read.
423 *
424 * @return the length of the media content data has been read.
425 * #JNI_DRM_EOF if reach to end of the media content.
426 * #JNI_DRM_FAILURE if fail.
427 */
428 private native int nativeReadContent(byte[] buf, int bufOff, int len, int mediaOff);
429
430 /**
431 * native method: get this DRM content type.
432 *
433 * @return the decrypted media content type.
434 * null if fail.
435 */
436 private native String nativeGetContentType();
437
438 /**
439 * native method: get this DRM decrypted media content length.
440 *
441 * @return the length of decrypted media content.
442 * #JNI_DRM_FAILURE if fail.
443 * #JNI_DRM_UNKNOWN_DATA_LEN if the length is unknown currently.
444 */
445 private native int nativeGetContentLength();
446
447 /**
448 * The finalizer of the DRMRawContent. Do some cleanup.
449 */
450 protected native void finalize();
451
452
453 /**
454 * Load the shared library to link the native methods.
455 */
456 static {
457 try {
458 System.loadLibrary("drm1_jni");
459 }
460 catch (UnsatisfiedLinkError ule) {
461 System.err.println("WARNING: Could not load libdrm1_jni.so");
462 }
463 }
464}