Add flag for displaying non-user's Windows to user.

Created a new flag that indicates that a window should be shown
to all users. For the flag to be valid the owner of the window
must have system permissions.

Also separated system window types into those that show to all
users (e.g. StatusBar, Keyguard, ....) and those that appear only
to the owning users (e.g. Drag, ANR, TOAST, ...). Those that appear
only to their owner can override their default behavior using
the new flag (e.g. LowBattery).

Fixes bug 7211965.

Change-Id: I1fdca25d57b7b523f0c7f8bceb819af656c388d4
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 6e51270..eb3f72e 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -298,12 +298,14 @@
          * Window type: the status bar.  There can be only one status bar
          * window; it is placed at the top of the screen, and all other
          * windows are shifted down so they are below it.
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW;
     
         /**
          * Window type: the search bar.  There can be only one search bar
          * window; it is placed at the top of the screen.
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1;
     
@@ -312,22 +314,26 @@
          * user interaction with the phone (in particular incoming calls).
          * These windows are normally placed above all applications, but behind
          * the status bar.
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2;
     
         /**
          * Window type: system window, such as low power alert. These windows
          * are always on top of application windows.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3;
         
         /**
          * Window type: keyguard window.
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4;
         
         /**
          * Window type: transient notifications.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5;
         
@@ -335,6 +341,7 @@
          * Window type: system overlay windows, which need to be displayed
          * on top of everything else.  These windows must not take input
          * focus, or they will interfere with the keyguard.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6;
         
@@ -342,22 +349,26 @@
          * Window type: priority phone UI, which needs to be displayed even if
          * the keyguard is active.  These windows must not take input
          * focus, or they will interfere with the keyguard.
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7;
         
         /**
          * Window type: panel that slides out from the status bar
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8;
     
         /**
          * Window type: dialogs that the keyguard shows
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9;
         
         /**
          * Window type: internal system error windows, appear on top of
          * everything they can.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10;
         
@@ -365,23 +376,27 @@
          * Window type: internal input methods windows, which appear above
          * the normal UI.  Application windows may be resized or panned to keep
          * the input focus visible while this window is displayed.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_INPUT_METHOD       = FIRST_SYSTEM_WINDOW+11;
 
         /**
          * Window type: internal input methods dialog windows, which appear above
          * the current input method window.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12;
 
         /**
          * Window type: wallpaper window, placed behind any window that wants
          * to sit on top of the wallpaper.
+         * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13;
 
         /**
          * Window type: panel that slides out from over the status bar
+         * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+14;
 
@@ -393,6 +408,8 @@
          * This is exactly like {@link #TYPE_SYSTEM_OVERLAY} except that only the
          * system itself is allowed to create these overlays.  Applications cannot
          * obtain permission to create secure system overlays.
+         *
+         * In multiuser systems shows only on the owning user's window.
          * @hide
          */
         public static final int TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15;
@@ -400,24 +417,28 @@
         /**
          * Window type: the drag-and-drop pseudowindow.  There is only one
          * drag layer (at most), and it is placed on top of all other windows.
+         * In multiuser systems shows only on the owning user's window.
          * @hide
          */
         public static final int TYPE_DRAG               = FIRST_SYSTEM_WINDOW+16;
 
         /**
          * Window type: panel that slides out from under the status bar
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17;
 
         /**
          * Window type: (mouse) pointer
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_POINTER = FIRST_SYSTEM_WINDOW+18;
 
         /**
          * Window type: Navigation bar (when distinct from status bar)
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19;
@@ -425,6 +446,7 @@
         /**
          * Window type: The volume level overlay/dialog shown when the user
          * changes the system volume.
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20;
@@ -432,6 +454,7 @@
         /**
          * Window type: The boot progress dialog, goes on top of everything
          * in the world.
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21;
@@ -439,30 +462,35 @@
         /**
          * Window type: Fake window to consume touch events when the navigation
          * bar is hidden.
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_HIDDEN_NAV_CONSUMER = FIRST_SYSTEM_WINDOW+22;
 
         /**
          * Window type: Dreams (screen saver) window, just above keyguard.
+         * In multiuser systems shows only on the owning user's window.
          * @hide
          */
         public static final int TYPE_DREAM = FIRST_SYSTEM_WINDOW+23;
 
         /**
          * Window type: Navigation bar panel (when navigation bar is distinct from status bar)
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24;
 
         /**
          * Window type: Behind the universe of the real windows.
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_UNIVERSE_BACKGROUND = FIRST_SYSTEM_WINDOW+25;
 
         /**
          * Window type: Display overlay window.  Used to simulate secondary display devices.
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_DISPLAY_OVERLAY = FIRST_SYSTEM_WINDOW+26;
@@ -470,11 +498,20 @@
         /**
          * Window type: Magnification overlay window. Used to highlight the magnified
          * portion of a display when accessibility magnification is enabled.
+         * In multiuser systems shows on all users' windows.
          * @hide
          */
         public static final int TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27;
 
         /**
+         * Window type: Recents. Same layer as {@link #TYPE_SYSTEM_DIALOG} but only appears on
+         * one user's screen.
+         * In multiuser systems shows on all users' windows.
+         * @hide
+         */
+        public static final int TYPE_RECENTS_OVERLAY = FIRST_SYSTEM_WINDOW+28;
+
+        /**
          * End of types of system windows.
          */
         public static final int LAST_SYSTEM_WINDOW      = 2999;
