Merge "Delaying taskbar loading until user setup completed" into sc-v2-dev am: bc9dd92220
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/16080048 Change-Id: I4a146f9442c0e2b2e956f4c2d6429e5ec6eb7220
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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<String> getGestureBlockedActivityPackages() {
|
||||
return mGestureBlockedActivities.stream().map(ComponentName::getPackageName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the system ui state flags from SystemUI.
|
||||
*/
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<TISBinder> mConnectionCallback;
|
||||
|
||||
private short mConnectionAttempts;
|
||||
private boolean mTisServiceBound;
|
||||
|
||||
public TISBindHelper(Context context, Consumer<TISBinder> 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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user