DrmManagerClient.java revision 365ce1db339db53cd5afb118ff867fe940644e45
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     * The keys are defined in {@link DrmStore.ConstraintsColumns}.
321     */
322    public ContentValues getConstraints(String path, int action) {
323        if (null == path || path.equals("") || !DrmStore.Action.isValid(action)) {
324            throw new IllegalArgumentException("Given usage or path is invalid/null");
325        }
326        return _getConstraints(mUniqueId, path, action);
327    }
328
329   /**
330    * Retrieves metadata information for rights-protected content.
331    *
332    * @param path Path to the content from which you are retrieving metadata information.
333    *
334    * @return A {@link android.content.ContentValues} instance that contains
335    * key-value pairs representing the metadata. Null in case of failure.
336    */
337    public ContentValues getMetadata(String path) {
338        if (null == path || path.equals("")) {
339            throw new IllegalArgumentException("Given path is invalid/null");
340        }
341        return _getMetadata(mUniqueId, path);
342    }
343
344    /**
345     * Retrieves constraint information for rights-protected content.
346     *
347     * @param uri URI for the content from which you are retrieving DRM constraints.
348     * @param action Action defined in {@link DrmStore.Action}.
349     *
350     * @return A {@link android.content.ContentValues} instance that contains
351     * key-value pairs representing the constraints. Null in case of failure.
352     */
353    public ContentValues getConstraints(Uri uri, int action) {
354        if (null == uri || Uri.EMPTY == uri) {
355            throw new IllegalArgumentException("Uri should be non null");
356        }
357        return getConstraints(convertUriToPath(uri), action);
358    }
359
360   /**
361    * Retrieves metadata information for rights-protected content.
362    *
363    * @param uri URI for the content from which you are retrieving metadata information.
364    *
365    * @return A {@link android.content.ContentValues} instance that contains
366    * key-value pairs representing the constraints. Null in case of failure.
367    */
368    public ContentValues getMetadata(Uri uri) {
369        if (null == uri || Uri.EMPTY == uri) {
370            throw new IllegalArgumentException("Uri should be non null");
371        }
372        return getMetadata(convertUriToPath(uri));
373    }
374
375    /**
376     * Saves rights to a specified path and associates that path with the content path.
377     *
378     * <p class="note"><strong>Note:</strong> For OMA or WM-DRM, <code>rightsPath</code> and
379     * <code>contentPath</code> can be null.</p>
380     *
381     * @param drmRights The {@link DrmRights} to be saved.
382     * @param rightsPath File path where rights will be saved.
383     * @param contentPath File path where content is saved.
384     *
385     * @return ERROR_NONE for success; ERROR_UNKNOWN for failure.
386     *
387     * @throws IOException If the call failed to save rights information at the given
388     * <code>rightsPath</code>.
389     */
390    public int saveRights(
391            DrmRights drmRights, String rightsPath, String contentPath) throws IOException {
392        if (null == drmRights || !drmRights.isValid()) {
393            throw new IllegalArgumentException("Given drmRights or contentPath is not valid");
394        }
395        if (null != rightsPath && !rightsPath.equals("")) {
396            DrmUtils.writeToFile(rightsPath, drmRights.getData());
397        }
398        return _saveRights(mUniqueId, drmRights, rightsPath, contentPath);
399    }
400
401    /**
402     * Installs a new DRM plug-in (agent) at runtime.
403     *
404     * @param engineFilePath File path to the plug-in file to be installed.
405     *
406     * {@hide}
407     */
408    public void installDrmEngine(String engineFilePath) {
409        if (null == engineFilePath || engineFilePath.equals("")) {
410            throw new IllegalArgumentException(
411                "Given engineFilePath: "+ engineFilePath + "is not valid");
412        }
413        _installDrmEngine(mUniqueId, engineFilePath);
414    }
415
416    /**
417     * Checks whether the given MIME type or path can be handled.
418     *
419     * @param path Path of the content to be handled.
420     * @param mimeType MIME type of the object to be handled.
421     *
422     * @return True if the given MIME type or path can be handled; false if they cannot be handled.
423     */
424    public boolean canHandle(String path, String mimeType) {
425        if ((null == path || path.equals("")) && (null == mimeType || mimeType.equals(""))) {
426            throw new IllegalArgumentException("Path or the mimetype should be non null");
427        }
428        return _canHandle(mUniqueId, path, mimeType);
429    }
430
431    /**
432     * Checks whether the given MIME type or URI can be handled.
433     *
434     * @param uri URI for the content to be handled.
435     * @param mimeType MIME type of the object to be handled
436     *
437     * @return True if the given MIME type or URI can be handled; false if they cannot be handled.
438     */
439    public boolean canHandle(Uri uri, String mimeType) {
440        if ((null == uri || Uri.EMPTY == uri) && (null == mimeType || mimeType.equals(""))) {
441            throw new IllegalArgumentException("Uri or the mimetype should be non null");
442        }
443        return canHandle(convertUriToPath(uri), mimeType);
444    }
445
446    /**
447     * Processes the given DRM information based on the information type.
448     *
449     * @param drmInfo The {@link DrmInfo} to be processed.
450     * @return ERROR_NONE for success; ERROR_UNKNOWN for failure.
451     */
452    public int processDrmInfo(DrmInfo drmInfo) {
453        if (null == drmInfo || !drmInfo.isValid()) {
454            throw new IllegalArgumentException("Given drmInfo is invalid/null");
455        }
456        int result = ERROR_UNKNOWN;
457        if (null != mEventHandler) {
458            Message msg = mEventHandler.obtainMessage(ACTION_PROCESS_DRM_INFO, drmInfo);
459            result = (mEventHandler.sendMessage(msg)) ? ERROR_NONE : result;
460        }
461        return result;
462    }
463
464    /**
465     * Retrieves information for registering, unregistering, or acquiring rights.
466     *
467     * @param drmInfoRequest The {@link DrmInfoRequest} that specifies the type of DRM
468     * information being retrieved.
469     *
470     * @return A {@link DrmInfo} instance.
471     */
472    public DrmInfo acquireDrmInfo(DrmInfoRequest drmInfoRequest) {
473        if (null == drmInfoRequest || !drmInfoRequest.isValid()) {
474            throw new IllegalArgumentException("Given drmInfoRequest is invalid/null");
475        }
476        return _acquireDrmInfo(mUniqueId, drmInfoRequest);
477    }
478
479    /**
480     * Processes a given {@link DrmInfoRequest} and returns the rights information asynchronously.
481     *<p>
482     * This is a utility method that consists of an
483     * {@link #acquireDrmInfo(DrmInfoRequest) acquireDrmInfo()} and a
484     * {@link #processDrmInfo(DrmInfo) processDrmInfo()} method call. This utility method can be
485     * used only if the selected DRM plug-in (agent) supports this sequence of calls. Some DRM
486     * agents, such as OMA, do not support this utility method, in which case an application must
487     * invoke {@link #acquireDrmInfo(DrmInfoRequest) acquireDrmInfo()} and
488     * {@link #processDrmInfo(DrmInfo) processDrmInfo()} separately.
489     *
490     * @param drmInfoRequest The {@link DrmInfoRequest} used to acquire the rights.
491     * @return ERROR_NONE for success; ERROR_UNKNOWN for failure.
492     */
493    public int acquireRights(DrmInfoRequest drmInfoRequest) {
494        DrmInfo drmInfo = acquireDrmInfo(drmInfoRequest);
495        if (null == drmInfo) {
496            return ERROR_UNKNOWN;
497        }
498        return processDrmInfo(drmInfo);
499    }
500
501    /**
502     * Retrieves the type of rights-protected object (for example, content object, rights
503     * object, and so on) using the specified path or MIME type. At least one parameter must
504     * be specified to retrieve the DRM object type.
505     *
506     * @param path Path to the content or null.
507     * @param mimeType MIME type of the content or null.
508     *
509     * @return An <code>int</code> that corresponds to a {@link DrmStore.DrmObjectType}.
510     */
511    public int getDrmObjectType(String path, String mimeType) {
512        if ((null == path || path.equals("")) && (null == mimeType || mimeType.equals(""))) {
513            throw new IllegalArgumentException("Path or the mimetype should be non null");
514        }
515        return _getDrmObjectType(mUniqueId, path, mimeType);
516    }
517
518    /**
519     * Retrieves the type of rights-protected object (for example, content object, rights
520     * object, and so on) using the specified URI or MIME type. At least one parameter must
521     * be specified to retrieve the DRM object type.
522     *
523     * @param uri URI for the content or null.
524     * @param mimeType MIME type of the content or null.
525     *
526     * @return An <code>int</code> that corresponds to a {@link DrmStore.DrmObjectType}.
527     */
528    public int getDrmObjectType(Uri uri, String mimeType) {
529        if ((null == uri || Uri.EMPTY == uri) && (null == mimeType || mimeType.equals(""))) {
530            throw new IllegalArgumentException("Uri or the mimetype should be non null");
531        }
532        String path = "";
533        try {
534            path = convertUriToPath(uri);
535        } catch (Exception e) {
536            // Even uri is invalid the mimetype shall be valid, so allow to proceed further.
537            Log.w(TAG, "Given Uri could not be found in media store");
538        }
539        return getDrmObjectType(path, mimeType);
540    }
541
542    /**
543     * Retrieves the MIME type embedded in the original content.
544     *
545     * @param path Path to the rights-protected content.
546     *
547     * @return The MIME type of the original content, such as <code>video/mpeg</code>.
548     */
549    public String getOriginalMimeType(String path) {
550        if (null == path || path.equals("")) {
551            throw new IllegalArgumentException("Given path should be non null");
552        }
553        return _getOriginalMimeType(mUniqueId, path);
554    }
555
556    /**
557     * Retrieves the MIME type embedded in the original content.
558     *
559     * @param uri URI of the rights-protected content.
560     *
561     * @return MIME type of the original content, such as <code>video/mpeg</code>.
562     */
563    public String getOriginalMimeType(Uri uri) {
564        if (null == uri || Uri.EMPTY == uri) {
565            throw new IllegalArgumentException("Given uri is not valid");
566        }
567        return getOriginalMimeType(convertUriToPath(uri));
568    }
569
570    /**
571     * Checks whether the given content has valid rights.
572     *
573     * @param path Path to the rights-protected content.
574     *
575     * @return An <code>int</code> representing the {@link DrmStore.RightsStatus} of the content.
576     */
577    public int checkRightsStatus(String path) {
578        return checkRightsStatus(path, DrmStore.Action.DEFAULT);
579    }
580
581    /**
582     * Check whether the given content has valid rights.
583     *
584     * @param uri URI of the rights-protected content.
585     *
586     * @return An <code>int</code> representing the {@link DrmStore.RightsStatus} of the content.
587     */
588    public int checkRightsStatus(Uri uri) {
589        if (null == uri || Uri.EMPTY == uri) {
590            throw new IllegalArgumentException("Given uri is not valid");
591        }
592        return checkRightsStatus(convertUriToPath(uri));
593    }
594
595    /**
596     * Checks whether the given rights-protected content has valid rights for the specified
597     * {@link DrmStore.Action}.
598     *
599     * @param path Path to the rights-protected content.
600     * @param action The {@link DrmStore.Action} to perform.
601     *
602     * @return An <code>int</code> representing the {@link DrmStore.RightsStatus} of the content.
603     */
604    public int checkRightsStatus(String path, int action) {
605        if (null == path || path.equals("") || !DrmStore.Action.isValid(action)) {
606            throw new IllegalArgumentException("Given path or action is not valid");
607        }
608        return _checkRightsStatus(mUniqueId, path, action);
609    }
610
611    /**
612     * Checks whether the given rights-protected content has valid rights for the specified
613     * {@link DrmStore.Action}.
614     *
615     * @param uri URI for the rights-protected content.
616     * @param action The {@link DrmStore.Action} to perform.
617     *
618     * @return An <code>int</code> representing the {@link DrmStore.RightsStatus} of the content.
619     */
620    public int checkRightsStatus(Uri uri, int action) {
621        if (null == uri || Uri.EMPTY == uri) {
622            throw new IllegalArgumentException("Given uri is not valid");
623        }
624        return checkRightsStatus(convertUriToPath(uri), action);
625    }
626
627    /**
628     * Removes the rights associated with the given rights-protected content.
629     *
630     * @param path Path to the rights-protected content.
631     *
632     * @return ERROR_NONE for success; ERROR_UNKNOWN for failure.
633     */
634    public int removeRights(String path) {
635        if (null == path || path.equals("")) {
636            throw new IllegalArgumentException("Given path should be non null");
637        }
638        return _removeRights(mUniqueId, path);
639    }
640
641    /**
642     * Removes the rights associated with the given rights-protected content.
643     *
644     * @param uri URI for the rights-protected content.
645     *
646     * @return ERROR_NONE for success; ERROR_UNKNOWN for failure.
647     */
648    public int removeRights(Uri uri) {
649        if (null == uri || Uri.EMPTY == uri) {
650            throw new IllegalArgumentException("Given uri is not valid");
651        }
652        return removeRights(convertUriToPath(uri));
653    }
654
655    /**
656     * Removes all the rights information of every DRM plug-in (agent) associated with
657     * the DRM framework. Will be used during a master reset.
658     *
659     * @return ERROR_NONE for success; ERROR_UNKNOWN for failure.
660     */
661    public int removeAllRights() {
662        int result = ERROR_UNKNOWN;
663        if (null != mEventHandler) {
664            Message msg = mEventHandler.obtainMessage(ACTION_REMOVE_ALL_RIGHTS);
665            result = (mEventHandler.sendMessage(msg)) ? ERROR_NONE : result;
666        }
667        return result;
668    }
669
670    /**
671     * Initiates a new conversion session. An application must initiate a conversion session
672     * with this method each time it downloads a rights-protected file that needs to be converted.
673     *<p>
674     * This method applies only to forward-locking (copy protection) DRM schemes.
675     *
676     * @param mimeType MIME type of the input data packet.
677     *
678     * @return A convert ID that is used used to maintain the conversion session.
679     */
680    public int openConvertSession(String mimeType) {
681        if (null == mimeType || mimeType.equals("")) {
682            throw new IllegalArgumentException("Path or the mimeType should be non null");
683        }
684        return _openConvertSession(mUniqueId, mimeType);
685    }
686
687    /**
688     * Converts the input data (content) that is part of a rights-protected file. The converted
689     * data and status is returned in a {@link DrmConvertedStatus} object. This method should be
690     * called each time there is a new block of data received by the application.
691     *
692     * @param convertId Handle for the conversion session.
693     * @param inputData Input data that needs to be converted.
694     *
695     * @return A {@link DrmConvertedStatus} object that contains the status of the data conversion,
696     * the converted data, and offset for the header and body signature. An application can
697     * ignore the offset because it is only relevant to the
698     * {@link #closeConvertSession closeConvertSession()} method.
699     */
700    public DrmConvertedStatus convertData(int convertId, byte[] inputData) {
701        if (null == inputData || 0 >= inputData.length) {
702            throw new IllegalArgumentException("Given inputData should be non null");
703        }
704        return _convertData(mUniqueId, convertId, inputData);
705    }
706
707    /**
708     * Informs the DRM plug-in (agent) that there is no more data to convert or that an error
709     * has occurred. Upon successful conversion of the data, the DRM agent will provide an offset
710     * value indicating where the header and body signature should be added. Appending the
711     * signature is necessary to protect the integrity of the converted file.
712     *
713     * @param convertId Handle for the conversion session.
714     *
715     * @return A {@link DrmConvertedStatus} object that contains the status of the data conversion,
716     * the converted data, and the offset for the header and body signature.
717     */
718    public DrmConvertedStatus closeConvertSession(int convertId) {
719        return _closeConvertSession(mUniqueId, convertId);
720    }
721
722    private int getEventType(int infoType) {
723        int eventType = -1;
724
725        switch (infoType) {
726        case DrmInfoRequest.TYPE_REGISTRATION_INFO:
727        case DrmInfoRequest.TYPE_UNREGISTRATION_INFO:
728        case DrmInfoRequest.TYPE_RIGHTS_ACQUISITION_INFO:
729            eventType = DrmEvent.TYPE_DRM_INFO_PROCESSED;
730            break;
731        }
732        return eventType;
733    }
734
735    private int getErrorType(int infoType) {
736        int error = -1;
737
738        switch (infoType) {
739        case DrmInfoRequest.TYPE_REGISTRATION_INFO:
740        case DrmInfoRequest.TYPE_UNREGISTRATION_INFO:
741        case DrmInfoRequest.TYPE_RIGHTS_ACQUISITION_INFO:
742            error = DrmErrorEvent.TYPE_PROCESS_DRM_INFO_FAILED;
743            break;
744        }
745        return error;
746    }
747
748    /**
749     * This method expects uri in the following format
750     *     content://media/<table_name>/<row_index> (or)
751     *     file://sdcard/test.mp4
752     *     http://test.com/test.mp4
753     *
754     * Here <table_name> shall be "video" or "audio" or "images"
755     * <row_index> the index of the content in given table
756     */
757    private String convertUriToPath(Uri uri) {
758        String path = null;
759        if (null != uri) {
760            String scheme = uri.getScheme();
761            if (null == scheme || scheme.equals("") ||
762                    scheme.equals(ContentResolver.SCHEME_FILE)) {
763                path = uri.getPath();
764
765            } else if (scheme.equals("http")) {
766                path = uri.toString();
767
768            } else if (scheme.equals(ContentResolver.SCHEME_CONTENT)) {
769                String[] projection = new String[] {MediaStore.MediaColumns.DATA};
770                Cursor cursor = null;
771                try {
772                    cursor = mContext.getContentResolver().query(uri, projection, null,
773                            null, null);
774                    if (null == cursor || 0 == cursor.getCount() || !cursor.moveToFirst()) {
775                        throw new IllegalArgumentException("Given Uri could not be found" +
776                                " in media store");
777                    }
778                    int pathIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
779                    path = cursor.getString(pathIndex);
780                } catch (SQLiteException e) {
781                    throw new IllegalArgumentException("Given Uri is not formatted in a way " +
782                            "so that it can be found in media store.");
783                } finally {
784                    if (null != cursor) {
785                        cursor.close();
786                    }
787                }
788            } else {
789                throw new IllegalArgumentException("Given Uri scheme is not supported");
790            }
791        }
792        return path;
793    }
794
795    // private native interfaces
796    private native int _initialize(Object weak_this);
797
798    private native void _finalize(int uniqueId);
799
800    private native void _installDrmEngine(int uniqueId, String engineFilepath);
801
802    private native ContentValues _getConstraints(int uniqueId, String path, int usage);
803
804    private native ContentValues _getMetadata(int uniqueId, String path);
805
806    private native boolean _canHandle(int uniqueId, String path, String mimeType);
807
808    private native DrmInfoStatus _processDrmInfo(int uniqueId, DrmInfo drmInfo);
809
810    private native DrmInfo _acquireDrmInfo(int uniqueId, DrmInfoRequest drmInfoRequest);
811
812    private native int _saveRights(
813            int uniqueId, DrmRights drmRights, String rightsPath, String contentPath);
814
815    private native int _getDrmObjectType(int uniqueId, String path, String mimeType);
816
817    private native String _getOriginalMimeType(int uniqueId, String path);
818
819    private native int _checkRightsStatus(int uniqueId, String path, int action);
820
821    private native int _removeRights(int uniqueId, String path);
822
823    private native int _removeAllRights(int uniqueId);
824
825    private native int _openConvertSession(int uniqueId, String mimeType);
826
827    private native DrmConvertedStatus _convertData(
828            int uniqueId, int convertId, byte[] inputData);
829
830    private native DrmConvertedStatus _closeConvertSession(int uniqueId, int convertId);
831
832    private native DrmSupportInfo[] _getAllSupportInfo(int uniqueId);
833}
834
835