Merge "Dismiss AllApps when scrim is clicked"
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 224c05e..00c58b0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -106,6 +106,10 @@
 
     private static final String NAV_BUTTONS_SEPARATE_WINDOW_TITLE = "Taskbar Nav Buttons";
 
+    public static final int ALPHA_INDEX_IMMERSIVE_MODE = 0;
+    public static final int ALPHA_INDEX_KEYGUARD_OR_DISABLE = 1;
+    private static final int NUM_ALPHA_CHANNELS = 2;
+
     private final ArrayList<StatePropertyHolder> mPropertyHolders = new ArrayList<>();
     private final ArrayList<ImageView> mAllButtons = new ArrayList<>();
     private int mState;
@@ -136,10 +140,13 @@
 
     // Initialized in init.
     private TaskbarControllers mControllers;
+    private boolean mIsImeRenderingNavButtons;
     private View mA11yButton;
     private int mSysuiStateFlags;
     private View mBackButton;
     private View mHomeButton;
+    private MultiValueAlpha mBackButtonAlpha;
+    private MultiValueAlpha mHomeButtonAlpha;
     private FloatingRotationButton mFloatingRotationButton;
 
     // Variables for moving nav buttons to a separate window above IME
@@ -168,20 +175,23 @@
         mNavButtonTranslationYMultiplier.value = 1;
 
         boolean isThreeButtonNav = mContext.isThreeButtonNav();
-        // IME switcher
-        View imeSwitcherButton = addButton(R.drawable.ic_ime_switcher, BUTTON_IME_SWITCH,
-                isThreeButtonNav ? mStartContextualContainer : mEndContextualContainer,
-                mControllers.navButtonController, R.id.ime_switcher);
-        mPropertyHolders.add(new StatePropertyHolder(imeSwitcherButton,
-                flags -> ((flags & MASK_IME_SWITCHER_VISIBLE) == MASK_IME_SWITCHER_VISIBLE)
-                        && ((flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0)));
+        mIsImeRenderingNavButtons =
+                InputMethodService.canImeRenderGesturalNavButtons() && mContext.isGestureNav();
+        if (!mIsImeRenderingNavButtons) {
+            // IME switcher
+            View imeSwitcherButton = addButton(R.drawable.ic_ime_switcher, BUTTON_IME_SWITCH,
+                    isThreeButtonNav ? mStartContextualContainer : mEndContextualContainer,
+                    mControllers.navButtonController, R.id.ime_switcher);
+            mPropertyHolders.add(new StatePropertyHolder(imeSwitcherButton,
+                    flags -> ((flags & MASK_IME_SWITCHER_VISIBLE) == MASK_IME_SWITCHER_VISIBLE)
+                            && ((flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0)));
+        }
 
         mPropertyHolders.add(new StatePropertyHolder(
                 mControllers.taskbarViewController.getTaskbarIconAlpha()
                         .getProperty(ALPHA_INDEX_KEYGUARD),
                 flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0
-                        && (flags & FLAG_SCREEN_PINNING_ACTIVE) == 0,
-                MultiValueAlpha.VALUE, 1, 0));
+                        && (flags & FLAG_SCREEN_PINNING_ACTIVE) == 0));
 
         mPropertyHolders.add(new StatePropertyHolder(mControllers.taskbarDragLayerController
                 .getKeyguardBgTaskbar(),
@@ -314,12 +324,14 @@
             mControllers.rotationButtonController.setRotationButton(mFloatingRotationButton,
                     mRotationButtonListener);
 
-            View imeDownButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
-                    mStartContextualContainer, mControllers.navButtonController, R.id.back);
-            imeDownButton.setRotation(Utilities.isRtl(mContext.getResources()) ? 90 : -90);
-            // Rotate when Ime visible
-            mPropertyHolders.add(new StatePropertyHolder(imeDownButton,
-                    flags -> (flags & FLAG_IME_VISIBLE) != 0));
+            if (!mIsImeRenderingNavButtons) {
+                View imeDownButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
+                        mStartContextualContainer, mControllers.navButtonController, R.id.back);
+                imeDownButton.setRotation(Utilities.isRtl(mContext.getResources()) ? 90 : -90);
+                // Only show when IME is visible.
+                mPropertyHolders.add(new StatePropertyHolder(imeDownButton,
+                        flags -> (flags & FLAG_IME_VISIBLE) != 0));
+            }
         }
 
         applyState();
@@ -347,7 +359,10 @@
 
         mBackButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
                 mNavButtonContainer, mControllers.navButtonController, R.id.back);
