Merging from ub-launcher3-master @ build 6150369

Test: manual, presubmit on the source branch
http://x20/teams/android-launcher/merge/ub-launcher3-master_6150369.html

Change-Id: Ia79497c0a9f03cf6ad9e9daa58ed34c02a36e879
diff --git a/CleanSpec.mk b/CleanSpec.mk
index f7bda94..489abd1 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -52,6 +52,7 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Launcher2.apk)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher2_intermediates)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Launcher2.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/Launcher3QuickStep)
 
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/priv-app/Launcher3)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/product/priv-app/Launcher3Go)
diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
index bcdbce5..d0db157 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
@@ -171,8 +171,7 @@
                 long updateTime = c.getLong(indexLastUpdate);
                 int version = c.getInt(indexVersion);
                 T app = componentMap.remove(component);
-                if (version == info.versionCode
-                        && updateTime == cachingLogic.getLastUpdatedTime(app, info)
+                if (version == info.versionCode && updateTime == info.lastUpdateTime
                         && TextUtils.equals(c.getString(systemStateIndex),
                                 mIconCache.getIconSystemState(info.packageName))) {
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 4b5ba95..9b36748 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -47,6 +47,7 @@
 import com.android.launcher3.util.TouchController;
 import com.android.launcher3.util.UiThreadHelper;
 import com.android.launcher3.util.UiThreadHelper.AsyncCommand;
+import com.android.quickstep.RecentsModel;
 import com.android.quickstep.SysUINavigationMode;
 import com.android.quickstep.SysUINavigationMode.Mode;
 import com.android.quickstep.SystemUiProxy;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
index c19754f..8149e64 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
@@ -117,4 +117,5 @@
             mActivity.dispatchKeyEvent(ev);
         }
     }
-}
\ No newline at end of file
+}
+
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index cb20ed0..04405a1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -17,7 +17,6 @@
 package com.android.quickstep.views;
 
 import static androidx.dynamicanimation.animation.DynamicAnimation.MIN_VISIBLE_CHANGE_PIXELS;
-
 import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
 import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS;
 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index ee53386..8eb639b 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -49,6 +49,7 @@
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.util.RemoteFadeOutAnimationListener;
 import com.android.quickstep.util.ShelfPeekAnim;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
 
 import java.util.stream.Stream;
 
@@ -144,6 +145,12 @@
     }
 
     @Override