@@ -879,6 +916,14 @@
          */
         public static final int PRIVATE_FLAG_SET_NEEDS_MENU_KEY = 0x00000008;
 
+        /** In a multiuser system if this flag is set and the owner is a system process then this
+         * window will appear on all user screens. This overrides the default behavior of window
+         * types that normally only appear on the owning user's screen. Refer to each window type
+         * to determine its default behavior.
+         *
+         * {@hide} */
+        public static final int PRIVATE_FLAG_SHOW_FOR_ALL_USERS = 0x00000010;
+
         /**
          * Control flags that are private to the platform.
          * @hide
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 82f07c7..2d399a2 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -500,6 +500,16 @@
     public int checkAddPermission(WindowManager.LayoutParams attrs);
 
     /**
+     * Check permissions when adding a window.
+     *
+     * @param attrs The window's LayoutParams.
+     *
+     * @return True if the window may only be shown to the current user, false if the window can
+     * be shown on all users' windows.
+     */
+    public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs);
+
+    /**
      * Sanitize the layout parameters coming from a client.  Allows the policy
      * to do things like ensure that windows of a specific type can't take
      * input focus.
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 3c30f5d..07fd0ab 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -207,6 +207,7 @@
             if (intent.resolveActivity(mContext.getPackageManager()) != null) {
                 b.setNegativeButton(R.string.battery_low_why,
                         new DialogInterface.OnClickListener() {
+                    @Override
                     public void onClick(DialogInterface dialog, int which) {
                         mContext.startActivity(intent);
                         dismissLowBatteryWarning();
@@ -216,12 +217,15 @@
 
             AlertDialog d = b.create();
             d.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                    @Override
                     public void onDismiss(DialogInterface dialog) {
                         mLowBatteryDialog = null;
                         mBatteryLevelTextView = null;
                     }
                 });
             d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+            d.getWindow().getAttributes().privateFlags |=
+                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
             d.show();
             mLowBatteryDialog = d;
         }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index ba76bcd7..5ed0a5c 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -17,7 +17,6 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
-import android.app.IUiModeManager;
 import android.app.ProgressDialog;
 import android.app.SearchManager;
 import android.app.UiModeManager;
@@ -101,6 +100,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
@@ -108,6 +108,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
@@ -119,6 +120,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
 import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
+import static android.view.WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
@@ -202,7 +204,7 @@
     static final int KEYGUARD_LAYER = 11;
     static final int KEYGUARD_DIALOG_LAYER = 12;
     // used for Dreams (screensavers with TYPE_DREAM windows)
-    static final int SCREENSAVER_LAYER = 13; 
+    static final int SCREENSAVER_LAYER = 13;
     static final int STATUS_BAR_SUB_PANEL_LAYER = 14;
     static final int STATUS_BAR_LAYER = 15;
     static final int STATUS_BAR_PANEL_LAYER = 16;
@@ -234,7 +236,7 @@
     static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
     static final int APPLICATION_PANEL_SUBLAYER = 1;
     static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
-    
+
     static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
     static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
     static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
@@ -289,7 +291,7 @@
 
     // Vibrator pattern for haptic feedback of a long press.
     long[] mLongPressVibePattern;
-    
+
     // Vibrator pattern for haptic feedback of virtual key press.
     long[] mVirtualKeyVibePattern;
     
@@ -1199,6 +1201,7 @@
     }
 
     /** {@inheritDoc} */
+    @Override
     public int checkAddPermission(WindowManager.LayoutParams attrs) {
         int type = attrs.type;
         
@@ -1236,7 +1239,55 @@
         }
         return WindowManagerGlobal.ADD_OKAY;
     }
