Merge "Secure windows, secure surface views and secure displays." into jb-mr1-dev
diff --git a/api/17.txt b/api/17.txt
index 31ed755..e7f02dc 100644
--- a/api/17.txt
+++ b/api/17.txt
@@ -23742,6 +23742,7 @@
     method public deprecated int getWidth();
     method public boolean isValid();
     field public static final int DEFAULT_DISPLAY = 0; // 0x0
+    field public static final int FLAG_SECURE = 2; // 0x2
     field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1
   }
 
@@ -24788,6 +24789,7 @@
     ctor public SurfaceView(android.content.Context, android.util.AttributeSet, int);
     method public boolean gatherTransparentRegion(android.graphics.Region);
     method public android.view.SurfaceHolder getHolder();
+    method public void setSecure(boolean);
     method public void setZOrderMediaOverlay(boolean);
     method public void setZOrderOnTop(boolean);
   }
diff --git a/api/current.txt b/api/current.txt
index 31ed755..e7f02dc 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23742,6 +23742,7 @@
     method public deprecated int getWidth();
     method public boolean isValid();
     field public static final int DEFAULT_DISPLAY = 0; // 0x0
+    field public static final int FLAG_SECURE = 2; // 0x2
     field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1
   }
 
@@ -24788,6 +24789,7 @@
     ctor public SurfaceView(android.content.Context, android.util.AttributeSet, int);
     method public boolean gatherTransparentRegion(android.graphics.Region);
     method public android.view.SurfaceHolder getHolder();
+    method public void setSecure(boolean);
     method public void setZOrderMediaOverlay(boolean);
     method public void setZOrderOnTop(boolean);
   }
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 662dc45..1cd3e05 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -82,22 +82,65 @@
      * Display flag: Indicates that the display supports compositing content
      * that is stored in protected graphics buffers.
      * <p>
+     * If this flag is set then the display device supports compositing protected buffers.
+     * </p><p>
+     * If this flag is not set then the display device may not support compositing
+     * protected buffers; the user may see a blank region on the screen instead of
+     * the protected content.
+     * </p><p>
      * 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>
-     * 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.
+     * An application can use the absence of this flag as a hint that it should not use protected
+     * buffers for this display because the content may not be visible.  For example,
+     * if the flag is not set then the application may choose not to show content on this
+     * display, show an informative error message, select an alternate content stream
+     * or adopt a different strategy for decoding content that does not rely on
+     * protected buffers.
      * </p>
+     *
+     * @see #getFlags
      */
     public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 0;
 
     /**
+     * Display flag: Indicates that the display has a secure video output and
+     * supports compositing secure surfaces.
+     * <p>
+     * If this flag is set then the display device has a secure video output
+     * and is capable of showing secure surfaces.  It may also be capable of
+     * showing {@link #FLAG_SUPPORTS_PROTECTED_BUFFERS protected buffers}.
+     * </p><p>
+     * If this flag is not set then the display device may not have a secure video
+     * output; the user may see a blank region on the screen instead of
+     * the contents of secure surfaces or protected buffers.
+     * </p><p>
+     * Secure surfaces are used to prevent content rendered into those surfaces
+     * by applications from appearing in screenshots or from being viewed
+     * on non-secure displays.  Protected buffers are used by secure video decoders
+     * for a similar purpose.
+     * </p><p>
+     * An application creates a window with a secure surface by specifying the
+     * {@link WindowManager.LayoutParams#FLAG_SECURE} window flag.
+     * Likewise, an application creates a {@link SurfaceView} with a secure surface
+     * by calling {@link SurfaceView#setSecure} before attaching the secure view to
+     * its containing window.
+     * </p><p>
+     * An application can use the absence of this flag as a hint that it should not create
+     * secure surfaces or protected buffers on this display because the content may
+     * not be visible.  For example, if the flag is not set then the application may
+     * choose not to show content on this display, show an informative error message,
+     * select an alternate content stream or adopt a different strategy for decoding
+     * content that does not rely on secure surfaces or protected buffers.
+     * </p>
+     *
+     * @see #getFlags
+     */
+    public static final int FLAG_SECURE = 1 << 1;
+
+    /**
      * Internal method to create a display.
      * Applications should use {@link android.view.WindowManager#getDefaultDisplay()}
      * or {@link android.hardware.display.DisplayManager#getDisplay}
@@ -182,6 +225,7 @@
      * @return The display flags.
      *
      * @see #FLAG_SUPPORTS_PROTECTED_BUFFERS
+     * @see #FLAG_SECURE
      */
     public int getFlags() {
         synchronized (this) {
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index fb04150..ead5ff4 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -299,6 +299,9 @@
 
     private static String flagsToString(int flags) {
         StringBuilder result = new StringBuilder();
+        if ((flags & Display.FLAG_SECURE) != 0) {
+            result.append(", FLAG_SECURE");
+        }
         if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
             result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
         }
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 0d16dd3..9008521 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -385,7 +385,27 @@
             mLayout.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         }
     }