-        mPropertyHolders.add(new StatePropertyHolder(mBackButton,
+        mBackButtonAlpha = new MultiValueAlpha(mBackButton, NUM_ALPHA_CHANNELS);
+        mBackButtonAlpha.setUpdateVisibility(true);
+        mPropertyHolders.add(new StatePropertyHolder(
+                mBackButtonAlpha.getProperty(ALPHA_INDEX_KEYGUARD_OR_DISABLE),
                 flags -> {
                     // Show only if not disabled, and if not on the keyguard or otherwise only when
                     // the bouncer or a lockscreen app is showing above the keyguard
@@ -373,7 +388,11 @@
         // home and recents buttons
         mHomeButton = addButton(R.drawable.ic_sysbar_home, BUTTON_HOME, navContainer,
                 navButtonController, R.id.home);
-        mPropertyHolders.add(new StatePropertyHolder(mHomeButton,
+        mHomeButtonAlpha = new MultiValueAlpha(mHomeButton, NUM_ALPHA_CHANNELS);
+        mHomeButtonAlpha.setUpdateVisibility(true);
+        mPropertyHolders.add(
+                new StatePropertyHolder(mHomeButtonAlpha.getProperty(
+                        ALPHA_INDEX_KEYGUARD_OR_DISABLE),
                 flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 &&
                         (flags & FLAG_DISABLE_HOME) == 0));
         View recentsButton = addButton(R.drawable.ic_sysbar_recent, BUTTON_RECENTS,
@@ -486,6 +505,20 @@
         }
     }
 
+    /**
+     * Returns multi-value alpha controller for back button.
+     */
+    public MultiValueAlpha getBackButtonAlpha() {
+        return mBackButtonAlpha;
+    }
+
+    /**
+     * Returns multi-value alpha controller for home button.
+     */
+    public MultiValueAlpha getHomeButtonAlpha() {
+        return mHomeButtonAlpha;
+    }
+
     /** Use to set the translationY for the all nav+contextual buttons */
     public AnimatedFloat getTaskbarNavButtonTranslationY() {
         return mTaskbarNavButtonTranslationY;
@@ -592,7 +625,7 @@
             return;
         }
 
-        if (InputMethodService.canImeRenderGesturalNavButtons() && mContext.isGestureNav()) {
+        if (mIsImeRenderingNavButtons) {
             // IME is rendering the nav buttons, so we don't need to create a new layer for them.
             return;
         }
@@ -778,6 +811,11 @@
             mAnimator.addListener(new AlphaUpdateListener(view));
         }
 
+        StatePropertyHolder(MultiValueAlpha.AlphaProperty alphaProperty,
+                IntPredicate enableCondition) {
+            this(alphaProperty, enableCondition, MultiValueAlpha.VALUE, 1, 0);
+        }
+
         <T> StatePropertyHolder(T target, IntPredicate enabledCondition,
                 Property<T, Float> property, float enabledValue, float disabledValue) {
             mEnableCondition = enabledCondition;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index e37bd21..6a59bc2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -188,7 +188,8 @@
                 new TaskbarStashController(this),
                 new TaskbarEduController(this),
                 new TaskbarAutohideSuspendController(this),
-                new TaskbarPopupController(this));
+                new TaskbarPopupController(this),
+                new TaskbarForceVisibleImmersiveController(this));
     }
 
     public void init(TaskbarSharedState sharedState) {
@@ -417,6 +418,7 @@
         mControllers.taskbarScrimViewController.updateStateForSysuiFlags(systemUiStateFlags,
                 fromInit);
         mControllers.navButtonController.updateSysuiFlags(systemUiStateFlags);
+        mControllers.taskbarForceVisibleImmersiveController.updateSysuiFlags(systemUiStateFlags);
     }
 
     /**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index f491669..8364137 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -47,6 +47,7 @@
     public final TaskbarEduController taskbarEduController;
     public final TaskbarAutohideSuspendController taskbarAutohideSuspendController;
     public final TaskbarPopupController taskbarPopupController;
+    public final TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController;
 
     @Nullable private LoggableTaskbarController[] mControllersToLog = null;
 
@@ -70,7 +71,8 @@
             TaskbarStashController taskbarStashController,
             TaskbarEduController taskbarEduController,
             TaskbarAutohideSuspendController taskbarAutoHideSuspendController,
-            TaskbarPopupController taskbarPopupController) {
+            TaskbarPopupController taskbarPopupController,
+            TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController) {
         this.taskbarActivityContext = taskbarActivityContext;
         this.taskbarDragController = taskbarDragController;
         this.navButtonController = navButtonController;
@@ -86,6 +88,7 @@
         this.taskbarEduController = taskbarEduController;
         this.taskbarAutohideSuspendController = taskbarAutoHideSuspendController;
         this.taskbarPopupController = taskbarPopupController;
+        this.taskbarForceVisibleImmersiveController = taskbarForceVisibleImmersiveController;
     }
 
     /**
@@ -108,6 +111,7 @@
         taskbarStashController.init(this, sharedState);
         taskbarEduController.init(this);
         taskbarPopupController.init(this);
+        taskbarForceVisibleImmersiveController.init(this);
 
         mControllersToLog = new LoggableTaskbarController[] {
                 taskbarDragController, navButtonController, navbarButtonsViewController,
@@ -142,6 +146,7 @@
         stashedHandleViewController.onDestroy();
         taskbarAutohideSuspendController.onDestroy();
         taskbarPopupController.onDestroy();
+        taskbarForceVisibleImmersiveController.onDestroy();
 
         mControllersToLog = null;
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index df004ef..4a80665 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -34,7 +34,6 @@
 import com.android.launcher3.R;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.TestProtocol;
-import com.android.launcher3.util.TouchController;
 import com.android.launcher3.views.BaseDragLayer;
 import com.android.systemui.shared.system.ViewTreeObserverWrapper;
 import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo;
@@ -105,7 +104,7 @@
 
     @Override
     public void recreateControllers() {
-        mControllers = new TouchController[] {mActivity.getDragController()};
+        mControllers = mControllerCallbacks.getTouchControllers();
     }
 
     private void onComputeTaskbarInsets(InsetsInfo insetsInfo) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index fa40992..1bd76b9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -26,6 +26,7 @@
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.R;
 import com.android.launcher3.anim.AlphaUpdateListener;
+import com.android.launcher3.util.TouchController;
 import com.android.quickstep.AnimatedFloat;
 import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo;
 
@@ -181,7 +182,8 @@
                 // Let touches pass through us.
                 insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
             } else if (mControllers.taskbarViewController.areIconsVisible()
-                    || AbstractFloatingView.getOpenView(mActivity, TYPE_ALL) != null) {
+                    || AbstractFloatingView.getOpenView(mActivity, TYPE_ALL) != null
+                    || mActivity.isNavBarKidsModeActive()) {
                 // Taskbar has some touchable elements, take over the full taskbar area
                 insetsInfo.setTouchableInsets(mActivity.isTaskbarWindowFullscreen()
                         ? TOUCHABLE_INSETS_FRAME : TOUCHABLE_INSETS_CONTENT);
@@ -217,5 +219,13 @@
         public int getTaskbarBackgroundHeight() {
             return mActivity.getDeviceProfile().taskbarSize;
         }
+
+        /**
+         * Returns touch controllers.
+         */
+        public TouchController[] getTouchControllers() {
+            return new TouchController[]{mActivity.getDragController(),
+                    mControllers.taskbarForceVisibleImmersiveController};
+        }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarForceVisibleImmersiveController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarForceVisibleImmersiveController.java
new file mode 100644
index 0000000..66a927f
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarForceVisibleImmersiveController.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2022 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.taskbar;
+
+import static com.android.launcher3.taskbar.NavbarButtonsViewController.ALPHA_INDEX_IMMERSIVE_MODE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IMMERSIVE_MODE;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.view.MotionEvent;
+
+import com.android.launcher3.util.MultiValueAlpha;
+import com.android.launcher3.util.TouchController;
+import com.android.quickstep.AnimatedFloat;
+
+import java.util.Optional;
+import java.util.function.Consumer;
+
+/**
+ * Controller for taskbar when force visible in immersive mode is set.
+ */
+public class TaskbarForceVisibleImmersiveController implements TouchController {
+    private static final int NAV_BAR_ICONS_DIM_ANIMATION_START_DELAY_MS = 4500;
+    private static final int NAV_BAR_ICONS_DIM_ANIMATION_DURATION_MS = 500;
+    private static final int NAV_BAR_ICONS_UNDIM_ANIMATION_DURATION_MS = 250;
+    private static final float NAV_BAR_ICONS_DIM_PCT = 0.15f;
+    private static final float NAV_BAR_ICONS_UNDIM_PCT = 1f;
+
+    private final TaskbarActivityContext mContext;
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+    private final Runnable mDimmingRunnable = this::dimIcons;
+    private final Runnable mUndimmingRunnable = this::undimIcons;
+    private final AnimatedFloat mIconAlphaForDimming = new AnimatedFloat(
+            this::updateIconDimmingAlpha);
+    private final Consumer<MultiValueAlpha> mImmersiveModeAlphaUpdater = alpha -> alpha.getProperty(
+            ALPHA_INDEX_IMMERSIVE_MODE).setValue(mIconAlphaForDimming.value);
+
+    // Initialized in init.
+    private TaskbarControllers mControllers;
+    private boolean mIsImmersiveMode;
+
+    public TaskbarForceVisibleImmersiveController(TaskbarActivityContext context) {
+        mContext = context;
+    }
+
+    /**
+     * Initialize controllers.
+     */
+    public void init(TaskbarControllers controllers) {
+        mControllers = controllers;
+    }
+
+    /** Update values tracked via sysui flags. */
+    public void updateSysuiFlags(int sysuiFlags) {
+        mIsImmersiveMode = (sysuiFlags & SYSUI_STATE_IMMERSIVE_MODE) != 0;
+        if (mContext.isNavBarKidsModeActive()) {
+            if (mIsImmersiveMode) {
+                startIconDimming();
+            } else {
+                startIconUndimming();
+            }
+        }
+    }
+
+    /** Clean up animations. */
+    public void onDestroy() {
+        startIconUndimming();
+    }
+
+    private void startIconUndimming() {
+        mHandler.removeCallbacks(mDimmingRunnable);
+        mHandler.removeCallbacks(mUndimmingRunnable);
+        mHandler.post(mUndimmingRunnable);
+    }
+
+    private void undimIcons() {
+        mIconAlphaForDimming.animateToValue(NAV_BAR_ICONS_UNDIM_PCT).setDuration(
+                NAV_BAR_ICONS_UNDIM_ANIMATION_DURATION_MS).start();
+    }
+
+    private void startIconDimming() {
+        mHandler.removeCallbacks(mDimmingRunnable);
+        mHandler.postDelayed(mDimmingRunnable, NAV_BAR_ICONS_DIM_ANIMATION_START_DELAY_MS);
+    }
+
+    private void dimIcons() {
+        mIconAlphaForDimming.animateToValue(NAV_BAR_ICONS_DIM_PCT).setDuration(
+                NAV_BAR_ICONS_DIM_ANIMATION_DURATION_MS).start();
+    }
+
+    /**
+     * Returns whether the taskbar is always visible in immersive mode.
+     */
+    private boolean isNavbarShownInImmersiveMode() {
+        return mIsImmersiveMode && mContext.isNavBarKidsModeActive();
+    }
+
+    private void updateIconDimmingAlpha() {
+        getBackButtonAlphaOptional().ifPresent(mImmersiveModeAlphaUpdater);
+        getHomeButtonAlphaOptional().ifPresent(mImmersiveModeAlphaUpdater);
+    }
+
+    private Optional<MultiValueAlpha> getBackButtonAlphaOptional() {
+        if (mControllers == null || mControllers.navbarButtonsViewController == null) {
+            return Optional.empty();
+        }
+        return Optional.ofNullable(mControllers.navbarButtonsViewController.getBackButtonAlpha());
+    }
+
+    private Optional<MultiValueAlpha> getHomeButtonAlphaOptional() {
+        if (mControllers == null || mControllers.navbarButtonsViewController == null) {
+            return Optional.empty();
+        }
+        return Optional.ofNullable(mControllers.navbarButtonsViewController.getHomeButtonAlpha());
+    }
+
+    @Override
+    public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+        if (!isNavbarShownInImmersiveMode()
+                || mControllers.taskbarStashController.supportsManualStashing()) {
+            return false;
+        }
+        return onControllerTouchEvent(ev);
+    }
+
+    @Override
+    public boolean onControllerTouchEvent(MotionEvent ev) {
+        switch (ev.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                startIconUndimming();
+                break;
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                startIconDimming();
+                break;
+        }
+        return false;
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 748557b..014e172 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -197,7 +197,7 @@
     /**
      * Returns whether the user can manually stash the taskbar based on the current device state.
      */
-    private boolean supportsManualStashing() {
+    protected boolean supportsManualStashing() {
         return supportsVisualStashing()
                 && (!Utilities.IS_RUNNING_IN_TEST_HARNESS || supportsStashingForTests());
     }
diff --git a/quickstep/src/com/android/quickstep/AnimatedFloat.java b/quickstep/src/com/android/quickstep/AnimatedFloat.java
index 6a7d066..6c7a885 100644
--- a/quickstep/src/com/android/quickstep/AnimatedFloat.java
+++ b/quickstep/src/com/android/quickstep/AnimatedFloat.java
@@ -98,6 +98,15 @@
         }
     }
 
+    /**
+     * Starts the animation.
+     */
+    public void startAnimation() {
+        if (mValueAnimator != null) {
+            mValueAnimator.start();
+        }
+    }
+
     public void cancelAnimation() {
         if (mValueAnimator != null) {
             mValueAnimator.cancel();
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 54ff6a0..4d79202 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -103,6 +103,9 @@
     private final RotationTouchHelper mRotationTouchHelper;
     private final TaskStackChangeListener mPipListener;
     private final List<ComponentName> mGestureBlockedActivities;
+    // Cache for better performance since it doesn't change at runtime.
+    private final boolean mCanImeRenderGesturalNavButtons =
+            InputMethodService.canImeRenderGesturalNavButtons();
 
     private final ArrayList<Runnable> mOnDestroyActions = new ArrayList<>();
 
@@ -596,7 +599,7 @@
 
     /** Returns whether IME is rendering nav buttons, and IME is currently showing. */
     public boolean isImeRenderingNavButtons() {
-        return InputMethodService.canImeRenderGesturalNavButtons() && mMode == NO_BUTTON
+        return mCanImeRenderGesturalNavButtons && mMode == NO_BUTTON
                 && ((mSystemUiStateFlags & SYSUI_STATE_IME_SHOWING) != 0);
     }
 
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 5d41741..041bee9 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -37,6 +37,7 @@
 import android.graphics.drawable.Drawable;
 import android.icu.text.MessageFormat;
 import android.text.TextPaint;
+import android.text.TextUtils;
 import android.text.TextUtils.TruncateAt;
 import android.util.AttributeSet;
 import android.util.Property;
@@ -805,7 +806,7 @@
                     invalidate();
                 }
             }
-            if (itemInfo.contentDescription != null) {
+            if (!TextUtils.isEmpty(itemInfo.contentDescription)) {
                 if (itemInfo.isDisabled()) {
                     setContentDescription(getContext().getString(R.string.disabled_app_label,
                             itemInfo.contentDescription));
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 225460d..cbc21eb 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -458,9 +458,10 @@
      * Trims the string, removing all whitespace at the beginning and end of the string.
      * Non-breaking whitespaces are also removed.
      */
+    @NonNull
     public static String trim(CharSequence s) {
         if (s == null) {
-            return null;
+            return "";
         }
 
         // Just strip any sequence of whitespace or java space characters from the beginning and end
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index cd168a2..d8f65c5 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -99,7 +99,7 @@
             "ENABLE_TWOLINE_ALLAPPS", false, "Enables two line label inside all apps.");
 
     public static final BooleanFlag ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING = new DeviceFlag(
-            "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", true,
+            "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", false,
             "Allows on device search in all apps logging");
 
     public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(
@@ -135,12 +135,12 @@
 
     public static final BooleanFlag ENABLE_BULK_WORKSPACE_ICON_LOADING = getDebugFlag(
             "ENABLE_BULK_WORKSPACE_ICON_LOADING",
-            true,
+            false,
             "Enable loading workspace icons in bulk.");
 
     public static final BooleanFlag ENABLE_BULK_ALL_APPS_ICON_LOADING = getDebugFlag(
             "ENABLE_BULK_ALL_APPS_ICON_LOADING",
-            true,
+            false,
             "Enable loading all apps icons in bulk.");
 
     // Keep as DeviceFlag for remote disable in emergency.
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index 739a64a..ae5b66a 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -202,8 +202,7 @@
      * Returns the title or empty string
      */
     private String getTitle() {
-        String title = getString(titleIndex);
-        return TextUtils.isEmpty(title) ? "" : Utilities.trim(title);
+        return Utilities.trim(getString(titleIndex));
     }
 
     /**
diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
index 4740097..2c9785c 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
@@ -33,7 +33,6 @@
 import com.android.launcher3.testcomponent.WidgetConfigActivity;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
 import com.android.launcher3.ui.TestViewHelpers;
-import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 import com.android.launcher3.util.rule.ShellCommandRule;
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
 
@@ -73,7 +72,6 @@
 
     @Test
     @PortraitLandscape
-    @ScreenRecord // b/215672979
     public void testConfigCancelled() throws Throwable {
         runTest(false);
     }