Allow device to be unprovisioned

bug: 12247651
Change-Id: Ie2e77566d2c65925091296da5bcbec327985c946
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d7aea39..0074635 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2811,7 +2811,13 @@
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.READ_INSTALL_SESSIONS"
         android:label="@string/permlab_readInstallSessions"
-        android:description="@string/permdesc_readInstallSessions"
+        android:description="@string/permdesc_readInstallSessions" />
+
+    <!-- @SystemApi Allows an application to remove DRM certificates
+         @hide This is not a third-party API (intended for system apps). -->
+    <permission android:name="android.permission.REMOVE_DRM_CERTIFICATES"
+        android:label="@string/permlab_removeDrmCertificates"
+        android:description="@string/permdesc_removeDrmCertificates"
         android:protectionLevel="signature|system" />
 
     <!-- The system process is explicitly the only one allowed to launch the
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 195851f..bb94d3a 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2167,6 +2167,11 @@
     <string name="permlab_handoverStatus">Receive Android Beam transfer status</string>
     <string name="permdesc_handoverStatus">Allows this application to receive information about current Android Beam transfers</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_removeDrmCertificates">remove DRM certificates</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_removeDrmCertificates">Allows an application to remove DRM certficates. Should never be needed for normal apps.</string>
+
     <!-- Policy administration -->
 
     <!-- Title of policy access to limiting the user's password choices -->
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 25f10d2..ca707d8 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -20,6 +20,7 @@
 import java.util.UUID;
 import java.util.HashMap;
 import java.util.List;
+import android.annotation.SystemApi;
 import android.os.Binder;
 import android.os.Debug;
 import android.os.Handler;
@@ -521,6 +522,18 @@
             throws DeniedByServerException;
 
     /**
+     * Remove provisioning from a device.  Only system apps may unprovision a
+     * device.  Note that removing provisioning will invalidate any keys saved
+     * for offline use (KEY_TYPE_OFFLINE), which may render downloaded content
+     * unplayable until new licenses are acquired.  Since provisioning is global
+     * to the device, license invalidation will apply to all content downloaded
+     * by any app, so appropriate warnings should be given to the user.
+     * @hide
+     */
+    @SystemApi
+    public native void unprovisionDevice();
+
+    /**
      * A means of enforcing limits on the number of concurrent streams per subscriber
      * across devices is provided via SecureStop. This is achieved by securely
      * monitoring the lifetime of sessions.
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 5f27b16..c678ac7 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -966,6 +966,22 @@
     return certificateObj;
 }
 
+static void android_media_MediaDrm_unprovisionDeviceNative(
+    JNIEnv *env, jobject thiz) {
+    sp<IDrm> drm = GetDrm(env, thiz);
+
+    if (drm == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+                          "MediaDrm obj is null");
+        return;
+    }
+
+    status_t err = drm->unprovisionDevice();
+
+    throwExceptionAsNecessary(env, err, "Failed to handle provision response");
+    return;
+}
+
 static jobject android_media_MediaDrm_getSecureStops(
     JNIEnv *env, jobject thiz) {
     sp<IDrm> drm = GetDrm(env, thiz);
@@ -1362,6 +1378,9 @@
     { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
       (void *)android_media_MediaDrm_provideProvisionResponseNative },
 
+    { "unprovisionDevice", "()V",
+      (void *)android_media_MediaDrm_unprovisionDeviceNative },
+
     { "getSecureStops", "()Ljava/util/List;",
       (void *)android_media_MediaDrm_getSecureStops },
 
@@ -1408,4 +1427,3 @@
     return AndroidRuntime::registerNativeMethods(env,
                 "android/media/MediaDrm", gMethods, NELEM(gMethods));
 }
-