-    
+
+    /**
+     * Control whether the surface view's content should be treated as secure,
+     * preventing it from appearing in screenshots or from being viewed on
+     * non-secure displays.
+     *
+     * <p>Note that this must be set before the surface view's containing
+     * window is attached to the window manager.
+     *
+     * <p>See {@link android.view.Display#FLAG_SECURE} for details.
+     *
+     * @param isSecure True if the surface view is secure.
+     */
+    public void setSecure(boolean isSecure) {
+        if (isSecure) {
+            mLayout.flags |= WindowManager.LayoutParams.FLAG_SECURE;
+        } else {
+            mLayout.flags &= ~WindowManager.LayoutParams.FLAG_SECURE;
+        }
+    }
+
     /**
      * Hack to allow special layering of windows.  The type is one of the
      * types in WindowManager.LayoutParams.  This is a hack so:
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 01923e2..3b31ff6 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -628,8 +628,13 @@
         @Deprecated
         public static final int FLAG_DITHER             = 0x00001000;
         
-        /** Window flag: don't allow screen shots while this window is
-         * displayed. Maps to Surface.SECURE. */
+        /** Window flag: Treat the content of the window as secure, preventing
+         * it from appearing in screenshots or from being viewed on non-secure
+         * displays.
+         *
+         * <p>See {@link android.view.Display#FLAG_SECURE} for more details about
+         * secure surfaces and secure displays.
+         */
         public static final int FLAG_SECURE             = 0x00002000;
         
         /** Window flag: a special mode where the layout parameters are used
diff --git a/services/java/com/android/server/display/LocalDisplayAdapter.java b/services/java/com/android/server/display/LocalDisplayAdapter.java
index d6c5248..fa56b83 100644
--- a/services/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/java/com/android/server/display/LocalDisplayAdapter.java
@@ -127,10 +127,12 @@
                 mInfo.height = mPhys.height;
                 mInfo.refreshRate = mPhys.refreshRate;
 
-                // Assume that all built-in displays have secure output (eg. HDCP) and
+                // Assume that all built-in displays that have secure output (eg. HDCP) also
                 // support compositing from gralloc protected buffers.
-                mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
-                        | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
+                if (mPhys.secure) {
+                    mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
+                            | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
+                }
 
                 if (mBuiltInDisplayId == Surface.BUILT_IN_DISPLAY_ID_MAIN) {
                     mInfo.name = getContext().getResources().getString(
diff --git a/services/java/com/android/server/display/LogicalDisplay.java b/services/java/com/android/server/display/LogicalDisplay.java
index aa7ea82..aa62aee 100644
--- a/services/java/com/android/server/display/LogicalDisplay.java
+++ b/services/java/com/android/server/display/LogicalDisplay.java
@@ -186,6 +186,9 @@
             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
                 mBaseDisplayInfo.flags |= Display.FLAG_SUPPORTS_PROTECTED_BUFFERS;
             }
+            if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SECURE) != 0) {
+                mBaseDisplayInfo.flags |= Display.FLAG_SECURE;
+            }
             mBaseDisplayInfo.name = deviceInfo.name;
             mBaseDisplayInfo.appWidth = deviceInfo.width;
             mBaseDisplayInfo.appHeight = deviceInfo.height;
diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java
index 97fc3e6..2ea83ee 100644
--- a/services/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/java/com/android/server/display/WifiDisplayAdapter.java
@@ -281,18 +281,19 @@
             scheduleStatusChangedBroadcastLocked();
         }
 
+        boolean secure = (flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0;
         int deviceFlags = 0;
-        if ((flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0) {
+        if (secure) {
             deviceFlags |= DisplayDeviceInfo.FLAG_SECURE;
-        }
-        if (mSupportsProtectedBuffers) {
-            deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
+            if (mSupportsProtectedBuffers) {
+                deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
+            }
         }
 
         float refreshRate = 60.0f; // TODO: get this for real
 
         String name = display.getFriendlyDisplayName();
-        IBinder displayToken = Surface.createDisplay(name, false);
+        IBinder displayToken = Surface.createDisplay(name, secure);
         mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height,
                 refreshRate, deviceFlags, surface);
         sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED);