Merge "Revert "Refactor the OnUserUnlock code out of RecentsAnimationDeviceState and"" into tm-qpr-dev am: 8989f839f5

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/21142878

Change-Id: I0b9740a98594304cca9603dc53583655dc6db976
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Stefan Andonian
2023-02-17 23:54:49 +00:00
committed by Automerger Merge Worker
4 changed files with 61 additions and 161 deletions

View File

@@ -17,6 +17,7 @@ package com.android.quickstep;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.content.Intent.ACTION_USER_UNLOCKED;
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
@@ -51,8 +52,10 @@ import android.content.Context;
import android.graphics.Region;
import android.inputmethodservice.InputMethodService;
import android.net.Uri;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserManager;
import android.provider.Settings;
import android.view.MotionEvent;
@@ -62,9 +65,9 @@ import androidx.annotation.NonNull;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.LockedUserState;
import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.SettingsCache;
import com.android.launcher3.util.SimpleBroadcastReceiver;
import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
import com.android.quickstep.util.NavBarPosition;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -108,6 +111,15 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
private final boolean mIsOneHandedModeSupported;
private boolean mPipIsActive;
private boolean mIsUserUnlocked;
private final ArrayList<Runnable> mUserUnlockedActions = new ArrayList<>();
private final SimpleBroadcastReceiver mUserUnlockedReceiver = new SimpleBroadcastReceiver(i -> {
if (ACTION_USER_UNLOCKED.equals(i.getAction())) {
mIsUserUnlocked = true;
notifyUserUnlocked();
}
});
private int mGestureBlockingTaskId = -1;
private @NonNull Region mExclusionRegion = new Region();
private SystemGestureExclusionListenerCompat mExclusionListener;
@@ -133,6 +145,14 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
runOnDestroy(mRotationTouchHelper::destroy);
}
// Register for user unlocked if necessary
mIsUserUnlocked = context.getSystemService(UserManager.class)
.isUserUnlocked(Process.myUserHandle());
if (!mIsUserUnlocked) {
mUserUnlockedReceiver.register(mContext, ACTION_USER_UNLOCKED);
}
runOnDestroy(() -> mUserUnlockedReceiver.unregisterReceiverSafely(mContext));
// Register for exclusion updates
mExclusionListener = new SystemGestureExclusionListenerCompat(mDisplayId) {
@Override
@@ -291,6 +311,25 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
return mDisplayId;
}
/**
* Adds a callback for when a user is unlocked. If the user is already unlocked, this listener
* will be called back immediately.
*/
public void runOnUserUnlocked(Runnable action) {
if (mIsUserUnlocked) {
action.run();
} else {
mUserUnlockedActions.add(action);
}
}
/**
* @return whether the user is unlocked.
*/
public boolean isUserUnlocked() {
return mIsUserUnlocked;
}
/**
* @return whether the user has completed setup wizard
*/
@@ -298,6 +337,14 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
return mIsUserSetupComplete;
}
private void notifyUserUnlocked() {
for (Runnable action : mUserUnlockedActions) {
action.run();
}
mUserUnlockedActions.clear();
mUserUnlockedReceiver.unregisterReceiverSafely(mContext);
}
/**
* Sets the task id where gestures should be blocked
*/
@@ -542,7 +589,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
pw.println(" assistantAvailable=" + mAssistantAvailable);
pw.println(" assistantDisabled="
+ QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags));
pw.println(" isUserUnlocked=" + LockedUserState.get(mContext).isUserUnlocked());
pw.println(" isUserUnlocked=" + mIsUserUnlocked);
pw.println(" isOneHandedModeEnabled=" + mIsOneHandedModeEnabled);
pw.println(" isSwipeToNotificationEnabled=" + mIsSwipeToNotificationEnabled);
pw.println(" deferredGestureRegion=" + mDeferredGestureRegion.getBounds());

View File

