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