+    protected void onUiChangedWhileSleeping() {
+        // Remove the snapshot because the content view may have obvious changes.
+        ActivityManagerWrapper.getInstance().invalidateHomeTaskSnapshot(this);
+    }
+
+    @Override
     public void startIntentSenderForResult(IntentSender intent, int requestCode,
             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options) {
         if (requestCode != -1) {
diff --git a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
index 96ac489..0d5d832 100644
--- a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
+++ b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
@@ -147,4 +147,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java b/quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java
new file mode 100644
index 0000000..d8aa235
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java
@@ -0,0 +1,159 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.uioverrides;
+
+import static android.os.IBinder.FLAG_ONEWAY;
+
+import android.os.Binder;
+import android.os.Build;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.util.Log;
+
+import androidx.annotation.MainThread;
+
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.function.BiConsumer;
+import java.util.function.Supplier;
+
+/**
+ * A binder proxy transaction listener for tracking non-whitelisted binder calls.
+ */
+public class DejankBinderTracker implements Binder.ProxyTransactListener {
+    private static final String TAG = "DejankBinderTracker";
+
+    private static final Object sLock = new Object();
+    private static final HashSet<String> sWhitelistedFrameworkClasses = new HashSet<>();
+    static {
+        // Common IPCs that are ok to block the main thread.
+        sWhitelistedFrameworkClasses.add("android.view.IWindowSession");
+        sWhitelistedFrameworkClasses.add("android.os.IPowerManager");
+    }
+    private static boolean sTemporarilyIgnoreTracking = false;
+
+    // Used by the client to limit binder tracking to specific regions
+    private static boolean sTrackingAllowed = false;
+
+    private BiConsumer<String, Integer> mUnexpectedTransactionCallback;
+    private boolean mIsTracking = false;
+
+    /**
+     * Temporarily ignore blocking binder calls for the duration of this {@link Runnable}.
+     */
+    @MainThread
+    public static void whitelistIpcs(Runnable runnable) {
+        sTemporarilyIgnoreTracking = true;
+        runnable.run();
+        sTemporarilyIgnoreTracking = false;
+    }
+
+    /**
+     * Temporarily ignore blocking binder calls for the duration of this {@link Supplier}.
+     */
+    @MainThread
+    public static <T> T whitelistIpcs(Supplier<T> supplier) {
+        sTemporarilyIgnoreTracking = true;
+        T value = supplier.get();
+        sTemporarilyIgnoreTracking = false;
+        return value;
+    }
+
+    /**
+     * Enables binder tracking during a test.
+     */
+    @MainThread
+    public static void allowBinderTrackingInTests() {
+        sTrackingAllowed = true;
+    }
+
+    /**
+     * Disables binder tracking during a test.
+     */
+    @MainThread
+    public static void disallowBinderTrackingInTests() {
+        sTrackingAllowed = false;
+    }
+
+    public DejankBinderTracker(BiConsumer<String, Integer> unexpectedTransactionCallback) {
+        mUnexpectedTransactionCallback = unexpectedTransactionCallback;
+    }
+
+    @MainThread
+    public void startTracking() {
+        if (!Build.TYPE.toLowerCase(Locale.ROOT).contains("debug")
+                && !Build.TYPE.toLowerCase(Locale.ROOT).equals("eng")) {
+            Log.wtf(TAG, "Unexpected use of binder tracker in non-debug build", new Exception());
+            return;
+        }
+        if (mIsTracking) {
+            return;
+        }
+        mIsTracking = true;
+        Binder.setProxyTransactListener(this);
+    }
+
+    @MainThread
+    public void stopTracking() {
+        if (!mIsTracking) {
+            return;
+        }
+        mIsTracking = false;
+        Binder.setProxyTransactListener(null);
+    }
+
+    // Override the hidden Binder#onTransactStarted method
+    public synchronized Object onTransactStarted(IBinder binder, int transactionCode, int flags) {
+        if (!mIsTracking
+                || !sTrackingAllowed
+                || sTemporarilyIgnoreTracking
+                || (flags & FLAG_ONEWAY) == FLAG_ONEWAY
+                || !isMainThread()) {
+            return null;
+        }
+
+        String descriptor;
+        try {
+            descriptor = binder.getInterfaceDescriptor();
+            if (sWhitelistedFrameworkClasses.contains(descriptor)) {
+                return null;
+            }
+        } catch (RemoteException e) {
+            e.printStackTrace();
+            descriptor = binder.getClass().getSimpleName();
+        }
+
+        mUnexpectedTransactionCallback.accept(descriptor, transactionCode);
+        return null;
+    }
+
+    @Override
+    public Object onTransactStarted(IBinder binder, int transactionCode) {
+        // Do nothing
+        return null;
+    }
+
+    @Override
+    public void onTransactEnded(Object session) {
+        // Do nothing
+    }
+
+    public static boolean isMainThread() {
+        return Thread.currentThread() == Looper.getMainLooper().getThread();
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index a466f12..53859ad 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -43,7 +43,7 @@
 import com.android.launcher3.userevent.nano.LauncherLogProto.ItemType;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
 import com.android.launcher3.util.ComponentKey;
-import com.android.systemui.shared.system.StatsLogCompat;
+import com.android.systemui.shared.system.SysUiStatsLog;
 
 import com.google.protobuf.nano.MessageNano;
 
@@ -72,8 +72,8 @@
         if (ext.srcTarget[0] != null) {
             ext.srcTarget[0].item = LauncherTarget.APP_ICON;
         }
-        StatsLogCompat.write(LAUNCH_APP, srcState, BACKGROUND /* dstState */,
-                MessageNano.toByteArray(ext), true);
+        SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_EVENT, LAUNCH_APP, srcState,
+                BACKGROUND /* dstState */, MessageNano.toByteArray(ext), true);
     }
 
     @Override
@@ -82,8 +82,8 @@
         ext.srcTarget = new LauncherTarget[SUPPORTED_TARGET_DEPTH];
         int srcState = OVERVIEW;
         fillInLauncherExtension(v, ext);
-        StatsLogCompat.write(LAUNCH_TASK, srcState, BACKGROUND /* dstState */,
-                MessageNano.toByteArray(ext), true);
+        SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_EVENT, LAUNCH_TASK, srcState,
+                BACKGROUND /* dstState */, MessageNano.toByteArray(ext), true);
     }
 
     @Override
