mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-17 17:48:20 +00:00
Merge "Refactor the OnUserUnlock code out of RecentsAnimationDeviceState and into its own class." into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
fb602d4db7
@@ -17,7 +17,6 @@ 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;
|
||||
@@ -50,10 +49,8 @@ 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;
|
||||
|
||||
@@ -63,9 +60,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;
|
||||
@@ -109,15 +106,6 @@ 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;
|
||||
@@ -143,14 +131,6 @@ 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
|
||||
@@ -309,25 +289,6 @@ 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
|
||||
*/
|
||||
@@ -335,14 +296,6 @@ 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
|
||||
*/
|
||||
@@ -585,7 +538,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
|
||||
pw.println(" assistantAvailable=" + mAssistantAvailable);
|
||||
pw.println(" assistantDisabled="
|
||||
+ QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags));
|
||||
pw.println(" isUserUnlocked=" + mIsUserUnlocked);
|
||||
pw.println(" isUserUnlocked=" + LockedUserState.get(mContext).isUserUnlocked());
|
||||
pw.println(" isOneHandedModeEnabled=" + mIsOneHandedModeEnabled);
|
||||
pw.println(" isSwipeToNotificationEnabled=" + mIsSwipeToNotificationEnabled);
|
||||
pw.println(" deferredGestureRegion=" + mDeferredGestureRegion.getBounds());
|
||||
|
||||
@@ -87,6 +87,7 @@ 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;
|
||||
@@ -406,8 +407,8 @@ public class TouchInteractionService extends Service
|
||||
mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
|
||||
|
||||
// Call runOnUserUnlocked() before any other callbacks to ensure everything is initialized.
|
||||
mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
|
||||
mDeviceState.runOnUserUnlocked(mTaskbarManager::onUserUnlocked);
|
||||
LockedUserState.get(this).runOnUserUnlocked(this::onUserUnlocked);
|
||||
LockedUserState.get(this).runOnUserUnlocked(mTaskbarManager::onUserUnlocked);
|
||||
mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
|
||||
|
||||
ProtoTracer.INSTANCE.get(this).add(this);
|
||||
@@ -477,7 +478,7 @@ public class TouchInteractionService extends Service
|
||||
}
|
||||
|
||||
private void resetHomeBounceSeenOnQuickstepEnabledFirstTime() {
|
||||
if (!mDeviceState.isUserUnlocked() || mDeviceState.isButtonNavMode()) {
|
||||
if (!LockedUserState.get(this).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;
|
||||
@@ -520,7 +521,7 @@ public class TouchInteractionService extends Service
|
||||
|
||||
@UiThread
|
||||
private void onSystemUiFlagsChanged(int lastSysUIFlags) {
|
||||
if (mDeviceState.isUserUnlocked()) {
|
||||
if (LockedUserState.get(this).isUserUnlocked()) {
|
||||
int systemUiStateFlags = mDeviceState.getSystemUiStateFlags();
|
||||
SystemUiProxy.INSTANCE.get(this).setLastSystemUiStateFlags(systemUiStateFlags);
|
||||
mOverviewComponentObserver.onSystemUiStateChanged();
|
||||
@@ -565,7 +566,7 @@ public class TouchInteractionService extends Service
|
||||
|
||||
@UiThread
|
||||
private void onAssistantVisibilityChanged() {
|
||||
if (mDeviceState.isUserUnlocked()) {
|
||||
if (LockedUserState.get(this).isUserUnlocked()) {
|
||||
mOverviewComponentObserver.getActivityInterface().onAssistantVisibilityChanged(
|
||||
mDeviceState.getAssistantVisibility());
|
||||
}
|
||||
@@ -575,7 +576,7 @@ public class TouchInteractionService extends Service
|
||||
public void onDestroy() {
|
||||
Log.d(TAG, "Touch service destroyed: user=" + getUserId());
|
||||
sIsInitialized = false;
|
||||
if (mDeviceState.isUserUnlocked()) {
|
||||
if (LockedUserState.get(this).isUserUnlocked()) {
|
||||
mInputConsumer.unregisterInputConsumer();
|
||||
mOverviewComponentObserver.onDestroy();
|
||||
}
|
||||
@@ -609,7 +610,7 @@ public class TouchInteractionService extends Service
|
||||
TestLogging.recordMotionEvent(
|
||||
TestProtocol.SEQUENCE_TIS, "TouchInteractionService.onInputEvent", event);
|
||||
|
||||
if (!mDeviceState.isUserUnlocked()) {
|
||||
if (!LockedUserState.get(this).isUserUnlocked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -631,7 +632,8 @@ public class TouchInteractionService extends Service
|
||||
mGestureState = newGestureState;
|
||||
mConsumer = newConsumer(prevGestureState, mGestureState, event);
|
||||
mUncheckedConsumer = mConsumer;
|
||||
} else if (mDeviceState.isUserUnlocked() && mDeviceState.isFullyGesturalNavMode()
|
||||
} else if (LockedUserState.get(this).isUserUnlocked()
|
||||
&& mDeviceState.isFullyGesturalNavMode()
|
||||
&& mDeviceState.canTriggerAssistantAction(event)) {
|
||||
mGestureState = createGestureState(mGestureState);
|
||||
// Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we
|
||||
@@ -751,7 +753,7 @@ public class TouchInteractionService extends Service
|
||||
|
||||
boolean canStartSystemGesture = mDeviceState.canStartSystemGesture();
|
||||
|
||||
if (!mDeviceState.isUserUnlocked()) {
|
||||
if (!LockedUserState.get(this).isUserUnlocked()) {
|
||||
CompoundString reasonString = newCompoundString("device locked");
|
||||
InputConsumer consumer;
|
||||
if (canStartSystemGesture) {
|
||||
@@ -1098,7 +1100,7 @@ public class TouchInteractionService extends Service
|
||||
}
|
||||
|
||||
private void preloadOverview(boolean fromInit, boolean forSUWAllSet) {
|
||||
if (!mDeviceState.isUserUnlocked()) {
|
||||
if (!LockedUserState.get(this).isUserUnlocked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1130,7 +1132,7 @@ public class TouchInteractionService extends Service
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
if (!mDeviceState.isUserUnlocked()) {
|
||||
if (!LockedUserState.get(this).isUserUnlocked()) {
|
||||
return;
|
||||
}
|
||||
final BaseActivityInterface activityInterface =
|
||||
@@ -1171,7 +1173,7 @@ public class TouchInteractionService extends Service
|
||||
} else {
|
||||
// Dump everything
|
||||
FeatureFlags.dump(pw);
|
||||
if (mDeviceState.isUserUnlocked()) {
|
||||
if (LockedUserState.get(this).isUserUnlocked()) {
|
||||
PluginManagerWrapper.INSTANCE.get(getBaseContext()).dump(pw);
|
||||
}
|
||||
mDeviceState.dump(pw);
|
||||
|
||||
57
src/com/android/launcher3/util/LockedUserState.kt
Normal file
57
src/com/android/launcher3/util/LockedUserState.kt
Normal file
@@ -0,0 +1,57 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
88
tests/src/com/android/launcher3/util/LockedUserStateTest.kt
Normal file
88
tests/src/com/android/launcher3/util/LockedUserStateTest.kt
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user