Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 00c8254c authored by Marvin Ramin's avatar Marvin Ramin
Browse files

Make MediaDrm device-aware

Cap DRM sessions at max. SW_SECURE_CRYPTO security level for sessions opened by
applications that are currently visible on a Virtual Device.

Goal is to ensure applications do not get misled that full hw backed DRM is available
(which it generally would be on the host device). As virtual devices
operate with virtual displays hw backed DRM will not be available and we now report
it as such for applications.

Bug: 306374719
Test: atest VirtualDeviceDrmTest
Change-Id: I55acb7d15e19611a702492c71dccce2f973fd37c
parent 048114ad
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -205,6 +205,10 @@ public final class MediaDrm implements AutoCloseable {
     * media container format specified by mimeType at the requested
     * security level.
     *
     * Calling this method while the application is running on the physical Android device or a
     * {@link android.companion.virtual.VirtualDevice} may lead to different results, based on
     * the different DRM capabilities of the devices.
     *
     * @param uuid The UUID of the crypto scheme.
     * @param mimeType The MIME type of the media container, e.g. "video/mp4"
     *   or "video/webm"
@@ -1400,6 +1404,10 @@ public final class MediaDrm implements AutoCloseable {
     * Open a new session with the MediaDrm object. A session ID is returned.
     * By default, sessions are opened at the native security level of the device.
     *
     * If the application is currently running on a {@link android.companion.virtual.VirtualDevice}
     * the security level will be adjusted accordingly to the maximum supported level for the
     * display.
     *
     * @throws NotProvisionedException if provisioning is needed
     * @throws ResourceBusyException if required resources are in use
     */
@@ -1422,6 +1430,10 @@ public final class MediaDrm implements AutoCloseable {
     * can be queried using {@link #getSecurityLevel}. A session
     * ID is returned.
     *
     * If the application is currently running on a {@link android.companion.virtual.VirtualDevice}
     * the security level will be adjusted accordingly to the maximum supported level for the
     * display.
     *
     * @param level the new security level
     * @throws NotProvisionedException if provisioning is needed
     * @throws ResourceBusyException if required resources are in use
@@ -2180,6 +2192,11 @@ public final class MediaDrm implements AutoCloseable {
     * Returns a value that may be passed as a parameter to {@link #openSession(int)}
     * requesting that the session be opened at the maximum security level of
     * the device.
     *
     * This security level is only valid for the application running on the physical Android
     * device (e.g. {@link android.content.Context#DEVICE_ID_DEFAULT}). While running on a
     * {@link android.companion.virtual.VirtualDevice} the maximum supported security level
     * might be different.
     */
    public static final int getMaxSecurityLevel() {
        return SECURITY_LEVEL_MAX;
+2 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ cc_library_shared {
        "libhidlbase",
        "libsonivox",
        "server_configurable_flags",
        "android.companion.virtual.virtualdevice_aidl-cpp",
        "android.hardware.cas@1.0",
        "android.hardware.cas.native@1.0",
        "android.hardware.drm@1.3",
@@ -100,6 +101,7 @@ cc_library_shared {
    static_libs: [
        "libgrallocusage",
        "libmedia_midiiowrapper",
        "android.companion.virtualdevice.flags-aconfig-cc",
        "android.media.playback.flags-aconfig-cc",
    ],

+43 −0
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@
#include "jni.h"
#include <nativehelper/JNIHelp.h>

#include <android_companion_virtualdevice_flags.h>
#include <android/companion/virtualnative/IVirtualDeviceManagerNative.h>
#include <android/hardware/drm/1.3/IDrmFactory.h>
#include <binder/Parcel.h>
#include <binder/PersistableBundle.h>
@@ -41,8 +43,10 @@
#include <map>
#include <string>

using ::android::companion::virtualnative::IVirtualDeviceManagerNative;
using ::android::os::PersistableBundle;
namespace drm = ::android::hardware::drm;
namespace virtualdevice_flags = android::companion::virtualdevice::flags;

namespace android {

@@ -1045,6 +1049,26 @@ DrmPlugin::SecurityLevel jintToSecurityLevel(jint jlevel) {
    return level;
}

std::vector<int> getVirtualDeviceIds() {
    if (!virtualdevice_flags::device_aware_drm()) {
        ALOGW("Device-aware DRM flag disabled.");
        return std::vector<int>();
    }

    sp<IBinder> binder =
            defaultServiceManager()->checkService(String16("virtualdevice_native"));
    if (binder != nullptr) {
        auto vdm = interface_cast<IVirtualDeviceManagerNative>(binder);
        std::vector<int> deviceIds;
        const uid_t uid = IPCThreadState::self()->getCallingUid();
        vdm->getDeviceIdsForUid(uid, &deviceIds);
        return deviceIds;
    } else {
        ALOGW("Cannot get virtualdevice_native service");
        return std::vector<int>();
    }
}

static jbyteArray android_media_MediaDrm_getSupportedCryptoSchemesNative(JNIEnv *env) {
    sp<IDrm> drm = android::DrmUtils::MakeDrm();
    if (drm == NULL) return env->NewByteArray(0);
@@ -1081,6 +1105,15 @@ static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
    }
    DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);

    if (getVirtualDeviceIds().size() > 0) {
        // Cap security level at max SECURITY_LEVEL_SW_SECURE_CRYPTO because at
        // higher security levels decode output cannot be captured and
        // streamed to virtual devices rendered on virtual displays.
        if (securityLevel > DrmPlugin::kSecurityLevelSwSecureCrypto) {
            return false;
        }
    }

    bool isSupported;
    status_t err = JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType,
            securityLevel, &isSupported);
@@ -1106,6 +1139,16 @@ static jbyteArray android_media_MediaDrm_openSession(
        return NULL;
    }

    if (getVirtualDeviceIds().size() > 0) {
        // Cap security level at max SECURITY_LEVEL_SW_SECURE_CRYPTO because at
        // higher security levels decode output cannot be captured and
        // streamed to virtual devices rendered on virtual displays.
        if (level == DrmPlugin::kSecurityLevelMax ||
            level > DrmPlugin::kSecurityLevelSwSecureCrypto) {
            level = DrmPlugin::kSecurityLevelSwSecureCrypto;
        }
    }

    DrmStatus err = drm->openSession(level, sessionId);

    if (throwExceptionAsNecessary(env, drm, err, "Failed to open session")) {
+2 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@

#include "jni.h"

#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <media/stagefright/foundation/ABase.h>
#include <mediadrm/IDrm.h>
#include <mediadrm/IDrmClient.h>