From 2a528a43c1e1cee250c274f41dc8a8c6745b3d5d Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 1 Oct 2021 11:31:45 -0700 Subject: [PATCH] Delaying taskbar loading until user setup completed > Also keeping it stashed while all-set activity is visible > Creating a shared state (simiar to saved instance state) for taskbar > Keeping taskbar stashed while all-set activity is visible Bug: 194786060 Bug: 201782272 Test: Manual Change-Id: Iab5e082243a206772266aece62d3028f5acb6400 --- .../launcher3/BaseQuickstepLauncher.java | 89 ++----------- .../taskbar/LauncherTaskbarUIController.java | 5 - .../taskbar/NavbarButtonsViewController.java | 42 +++--- .../taskbar/TaskbarActivityContext.java | 25 +++- .../launcher3/taskbar/TaskbarControllers.java | 6 +- .../launcher3/taskbar/TaskbarManager.java | 19 ++- .../launcher3/taskbar/TaskbarSharedState.java | 27 ++++ .../taskbar/TaskbarStashController.java | 29 ++-- .../taskbar/TaskbarViewController.java | 5 +- .../RecentsAnimationDeviceState.java | 9 -- .../quickstep/TouchInteractionService.java | 17 --- .../quickstep/interaction/AllSetActivity.java | 33 +++++ .../android/quickstep/util/TISBindHelper.java | 124 ++++++++++++++++++ 13 files changed, 259 insertions(+), 171 deletions(-) create mode 100644 quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java create mode 100644 quickstep/src/com/android/quickstep/util/TISBindHelper.java diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java index 088009a857..216e79bf42 100644 --- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java @@ -31,19 +31,14 @@ import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SY import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.app.ActivityOptions; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentSender; -import android.content.ServiceConnection; import android.graphics.Insets; import android.hardware.SensorManager; import android.hardware.devicestate.DeviceStateManager; import android.os.Bundle; import android.os.CancellationSignal; -import android.os.Handler; -import android.os.IBinder; -import android.util.Log; import android.view.View; import android.view.WindowInsets; import android.window.SplashScreen; @@ -76,13 +71,13 @@ import com.android.quickstep.SysUINavigationMode.Mode; import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.TaskUtils; -import com.android.quickstep.TouchInteractionService; import com.android.quickstep.TouchInteractionService.TISBinder; import com.android.quickstep.util.LauncherUnfoldAnimationController; import com.android.quickstep.util.ProxyScreenStatusProvider; import com.android.quickstep.util.RemoteAnimationProvider; import com.android.quickstep.util.RemoteFadeOutAnimationListener; import com.android.quickstep.util.SplitSelectStateController; +import com.android.quickstep.util.TISBindHelper; import com.android.quickstep.views.OverviewActionsView; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.system.ActivityManagerWrapper; @@ -103,11 +98,6 @@ import java.util.stream.Stream; public abstract class BaseQuickstepLauncher extends Launcher implements NavigationModeChangeListener { - private static final long BACKOFF_MILLIS = 1000; - - // Max backoff caps at 5 mins - private static final long MAX_BACKOFF_MILLIS = 10 * 60 * 1000; - private DepthController mDepthController = new DepthController(this); private QuickstepTransitionManager mAppTransitionManager; @@ -120,45 +110,12 @@ public abstract class BaseQuickstepLauncher extends Launcher private OverviewActionsView mActionsView; + private TISBindHelper mTISBindHelper; private @Nullable TaskbarManager mTaskbarManager; private @Nullable OverviewCommandHelper mOverviewCommandHelper; private @Nullable LauncherTaskbarUIController mTaskbarUIController; - private final ServiceConnection mTisBinderConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName componentName, IBinder iBinder) { - if (!(iBinder instanceof TISBinder)) { - // Seems like there can be a race condition when user unlocks, which kills the TIS - // process and re-starts it. I guess in the meantime service can be connected to - // a killed TIS? Either way, unbind and try to re-connect in that case. - internalUnbindToTIS(); - mHandler.postDelayed(mConnectionRunnable, BACKOFF_MILLIS); - return; - } - mTaskbarManager = ((TISBinder) iBinder).getTaskbarManager(); - mTaskbarManager.setLauncher(BaseQuickstepLauncher.this); - - Log.d(TAG, "TIS service connected"); - resetServiceBindRetryState(); - - mOverviewCommandHelper = ((TISBinder) iBinder).getOverviewCommandHelper(); - } - - @Override - public void onServiceDisconnected(ComponentName componentName) { } - - @Override - public void onBindingDied(ComponentName name) { - Log.w(TAG, "TIS binding died"); - internalBindToTIS(); - } - }; - - private final Runnable mConnectionRunnable = this::internalBindToTIS; - private short mConnectionAttempts; private final TaskbarStateHandler mTaskbarStateHandler = new TaskbarStateHandler(this); - private final Handler mHandler = new Handler(); - private boolean mTisServiceBound; // Will be updated when dragging from taskbar. private @Nullable DragOptions mNextWorkspaceDragOptions = null; @@ -201,11 +158,10 @@ public abstract class BaseQuickstepLauncher extends Launcher SysUINavigationMode.INSTANCE.get(this).removeModeChangeListener(this); - internalUnbindToTIS(); + mTISBindHelper.onDestroy(); if (mTaskbarManager != null) { mTaskbarManager.clearLauncher(this); } - resetServiceBindRetryState(); if (mLauncherUnfoldAnimationController != null) { mLauncherUnfoldAnimationController.onDestroy(); @@ -357,42 +313,13 @@ public abstract class BaseQuickstepLauncher extends Launcher mAppTransitionManager.registerRemoteAnimations(); mAppTransitionManager.registerRemoteTransitions(); - internalBindToTIS(); + mTISBindHelper = new TISBindHelper(this, this::onTISConnected); } - /** - * Binds {@link #mTisBinderConnection} to {@link TouchInteractionService}. If the binding fails, - * attempts to retry via {@link #mConnectionRunnable}. - * Unbind via {@link #internalUnbindToTIS()} - */ - private void internalBindToTIS() { - mTisServiceBound = bindService(new Intent(this, TouchInteractionService.class), - mTisBinderConnection, 0); - if (mTisServiceBound) { - resetServiceBindRetryState(); - return; - } - - Log.w(TAG, "Retrying TIS Binder connection attempt: " + mConnectionAttempts); - final long timeoutMs = (long) Math.min( - Math.scalb(BACKOFF_MILLIS, mConnectionAttempts), MAX_BACKOFF_MILLIS); - mHandler.postDelayed(mConnectionRunnable, timeoutMs); - mConnectionAttempts++; - } - - /** See {@link #internalBindToTIS()} */ - private void internalUnbindToTIS() { - if (mTisServiceBound) { - unbindService(mTisBinderConnection); - mTisServiceBound = false; - } - } - - private void resetServiceBindRetryState() { - if (mHandler.hasCallbacks(mConnectionRunnable)) { - mHandler.removeCallbacks(mConnectionRunnable); - } - mConnectionAttempts = 0; + private void onTISConnected(TISBinder binder) { + mTaskbarManager = binder.getTaskbarManager(); + mTaskbarManager.setLauncher(BaseQuickstepLauncher.this); + mOverviewCommandHelper = binder.getOverviewCommandHelper(); } private void initUnfoldTransitionProgressProvider() { diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 9d10e1e0a9..71a93d1f99 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -19,7 +19,6 @@ import static com.android.launcher3.LauncherState.HOTSEAT_ICONS; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP; import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE; -import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_IN_APP_SETUP; import static com.android.launcher3.taskbar.TaskbarStashController.TASKBAR_STASH_DURATION; import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME; @@ -255,10 +254,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController { TaskbarStashController stashController = mControllers.taskbarStashController; stashController.updateStateForFlag(FLAG_IN_APP, !isResumed); - if (isResumed) { - // Launcher is resumed, meaning setup must be finished. - stashController.updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, false); - } stashController.applyState(duration); } diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java index f2ca711a12..b768d60306 100644 --- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java @@ -41,7 +41,6 @@ import android.graphics.Rect; import android.graphics.Region; import android.graphics.Region.Op; import android.graphics.drawable.AnimatedVectorDrawable; -import android.provider.Settings; import android.util.Property; import android.view.Gravity; import android.view.View; @@ -59,7 +58,6 @@ import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton; import com.android.launcher3.taskbar.contextual.RotationButton; import com.android.launcher3.taskbar.contextual.RotationButtonController; import com.android.launcher3.util.MultiValueAlpha; -import com.android.launcher3.util.SettingsCache; import com.android.launcher3.util.Themes; import com.android.quickstep.AnimatedFloat; @@ -118,9 +116,10 @@ public class NavbarButtonsViewController { /** * Initializes the controller */ - public void init(TaskbarControllers controllers) { + public void init(TaskbarControllers controllers, TaskbarSharedState sharedState) { mControllers = controllers; mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarSize; + parseSystemUiFlags(sharedState.sysuiStateFlags); mA11yLongClickListener = view -> { mControllers.navButtonController.onButtonClick(BUTTON_A11Y_LONG_CLICK); @@ -151,8 +150,7 @@ public class NavbarButtonsViewController { flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0, AnimatedFloat.VALUE, 1, 0)); // Force nav buttons (specifically back button) to be visible during setup wizard. - boolean isInSetup = !SettingsCache.INSTANCE.get(mContext).getValue( - Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 0); + boolean isInSetup = !mContext.isUserSetupComplete(); if (isThreeButtonNav || isInSetup) { initButtons(mNavButtonContainer, mEndContextualContainer, mControllers.navButtonController); @@ -252,23 +250,14 @@ public class NavbarButtonsViewController { mA11yButton.setOnLongClickListener(mA11yLongClickListener); } - public void updateStateForSysuiFlags(int systemUiStateFlags, boolean forceUpdate) { - boolean isImeVisible = (systemUiStateFlags & SYSUI_STATE_IME_SHOWING) != 0; - boolean isImeSwitcherShowing = (systemUiStateFlags & SYSUI_STATE_IME_SWITCHER_SHOWING) != 0; - boolean a11yVisible = (systemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; - boolean a11yLongClickable = - (systemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0; - boolean isHomeDisabled = - (systemUiStateFlags & SYSUI_STATE_HOME_DISABLED) != 0; - boolean isRecentsDisabled = - (systemUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0; - boolean isBackDisabled = - (systemUiStateFlags & SYSUI_STATE_BACK_DISABLED) != 0; - - if (!forceUpdate && systemUiStateFlags == mSysuiStateFlags) { - return; - } - mSysuiStateFlags = systemUiStateFlags; + private void parseSystemUiFlags(int sysUiStateFlags) { + mSysuiStateFlags = sysUiStateFlags; + boolean isImeVisible = (sysUiStateFlags & SYSUI_STATE_IME_SHOWING) != 0; + boolean isImeSwitcherShowing = (sysUiStateFlags & SYSUI_STATE_IME_SWITCHER_SHOWING) != 0; + boolean a11yVisible = (sysUiStateFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; + boolean isHomeDisabled = (sysUiStateFlags & SYSUI_STATE_HOME_DISABLED) != 0; + boolean isRecentsDisabled = (sysUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0; + boolean isBackDisabled = (sysUiStateFlags & SYSUI_STATE_BACK_DISABLED) != 0; // TODO(b/202218289) we're getting IME as not visible on lockscreen from system updateStateForFlag(FLAG_IME_VISIBLE, isImeVisible); @@ -280,8 +269,17 @@ public class NavbarButtonsViewController { if (mA11yButton != null) { // Only used in 3 button + boolean a11yLongClickable = + (sysUiStateFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0; mA11yButton.setLongClickable(a11yLongClickable); } + } + + public void updateStateForSysuiFlags(int systemUiStateFlags) { + if (systemUiStateFlags == mSysuiStateFlags) { + return; + } + parseSystemUiFlags(systemUiStateFlags); applyState(); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 973c52b0b0..f1d7d41fba 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -35,6 +35,7 @@ import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.Process; import android.os.SystemProperties; +import android.provider.Settings; import android.util.Log; import android.view.ContextThemeWrapper; import android.view.Display; @@ -61,6 +62,7 @@ import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.taskbar.contextual.RotationButtonController; import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.util.PackageManagerHelper; +import com.android.launcher3.util.SettingsCache; import com.android.launcher3.util.Themes; import com.android.launcher3.util.TraceHelper; import com.android.launcher3.util.ViewCache; @@ -102,6 +104,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ private final ViewCache mViewCache = new ViewCache(); private final boolean mIsSafeModeEnabled; + private final boolean mIsUserSetupComplete; private boolean mIsDestroyed = false; public TaskbarActivityContext(Context windowContext, DeviceProfile dp, @@ -113,6 +116,8 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ mNavMode = SysUINavigationMode.getMode(windowContext); mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode", () -> getPackageManager().isSafeMode()); + mIsUserSetupComplete = SettingsCache.INSTANCE.get(this).getValue( + Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 0); float taskbarIconSize = getResources().getDimension(R.dimen.taskbar_icon_size); mDeviceProfile.updateIconSize(1, getResources()); @@ -155,7 +160,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ new TaskbarEduController(this)); } - public void init() { + public void init(TaskbarSharedState sharedState) { mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight(); mWindowLayoutParams = new WindowManager.LayoutParams( MATCH_PARENT, @@ -184,7 +189,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ getDefaultTaskbarWindowHeight() - mDeviceProfile.taskbarSize, 0, 0); // Initialize controllers after all are constructed. - mControllers.init(); + mControllers.init(sharedState); mWindowManager.addView(mDragLayer, mWindowLayoutParams); } @@ -302,6 +307,13 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ mControllers.uiController.init(mControllers); } + /** + * Sets the flag indicating setup UI is visible + */ + public void setSetupUIVisible(boolean isVisible) { + mControllers.taskbarStashController.setSetupUIVisible(isVisible); + } + /** * Called when this instance of taskbar is no longer needed */ @@ -312,9 +324,8 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ mWindowManager.removeViewImmediate(mDragLayer); } - public void updateSysuiStateFlags(int systemUiStateFlags, boolean forceUpdate) { - mControllers.navbarButtonsViewController.updateStateForSysuiFlags( - systemUiStateFlags, forceUpdate); + public void updateSysuiStateFlags(int systemUiStateFlags) { + mControllers.navbarButtonsViewController.updateStateForSysuiFlags(systemUiStateFlags); mControllers.taskbarViewController.setImeIsVisible( mControllers.navbarButtonsViewController.isImeVisible()); boolean panelExpanded = (systemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0; @@ -467,4 +478,8 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ public void startTaskbarUnstashHint(boolean animateForward) { mControllers.taskbarStashController.startUnstashHint(animateForward); } + + protected boolean isUserSetupComplete() { + return mIsUserSetupComplete; + } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java index e13f849278..8684c2925c 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java @@ -74,8 +74,8 @@ public class TaskbarControllers { * TaskbarControllers instance, but should be careful to only access things that were created * in constructors for now, as some controllers may still be waiting for init(). */ - public void init() { - navbarButtonsViewController.init(this); + public void init(TaskbarSharedState sharedState) { + navbarButtonsViewController.init(this, sharedState); if (taskbarActivityContext.isThreeButtonNav()) { rotationButtonController.init(); } @@ -85,7 +85,7 @@ public class TaskbarControllers { taskbarUnfoldAnimationController.init(this); taskbarKeyguardController.init(navbarButtonsViewController); stashedHandleViewController.init(this); - taskbarStashController.init(this); + taskbarStashController.init(this, sharedState); taskbarEduController.init(this); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java index 9d88956dcd..63d07f3dc0 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -76,7 +76,7 @@ public class TaskbarManager implements DisplayController.DisplayInfoChangeListen * Cache a copy here so we can initialize state whenever taskbar is recreated, since * this class does not get re-initialized w/ new taskbars. */ - private int mSysuiStateFlags; + private final TaskbarSharedState mSharedState = new TaskbarSharedState(); private static final int CHANGE_FLAGS = CHANGE_ACTIVE_SCREEN | CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS; @@ -192,22 +192,27 @@ public class TaskbarManager implements DisplayController.DisplayInfoChangeListen mTaskbarActivityContext = new TaskbarActivityContext(mContext, dp.copy(mContext), mNavButtonController, mUnfoldProgressProvider); - mTaskbarActivityContext.init(); + mTaskbarActivityContext.init(mSharedState); if (mLauncher != null) { mTaskbarActivityContext.setUIController( new LauncherTaskbarUIController(mLauncher, mTaskbarActivityContext)); } - onSysuiFlagsChangedInternal(mSysuiStateFlags, true /* forceUpdate */); } public void onSystemUiFlagsChanged(int systemUiStateFlags) { - onSysuiFlagsChangedInternal(systemUiStateFlags, false /* forceUpdate */); + mSharedState.sysuiStateFlags = systemUiStateFlags; + if (mTaskbarActivityContext != null) { + mTaskbarActivityContext.updateSysuiStateFlags(systemUiStateFlags); + } } - private void onSysuiFlagsChangedInternal(int systemUiStateFlags, boolean forceUpdate) { - mSysuiStateFlags = systemUiStateFlags; + /** + * Sets the flag indicating setup UI is visible + */ + public void setSetupUIVisible(boolean isVisible) { + mSharedState.setupUIVisible = isVisible; if (mTaskbarActivityContext != null) { - mTaskbarActivityContext.updateSysuiStateFlags(systemUiStateFlags, forceUpdate); + mTaskbarActivityContext.setSetupUIVisible(isVisible); } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java new file mode 100644 index 0000000000..23beef0a8a --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 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; + +/** + * State shared across different taskbar instance + */ +public class TaskbarSharedState { + + public int sysuiStateFlags; + + public boolean setupUIVisible = false; + +} diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index 7a892240e0..0dd4ef19b3 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -25,21 +25,15 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.annotation.Nullable; -import android.app.ActivityManager; -import android.content.ComponentName; import android.content.SharedPreferences; import android.content.res.Resources; -import android.provider.Settings; import android.view.ViewConfiguration; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; -import com.android.launcher3.util.SettingsCache; import com.android.quickstep.AnimatedFloat; import com.android.quickstep.SystemUiProxy; -import com.android.quickstep.interaction.AllSetActivity; -import com.android.systemui.shared.system.ActivityManagerWrapper; import java.util.function.IntPredicate; @@ -136,7 +130,7 @@ public class TaskbarStashController { mUnstashedHeight = mActivity.getDeviceProfile().taskbarSize; } - public void init(TaskbarControllers controllers) { + public void init(TaskbarControllers controllers, TaskbarSharedState sharedState) { mControllers = controllers; TaskbarDragLayerController dragLayerController = controllers.taskbarDragLayerController; @@ -157,7 +151,8 @@ public class TaskbarStashController { boolean isManuallyStashedInApp = supportsManualStashing() && mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF); updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp); - updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup()); + updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, + !mActivity.isUserSetupComplete() || sharedState.setupUIVisible); applyState(); SystemUiProxy.INSTANCE.get(mActivity) @@ -186,20 +181,12 @@ public class TaskbarStashController { } /** - * Returns whether we are in Setup Wizard or the corresponding AllSetActivity that follows it. + * Sets the flag indicating setup UI is visible */ - private boolean isInSetup() { - boolean isInSetup = !SettingsCache.INSTANCE.get(mActivity).getValue( - Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 0); - if (isInSetup) { - return true; - } - ActivityManager.RunningTaskInfo runningTask = - ActivityManagerWrapper.getInstance().getRunningTask(); - if (runningTask == null || runningTask.baseActivity == null) { - return false; - } - return runningTask.baseActivity.equals(new ComponentName(mActivity, AllSetActivity.class)); + protected void setSetupUIVisible(boolean isVisible) { + updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, + isVisible || !mActivity.isUserSetupComplete()); + applyState(); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index ff04799c92..d14622b2b3 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -88,7 +88,10 @@ public class TaskbarViewController { mTaskbarIconScaleForStash.updateValue(1f); mModelCallbacks.init(controllers); - LauncherAppState.getInstance(mActivity).getModel().addCallbacksAndLoad(mModelCallbacks); + if (mActivity.isUserSetupComplete()) { + // Only load the callbacks if user setup is completed + LauncherAppState.getInstance(mActivity).getModel().addCallbacksAndLoad(mModelCallbacks); + } mTaskbarNavButtonTranslationY = controllers.navbarButtonsViewController.getTaskbarNavButtonTranslationY(); } diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java index 8a9bf7c826..e2441edee6 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java @@ -84,7 +84,6 @@ import com.android.systemui.shared.system.TaskStackChangeListeners; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; /** * Manages the state of the system during a swipe up gesture. @@ -397,14 +396,6 @@ public class RecentsAnimationDeviceState implements && mGestureBlockedActivities.contains(runningTaskInfo.topActivity); } - /** - * @return the packages of gesture-blocked activities. - */ - public List getGestureBlockedActivityPackages() { - return mGestureBlockedActivities.stream().map(ComponentName::getPackageName) - .collect(Collectors.toList()); - } - /** * Updates the system ui state flags from SystemUI. */ diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 46b228ed30..4844f6b54a 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -66,7 +66,6 @@ import androidx.annotation.BinderThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; -import androidx.annotation.WorkerThread; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.R; @@ -972,22 +971,6 @@ public class TouchInteractionService extends Service mInputConsumer); } - protected boolean shouldNotifyBackGesture() { - return mBackGestureNotificationCounter > 0 && - !mDeviceState.getGestureBlockedActivityPackages().isEmpty(); - } - - @WorkerThread - protected void tryNotifyBackGesture() { - if (shouldNotifyBackGesture()) { - mBackGestureNotificationCounter--; - Utilities.getDevicePrefs(this).edit() - .putInt(KEY_BACK_NOTIFICATION_COUNT, mBackGestureNotificationCounter).apply(); - mDeviceState.getGestureBlockedActivityPackages().forEach(blockedPackage -> - sendBroadcast(new Intent(NOTIFY_ACTION_BACK).setPackage(blockedPackage))); - } - } - @Override public void writeToProto(LauncherTraceProto.Builder proto) { TouchInteractionServiceProto.Builder serviceProto = diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java index 4472bdcf73..f731cb3a7b 100644 --- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java +++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java @@ -32,6 +32,8 @@ import androidx.annotation.Nullable; import com.android.launcher3.R; import com.android.launcher3.Utilities; +import com.android.quickstep.TouchInteractionService.TISBinder; +import com.android.quickstep.util.TISBindHelper; import java.net.URISyntaxException; @@ -47,6 +49,9 @@ public class AllSetActivity extends Activity { private static final String EXTRA_ACCENT_COLOR_DARK_MODE = "suwColorAccentDark"; private static final String EXTRA_ACCENT_COLOR_LIGHT_MODE = "suwColorAccentLight"; + private TISBindHelper mTISBindHelper; + private TISBinder mBinder; + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -73,6 +78,34 @@ public class AllSetActivity extends Activity { }); findViewById(R.id.hint).setAccessibilityDelegate(new SkipButtonAccessibilityDelegate()); + mTISBindHelper = new TISBindHelper(this, this::onTISConnected); + } + + @Override + protected void onResume() { + super.onResume(); + if (mBinder != null) { + mBinder.getTaskbarManager().setSetupUIVisible(true); + } + } + + private void onTISConnected(TISBinder binder) { + mBinder = binder; + mBinder.getTaskbarManager().setSetupUIVisible(isResumed()); + } + + @Override + protected void onPause() { + super.onPause(); + if (mBinder != null) { + mBinder.getTaskbarManager().setSetupUIVisible(false); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mTISBindHelper.onDestroy(); } /** diff --git a/quickstep/src/com/android/quickstep/util/TISBindHelper.java b/quickstep/src/com/android/quickstep/util/TISBindHelper.java new file mode 100644 index 0000000000..92c60c84b5 --- /dev/null +++ b/quickstep/src/com/android/quickstep/util/TISBindHelper.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2021 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.quickstep.util; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Handler; +import android.os.IBinder; +import android.util.Log; + +import com.android.quickstep.TouchInteractionService; +import com.android.quickstep.TouchInteractionService.TISBinder; + +import java.util.function.Consumer; + +/** + * Utility class to simplify binding to {@link TouchInteractionService} + */ +public class TISBindHelper implements ServiceConnection { + + private static final String TAG = "TISBindHelper"; + + private static final long BACKOFF_MILLIS = 1000; + + // Max backoff caps at 5 mins + private static final long MAX_BACKOFF_MILLIS = 10 * 60 * 1000; + + private final Handler mHandler = new Handler(); + private final Runnable mConnectionRunnable = this::internalBindToTIS; + private final Context mContext; + private final Consumer mConnectionCallback; + + private short mConnectionAttempts; + private boolean mTisServiceBound; + + public TISBindHelper(Context context, Consumer connectionCallback) { + mContext = context; + mConnectionCallback = connectionCallback; + internalBindToTIS(); + } + + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + if (!(iBinder instanceof TISBinder)) { + // Seems like there can be a race condition when user unlocks, which kills the TIS + // process and re-starts it. I guess in the meantime service can be connected to + // a killed TIS? Either way, unbind and try to re-connect in that case. + internalUnbindToTIS(); + mHandler.postDelayed(mConnectionRunnable, BACKOFF_MILLIS); + return; + } + + Log.d(TAG, "TIS service connected"); + mConnectionCallback.accept((TISBinder) iBinder); + resetServiceBindRetryState(); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { } + + @Override + public void onBindingDied(ComponentName name) { + Log.w(TAG, "TIS binding died"); + internalBindToTIS(); + } + + + /** + * Binds to {@link TouchInteractionService}. If the binding fails, attempts to retry via + * {@link #mConnectionRunnable}. Unbind via {@link #internalUnbindToTIS()} + */ + private void internalBindToTIS() { + mTisServiceBound = mContext.bindService(new Intent(mContext, TouchInteractionService.class), + this, 0); + if (mTisServiceBound) { + resetServiceBindRetryState(); + return; + } + + Log.w(TAG, "Retrying TIS Binder connection attempt: " + mConnectionAttempts); + final long timeoutMs = (long) Math.min( + Math.scalb(BACKOFF_MILLIS, mConnectionAttempts), MAX_BACKOFF_MILLIS); + mHandler.postDelayed(mConnectionRunnable, timeoutMs); + mConnectionAttempts++; + } + + /** See {@link #internalBindToTIS()} */ + private void internalUnbindToTIS() { + if (mTisServiceBound) { + mContext.unbindService(this); + mTisServiceBound = false; + } + } + + private void resetServiceBindRetryState() { + if (mHandler.hasCallbacks(mConnectionRunnable)) { + mHandler.removeCallbacks(mConnectionRunnable); + } + mConnectionAttempts = 0; + } + + /** + * Called when the activity is destroyed to clear the binding + */ + public void onDestroy() { + internalUnbindToTIS(); + resetServiceBindRetryState(); + } +}