Merge "DozeScrimController: Fix tight-posting bug" into oc-mr1-dev
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 68fb7bc..c8d9839 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -262,4 +262,10 @@
      * Clears the previously saved activity manager ANR state.
      */
     public abstract void clearSavedANRState();
+
+    /**
+     * Set focus on an activity.
+     * @param token The IApplicationToken for the activity
+     */
+    public abstract void setFocusedActivity(IBinder token);
 }
diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java
index 95a6394..bb9e391 100644
--- a/core/java/android/view/WindowInfo.java
+++ b/core/java/android/view/WindowInfo.java
@@ -41,6 +41,7 @@
     public int layer;
     public IBinder token;
     public IBinder parentToken;
+    public IBinder activityToken;
     public boolean focused;
     public final Rect boundsInScreen = new Rect();
     public List<IBinder> childTokens;
@@ -66,6 +67,7 @@
         window.layer = other.layer;
         window.token = other.token;
         window.parentToken = other.parentToken;
+        window.activityToken = other.activityToken;
         window.focused = other.focused;
         window.boundsInScreen.set(other.boundsInScreen);
         window.title = other.title;
@@ -99,6 +101,7 @@
         parcel.writeInt(layer);
         parcel.writeStrongBinder(token);
         parcel.writeStrongBinder(parentToken);
+        parcel.writeStrongBinder(activityToken);
         parcel.writeInt(focused ? 1 : 0);
         boundsInScreen.writeToParcel(parcel, flags);
         parcel.writeCharSequence(title);
@@ -135,6 +138,7 @@
         layer = parcel.readInt();
         token = parcel.readStrongBinder();
         parentToken = parcel.readStrongBinder();
+        activityToken = parcel.readStrongBinder();
         focused = (parcel.readInt() == 1);
         boundsInScreen.readFromParcel(parcel);
         title = parcel.readCharSequence();
@@ -155,6 +159,7 @@
         layer = 0;
         token = null;
         parentToken = null;
