DrmManagerClient.java revision a17d454fd0d20d14cf1fbc09f0f296cb6cbb870b
1/*
2 * Copyright (C) 2010 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;
18
19import android.content.ContentResolver;
20import android.content.ContentValues;
21import android.content.Context;
22import android.database.Cursor;
23import android.database.sqlite.SQLiteException;
24import android.net.Uri;
25import android.os.Handler;
26import android.os.HandlerThread;
27import android.os.Looper;
28import android.os.Message;
29import android.provider.MediaStore;
30import android.util.Log;
31
32import java.io.IOException;
33import java.lang.ref.WeakReference;
34import java.util.ArrayList;
35import java.util.HashMap;
36
37/**
38 * The main programming interface for the DRM framework. An application must instantiate this class
39 * to access DRM agents through the DRM framework.
40 *
41 */
42public class DrmManagerClient {
43    /**
44     * Indicates that a request was successful or that no error occurred.
45     */
46    public static final int ERROR_NONE = 0;
47    /**
48     * Indicates that an error occurred and the reason is not known.
49     */
50    public static final int ERROR_UNKNOWN = -2000;
51
52    private static final String TAG = "DrmManagerClient";
53
54    static {
55        // Load the respective library
56        System.loadLibrary("drmframework_jni");
57    }
58
59    /**
60     * Interface definition for a callback that receives status messages and warnings
61     * during registration and rights acquisition.
62     */
63    public interface OnInfoListener {
64        /**
65         * Called when the DRM framework sends status or warning information during registration
66         * and rights acquisition.
67         *
68         * @param client The <code>DrmManagerClient</code> instance.
69         * @param event The {@link DrmInfoEvent} instance that wraps the status information or
70         * warnings.
71         */
72        public void onInfo(DrmManagerClient client, DrmInfoEvent event);
73    }
74
75    /**
76     * Interface definition for a callback that receives information
77     * about DRM processing events.
78     */
79    public interface OnEventListener {
80        /**
81         * Called when the DRM framework sends information about a DRM processing request.
82         *
83         * @param client The <code>DrmManagerClient</code> instance.
84         * @param event The {@link DrmEvent} instance that wraps the information being
85         * conveyed, such as the information type and message.
86         */
87        public void onEvent(DrmManagerClient client, DrmEvent event);
88    }
89
90    /**
91     * Interface definition for a callback that receives information about DRM framework errors.
92     */
93    public interface OnErrorListener {
94        /**
95         * Called when the DRM framework sends error information.
96         *
97         * @param client The <code>DrmManagerClient</code> instance.
98         * @param event The {@link DrmErrorEvent} instance that wraps the error type and message.
99         */
100        public void onError(DrmManagerClient client, DrmErrorEvent event);
101    }
102
103    private static final int ACTION_REMOVE_ALL_RIGHTS = 1001;
104    private static final int ACTION_PROCESS_DRM_INFO = 1002;
105
106    private int mUniqueId;
107    private int mNativeContext;
108    private Context mContext;
109    private InfoHandler mInfoHandler;
110    private EventHandler mEventHandler;
111    private OnInfoListener mOnInfoListener;
112    private OnEventListener mOnEventListener;
113    private OnErrorListener mOnErrorListener;
114
115    private class EventHandler extends Handler {
116
117        public EventHandler(Looper looper) {
118            super(looper);
119        }
120
121        public void handleMessage(Message msg) {
122            DrmEvent event = null;
123            DrmErrorEvent error = null;
124            HashMap<String, Object> attributes = new HashMap<String, Object>();
125
126            switch(msg.what) {
127            case ACTION_PROCESS_DRM_INFO: {
128                final DrmInfo drmInfo = (DrmInfo) msg.obj;
129                DrmInfoStatus status = _processDrmInfo(mUniqueId, drmInfo);
130
131                attributes.put(DrmEvent.DRM_INFO_STATUS_OBJECT, status);
132                attributes.put(DrmEvent.DRM_INFO_OBJECT, drmInfo);
133
134                if (null != status && DrmInfoStatus.STATUS_OK == status.statusCode) {
135                    event = new DrmEvent(mUniqueId,
136                            getEventType(status.infoType), null, attributes);
137                } else {
138                    int infoType = (null != status) ? status.infoType : drmInfo.getInfoType();
139                    error = new DrmErrorEvent(mUniqueId,
140                            getErrorType(infoType), null, attributes);
141                }
142                break;
143            }
144            case ACTION_REMOVE_ALL_RIGHTS: {
145                if (ERROR_NONE == _removeAllRights(mUniqueId)) {
146                    event = new DrmEvent(mUniqueId, DrmEvent.TYPE_ALL_RIGHTS_REMOVED, null);
147                } else {
148                    error = new DrmErrorEvent(mUniqueId,
149                            DrmErrorEvent.TYPE_REMOVE_ALL_RIGHTS_FAILED, null);
150                }
151                break;
152            }
153            default:
154                Log.e(TAG, "Unknown message type " + msg.what);
155                return;
156            }
157            if (null != mOnEventListener && null != event) {
158                mOnEventListener.onEvent(DrmManagerClient.this, event);
159            }
160            if (null != mOnErrorListener && null != error) {
161                mOnErrorListener.onError(DrmManagerClient.this, error);
162            }
163        }
164    }
165
166    /**
167     * {@hide}
168     */
169    public static void notify(
170            Object thisReference, int uniqueId, int infoType, String message) {
171        DrmManagerClient instance = (DrmManagerClient)((WeakReference)thisReference).get();
172
173        if (null != instance && null != instance.mInfoHandler) {
174            Message m = instance.mInfoHandler.obtainMessage(
175                InfoHandler.INFO_EVENT_TYPE, uniqueId, infoType, message);
176            instance.mInfoHandler.sendMessage(m);
177        }
178    }
179
180    private class InfoHandler extends Handler {
181        public static final int INFO_EVENT_TYPE = 1;
182
183        public InfoHandler(Looper looper) {
184            super(looper);
185        }
186
187        public void handleMessage(Message msg) {
188            DrmInfoEvent info = null;
189            DrmErrorEvent error = null;
190
191            switch (msg.what) {
192            case InfoHandler.INFO_EVENT_TYPE:
193                int uniqueId = msg.arg1;
194                int infoType = msg.arg2;
195                String message = msg.obj.toString();
196
197                switch (infoType) {
198                case DrmInfoEvent.TYPE_REMOVE_RIGHTS: {
199                    try {
200                        DrmUtils.removeFile(message);
201                    } catch (IOException e) {
202                        e.printStackTrace();
203                    }
204                    info = new DrmInfoEvent(uniqueId, infoType, message);
205                    break;
206                }
207                case DrmInfoEvent.TYPE_ALREADY_REGISTERED_BY_ANOTHER_ACCOUNT:
208                case DrmInfoEvent.TYPE_RIGHTS_INSTALLED:
209                case DrmInfoEvent.TYPE_WAIT_FOR_RIGHTS:
210                case DrmInfoEvent.TYPE_ACCOUNT_ALREADY_REGISTERED:
211                case DrmInfoEvent.TYPE_RIGHTS_REMOVED: {
212                    info = new DrmInfoEvent(uniqueId, infoType, message);
213                    break;
214                }
215                default:
216                    error = new DrmErrorEvent(uniqueId, infoType, message);
217                    break;
218                }
219
220                if (null != mOnInfoListener && null != info) {
221                    mOnInfoListener.onInfo(DrmManagerClient.this, info);
222                }
223                if (null != mOnErrorListener && null != error) {
224                    mOnErrorListener.onError(DrmManagerClient.this, error);
225                }
226                return;
227            default:
228                Log.e(TAG, "Unknown message type " + msg.what);
229                return;
230            }
231        }
232    }
233
234    /**
235     * Creates a <code>DrmManagerClient</code>.
236     *
237     * @param context Context of the caller.
238     */
239    public DrmManagerClient(Context context) {
240        mContext = context;
241
242        HandlerThread infoThread = new HandlerThread("DrmManagerClient.InfoHandler");
243        infoThread.start();
244        mInfoHandler = new InfoHandler(infoThread.getLooper());
245
246        HandlerThread eventThread = new HandlerThread("DrmManagerClient.EventHandler");
247        eventThread.start();
248        mEventHandler = new EventHandler(eventThread.getLooper());
249
250        // save the unique id
251        mUniqueId = _initialize(new WeakReference<DrmManagerClient>(this));
252    }
253
254    protected void finalize() {
255        _finalize(mUniqueId);
256    }
257
258    /**
259     * Registers an {@link DrmManagerClient.OnInfoListener} callback, which is invoked when the
260     * DRM framework sends status or warning information during registration or rights acquisition.
261     *
262     * @param infoListener Interface definition for the callback.
263     */
264    public synchronized void setOnInfoListener(OnInfoListener infoListener) {
265        if (null != infoListener) {
266            mOnInfoListener = infoListener;
267        }
268    }
269
270    /**
271     * Registers an {@link DrmManagerClient.OnEventListener} callback, which is invoked when the
272     * DRM framework sends information about DRM processing.
273     *
274     * @param eventListener Interface definition for the callback.
275     */
276    public synchronized void setOnEventListener(OnEventListener eventListener) {
277        if (null != eventListener) {
278            mOnEventListener = eventListener;
279        }
280    }
281
282    /**
283     * Registers an {@link DrmManagerClient.OnErrorListener} callback, which is invoked when
284     * the DRM framework sends error information.
285     *
286     * @param errorListener Interface definition for the callback.
287     */
288    public synchronized void setOnErrorListener(OnErrorListener errorListener) {
289        if (null != errorListener) {
290            mOnErrorListener = errorListener;
291        }
292    }
293
294    /**
295     * Retrieves information about all the DRM plug-ins (agents) that are registered with
296     * the DRM framework.
297     *
298     * @return A <code>String</code> array of DRM plug-in descriptions.
299     */
300    public String[] getAvailableDrmEngines() {
301        DrmSupportInfo[] supportInfos = _getAllSupportInfo(mUniqueId);
302        ArrayList<String> descriptions = new ArrayList<String>();
303
304        for (int i = 0; i < supportInfos.length; i++) {
305            descriptions.add(supportInfos[i].getDescriprition());
306        }
307
308        String[] drmEngines = new String[descriptions.size()];
309        return descriptions.toArray(drmEngines);
310    }
311
312    /**
313     * Retrieves constraint information for rights-protected content.
314     *
315     * @param path Path to the content from which you are retrieving DRM constraints.
316     * @param action Action defined in {@link DrmStore.Action}.
317     *
318     * @return A {@link android.content.ContentValues} instance that contains
319     * key-value pairs representing the constraints. Null in case of failure.
320     */
321    public ContentValues getConstraints(String path, int action) {
322        if (null == path || path.equals("") || !DrmStore.Action.isValid(action)) {
323            throw new IllegalArgumentException("Given usage or path is invalid/null");
324        }
325        return _getConstraints(mUniqueId, path, action);
326    }
327
328   /**
329    * Retrieves metadata information for rights-protected content.
330    *
331    * @param path Path to the content from which you are retrieving metadata information.
332    *
333    * @return A {@link android.content.ContentValues} instance that contains
334    * key-value pairs representing the metadata. Null in case of failure.
335    */
336    public ContentValues getMetadata(String path) {
337        if (null == path || path.equals("")) {
338            throw new IllegalArgumentException("Given path is invalid/null");
339        }
340        return _getMetadata(mUniqueId, path);
341    }
342
343    /**
344     * Retrieves constraint information for rights-protected content.
345     *
346     * @param uri URI for the content from which you are retrieving DRM constraints.
347     * @param action Action defined in {@link DrmStore.Action}.
348     *
349     * @return A {@link android.content.ContentValues} instance that contains
350     * key-value pairs representing the constraints. Null in case of failure.
351     */
352    public ContentValues getConstraints(Uri uri, int action) {
353        if (null == uri || Uri.EMPTY == uri) {
354            throw new IllegalArgumentException("Uri should be non null");
355        }
356        return getConstraints(convertUriToPath(uri), action);
357    }
358
359   /**
360    * Retrieves metadata information for rights-protected content.
361    *
362    * @param uri URI for the content from which you are retrieving metadata information.
363    *
364    * @return A {@link android.content.ContentValues} instance that contains
365    * key-value pairs representing the constraints. Null in case of failure.
366    */
367    public ContentValues getMetadata(Uri uri) {
368        if (null == uri || Uri.EMPTY == uri) {
369            throw new IllegalArgumentException("Uri should be non null");
370        }
371        return getMetadata(convertUriToPath(uri));
372    }
373
374    /**
375     * Saves rights to a specified path and associates that path with the content path.
376     *
377     * <p class="note"><strong>Note:</strong> For OMA or WM-DRM, <code>rightsPath</code> and
378     * <code>contentPath</code> can be null.</p>
379     *
380     * @param drmRights The {@link DrmRights} to be saved.
381     * @param rightsPath File path where rights will be saved.
382     * @param contentPath File path where content is saved.
383     *
384     * @return ERROR_NONE for success; ERROR_UNKNOWN for failure.
385     *
386     * @throws IOException If the call failed to save rights information at the given
387     * <code>rightsPath</code>.
388     */
389    public int saveRights(
390            DrmRights drmRights, String rightsPath, String contentPath) throws IOException {
391        if (null == drmRights || !drmRights.isValid()) {
392            throw new IllegalArgumentException("Given drmRights or contentPath is not valid");
393        }
394        if (null != rightsPath && !rightsPath.equals("")) {
395            DrmUtils.writeToFile(rightsPath, drmRights.getData());
396        }
397        return _saveRights(mUniqueId, drmRights, rightsPath, contentPath);
398    }
399
400    /**
401     * Installs a new DRM plug-in (agent) at runtime.
402     *
403     * @param engineFilePath File path to the plug-in file to be installed.
404     *
405     * {@hide}
406     */
407    public void installDrmEngine(String engineFilePath) {
408        if (null == engineFilePath || engineFilePath.equals("")) {
409            throw new IllegalArgumentException(
410                "Given engineFilePath: "+ engineFilePath + "is not valid");
411        }
412        _installDrmEngine(mUniqueId, engineFilePath);
413    }
414
415    /**
416     * Checks whether the given MIME type or path can be handled.
417     *
418     * @param path Path of the content to be handled.
419     * @param mimeType MIME type of the object to be handled.
420     *
421     * @return True if the given MIME type or path can be handled; false if they cannot be handled.
422     */
423    public boolean canHandle(String path, String mimeType) {
424        if ((null == path || path.equals("")) && (null == mimeType || mimeType.equals(""))) {
425            throw new IllegalArgumentException("Path or the mimetype should be non null");
426        }
427        return _canHandle(mUniqueId, path, mimeType);
428    }
429
430    /**
431     * Checks whether the given MIME type or URI can be handled.
432     *
433     * @param uri URI for the content to be handled.
434     * @param mimeType MIME type of the object to be handled
435     *
436     * @return True if the given MIME type or URI can be handled; false if they cannot be handled.
437     */
438    public boolean canHandle(Uri uri, String mimeType) {
439        if ((null == uri || Uri.EMPTY == uri) && (null == mimeType || mimeType.equals(""))) {
440            throw new IllegalArgumentException("Uri or the mimetype should be non null");
441        }
442        return canHandle(convertUriToPath(uri), mimeType);
443    }
444
445    /**
446     * Processes the given DRM information based on the information type.
447     *
448     * @param drmInfo The {@link DrmInfo} to be processed.
449     * @return ERROR_NONE for success; ERROR_UNKNOWN for failure.
450     */
451    public int processDrmInfo(DrmInfo drmInfo) {
452        if (null == drmInfo || !drmInfo.isValid()) {
453            throw new IllegalArgumentException("Given drmInfo is invalid/null");
454        }
455        int result = ERROR_UNKNOWN;
456        if (null != mEventHandler) {
457            Message msg = mEventHandler.obtainMessage(ACTION_PROCESS_DRM_INFO, drmInfo);
458            result = (mEventHandler.sendMessage(msg)) ? ERROR_NONE : result;
459        }
460        return result;
461    }
462
463    /**
464     * Retrieves information for registering, unregistering, or acquiring rights.
465     *
466     * @param drmInfoRequest The {@link DrmInfoRequest} that specifies the type of DRM
467     * information being retrieved.
468     *
469     * @return A {@link DrmInfo} instance.
470     */
471    public DrmInfo acquireDrmInfo(DrmInfoRequest drmInfoRequest) {
472        if (null == drmInfoRequest || !drmInfoRequest.isValid()) {
473            throw new IllegalArgumentException("Given drmInfoRequest is invalid/null");
474        }
475        return _acquireDrmInfo(mUniqueId, drmInfoRequest);
476    }
477
478    /**
479     * Processes a given {@link DrmInfoRequest} and returns the rights information asynchronously.
480     *<p>
481     * This is a utility method that consists of an
482     * {@link #acquireDrmInfo(DrmInfoRequest) acquireDrmInfo()} and a
483     * {@link #processDrmInfo(DrmInfo) processDrmInfo()} method call. This utility method can be
484     * used only if the selected DRM plug-in (agent) supports this sequence of calls. Some DRM
485     * agents, such as OMA, do not support this utility method, in which case an application must
486     * invoke {@link #acquireDrmInfo(DrmInfoRequest) acquireDrmInfo()} and
487     * {@link #processDrmInfo(DrmInfo) processDrmInfo()} separately.
488     *
489     * @param drmInfoRequest The {@link DrmInfoRequest} used to acquire the rights.
490     * @return ERROR_NONE for success; ERROR_UNKNOWN for failure.
491     */
492    public int acquireRights(DrmInfoRequest drmInfoRequest) {
493        DrmInfo drmInfo = acquireDrmInfo(drmInfoRequest);
494        if (null == drmInfo) {
495            return ERROR_UNKNOWN;
496        }
497        return processDrmInfo(drmInfo);
498    }
499
500    /**
501     * Retrieves the type of rights-protected object (for example, content object, rights
502     * object, and so on) using the specified path or MIME type. At least one parameter must
503     * be specified to retrieve the DRM object type.
504     *
505     * @param path Path to the content or null.
506     * @param mimeType MIME type of the content or null.
507     *
508     * @return An <code>int</code> that corresponds to a {@link DrmStore.DrmObjectType}.
509     */
510    public int getDrmObjectType(String path, String mimeType) {
511        if ((null == path || path.equals("")) && (null == mimeType || mimeType.equals(""))) {
512            throw new IllegalArgumentException("Path or the mimetype should be non null");
513        }
514        return _getDrmObjectType(mUniqueId, path, mimeType);
515    }
516
517    /**
518     * Retrieves the type of rights-protected object (for example, content object, rights
519     * object, and so on) using the specified URI or MIME type. At least one parameter must
520     * be specified to retrieve the DRM object type.
521     *
522     * @param uri URI for the content or null.
523     * @param mimeType MIME type of the content or null.
524     *
525     * @return An <code>int</code> that corresponds to a {@link DrmStore.DrmObjectType}.
526     */
527    public int getDrmObjectType(Uri uri, String mimeType) {
528        if ((null == uri || Uri.EMPTY == uri) && (null == mimeType || mimeType.equals(""))) {
529            throw new IllegalArgumentException("Uri or the mimetype should be non null");
530        }
531        String path = "";
532        try {
533            path = convertUriToPath(uri);
534        } catch (Exception e) {
535            // Even uri is invalid the mimetype shall be valid, so allow to proceed further.
536            Log.w(TAG, "Given Uri could not be found in media store");
537        }
538        return getDrmObjectType(path, mimeType);
539    }
540
541    /**
542     * Retrieves the MIME type embedded in the original content.
543     *
544     * @param path Path to the rights-protected content.
545     *
546     * @return The MIME type of the original content, such as <code>video/mpeg</code>.
547     */
548    public String getOriginalMimeType(String path) {
549        if (null == path || path.equals("")) {
550            throw new IllegalArgumentException("Given path should be non null");
551        }
552        return _getOriginalMimeType(mUniqueId, path);
553    }
554
555    /**
556     * Retrieves the MIME type embedded in the original content.
557     *
558     * @param uri URI of the rights-protected content.
559     *
560     * @return MIME type of the original content, such as <code>video/mpeg</code>.
561     */
562    public String getOriginalMimeType(Uri uri) {
563        if (null == uri || Uri.EMPTY == uri) {
564            throw new IllegalArgumentException("Given uri is not valid");
565        }
566        return getOriginalMimeType(convertUriToPath(uri));
567    }
568
569    /**
570     * Checks whether the given content has valid rights.
571     *
572     * @param path Path to the rights-protected content.
573     *
574     * @return An <code>int</code> representing the {@link DrmStore.RightsStatus} of the content.
575     */
576    public int checkRightsStatus(String path) {
577        return checkRightsStatus(path, DrmStore.Action.DEFAULT);
578    }
579
580    /**
581     * Check whether the given content has valid rights.
582     *
583     * @param uri URI of the rights-protected content.
584     *
585     * @return An <code>int</code> representing the {@link DrmStore.RightsStatus} of the content.
586     */
587    public int checkRightsStatus(Uri uri) {
588        if (null == uri || Uri.EMPTY == uri) {
589            throw new IllegalArgumentException("Given uri is not valid");
590        }
591        return checkRightsStatus(convertUriToPath(uri));
592    }
593
594    /**
595     * Checks whether the given rights-protected content has valid rights for the specified
596     * {@link DrmStore.Action}.
597     *
598     * @param path Path to the rights-protected content.
599     * @param action The {@link DrmStore.Action} to perform.
600     *
601     * @return An <code>int</code> representing the {@link DrmStore.RightsStatus} of the content.
602     */
603    public int checkRightsStatus(String path, int action) {
604        if (null == path || path.equals("") || !DrmStore.Action.isValid(action)) {
605            throw new IllegalArgumentException("Given path or action is not valid");
606        }
607        return _checkRightsStatus(mUniqueId, path, action);
608    }
609
610    /**
611     * Checks whether the given rights-protected content has valid rights for the specified
612     * {@link DrmStore.Action}.
613     *
614     * @param uri URI for the rights-protected content.
615     * @param action The {@link DrmStore.Action} to perform.
616     *
617     * @return An <code>int</code> representing the {@link DrmStore.RightsStatus} of the content.
618     */
619    public int checkRightsStatus(Uri uri, int action) {
620        if (null == uri || Uri.EMPTY == uri) {
621            throw new IllegalArgumentException("Given uri is not valid");
622        }
623        return checkRightsStatus(convertUriToPath(uri), action);
624    }
625
626    /**
627     * Removes the rights associated with the given rights-protected content.
628     *
629     * @param path Path to the rights-protected content.
630     *
631     * @return ERROR_NONE for success; ERROR_UNKNOWN for failure.
632     */
633    public int removeRights(String path) {
634        if (null == path || path.equals("")) {
635            throw new IllegalArgumentException("Given path should be non null");
636        }
637        return _removeRights(mUniqueId, path);
638    }
639
640    /**
641     * Removes the rights associated with the given rights-protected content.
642     *
643     * @param uri URI for the rights-protected content.
644     *
645     * @return ERROR_NONE for success; ERROR_UNKNOWN for failure.
646     */
647    public int removeRights(Uri uri) {
648        if (null == uri || Uri.EMPTY == uri) {
649            throw new IllegalArgumentException("Given uri is not valid");
650        }
651        return removeRights(convertUriToPath(uri));
652    }
653
654    /**
655     * Removes all the rights information of every DRM plug-in (agent) associated with
656     * the DRM framework. Will be used during a master reset.
657     *
658     * @return ERROR_NONE for success; ERROR_UNKNOWN for failure.
659     */
660    public int removeAllRights() {
661        int result = ERROR_UNKNOWN;
662        if (null != mEventHandler) {
663            Message msg = mEventHandler.obtainMessage(ACTION_REMOVE_ALL_RIGHTS);
664            result = (mEventHandler.sendMessage(msg)) ? ERROR_NONE : result;
665        }
666        return result;
667    }
668
669    /**
670     * Initiates a new conversion session. An application must initiate a conversion session
671     * with this method each time it downloads a rights-protected file that needs to be converted.
672     *<p>
673     * This method applies only to forward-locking (copy protection) DRM schemes.
674     *
675     * @param mimeType MIME type of the input data packet.
676     *
677     * @return A convert ID that is used used to maintain the conversion session.
678     */
679    public int openConvertSession(String mimeType) {
680        if (null == mimeType || mimeType.equals("")) {
681            throw new IllegalArgumentException("Path or the mimeType should be non null");
682        }
683        return _openConvertSession(mUniqueId, mimeType);
684    }
685
686    /**
687     * Converts the input data (content) that is part of a rights-protected file. The converted
688     * data and status is returned in a {@link DrmConvertedStatus} object. This method should be
689     * called each time there is a new block of data received by the application.
690     *
691     * @param convertId Handle for the conversion session.
692     * @param inputData Input data that needs to be converted.
693     *
694     * @return A {@link DrmConvertedStatus} object that contains the status of the data conversion,
695     * the converted data, and offset for the header and body signature. An application can
696     * ignore the offset because it is only relevant to the
697     * {@link #closeConvertSession closeConvertSession()} method.
698     */
699    public DrmConvertedStatus convertData(int convertId, byte[] inputData) {
700        if (null == inputData || 0 >= inputData.length) {
701            throw new IllegalArgumentException("Given inputData should be non null");
702        }
703        return _convertData(mUniqueId, convertId, inputData);
704    }
705
706    /**
707     * Informs the DRM plug-in (agent) that there is no more data to convert or that an error
708     * has occurred. Upon successful conversion of the data, the DRM agent will provide an offset
709     * value indicating where the header and body signature should be added. Appending the
710     * signature is necessary to protect the integrity of the converted file.
711     *
712     * @param convertId Handle for the conversion session.
713     *
714     * @return A {@link DrmConvertedStatus} object that contains the status of the data conversion,
715     * the converted data, and the offset for the header and body signature.
716     */
717    public DrmConvertedStatus closeConvertSession(int convertId) {
718        return _closeConvertSession(mUniqueId, convertId);
719    }
720
721    private int getEventType(int infoType) {
722        int eventType = -1;
723
724        switch (infoType) {
725        case DrmInfoRequest.TYPE_REGISTRATION_INFO:
726        case DrmInfoRequest.TYPE_UNREGISTRATION_INFO:
727        case DrmInfoRequest.TYPE_RIGHTS_ACQUISITION_INFO:
728            eventType = DrmEvent.TYPE_DRM_INFO_PROCESSED;
729            break;
730        }
731        return eventType;
732    }
733
734    private int getErrorType(int infoType) {
735        int error = -1;
736
737        switch (infoType) {
738        case DrmInfoRequest.TYPE_REGISTRATION_INFO:
739        case DrmInfoRequest.TYPE_UNREGISTRATION_INFO:
740        case DrmInfoRequest.TYPE_RIGHTS_ACQUISITION_INFO:
741            error = DrmErrorEvent.TYPE_PROCESS_DRM_INFO_FAILED;
742            break;
743        }
744        return error;
745    }
746
747    /**
748     * This method expects uri in the following format
749     *     content://media/<table_name>/<row_index> (or)
750     *     file://sdcard/test.mp4
751     *     http://test.com/test.mp4
752     *
753     * Here <table_name> shall be "video" or "audio" or "images"
754     * <row_index> the index of the content in given table
755     */
756    private String convertUriToPath(Uri uri) {
757        String path = null;
758        if (null != uri) {
759            String scheme = uri.getScheme();
760            if (null == scheme || scheme.equals("") ||
761                    scheme.equals(ContentResolver.SCHEME_FILE)) {
762                path = uri.getPath();
763
764            } else if (scheme.equals("http")) {
765                path = uri.toString();
766
767            } else if (scheme.equals(ContentResolver.SCHEME_CONTENT)) {
768                String[] projection = new String[] {MediaStore.MediaColumns.DATA};
769                Cursor cursor = null;
770                try {
771                    cursor = mContext.getContentResolver().query(uri, projection, null,
772                            null, null);
773                    if (null == cursor || 0 == cursor.getCount() || !cursor.moveToFirst()) {
774                        throw new IllegalArgumentException("Given Uri could not be found" +
775                                " in media store");
776                    }
777                    int pathIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
778                    path = cursor.getString(pathIndex);
779                } catch (SQLiteException e) {
780                    throw new IllegalArgumentException("Given Uri is not formatted in a way " +
781                            "so that it can be found in media store.");
782                } finally {
783                    if (null != cursor) {
784                        cursor.close();
785                    }
786                }
787            } else {
788                throw new IllegalArgumentException("Given Uri scheme is not supported");
789            }
790        }
791        return path;
792    }
793
794    // private native interfaces
795    private native int _initialize(Object weak_this);
796
797    private native void _finalize(int uniqueId);
798
799    private native void _installDrmEngine(int uniqueId, String engineFilepath);
800
801    private native ContentValues _getConstraints(int uniqueId, String path, int usage);
802
803    private native ContentValues _getMetadata(int uniqueId, String path);
804
805    private native boolean _canHandle(int uniqueId, String path, String mimeType);
806
807    private native DrmInfoStatus _processDrmInfo(int uniqueId, DrmInfo drmInfo);
808
809    private native DrmInfo _acquireDrmInfo(int uniqueId, DrmInfoRequest drmInfoRequest);
810
811    private native int _saveRights(
812            int uniqueId, DrmRights drmRights, String rightsPath, String contentPath);
813
814    private native int _getDrmObjectType(int uniqueId, String path, String mimeType);
815
816    private native String _getOriginalMimeType(int uniqueId, String path);
817
818    private native int _checkRightsStatus(int uniqueId, String path, int action);
819
820    private native int _removeRights(int uniqueId, String path);
821
822    private native int _removeAllRights(int uniqueId);
823
824    private native int _openConvertSession(int uniqueId, String mimeType);
825
826    private native DrmConvertedStatus _convertData(
827            int uniqueId, int convertId, byte[] inputData);
828
829    private native DrmConvertedStatus _closeConvertSession(int uniqueId, int convertId);
830
831    private native DrmSupportInfo[] _getAllSupportInfo(int uniqueId);
832}
833
834