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

Commit 683cc4a8 authored by Huihong Luo's avatar Huihong Luo
Browse files

Update HDCP for physical displays

A special HDCP level change event is posted from SurfaceFlinger to
display manager, and the secure flag of each display gets updated.

Bug: 280818362
Test: manual
Change-Id: I88c5005dceacba69e1a941153b112b5358faca42
parent 1ccc6e6e
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -286,6 +286,16 @@ public abstract class DisplayEventReceiver {
            long renderPeriod) {
    }

    /**
     * Called when a display hdcp levels change event is received.
     *
     * @param physicalDisplayId Stable display ID that uniquely describes a (display, port) pair.
     * @param connectedLevel the new connected HDCP level
     * @param maxLevel the maximum HDCP level
     */
    public void onHdcpLevelsChanged(long physicalDisplayId, int connectedLevel, int maxLevel) {
    }

    /**
     * Represents a mapping between a UID and an override frame rate
     */
@@ -374,4 +384,11 @@ public abstract class DisplayEventReceiver {
        onFrameRateOverridesChanged(timestampNanos, physicalDisplayId, overrides);
    }

    // Called from native code.
    @SuppressWarnings("unused")
    private void dispatchHdcpLevelsChanged(long physicalDisplayId, int connectedLevel,
            int maxLevel) {
        onHdcpLevelsChanged(physicalDisplayId, connectedLevel, maxLevel);
    }

}
+22 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ static struct {
    jmethodID dispatchHotplugConnectionError;
    jmethodID dispatchModeChanged;
    jmethodID dispatchFrameRateOverrides;
    jmethodID dispatchHdcpLevelsChanged;

    struct {
        jclass clazz;
@@ -96,6 +97,8 @@ private:
    void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId,
                                    std::vector<FrameRateOverride> overrides) override;
    void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) override {}
    void dispatchHdcpLevelsChanged(PhysicalDisplayId displayId, int connectedLevel,
                                   int maxLevel) override;
};

NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak,
@@ -294,6 +297,22 @@ void NativeDisplayEventReceiver::dispatchFrameRateOverrides(
    mMessageQueue->raiseAndClearException(env, "dispatchModeChanged");
}

void NativeDisplayEventReceiver::dispatchHdcpLevelsChanged(PhysicalDisplayId displayId,
                                                           int connectedLevel, int maxLevel) {
    JNIEnv* env = AndroidRuntime::getJNIEnv();

    ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
    if (receiverObj.get()) {
        ALOGV("receiver %p ~ Invoking hdcp levels changed handler.", this);
        env->CallVoidMethod(receiverObj.get(),
                            gDisplayEventReceiverClassInfo.dispatchHdcpLevelsChanged,
                            displayId.value, connectedLevel, maxLevel);
        ALOGV("receiver %p ~ Returned from hdcp levels changed handler.", this);
    }

    mMessageQueue->raiseAndClearException(env, "dispatchHdcpLevelsChanged");
}

static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject vsyncEventDataWeak,
                        jobject messageQueueObj, jint vsyncSource, jint eventRegistration,
                        jlong layerHandle) {
@@ -385,6 +404,9 @@ int register_android_view_DisplayEventReceiver(JNIEnv* env) {
            GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz,
                             "dispatchFrameRateOverrides",
                             "(JJ[Landroid/view/DisplayEventReceiver$FrameRateOverride;)V");
    gDisplayEventReceiverClassInfo.dispatchHdcpLevelsChanged =
            GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz, "dispatchHdcpLevelsChanged",
                             "(JII)V");

    jclass frameRateOverrideClazz =
            FindClassOrDie(env, "android/view/DisplayEventReceiver$FrameRateOverride");