-    
+
+    @Override
+    public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
+
+        // If this switch statement is modified, modify the comment in the declarations of
+        // the type in {@link WindowManager.LayoutParams} as well.
+        switch (attrs.type) {
+            default:
+                // These are the windows that by default are shown only to the user that created
+                // them. If this needs to be overridden, set
+                // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
+                // {@link WindowManager.LayoutParams}. Note that permission
+                // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
+                if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
+                    return true;
+                }
+                break;
+
+            // These are the windows that by default are shown to all users. However, to
+            // protect against spoofing, check permissions below.
+            case TYPE_APPLICATION_STARTING:
+            case TYPE_BOOT_PROGRESS:
+            case TYPE_DISPLAY_OVERLAY:
+            case TYPE_HIDDEN_NAV_CONSUMER:
+            case TYPE_KEYGUARD:
+            case TYPE_KEYGUARD_DIALOG:
+            case TYPE_MAGNIFICATION_OVERLAY:
+            case TYPE_NAVIGATION_BAR:
+            case TYPE_NAVIGATION_BAR_PANEL:
+            case TYPE_PHONE:
+            case TYPE_POINTER:
+            case TYPE_PRIORITY_PHONE:
+            case TYPE_RECENTS_OVERLAY:
+            case TYPE_SEARCH_BAR:
+            case TYPE_STATUS_BAR:
+            case TYPE_STATUS_BAR_PANEL:
+            case TYPE_STATUS_BAR_SUB_PANEL:
+            case TYPE_SYSTEM_DIALOG:
+            case TYPE_UNIVERSE_BACKGROUND:
+            case TYPE_VOLUME_OVERLAY:
+                break;
+        }
+
+        // Check if third party app has set window to system window type.
+        return mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.INTERNAL_SYSTEM_WINDOW)
+                        != PackageManager.PERMISSION_GRANTED;
+    }
+
     public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
         switch (attrs.type) {
             case TYPE_SYSTEM_OVERLAY:
@@ -1355,6 +1406,8 @@
             return DISPLAY_OVERLAY_LAYER;
         case TYPE_MAGNIFICATION_OVERLAY:
             return MAGNIFICATION_OVERLAY_LAYER;
+        case TYPE_RECENTS_OVERLAY:
+            return SYSTEM_DIALOG_LAYER;
         }
         Log.e(TAG, "Unknown window type: " + type);
         return APPLICATION_LAYER;
@@ -1510,6 +1563,7 @@
                     com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
             params.privateFlags |=
                     WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
+            params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
             params.setTitle("Starting " + packageName);
 
             WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
diff --git a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
index b9903dd..2f0d7d6 100644
--- a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
+++ b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
@@ -94,7 +94,7 @@
 
         Window window = getWindow();
         window.requestFeature(Window.FEATURE_NO_TITLE);
-        window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
+        window.setType(WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY);
         window.setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
         window.setTitle("Recents");
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
index 23a96fb..7a1e235 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
@@ -164,6 +164,9 @@
                         WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
             }
             lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
+            if (isActivity) {
+                lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+            }
             lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
             lp.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
             lp.setTitle(isActivity ? "KeyguardMock" : "Keyguard");
diff --git a/services/java/com/android/server/accessibility/ScreenMagnifier.java b/services/java/com/android/server/accessibility/ScreenMagnifier.java
index 14762a1..ec3c88c 100644
--- a/services/java/com/android/server/accessibility/ScreenMagnifier.java
+++ b/services/java/com/android/server/accessibility/ScreenMagnifier.java
@@ -1009,7 +1009,8 @@
                                 case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
                                 case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
                                 case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY:
