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