+        activityToken = null;
         focused = false;
         boundsInScreen.setEmpty();
         if (childTokens != null) {
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 9b2bffd..340b2e1 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2051,4 +2051,10 @@
     <!-- Prompt to turn off data usage [CHAR LIMIT=NONE] -->
     <string name="data_usage_disable_mobile" msgid="8656552431969276305">Turn off mobile data?</string>
 
+    <!-- Warning shown when user input has been blocked due to another app overlaying screen
+     content. Since we don't know what the app is showing on top of the input target, we
+     can't verify user consent. [CHAR LIMIT=NONE] -->
+    <string name="touch_filtered_warning">Because an app is obscuring a permission request, Settings
+        can’t verify your response.</string>
+
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
index f5447a2..70efe5c 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
@@ -31,8 +31,12 @@
 import android.os.SystemProperties;
 import android.util.Log;
 import android.view.LayoutInflater;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
 import android.widget.CheckBox;
+import android.widget.Toast;
 
 import com.android.internal.app.AlertActivity;
 import com.android.internal.app.AlertController;
@@ -48,6 +52,9 @@
 
     @Override
     public void onCreate(Bundle icicle) {
+        Window window = getWindow();
+        window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
+
         super.onCreate(icicle);
 
         if (SystemProperties.getInt("service.adb.tcp.port", 0) == 0) {
@@ -79,6 +86,29 @@
         ap.mView = checkbox;
 
         setupAlert();
+
+        // adding touch listener on affirmative button - checks if window is obscured
+        // if obscured, do not let user give permissions (could be tapjacking involved)
+        final View.OnTouchListener filterTouchListener = (View v, MotionEvent event) -> {
+            // Filter obscured touches by consuming them.
+            if (((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0)
+                    || ((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) != 0)) {
+                if (event.getAction() == MotionEvent.ACTION_UP) {
+                    Toast.makeText(v.getContext(),
+                            R.string.touch_filtered_warning,
+                            Toast.LENGTH_SHORT).show();
+                }
+                return true;
+            }
+            return false;
+        };
+        mAlert.getButton(BUTTON_POSITIVE).setOnTouchListener(filterTouchListener);
+
+    }
+
+    @Override
+    public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
+        super.onWindowAttributesChanged(params);
     }
 
     private class UsbDisconnectedReceiver extends BroadcastReceiver {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index a59844d..a97e16b 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -19,6 +19,8 @@
 import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
 
 import android.Manifest;
 import android.accessibilityservice.AccessibilityService;
@@ -27,6 +29,7 @@
 import android.accessibilityservice.IAccessibilityServiceClient;
 import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.annotation.NonNull;
+import android.app.ActivityManagerInternal;
 import android.app.AlertDialog;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
@@ -847,7 +850,7 @@
             if (resolvedUserId != mCurrentUserId) {
                 return null;
             }
-            if (mSecurityPolicy.findWindowById(windowId) == null) {
+            if (mSecurityPolicy.findA11yWindowInfoById(windowId) == null) {
                 return null;
             }
             IBinder token = mGlobalWindowTokens.get(windowId);
@@ -3010,7 +3013,7 @@
                 if (!permissionGranted) {
                     return null;
                 }
-                AccessibilityWindowInfo window = mSecurityPolicy.findWindowById(windowId);
+                AccessibilityWindowInfo window = mSecurityPolicy.findA11yWindowInfoById(windowId);
                 if (window != null) {
                     AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window);
                     windowClone.setConnectionId(mId);
@@ -3332,31 +3335,30 @@
                 throws RemoteException {
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
+            IBinder activityToken = null;
             synchronized (mLock) {
                 if (!isCalledForCurrentUserLocked()) {
                     return false;
                 }
                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
-                final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
-                        this, resolvedWindowId);
-                if (!permissionGranted) {
+                if (!mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId)) {
                     return false;
-                } else {
-                    connection = getConnectionLocked(resolvedWindowId);
-                    if (connection == null) {
-                        return false;
-                    }
-                    AccessibilityWindowInfo windowInfo =
-                            mSecurityPolicy.findWindowById(resolvedWindowId);
-                    if ((windowInfo != null) && windowInfo.inPictureInPicture()) {
-                        boolean isA11yFocusAction =
-                                (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS)
-                                || (action ==
-                                        AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
-                        if ((mPictureInPictureActionReplacingConnection != null)
-                                && !isA11yFocusAction) {
-                            connection = mPictureInPictureActionReplacingConnection.mConnection;
-                        }
+                }
+                connection = getConnectionLocked(resolvedWindowId);
+                if (connection == null) return false;
+                final boolean isA11yFocusAction = (action == ACTION_ACCESSIBILITY_FOCUS)
+                        || (action == ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+                final AccessibilityWindowInfo a11yWindowInfo =
+                        mSecurityPolicy.findA11yWindowInfoById(resolvedWindowId);
+                if (!isA11yFocusAction) {
+                    final WindowInfo windowInfo =
+                            mSecurityPolicy.findWindowInfoById(resolvedWindowId);
+                    if (windowInfo != null) activityToken = windowInfo.activityToken;
+                }
+                if ((a11yWindowInfo != null) && a11yWindowInfo.inPictureInPicture()) {
+                    if ((mPictureInPictureActionReplacingConnection != null)
+                            && !isA11yFocusAction) {
+                        connection = mPictureInPictureActionReplacingConnection.mConnection;
                     }
                 }
             }
@@ -3368,6 +3370,10 @@
                 mPowerManager.userActivity(SystemClock.uptimeMillis(),
                         PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
 
+                if (activityToken != null) {
+                    LocalServices.getService(ActivityManagerInternal.class)
+                            .setFocusedActivity(activityToken);
+                }
                 connection.performAccessibilityAction(accessibilityNodeId, action, arguments,
                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid);
             } catch (RemoteException re) {
@@ -4072,7 +4078,8 @@
                 IAccessibilityInteractionConnectionCallback originalCallback,
                 int resolvedWindowId, int interactionId, int interrogatingPid,
                 long interrogatingTid) {
-            AccessibilityWindowInfo windowInfo = mSecurityPolicy.findWindowById(resolvedWindowId);
+            AccessibilityWindowInfo windowInfo =
+                    mSecurityPolicy.findA11yWindowInfoById(resolvedWindowId);
             if ((windowInfo == null) || !windowInfo.inPictureInPicture()
                     || (mPictureInPictureActionReplacingConnection == null)) {
                 return originalCallback;
@@ -4193,24 +4200,12 @@
         @Override
         public void onWindowsForAccessibilityChanged(List<WindowInfo> windows) {
             synchronized (mLock) {
-                // Populate the windows to report.
-                List<AccessibilityWindowInfo> reportedWindows = new ArrayList<>();
-                final int receivedWindowCount = windows.size();
-                for (int i = 0; i < receivedWindowCount; i++) {
-                    WindowInfo receivedWindow = windows.get(i);
-                    AccessibilityWindowInfo reportedWindow = populateReportedWindow(
-                            receivedWindow);
-                    if (reportedWindow != null) {
-                        reportedWindows.add(reportedWindow);
-                    }
-                }
-
                 if (DEBUG) {
-                    Slog.i(LOG_TAG, "Windows changed: " + reportedWindows);
+                    Slog.i(LOG_TAG, "Windows changed: " + windows);
                 }
 
                 // Let the policy update the focused and active windows.
-                mSecurityPolicy.updateWindowsLocked(reportedWindows);
+                mSecurityPolicy.updateWindowsLocked(windows);
 
                 // Someone may be waiting for the windows - advertise it.
                 mLock.notifyAll();
@@ -4432,7 +4427,8 @@
 
         // In Z order
         public List<AccessibilityWindowInfo> mWindows;
-        public SparseArray<AccessibilityWindowInfo> mWindowsById = new SparseArray<>();
+        public SparseArray<AccessibilityWindowInfo> mA11yWindowInfoById = new SparseArray<>();
+        public SparseArray<WindowInfo> mWindowInfoById = new SparseArray<>();
 
         public int mActiveWindowId = INVALID_WINDOW_ID;
         public int mFocusedWindowId = INVALID_WINDOW_ID;
@@ -4476,14 +4472,14 @@
         }
 
         public void clearWindowsLocked() {
-            List<AccessibilityWindowInfo> windows = Collections.emptyList();
+            List<WindowInfo> windows = Collections.emptyList();
             final int activeWindowId = mActiveWindowId;
             updateWindowsLocked(windows);
             mActiveWindowId = activeWindowId;
             mWindows = null;
         }
 
-        public void updateWindowsLocked(List<AccessibilityWindowInfo> windows) {
+        public void updateWindowsLocked(List<WindowInfo> windows) {
             if (mWindows == null) {
                 mWindows = new ArrayList<>();
             }
@@ -4492,7 +4488,12 @@
             for (int i = oldWindowCount - 1; i >= 0; i--) {
                 mWindows.remove(i).recycle();
             }
-            mWindowsById.clear();
+            mA11yWindowInfoById.clear();
+
+            for (int i = 0; i < mWindowInfoById.size(); i++) {
+                mWindowInfoById.valueAt(i).recycle();
+            }
+            mWindowInfoById.clear();
 
             mFocusedWindowId = INVALID_WINDOW_ID;
             if (!mTouchInteractionInProgress) {
@@ -4509,19 +4510,25 @@
             final int windowCount = windows.size();
             if (windowCount > 0) {
                 for (int i = 0; i < windowCount; i++) {
-                    AccessibilityWindowInfo window = windows.get(i);
-                    final int windowId = window.getId();
-                    if (window.isFocused()) {
-                        mFocusedWindowId = windowId;
-                        if (!mTouchInteractionInProgress) {
-                            mActiveWindowId = windowId;
-                            window.setActive(true);
-                        } else if (windowId == mActiveWindowId) {
-                            activeWindowGone = false;
+                    WindowInfo windowInfo = windows.get(i);
+                    AccessibilityWindowInfo window = (mWindowsForAccessibilityCallback != null)
+                            ? mWindowsForAccessibilityCallback.populateReportedWindow(windowInfo)
+                            : null;
+                    if (window != null) {
+                        final int windowId = window.getId();
+                        if (window.isFocused()) {
+                            mFocusedWindowId = windowId;
+                            if (!mTouchInteractionInProgress) {
+                                mActiveWindowId = windowId;
+                                window.setActive(true);
+                            } else if (windowId == mActiveWindowId) {
+                                activeWindowGone = false;
+                            }
                         }
+                        mWindows.add(window);
+                        mA11yWindowInfoById.put(windowId, window);
+                        mWindowInfoById.put(windowId, WindowInfo.obtain(windowInfo));
                     }
-                    mWindows.add(window);
-                    mWindowsById.put(windowId, window);
                 }
 
                 if (mTouchInteractionInProgress && activeWindowGone) {
@@ -4530,7 +4537,8 @@
 
                 // Focused window may change the active one, so set the
                 // active window once we decided which it is.
-                for (int i = 0; i < windowCount; i++) {
+                final int accessibilityWindowCount = mWindows.size();
+                for (int i = 0; i < accessibilityWindowCount; i++) {
                     AccessibilityWindowInfo window = mWindows.get(i);
                     if (window.getId() == mActiveWindowId) {
                         window.setActive(true);
@@ -4833,11 +4841,15 @@
             if (windowId == mActiveWindowId) {
                 return true;
             }
-            return findWindowById(windowId) != null;
+            return findA11yWindowInfoById(windowId) != null;
         }
 
-        private AccessibilityWindowInfo findWindowById(int windowId) {
-            return mWindowsById.get(windowId);
+        private AccessibilityWindowInfo findA11yWindowInfoById(int windowId) {
+            return mA11yWindowInfoById.get(windowId);
+        }
+
+        private WindowInfo findWindowInfoById(int windowId) {
+            return mWindowInfoById.get(windowId);
         }
 
         private AccessibilityWindowInfo getPictureInPictureWindow() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 45387bd..d9f3454 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -24101,6 +24101,21 @@
                 mLastANRState = null;
             }
         }
+
+        @Override
+        public void setFocusedActivity(IBinder token) {
+            synchronized (ActivityManagerService.this) {
+                final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+                if (r == null) {
+                    throw new IllegalArgumentException(
+                            "setFocusedActivity: No activity record matching token=" + token);
+                }
+                if (mStackSupervisor.moveFocusableActivityStackToFrontLocked(
+                        r, "setFocusedActivity")) {
+                    mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                }
+            }
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index da739ac..02edd93 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3972,6 +3972,9 @@
         windowInfo.type = mAttrs.type;
         windowInfo.layer = mLayer;
         windowInfo.token = mClient.asBinder();
+        if (mAppToken != null) {
+            windowInfo.activityToken = mAppToken.appToken.asBinder();
+        }
         windowInfo.title = mAttrs.accessibilityTitle;
         windowInfo.accessibilityIdOfAnchor = mAttrs.accessibilityIdOfAnchor;
         windowInfo.focused = isFocused();