-                                case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL: {
+                                case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
+                                case WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY: {
                                     Rect magnifiedRegionBounds = mMagnificationController
                                             .getMagnifiedRegionBounds();
                                     Rect touchableRegion = info.touchableRegion;
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 180579d..1b1d85b 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -34,6 +34,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
 import static android.view.WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND;
@@ -2083,6 +2084,7 @@
         WindowState attachedWindow = null;
         WindowState win = null;
         long origId;
+        final int type = attrs.type;
 
         synchronized(mWindowMap) {
             if (!mDisplayReady) {
@@ -2094,7 +2096,7 @@
                 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
             }
 
-            if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
+            if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
                 attachedWindow = windowForClientLocked(null, attrs.token, false);
                 if (attachedWindow == null) {
                     Slog.w(TAG, "Attempted to add window with token that is not a window: "
@@ -2112,31 +2114,29 @@
             boolean addToken = false;
             WindowToken token = mTokenMap.get(attrs.token);
             if (token == null) {
-                if (attrs.type >= FIRST_APPLICATION_WINDOW
-                        && attrs.type <= LAST_APPLICATION_WINDOW) {
+                if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
                     Slog.w(TAG, "Attempted to add application window with unknown token "
                           + attrs.token + ".  Aborting.");
                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
-                if (attrs.type == TYPE_INPUT_METHOD) {
+                if (type == TYPE_INPUT_METHOD) {
                     Slog.w(TAG, "Attempted to add input method window with unknown token "
                           + attrs.token + ".  Aborting.");
                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
-                if (attrs.type == TYPE_WALLPAPER) {
+                if (type == TYPE_WALLPAPER) {
                     Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
                           + attrs.token + ".  Aborting.");
                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
-                if (attrs.type == TYPE_DREAM) {
+                if (type == TYPE_DREAM) {
                     Slog.w(TAG, "Attempted to add Dream window with unknown token "
                           + attrs.token + ".  Aborting.");
                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
                 token = new WindowToken(this, attrs.token, -1, false);
                 addToken = true;
-            } else if (attrs.type >= FIRST_APPLICATION_WINDOW
-                    && attrs.type <= LAST_APPLICATION_WINDOW) {
+            } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
                 AppWindowToken atoken = token.appWindowToken;
                 if (atoken == null) {
                     Slog.w(TAG, "Attempted to add window with non-application token "
@@ -2147,25 +2147,25 @@
                           + token + ".  Aborting.");
                     return WindowManagerGlobal.ADD_APP_EXITING;
                 }
-                if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
+                if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
                     // No need for this guy!
                     if (localLOGV) Slog.v(
                             TAG, "**** NO NEED TO START: " + attrs.getTitle());
                     return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
                 }
-            } else if (attrs.type == TYPE_INPUT_METHOD) {
+            } else if (type == TYPE_INPUT_METHOD) {
                 if (token.windowType != TYPE_INPUT_METHOD) {
                     Slog.w(TAG, "Attempted to add input method window with bad token "
                             + attrs.token + ".  Aborting.");
                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
-            } else if (attrs.type == TYPE_WALLPAPER) {
+            } else if (type == TYPE_WALLPAPER) {
                 if (token.windowType != TYPE_WALLPAPER) {
                     Slog.w(TAG, "Attempted to add wallpaper window with bad token "
                             + attrs.token + ".  Aborting.");
                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
-            } else if (attrs.type == TYPE_DREAM) {
+            } else if (type == TYPE_DREAM) {
                 if (token.windowType != TYPE_DREAM) {
                     Slog.w(TAG, "Attempted to add Dream window with bad token "
                             + attrs.token + ".  Aborting.");
@@ -2185,6 +2185,7 @@
             }
 
             mPolicy.adjustWindowParamsLw(win.mAttrs);
+            win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
 
             res = mPolicy.prepareAddWindowLw(win, attrs);
             if (res != WindowManagerGlobal.ADD_OKAY) {
@@ -2213,8 +2214,7 @@
             win.attach();
             mWindowMap.put(client.asBinder(), win);
 
-            if (attrs.type == TYPE_APPLICATION_STARTING &&
-                    token.appWindowToken != null) {
+            if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) {
                 token.appWindowToken.startingWindow = win;
                 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken
                         + " startingWindow=" + win);
@@ -2222,19 +2222,19 @@
 
             boolean imMayMove = true;
 
-            if (attrs.type == TYPE_INPUT_METHOD) {
+            if (type == TYPE_INPUT_METHOD) {
                 win.mGivenInsetsPending = true;
                 mInputMethodWindow = win;
                 addInputMethodWindowToListLocked(win);
                 imMayMove = false;
-            } else if (attrs.type == TYPE_INPUT_METHOD_DIALOG) {
+            } else if (type == TYPE_INPUT_METHOD_DIALOG) {
                 mInputMethodDialogs.add(win);
                 addWindowToListInOrderLocked(win, true);
                 adjustInputMethodDialogsLocked();
                 imMayMove = false;
             } else {
                 addWindowToListInOrderLocked(win, true);
-                if (attrs.type == TYPE_WALLPAPER) {
+                if (type == TYPE_WALLPAPER) {
                     mLastWallpaperTimeoutTime = 0;
                     adjustWallpaperWindowsLocked();
                 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
@@ -5404,6 +5404,22 @@
         synchronized (mWindowMap) {
             mCurrentUserId = newUserId;
             mPolicy.setCurrentUserLw(newUserId);
+
+            // Hide windows that should not be seen by the new user.
+            DisplayContentsIterator iterator = new DisplayContentsIterator();
+            while (iterator.hasNext()) {
+                final WindowList windows = iterator.next().getWindowList();
+                for (int i = 0; i < windows.size(); i++) {
+                    final WindowState win = windows.get(i);
+                    if (win.isOtherUsersAppWindow()) {
+                        Slog.w(TAG, "current user violation " + newUserId + " hiding "
+                                + win + ", attrs=" + win.mAttrs.type + ", belonging to "
+                                + win.mOwnerUid);
+                        win.hideLw(false);
+                    }
+                }
+            }
+            performLayoutAndPlaceSurfacesLocked();
         }
     }
 
@@ -8784,6 +8800,7 @@
             final int type = attrs.type;
             if (canBeSeen
                     && (type == TYPE_SYSTEM_DIALOG
+                     || type == TYPE_RECENTS_OVERLAY
                      || type == TYPE_KEYGUARD
                      || type == TYPE_SYSTEM_ERROR)) {
                 mInnerFields.mSyswin = true;
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index d23448b..6e388f2 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -22,9 +22,6 @@
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 
 import com.android.server.input.InputWindowHandle;
 
@@ -36,7 +33,6 @@
 import android.graphics.RectF;
 import android.graphics.Region;
 import android.os.IBinder;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Slog;
@@ -263,7 +259,10 @@
     DisplayContent  mDisplayContent;
 
     // UserId and appId of the owner. Don't display windows of non-current user.
-    final int mOwnerUid;
+    int mOwnerUid;
+
+    /** When true this window can be displayed on screens owther than mOwnerUid's */
+    private boolean mShowToOwnerOnly;
 
     WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState attachedWindow, int seq, WindowManager.LayoutParams a,
@@ -654,6 +653,7 @@
      * surface, or we are in the process of running an exit animation
      * that will remove the surface, or its app token has been hidden.
      */
+    @Override
     public boolean isVisibleLw() {
         final AppWindowToken atoken = mAppToken;
         return mHasSurface && mPolicyVisibility && !mAttachedHidden
@@ -669,6 +669,7 @@
      * for this "hidden behind keyguard" state rather than overloading
      * mPolicyVisibility.  Ungh.
      */
+    @Override
     public boolean isVisibleOrBehindKeyguardLw() {
         if (mRootToken.waitingToShow &&
                 mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
@@ -940,7 +941,7 @@
 
     boolean showLw(boolean doAnimation, boolean requestAnim) {
         if (isOtherUsersAppWindow()) {
-            Slog.w(TAG, "Current user " + mService.mCurrentUserId + " trying to display "
+            Slog.w(TAG, "current user violation " + mService.mCurrentUserId + " trying to display "
                     + this + ", type " + mAttrs.type + ", belonging to " + mOwnerUid);
             return false;
         }
@@ -1025,15 +1026,12 @@
         return mDisplayContent.isDefaultDisplay;
     }
 
+    public void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) {
+        mShowToOwnerOnly = showToOwnerOnly;
+    }
+
     boolean isOtherUsersAppWindow() {
-        final int type = mAttrs.type;
-        if ((UserHandle.getUserId(mOwnerUid) != mService.mCurrentUserId)
-                && (mOwnerUid != Process.SYSTEM_UID)
-                && (type >= TYPE_BASE_APPLICATION) && (type <= LAST_APPLICATION_WINDOW)
-                && (type != TYPE_APPLICATION_STARTING)) {
-            return true;
-        }
-        return false;
+        return mShowToOwnerOnly && UserHandle.getUserId(mOwnerUid) != mService.mCurrentUserId;
     }
 
     private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
@@ -1072,6 +1070,8 @@
         pw.print(prefix); pw.print("mDisplayId="); pw.print(mDisplayContent.getDisplayId());
                 pw.print(" mSession="); pw.print(mSession);
                 pw.print(" mClient="); pw.println(mClient.asBinder());
+        pw.print(prefix); pw.print("mOwnerUid="); pw.print(mOwnerUid);
+                pw.print(" mShowToOwnerOnly="); pw.println(mShowToOwnerOnly);
         pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
         pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
                 pw.print(" h="); pw.print(mRequestedHeight);
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index acf452f..817a234 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -1335,7 +1335,7 @@
     // This must be called while inside a transaction.
     boolean performShowLocked() {
         if (mWin.isOtherUsersAppWindow()) {
-            Slog.w(TAG, "Current user " + mService.mCurrentUserId + " trying to display "
+            Slog.w(TAG, "current user violation " + mService.mCurrentUserId + " trying to display "
                     + this + ", type " + mWin.mAttrs.type + ", belonging to " + mWin.mOwnerUid);
             return false;
         }