diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2a96580b1410c..e3504fa349a09 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2812,7 +2812,13 @@
@hide This is not a third-party API (intended for system apps). -->
+
+
+
+ remove DRM certificates
+
+ Allows an application to remove DRM certficates. Should never be needed for normal apps.
+
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 25f10d230eb2e..ca707d87460da 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -20,6 +20,7 @@ import java.lang.ref.WeakReference;
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;
@@ -520,6 +521,18 @@ public final class MediaDrm {
private native Certificate provideProvisionResponseNative(byte[] response)
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
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 5f27b168739ba..c678ac7248e86 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -966,6 +966,22 @@ static jobject android_media_MediaDrm_provideProvisionResponseNative(
return certificateObj;
}
+static void android_media_MediaDrm_unprovisionDeviceNative(
+ JNIEnv *env, jobject thiz) {
+ sp 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 drm = GetDrm(env, thiz);
@@ -1362,6 +1378,9 @@ static JNINativeMethod gMethods[] = {
{ "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 @@ int register_android_media_Drm(JNIEnv *env) {
return AndroidRuntime::registerNativeMethods(env,
"android/media/MediaDrm", gMethods, NELEM(gMethods));
}
-