@@ -92,8 +92,8 @@
         ext.srcTarget = new LauncherTarget[SUPPORTED_TARGET_DEPTH];
         int srcState = OVERVIEW;
         fillInLauncherExtension(v, ext);
-        StatsLogCompat.write(DISMISS_TASK, srcState, BACKGROUND /* dstState */,
-                MessageNano.toByteArray(ext), true);
+        SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_EVENT, DISMISS_TASK, srcState,
+                BACKGROUND /* dstState */, MessageNano.toByteArray(ext), true);
     }
 
     @Override
@@ -103,7 +103,7 @@
         int srcState = mStateProvider.getCurrentState();
         fillInLauncherExtensionWithPageId(ext, pageId);
         int launcherAction = isSwipingToLeft ? Launcher.SWIPE_LEFT : Launcher.SWIPE_RIGHT;
-        StatsLogCompat.write(launcherAction, srcState, srcState,
+        SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_EVENT, launcherAction, srcState, srcState,
                 MessageNano.toByteArray(ext), true);
     }
 
diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
index 891bf24..d60fa1e 100644
--- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
+++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
@@ -103,4 +103,4 @@
             mLauncher.getBackground().switchToOverview();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 8066d38..1549f57 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -926,6 +926,9 @@
 
     @Override
     protected void onStop() {
+        final boolean wasActive = isUserActive();
+        final LauncherState origState = getStateManager().getState();
+        final int origDragLayerChildCount = mDragLayer.getChildCount();
         super.onStop();
 
         if (mDeferOverlayCallbacks) {
@@ -943,6 +946,20 @@
 
         // Workaround for b/78520668, explicitly trim memory once UI is hidden
         onTrimMemory(TRIM_MEMORY_UI_HIDDEN);
+
+        if (wasActive) {
+            // The expected condition is that this activity is stopped because the device goes to
+            // sleep and the UI may have noticeable changes.
+            mDragLayer.post(() -> {
+                if ((!getStateManager().isInStableState(origState)
+                        // The drag layer may be animating (e.g. dismissing QSB).
+                        || mDragLayer.getAlpha() < 1
+                        // Maybe an ArrowPopup is closed.
+                        || mDragLayer.getChildCount() != origDragLayerChildCount)) {
+                    onUiChangedWhileSleeping();
+                }
+            });
+        }
     }
 
     @Override
@@ -1337,11 +1354,16 @@
             // Reset AllApps to its initial state only if we are not in the middle of
             // processing a multi-step drop
             if (mPendingRequestArgs == null) {
+                if (!isInState(NORMAL)) {
+                    onUiChangedWhileSleeping();
+                }
                 mStateManager.goToState(NORMAL);
             }
         }
     };
 
+    protected void onUiChangedWhileSleeping() { }
+
     public void updateNotificationDots(Predicate<PackageUserKey> updatedDots) {
         mWorkspace.updateNotificationDots(updatedDots);
         mAppsView.getAppsStore().updateNotificationDots(updatedDots);
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index daf270b..810aff6 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -164,6 +164,15 @@
     }
 
     /**
+     * @return {@code true} if the state matches the current state and there is no active
+     *         transition to different state.
+     */
+    public boolean isInStableState(LauncherState state) {
+        return mState == state && mCurrentStableState == state
+                && (mConfig.mTargetState == null || mConfig.mTargetState == state);
+    }
+
+    /**
      * @see #goToState(LauncherState, boolean, Runnable)
      */
     public void goToState(LauncherState state) {
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 6df8790..a7fbfc6 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -1222,4 +1222,4 @@
                 + ", expected=" + mExpectedEvents
                 + ", actual=" + actual;
     }
-}
\ No newline at end of file
+}