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