+56 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.hardware.display.DisplayManagerInternal.DisplayOffloadSession;
import android.hardware.sidekick.SidekickInternal;
import android.media.MediaDrm;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
@@ -242,6 +243,10 @@ final class LocalDisplayAdapter extends DisplayAdapter {
        private SurfaceControl.DisplayMode mActiveSfDisplayMode;
        // The active display vsync period in SurfaceFlinger
        private float mActiveRenderFrameRate;
        // The current HDCP level supported by the display, 0 indicates unset
        // values are defined in hardware/interfaces/drm/aidl/android/hardware/drm/HdcpLevel.aidl
        private int mConnectedHdcpLevel;

        private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides =
                new DisplayEventReceiver.FrameRateOverride[0];

@@ -675,8 +680,9 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                mInfo.yDpi = mActiveSfDisplayMode.yDpi;
                mInfo.deviceProductInfo = mStaticDisplayInfo.deviceProductInfo;

                // Assume that all built-in displays that have secure output (eg. HDCP) also
                // support compositing from gralloc protected buffers.
                if (mConnectedHdcpLevel != 0) {
                    mStaticDisplayInfo.secure = mConnectedHdcpLevel >= MediaDrm.HDCP_V1;
                }
                if (mStaticDisplayInfo.secure) {
                    mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
                            | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
@@ -1093,6 +1099,12 @@ final class LocalDisplayAdapter extends DisplayAdapter {
            }
        }

        public void onHdcpLevelsChangedLocked(int connectedLevel, int maxLevel) {
            if (updateHdcpLevelsLocked(connectedLevel, maxLevel)) {
                updateDeviceInfoLocked();
            }
        }

        public boolean updateActiveModeLocked(int activeSfModeId, float renderFrameRate) {
            if (mActiveSfDisplayMode.id == activeSfModeId
                    && mActiveRenderFrameRate == renderFrameRate) {
@@ -1118,6 +1130,22 @@ final class LocalDisplayAdapter extends DisplayAdapter {
            return true;
        }

        public boolean updateHdcpLevelsLocked(int connectedLevel, int maxLevel) {
            if (connectedLevel > maxLevel) {
                Slog.w(TAG, "HDCP connected level: " + connectedLevel
                        + " is larger than max level: " + maxLevel
                        + ", ignoring request.");
                return false;
            }

            if (mConnectedHdcpLevel == connectedLevel) {
                return false;
            }

            mConnectedHdcpLevel = connectedLevel;
            return true;
        }

        public void requestColorModeLocked(int colorMode) {
            if (mActiveColorMode == colorMode) {
                return;
@@ -1387,6 +1415,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                long renderPeriod);
        void onFrameRateOverridesChanged(long timestampNanos, long physicalDisplayId,
                DisplayEventReceiver.FrameRateOverride[] overrides);
        void onHdcpLevelsChanged(long physicalDisplayId, int connectedLevel, int maxLevel);

    }

@@ -1420,6 +1449,11 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                DisplayEventReceiver.FrameRateOverride[] overrides) {
            mListener.onFrameRateOverridesChanged(timestampNanos, physicalDisplayId, overrides);
        }

        @Override
        public void onHdcpLevelsChanged(long physicalDisplayId, int connectedLevel, int maxLevel) {
            mListener.onHdcpLevelsChanged(physicalDisplayId, connectedLevel, maxLevel);
        }
    }

    private final class LocalDisplayEventListener implements DisplayEventListener {
@@ -1489,6 +1523,26 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                device.onFrameRateOverridesChanged(overrides);
            }
        }

        @Override
        public void onHdcpLevelsChanged(long physicalDisplayId, int connectedLevel, int maxLevel) {
            if (DEBUG) {
                Slog.d(TAG, "onHdcpLevelsChanged(physicalDisplayId=" + physicalDisplayId
                        + ", connectedLevel=" + connectedLevel + ", maxLevel=" + maxLevel + ")");
            }
            synchronized (getSyncRoot()) {
                LocalDisplayDevice device = mDevices.get(physicalDisplayId);
                if (device == null) {
                    if (DEBUG) {
                        Slog.d(TAG, "Received hdcp levels change for unhandled physical display: "
                                + "physicalDisplayId=" + physicalDisplayId);
                    }
                    return;
                }

                device.onHdcpLevelsChangedLocked(connectedLevel, maxLevel);
            }
        }
    }

    @VisibleForTesting