OSDN Git Service

Add new Display API for secure video capabilities.
authorJeff Brown <jeffbrown@google.com>
Tue, 2 Oct 2012 04:07:03 +0000 (21:07 -0700)
committerJeff Brown <jeffbrown@google.com>
Tue, 2 Oct 2012 23:25:10 +0000 (16:25 -0700)
Added a new API to determine whether the display supports
protected buffers so that an application can choose a different
content stream or change how it decodes the content so
that it will be viewable on the display.

At present, wifi display does not fully support protected
buffers although this may be enhanced in the future.

Bug: 6986623
Change-Id: If53a53d72b0ec92753cc4b29f99fcb131e00449b

12 files changed:
api/17.txt
api/current.txt
core/java/android/view/Display.java
core/java/android/view/DisplayInfo.java
core/res/res/values/config.xml
core/res/res/values/symbols.xml
services/java/com/android/server/display/DisplayDeviceInfo.java
services/java/com/android/server/display/HeadlessDisplayAdapter.java
services/java/com/android/server/display/LocalDisplayAdapter.java
services/java/com/android/server/display/LogicalDisplay.java
services/java/com/android/server/display/OverlayDisplayAdapter.java
services/java/com/android/server/display/WifiDisplayAdapter.java

index 1a6657c..f35a706 100644 (file)
@@ -23714,6 +23714,7 @@ package android.view {
   public final class Display {
     method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point);
     method public int getDisplayId();
+    method public int getFlags();
     method public deprecated int getHeight();
     method public void getMetrics(android.util.DisplayMetrics);
     method public java.lang.String getName();
@@ -23728,6 +23729,7 @@ package android.view {
     method public deprecated int getWidth();
     method public boolean isValid();
     field public static final int DEFAULT_DISPLAY = 0; // 0x0
+    field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1
   }
 
   public class DragEvent implements android.os.Parcelable {
index 4e7d012..a36727d 100644 (file)
@@ -23719,6 +23719,7 @@ package android.view {
   public final class Display {
     method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point);
     method public int getDisplayId();
+    method public int getFlags();
     method public deprecated int getHeight();
     method public void getMetrics(android.util.DisplayMetrics);
     method public java.lang.String getName();
@@ -23733,6 +23734,7 @@ package android.view {
     method public deprecated int getWidth();
     method public boolean isValid();
     field public static final int DEFAULT_DISPLAY = 0; // 0x0
+    field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1
   }
 
   public class DragEvent implements android.os.Parcelable {
index cf58458..662dc45 100644 (file)
@@ -79,38 +79,23 @@ public final class Display {
     public static final int DEFAULT_DISPLAY = 0;
 
     /**
-     * Display flag: Indicates that the display supports secure video output.
+     * Display flag: Indicates that the display supports compositing content
+     * that is stored in protected graphics buffers.
      * <p>
-     * This flag is used to indicate that the display supports content protection
-     * mechanisms for secure video output at the display interface, such as HDCP.
-     * These mechanisms may be used to protect secure content as it leaves the device.
+     * Secure (DRM) video decoders may allocate protected graphics buffers to request that
+     * a hardware-protected path be provided between the video decoder and the external
+     * display sink.  If a hardware-protected path is not available, then content stored
+     * in protected graphics buffers may not be composited.
      * </p><p>
-     * While mirroring content to multiple displays, it can happen that certain
-     * display devices support secure video output while other display devices do not.
-     * The secure content will be shown only on the display devices that support
-     * secure video output and will be blanked on other display devices that do
-     * not support secure video output.
-     * </p><p>
-     * This flag mainly applies to external display devices such as HDMI or
-     * Wifi display.  Built-in display devices are usually considered secure.
-     * </p>
-     *
-     * @hide pending review
-     */
-    public static final int FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT = 1 << 0;
-
-    /**
-     * Display flag: Indicates that the display supports secure in-memory video buffers.
-     * <p>
-     * This flag is used to indicate that the display supports content protection
-     * mechanisms for in-memory video buffers, such as secure memory areas.
-     * These mechanisms may be used to protect secure video buffers in memory from
-     * the video decoder to the display compositor and the video interface.
+     * If this flag is not set, then the display device does not support compositing
+     * protected buffers; the user may see a blank region on the screen instead of
+     * the protected content.  An application can use this flag as a hint that it should
+     * select an alternate content stream or adopt a different strategy for decoding
+     * content that does not rely on protected buffers so as to ensure that the user
+     * can view the content on the display as expected.
      * </p>
-     *
-     * @hide pending review
      */
-    public static final int FLAG_SUPPORTS_SECURE_VIDEO_BUFFERS = 1 << 1;
+    public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 0;
 
     /**
      * Internal method to create a display.
@@ -196,7 +181,7 @@ public final class Display {
      *
      * @return The display flags.
      *
-     * @hide pending review
+     * @see #FLAG_SUPPORTS_PROTECTED_BUFFERS
      */
     public int getFlags() {
         synchronized (this) {
index c968ec5..fe05634 100644 (file)
@@ -299,11 +299,8 @@ public final class DisplayInfo implements Parcelable {
 
     private static String flagsToString(int flags) {
         StringBuilder result = new StringBuilder();
-        if ((flags & Display.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT) != 0) {
-            result.append(", FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT");
-        }
-        if ((flags & Display.FLAG_SUPPORTS_SECURE_VIDEO_BUFFERS) != 0) {
-            result.append(", FLAG_SUPPORTS_SECURE_VIDEO_BUFFERS");
+        if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
+            result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
         }
         return result.toString();
     }
index d3d994f..16960c8 100755 (executable)
     <!-- Whether safe headphone volume is enabled or not (country specific). -->
     <bool name="config_safe_media_volume_enabled">true</bool>
 
+    <!-- Set to true if the wifi display supports compositing content stored
+         in gralloc protected buffers.  For this to be true, there must exist
+         a protected hardware path for surface flinger to composite and send
+         protected buffers to the wifi display video encoder.
+
+         If this flag is false, we advise applications not to use protected
+         buffers (if possible) when presenting content to a wifi display because
+         the content may be blanked.
+
+         This flag controls whether the {@link Display#FLAG_SUPPORTS_PROTECTED_BUFFERS}
+         flag is set for wifi displays.
+    -->
+    <bool name="config_wifiDisplaySupportsProtectedBuffers">false</bool>
+
 </resources>
index 6499d8b..14bd528 100644 (file)
   <java-symbol type="bool" name="config_ui_enableFadingMarquee" />
   <java-symbol type="bool" name="config_use_strict_phone_number_comparation" />
   <java-symbol type="bool" name="config_voice_capable" />
+  <java-symbol type="bool" name="config_wifiDisplaySupportsProtectedBuffers" />
   <java-symbol type="bool" name="preferences_prefer_dual_pane" />
   <java-symbol type="bool" name="skip_restoring_network_selection" />
   <java-symbol type="bool" name="split_action_bar_is_narrow" />
index f0cd0f5..b4dab86 100644 (file)
@@ -38,9 +38,15 @@ final class DisplayDeviceInfo {
     public static final int FLAG_SUPPORTS_ROTATION = 1 << 1;
 
     /**
-     * Flag: Indicates that this display device can show secure surfaces.
+     * Flag: Indicates that this display device has secure video output, such as HDCP.
      */
-    public static final int FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT = 1 << 2;
+    public static final int FLAG_SECURE = 1 << 2;
+
+    /**
+     * Flag: Indicates that this display device supports compositing
+     * from gralloc protected buffers.
+     */
+    public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 3;
 
     /**
      * Touch attachment: Display does not receive touch.
@@ -182,8 +188,11 @@ final class DisplayDeviceInfo {
         if ((flags & FLAG_SUPPORTS_ROTATION) != 0) {
             msg.append(", FLAG_SUPPORTS_ROTATION");
         }
-        if ((flags & FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT) != 0) {
-            msg.append(", FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT");
+        if ((flags & FLAG_SECURE) != 0) {
+            msg.append(", FLAG_SECURE");
+        }
+        if ((flags & FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
+            msg.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
         }
         return msg.toString();
     }
index f3bec1d..7ec537f 100644 (file)
@@ -60,7 +60,8 @@ final class HeadlessDisplayAdapter extends DisplayAdapter {
                 mInfo.xDpi = 160;
                 mInfo.yDpi = 160;
                 mInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
-                        | DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT;
+                        | DisplayDeviceInfo.FLAG_SECURE
+                        | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
                 mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
             }
             return mInfo;
index 9c51463..679a67e 100644 (file)
@@ -124,11 +124,16 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                 mInfo.width = mPhys.width;
                 mInfo.height = mPhys.height;
                 mInfo.refreshRate = mPhys.refreshRate;
+
+                // Assume that all built-in displays have secure output (eg. HDCP) and
+                // support compositing from gralloc protected buffers.
+                mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
+                        | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
+
                 if (mBuiltInDisplayId == Surface.BUILT_IN_DISPLAY_ID_MAIN) {
                     mInfo.name = getContext().getResources().getString(
                             com.android.internal.R.string.display_manager_built_in_display_name);
-                    mInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
-                            | DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT
+                    mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
                             | DisplayDeviceInfo.FLAG_SUPPORTS_ROTATION;
                     mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f);
                     mInfo.xDpi = mPhys.xDpi;
@@ -137,7 +142,6 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                 } else {
                     mInfo.name = getContext().getResources().getString(
                             com.android.internal.R.string.display_manager_hdmi_display_name);
-                    mInfo.flags = DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT;
                     mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
                     mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height);
                 }
index 3607de1..f4cb84d 100644 (file)
@@ -179,8 +179,8 @@ final class LogicalDisplay {
         if (!Objects.equal(mPrimaryDisplayDeviceInfo, deviceInfo)) {
             mBaseDisplayInfo.layerStack = mLayerStack;
             mBaseDisplayInfo.flags = 0;
-            if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT) != 0) {
-                mBaseDisplayInfo.flags |= Display.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT;
+            if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
+                mBaseDisplayInfo.flags |= Display.FLAG_SUPPORTS_PROTECTED_BUFFERS;
             }
             mBaseDisplayInfo.name = deviceInfo.name;
             mBaseDisplayInfo.appWidth = deviceInfo.width;
index 0767fc0..6ffb629 100644 (file)
@@ -19,14 +19,10 @@ package com.android.server.display;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.database.ContentObserver;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.DisplayMetrics;
 import android.util.Slog;
@@ -227,7 +223,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
                 mInfo.densityDpi = mDensityDpi;
                 mInfo.xDpi = mDensityDpi;
                 mInfo.yDpi = mDensityDpi;
-                mInfo.flags = DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT;
+                mInfo.flags = 0;
                 mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
             }
             return mInfo;
index 4a89be7..b2beb5e 100644 (file)
@@ -50,7 +50,8 @@ import java.util.Arrays;
 final class WifiDisplayAdapter extends DisplayAdapter {
     private static final String TAG = "WifiDisplayAdapter";
 
-    private PersistentDataStore mPersistentDataStore;
+    private final PersistentDataStore mPersistentDataStore;
+    private final boolean mSupportsProtectedBuffers;
 
     private WifiDisplayController mDisplayController;
     private WifiDisplayDevice mDisplayDevice;
@@ -70,6 +71,8 @@ final class WifiDisplayAdapter extends DisplayAdapter {
             PersistentDataStore persistentDataStore) {
         super(syncRoot, context, handler, listener, TAG);
         mPersistentDataStore = persistentDataStore;
+        mSupportsProtectedBuffers = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers);
     }
 
     @Override
@@ -84,6 +87,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
         pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays));
         pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays));
         pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast);
+        pw.println("mSupportsProtectedBuffers=" + mSupportsProtectedBuffers);
 
         // Try to dump the controller state.
         if (mDisplayController == null) {
@@ -217,7 +221,10 @@ final class WifiDisplayAdapter extends DisplayAdapter {
 
         int deviceFlags = 0;
         if ((flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0) {
-            deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT;
+            deviceFlags |= DisplayDeviceInfo.FLAG_SECURE;
+        }
+        if (mSupportsProtectedBuffers) {
+            deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
         }
 
         float refreshRate = 60.0f; // TODO: get this for real