Add new Display API for secure video capabilities.
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
This commit is contained in:
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
* 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_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.
|
||||
* </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) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -967,4 +967,18 @@
|
||||
<!-- 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>
|
||||
|
@ -261,6 +261,7 @@
|
||||
<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" />
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user