Merge "Remove invisible home task view as soon as gesture to Recents ends" into ub-launcher3-master
diff --git a/quickstep/src/com/android/launcher3/model/WellbeingModel.java b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
index 810f4e3..f92b3e3 100644
--- a/quickstep/src/com/android/launcher3/model/WellbeingModel.java
+++ b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
@@ -63,7 +63,6 @@
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.function.Consumer;
 
 /**
  * Data model for digital wellbeing status of apps.
@@ -222,9 +221,8 @@
             reloadLauncherInNormalMode(context);
             return;
         }
-        runWithMinimalDeviceConfigs((bundle) -> {
-            if (bundle.getInt(EXTRA_MINIMAL_DEVICE_STATE, UNKNOWN_MINIMAL_DEVICE_STATE)
-                    == IN_MINIMAL_DEVICE) {
+        mWorkerHandler.post(() -> {
+            if (isInMinimalDeviceMode()) {
                 reloadLauncherInMinimalMode(context);
             } else {
                 reloadLauncherInNormalMode(context);
@@ -253,31 +251,30 @@
                 .authority(mWellbeingProviderPkg + ".api");
     }
 
-    /**
-     * Fetch most up-to-date minimal device config.
-     */
     @WorkerThread
-    private void runWithMinimalDeviceConfigs(Consumer<Bundle> consumer) {
+    private boolean isInMinimalDeviceMode() {
         if (!FeatureFlags.ENABLE_MINIMAL_DEVICE.get()) {
-            return;
+            return false;
         }
         if (DEBUG || mIsInTest) {
-            Log.d(TAG, "runWithMinimalDeviceConfigs() called");
+            Log.d(TAG, "isInMinimalDeviceMode() called");
         }
         Preconditions.assertNonUiThread();
 
         final Uri contentUri = apiBuilder().build();
-        final Bundle remoteBundle;
         try (ContentProviderClient client = mContext.getContentResolver()
                 .acquireUnstableContentProviderClient(contentUri)) {
-            remoteBundle = client.call(
+            final Bundle remoteBundle = client == null ? null : client.call(
                     METHOD_GET_MINIMAL_DEVICE_CONFIG, null /* args */, null /* extras */);
-            consumer.accept(remoteBundle);
+            return remoteBundle != null
+                    && remoteBundle.getInt(EXTRA_MINIMAL_DEVICE_STATE,
+                    UNKNOWN_MINIMAL_DEVICE_STATE) == IN_MINIMAL_DEVICE;
         } catch (Exception e) {
             Log.e(TAG, "Failed to retrieve data from " + contentUri + ": " + e);
             if (mIsInTest) throw new RuntimeException(e);
         }
-        if (DEBUG || mIsInTest) Log.i(TAG, "runWithMinimalDeviceConfigs(): finished");
+        if (DEBUG || mIsInTest) Log.i(TAG, "isInMinimalDeviceMode(): finished");
+        return false;
     }
 
     private boolean updateActions(String... packageNames) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index 656d59e..d47eba6 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -246,7 +246,7 @@
         setScaleX(taskView.getScaleX());
         setScaleY(taskView.getScaleY());
         boolean canActivityRotate = taskView.getRecentsView()
-            .mOrientationState.canRecentsActivityRotate();
+            .mOrientationState.isRecentsActivityRotationAllowed();
         mOptionLayout.setOrientation(orientationHandler
                 .getTaskMenuLayoutOrientation(canActivityRotate, mOptionLayout));
         setPosition(sTempRect.left - insets.left, sTempRect.top - insets.top,
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index ecd4e2b..c5863c1 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -201,6 +201,12 @@
     @PortraitLandscape
     public void testOverviewActions() throws Exception {
         if (mLauncher.getNavigationModel() != NavigationModel.TWO_BUTTON) {
+            // Experimenting for b/165029151:
+            final Overview overview = mLauncher.pressHome().switchToOverview();
+            if (overview.hasTasks()) overview.dismissAllTasks();
+            mLauncher.pressHome();
+            //
+
             startTestAppsWithCheck();
             OverviewActions actionsView =
                     mLauncher.pressHome().switchToOverview().getOverviewActions();
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 90566f3..1cf2e89 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
+import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO;
 import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
 
 import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
@@ -70,6 +71,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.database.sqlite.SQLiteDatabase;
+import android.graphics.Bitmap;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.CancellationSignal;
@@ -88,9 +90,10 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.OvershootInterpolator;
+import android.widget.ImageView;
 import android.widget.Toast;
 
 import androidx.annotation.CallSuper;
@@ -117,6 +120,7 @@
 import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.folder.FolderGridOrganizer;
 import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.icons.BitmapRenderer;
 import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.keyboard.CustomActionsPopup;
 import com.android.launcher3.keyboard.ViewGroupFocusHelper;
@@ -269,6 +273,8 @@
     private static final int APPS_VIEW_ALPHA_CHANNEL_INDEX = 1;
     private static final int SCRIM_VIEW_ALPHA_CHANNEL_INDEX = 0;
 
+    private static final int THEME_CROSS_FADE_ANIMATION_DURATION = 375;
+
     private LauncherAppTransitionManager mAppTransitionManager;
     private Configuration mOldConfig;
 
@@ -400,6 +406,7 @@
 
         inflateRootView(R.layout.launcher);
         setupViews();
+        crossFadeWithPreviousAppearance();
         mPopupDataProvider = new PopupDataProvider(this::updateNotificationDots);
 
         mAppTransitionManager = LauncherAppTransitionManager.newInstance(this);
@@ -476,7 +483,7 @@
                 () -> getStateManager().goToState(NORMAL));
 
         if (Utilities.ATLEAST_R) {
-            getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
+            getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
         }
 
         mLifecycleRegistry = new LifecycleRegistry(this);
@@ -1364,6 +1371,18 @@
         closeContextMenu();
     }
 
+    @Override
+    public Object onRetainNonConfigurationInstance() {
+        int width = mDragLayer.getWidth();
+        int height = mDragLayer.getHeight();
+
+        if (width <= 0 || height <= 0) {
+            return null;
+        }
+
+        return BitmapRenderer.createHardwareBitmap(width, height, mDragLayer::draw);
+    }
+
     public AllAppsTransitionController getAllAppsController() {
         return mAllAppsController;
     }
@@ -2758,4 +2777,40 @@
 
         void onLauncherResume();
     }
+
+    /**
+     * Cross-fades the launcher's updated appearance with its previous appearance.
+     *
+     * This method is used to cross-fade UI updates on activity creation, specifically dark mode
+     * updates.
+     */
+    private void crossFadeWithPreviousAppearance() {
+        Bitmap previousAppearanceBitmap = (Bitmap) getLastNonConfigurationInstance();
+
+        if (previousAppearanceBitmap == null) {
+            return;
+        }
+
+        ImageView crossFadeHelper = new ImageView(this);
+
+        crossFadeHelper.setImageBitmap(previousAppearanceBitmap);
+        crossFadeHelper.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+
+        InsettableFrameLayout.LayoutParams layoutParams = new InsettableFrameLayout.LayoutParams(
+                InsettableFrameLayout.LayoutParams.MATCH_PARENT,
+                InsettableFrameLayout.LayoutParams.MATCH_PARENT);
+
+        layoutParams.ignoreInsets = true;
+
+        crossFadeHelper.setLayoutParams(layoutParams);
+
+        getRootView().addView(crossFadeHelper);
+
+        crossFadeHelper
+                .animate()
+                .setDuration(THEME_CROSS_FADE_ANIMATION_DURATION)
+                .alpha(0f)
+                .withEndAction(() -> getRootView().removeView(crossFadeHelper))
+                .start();
+    }
 }
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 2627149..4175280 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -177,8 +177,8 @@
             "SEPARATE_RECENTS_ACTIVITY", false,
             "Uses a separate recents activity instead of using the integrated recents+Launcher UI");
 
