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();
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 {
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();
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 {
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.
*
* @return The display flags.
*
- * @hide pending review
+ * @see #FLAG_SUPPORTS_PROTECTED_BUFFERS
*/
public int getFlags() {
synchronized (this) {
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();
}
<!-- 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>
<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" />
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.
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();
}
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;
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;
} 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);
}
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;
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;
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;
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;
PersistentDataStore persistentDataStore) {
super(syncRoot, context, handler, listener, TAG);
mPersistentDataStore = persistentDataStore;
+ mSupportsProtectedBuffers = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers);
}
@Override
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) {
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