@@ -88,7 +88,6 @@ import com.android.launcher3.tracing.LauncherTraceProto;
import com.android.launcher3.tracing.TouchInteractionServiceProto;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.LockedUserState;
import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
@@ -412,8 +411,8 @@ public class TouchInteractionService extends Service
mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
// Call runOnUserUnlocked() before any other callbacks to ensure everything is initialized.
LockedUserState.get(this).runOnUserUnlocked(this::onUserUnlocked);
LockedUserState.get(this).runOnUserUnlocked(mTaskbarManager::onUserUnlocked);
mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
mDeviceState.runOnUserUnlocked(mTaskbarManager::onUserUnlocked);
mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
ProtoTracer.INSTANCE.get(this).add(this);
@@ -483,7 +482,7 @@ public class TouchInteractionService extends Service
}
private void resetHomeBounceSeenOnQuickstepEnabledFirstTime() {
if (!LockedUserState.get(this).isUserUnlocked() || mDeviceState.isButtonNavMode()) {
if (!mDeviceState.isUserUnlocked() || mDeviceState.isButtonNavMode()) {
// Skip if not yet unlocked (can't read user shared prefs) or if the current navigation
// mode doesn't have gestures
return;
@@ -526,7 +525,7 @@ public class TouchInteractionService extends Service
@UiThread
private void onSystemUiFlagsChanged(int lastSysUIFlags) {
if (LockedUserState.get(this).isUserUnlocked()) {
if (mDeviceState.isUserUnlocked()) {
int systemUiStateFlags = mDeviceState.getSystemUiStateFlags();
SystemUiProxy.INSTANCE.get(this).setLastSystemUiStateFlags(systemUiStateFlags);
mOverviewComponentObserver.onSystemUiStateChanged();
@@ -571,7 +570,7 @@ public class TouchInteractionService extends Service
@UiThread
private void onAssistantVisibilityChanged() {
if (LockedUserState.get(this).isUserUnlocked()) {
if (mDeviceState.isUserUnlocked()) {
mOverviewComponentObserver.getActivityInterface().onAssistantVisibilityChanged(
mDeviceState.getAssistantVisibility());
}
@@ -581,7 +580,7 @@ public class TouchInteractionService extends Service
public void onDestroy() {
Log.d(TAG, "Touch service destroyed: user=" + getUserId());
sIsInitialized = false;
if (LockedUserState.get(this).isUserUnlocked()) {
if (mDeviceState.isUserUnlocked()) {
mInputConsumer.unregisterInputConsumer();
mOverviewComponentObserver.onDestroy();
}
@@ -615,7 +614,7 @@ public class TouchInteractionService extends Service
TestLogging.recordMotionEvent(
TestProtocol.SEQUENCE_TIS, "TouchInteractionService.onInputEvent", event);
if (!LockedUserState.get(this).isUserUnlocked()) {
if (!mDeviceState.isUserUnlocked()) {
return;
}
@@ -637,8 +636,7 @@ public class TouchInteractionService extends Service
mGestureState = newGestureState;
mConsumer = newConsumer(prevGestureState, mGestureState, event);
mUncheckedConsumer = mConsumer;
} else if (LockedUserState.get(this).isUserUnlocked()
&& mDeviceState.isFullyGesturalNavMode()
} else if (mDeviceState.isUserUnlocked() && mDeviceState.isFullyGesturalNavMode()
&& mDeviceState.canTriggerAssistantAction(event)) {
mGestureState = createGestureState(mGestureState);
// Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we
@@ -758,7 +756,7 @@ public class TouchInteractionService extends Service
boolean canStartSystemGesture = mDeviceState.canStartSystemGesture();
if (!LockedUserState.get(this).isUserUnlocked()) {
if (!mDeviceState.isUserUnlocked()) {
CompoundString reasonString = newCompoundString("device locked");
InputConsumer consumer;
if (canStartSystemGesture) {
@@ -1105,7 +1103,7 @@ public class TouchInteractionService extends Service
}
private void preloadOverview(boolean fromInit, boolean forSUWAllSet) {
if (!LockedUserState.get(this).isUserUnlocked()) {
if (!mDeviceState.isUserUnlocked()) {
return;
}
@@ -1137,7 +1135,7 @@ public class TouchInteractionService extends Service
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (!LockedUserState.get(this).isUserUnlocked()) {
if (!mDeviceState.isUserUnlocked()) {
return;
}
final BaseActivityInterface activityInterface =
@@ -1178,7 +1176,7 @@ public class TouchInteractionService extends Service
} else {
// Dump everything
FeatureFlags.dump(pw);
if (LockedUserState.get(this).isUserUnlocked()) {
if (mDeviceState.isUserUnlocked()) {
PluginManagerWrapper.INSTANCE.get(getBaseContext()).dump(pw);
}
mDeviceState.dump(pw);

View File

@@ -1,57 +0,0 @@
package com.android.launcher3.util
import android.content.Context
import android.content.Intent
import android.os.Process
import android.os.UserManager
import androidx.annotation.VisibleForTesting
class LockedUserState(private val mContext: Context) : SafeCloseable {
var isUserUnlocked: Boolean
private set
private val mUserUnlockedActions: RunnableList = RunnableList()
@VisibleForTesting
val mUserUnlockedReceiver = SimpleBroadcastReceiver {
if (Intent.ACTION_USER_UNLOCKED == it.action) {
isUserUnlocked = true
notifyUserUnlocked()
}
}
init {
isUserUnlocked =
mContext
.getSystemService(UserManager::class.java)!!
.isUserUnlocked(Process.myUserHandle())
if (isUserUnlocked) {
notifyUserUnlocked()
} else {
mUserUnlockedReceiver.register(mContext, Intent.ACTION_USER_UNLOCKED)
}
}
private fun notifyUserUnlocked() {
mUserUnlockedActions.executeAllAndDestroy()
mUserUnlockedReceiver.unregisterReceiverSafely(mContext)
}
/** Stops the receiver from listening for ACTION_USER_UNLOCK broadcasts. */
override fun close() {
mUserUnlockedReceiver.unregisterReceiverSafely(mContext)
}
/**
* Adds a `Runnable` to be executed when a user is unlocked. If the user is already unlocked,
* this runnable will run immediately because RunnableList will already have been destroyed.
*/
fun runOnUserUnlocked(action: Runnable) {
mUserUnlockedActions.add(action)
}
companion object {
@VisibleForTesting val INSTANCE = MainThreadInitializedObject { LockedUserState(it) }
@JvmStatic fun get(context: Context): LockedUserState = INSTANCE.get(context)
}
}

View File

@@ -1,88 +0,0 @@
/*
* Copyright (C) 2023 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.util
import android.content.Context
import android.content.Intent
import android.os.Process
import android.os.UserManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
/** Unit tests for {@link LockedUserUtil} */
@SmallTest
@RunWith(AndroidJUnit4::class)
class LockedUserStateTest {
@Mock lateinit var userManager: UserManager
@Mock lateinit var context: Context
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
`when`(context.getSystemService(UserManager::class.java)).thenReturn(userManager)
}
@Test
fun runOnUserUnlocked_runs_action_immediately_if_already_unlocked() {
`when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(true)
LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
val action: Runnable = mock()
LockedUserState.get(context).runOnUserUnlocked(action)
verify(action).run()
}
@Test
fun runOnUserUnlocked_waits_to_run_action_until_user_is_unlocked() {
`when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(false)
LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
val action: Runnable = mock()
LockedUserState.get(context).runOnUserUnlocked(action)
verifyZeroInteractions(action)
LockedUserState.get(context)
.mUserUnlockedReceiver
.onReceive(context, Intent(Intent.ACTION_USER_UNLOCKED))
verify(action).run()
}
@Test
fun isUserUnlocked_returns_true_when_user_is_unlocked() {
`when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(true)
LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
assertThat(LockedUserState.get(context).isUserUnlocked).isTrue()
}
@Test
fun isUserUnlocked_returns_false_when_user_is_locked() {
`when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(false)
LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
assertThat(LockedUserState.get(context).isUserUnlocked).isFalse()
}
}