-    public static final BooleanFlag ENABLE_MINIMAL_DEVICE = new DeviceFlag(
-            "ENABLE_MINIMAL_DEVICE", false,
+    public static final BooleanFlag ENABLE_MINIMAL_DEVICE = getDebugFlag(
+            "ENABLE_MINIMAL_DEVICE", true,
             "Allow user to toggle minimal device mode in launcher.");
 
     public static void initialize(Context context) {
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index c841b7b..281598a 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -58,6 +58,7 @@
 import android.widget.TextView;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 
 import com.android.launcher3.AbstractFloatingView;
@@ -216,6 +217,8 @@
 
     private StatsLogManager mStatsLogManager;
 
+    @Nullable private FolderWindowInsetsAnimationCallback mFolderWindowInsetsAnimationCallback;
+
     /**
      * Used to inflate the Workspace from XML.
      *
@@ -262,10 +265,10 @@
         mFooterHeight = mFooter.getMeasuredHeight();
 
         if (Utilities.ATLEAST_R) {
-            WindowInsetsAnimation.Callback cb = new FolderWindowInsetsAnimationCallback(
-                    DISPATCH_MODE_STOP, this);
+            mFolderWindowInsetsAnimationCallback =
+                    new FolderWindowInsetsAnimationCallback(DISPATCH_MODE_STOP, this);
 
-            setWindowInsetsAnimationCallback(cb);
+            setWindowInsetsAnimationCallback(mFolderWindowInsetsAnimationCallback);
         }
     }
 
@@ -755,11 +758,17 @@
         a.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(Animator animation) {
+                if (Utilities.ATLEAST_R) {
+                    setWindowInsetsAnimationCallback(null);
+                }
                 mIsAnimatingClosed = true;
             }
 
             @Override
             public void onAnimationEnd(Animator animation) {
+                if (Utilities.ATLEAST_R && mFolderWindowInsetsAnimationCallback != null) {
+                    setWindowInsetsAnimationCallback(mFolderWindowInsetsAnimationCallback);
+                }
                 closeComplete(true);
                 announceAccessibilityChanges();
                 mIsAnimatingClosed = false;
diff --git a/src/com/android/launcher3/pm/UserCache.java b/src/com/android/launcher3/pm/UserCache.java
index 2d7d6b0..5aab41a 100644
--- a/src/com/android/launcher3/pm/UserCache.java
+++ b/src/com/android/launcher3/pm/UserCache.java
@@ -21,10 +21,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.ArrayMap;
-import android.util.Log;
 import android.util.LongSparseArray;
 
-import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.SafeCloseable;
 import com.android.launcher3.util.SimpleBroadcastReceiver;
@@ -104,9 +102,6 @@
                 mUsers = null;
                 mUserToSerialMap = null;
             }
-            if (TestProtocol.sDebugTracing) {
-                Log.d(TestProtocol.WORK_PROFILE_REMOVED, "Work profile removed", new Exception());
-            }
         }
     }
 
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index b2d0081..7f76355 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -106,5 +106,4 @@
     public static final String PAUSE_NOT_DETECTED = "b/139891609";
     public static final String OVERIEW_NOT_ALLAPPS = "b/156095088";
     public static final String NO_SWIPE_TO_HOME = "b/158017601";
-    public static final String WORK_PROFILE_REMOVED = "b/159671700";
 }
diff --git a/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java b/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java
index 437cf3c..48369a4 100644
--- a/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java
+++ b/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.plugins;
 
+import android.app.Activity;
+import android.view.View;
+
 import com.android.systemui.plugins.annotations.ProvidesInterface;
 import com.android.systemui.plugins.shared.SearchTarget;
 import com.android.systemui.plugins.shared.SearchTargetEvent;
@@ -29,22 +32,26 @@
 @ProvidesInterface(action = AllAppsSearchPlugin.ACTION, version = AllAppsSearchPlugin.VERSION)
 public interface AllAppsSearchPlugin extends Plugin {
     String ACTION = "com.android.systemui.action.PLUGIN_ALL_APPS_SEARCH_ACTIONS";
-    int VERSION = 5;
+    int VERSION = 6;
 
+    void setup(Activity activity, View view);
 
     /**
-     * Send signal when user enters all apps.
+     * Send launcher state related signals.
      */
-    void startAllAppsSession();
+    void onStateTransitionStart(int fromState, int toState);
+    void onStateTransitionComplete(int state);
 
     /**
-     * Send signal when user starts typing.
+     * Send launcher window focus and visibility changed signals.
+     */
+    void onWindowFocusChanged(boolean hasFocus);
+    void onWindowVisibilityChanged(int visibility);
+
+    /**
+     * Send signal when user starts typing, perform search, when search ends
      */
     void startedSearchSession();
-
-    /**
-     * Send over the query and get the search results.
-     */
     void performSearch(String query, Consumer<List<SearchTarget>> results);
 
     /**
@@ -53,7 +60,8 @@
     void notifySearchTargetEvent(SearchTargetEvent event);
 
     /**
-     * Send signal when user exits all apps.
+     * Launcher activity lifecycle callbacks
      */
-    void endAllAppsSession();
+    void onResume(int state);
+    void onStop(int state);
 }
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/ui/WorkTabTest.java b/tests/src/com/android/launcher3/ui/WorkTabTest.java
index f5f93c4..e51c1ca 100644
--- a/tests/src/com/android/launcher3/ui/WorkTabTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkTabTest.java
@@ -24,7 +24,6 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.util.Log;
 import android.widget.TextView;
 
 import androidx.test.filters.LargeTest;
@@ -35,7 +34,6 @@
 import com.android.launcher3.allapps.AllAppsPagedView;
 import com.android.launcher3.allapps.WorkModeSwitch;
 import com.android.launcher3.dragndrop.DragLayer;
-import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.views.WorkEduView;
 
 import org.junit.After;
@@ -135,9 +133,6 @@
             workEduView.findViewById(R.id.proceed).callOnClick();
         });
 
-        executeOnLauncher(launcher -> Log.d(TestProtocol.WORK_PROFILE_REMOVED,
-                "Work profile status: " + launcher.getAppsView().isPersonalTabVisible()));
-
         // verify work edu is seen next
         waitForLauncherCondition("Launcher did not show the next edu screen", l ->
                 ((AllAppsPagedView) l.getAppsView().getContentView()).getCurrentPage() == WORK_PAGE