Merge changes from topic "mpietal_users" into main
* changes:
Fix user switching race condition on boot
Reset keyguard/bouncer on sim NOT_READY
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 02e8cd6..7974f92 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1313,6 +1313,16 @@
}
flag {
+ name: "sim_pin_bouncer_reset"
+ namespace: "systemui"
+ description: "The SIM PIN bouncer does not close after unlocking"
+ bug: "297461589"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "use_transitions_for_keyguard_occluded"
namespace: "systemui"
description: "Use Keyguard Transitions to set Notification Shade occlusion state"
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java b/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java
index a5b62b6..b16c683 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java
@@ -28,5 +28,4 @@
* be used temporarily for debugging.
*/
public static final boolean DEBUG = Log.isLoggable("Keyguard", Log.DEBUG);
- public static final boolean DEBUG_SIM_STATES = true;
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
index 1c1acf8..52c93f7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
@@ -53,7 +53,6 @@
extends KeyguardPinBasedInputViewController<KeyguardSimPinView> {
public static final String TAG = "KeyguardSimPinView";
private static final String LOG_TAG = "KeyguardSimPinView";
- private static final boolean DEBUG = KeyguardConstants.DEBUG_SIM_STATES;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final TelephonyManager mTelephonyManager;
@@ -71,7 +70,7 @@
KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() {
@Override
public void onSimStateChanged(int subId, int slotId, int simState) {
- if (DEBUG) Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")");
+ Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")");
// If subId has gone to PUK required then we need to go to the PUK screen.
if (subId == mSubId && simState == TelephonyManager.SIM_STATE_PUK_REQUIRED) {
getKeyguardSecurityCallback().showCurrentSecurityScreen();
@@ -129,7 +128,7 @@
@Override
void resetState() {
super.resetState();
- if (DEBUG) Log.v(TAG, "Resetting state");
+ Log.v(TAG, "Resetting state");
handleSubInfoChangeIfNeeded();
mMessageAreaController.setMessage("");
if (mShowDefaultMessage) {
@@ -216,11 +215,9 @@
mMessageAreaController.setMessage(mView.getResources().getString(
R.string.kg_password_pin_failed));
}
- if (DEBUG) {
- Log.d(LOG_TAG, "verifyPasswordAndUnlock "
- + " CheckSimPin.onSimCheckResponse: " + result
- + " attemptsRemaining=" + result.getAttemptsRemaining());
- }
+ Log.d(LOG_TAG, "verifyPasswordAndUnlock "
+ + " CheckSimPin.onSimCheckResponse: " + result
+ + " attemptsRemaining=" + result.getAttemptsRemaining());
}
getKeyguardSecurityCallback().userActivity();
mCheckSimPinThread = null;
@@ -280,10 +277,8 @@
displayMessage = mView.getResources()
.getString(R.string.kg_sim_lock_esim_instructions, displayMessage);
}
- if (DEBUG) {
- Log.d(LOG_TAG, "getPinPasswordErrorMessage: attemptsRemaining="
- + attemptsRemaining + " displayMessage=" + displayMessage);
- }
+ Log.d(LOG_TAG, "getPinPasswordErrorMessage: attemptsRemaining="
+ + attemptsRemaining + " displayMessage=" + displayMessage);
return displayMessage;
}
@@ -323,14 +318,10 @@
@Override
public void run() {
- if (DEBUG) {
- Log.v(TAG, "call supplyIccLockPin(subid=" + mSubId + ")");
- }
+ Log.v(TAG, "call supplyIccLockPin(subid=" + mSubId + ")");
TelephonyManager telephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
final PinResult result = telephonyManager.supplyIccLockPin(mPin);
- if (DEBUG) {
- Log.v(TAG, "supplyIccLockPin returned: " + result.toString());
- }
+ Log.v(TAG, "supplyIccLockPin returned: " + result.toString());
mView.post(() -> onSimCheckResponse(result));
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f731186..22130f8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -43,6 +43,7 @@
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+import static com.android.systemui.Flags.simPinBouncerReset;
import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_OPENED;
import android.annotation.AnyThread;
@@ -1703,6 +1704,9 @@
intent.getStringExtra(Intent.EXTRA_SIM_STATE),
args.slotId,
args.subId);
+ if (args.slotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ return;
+ }
mHandler.obtainMessage(MSG_SIM_STATE_CHANGE, args.subId, args.slotId, args.simState)
.sendToTarget();
} else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
@@ -1940,7 +1944,13 @@
}
int state = TelephonyManager.SIM_STATE_UNKNOWN;
String stateExtra = intent.getStringExtra(Intent.EXTRA_SIM_STATE);
- int slotId = intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 0);
+
+ int defaultSlotId = 0;
+ if (simPinBouncerReset()) {
+ defaultSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+ }
+ int slotId = intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX,
+ defaultSlotId);
int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
if (Intent.SIM_STATE_ABSENT.equals(stateExtra)) {
@@ -2479,6 +2489,12 @@
this::onTransitionStateChanged
);
}
+
+ // start() can be invoked in the middle of user switching, so check for this state and issue
+ // the call manually as that important event was missed.
+ if (mUserTracker.isUserSwitching()) {
+ handleUserSwitching(mUserTracker.getUserId(), () -> {});
+ }
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt b/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
index 342325f..6df8355 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
@@ -54,29 +54,25 @@
addURI(
Contract.AUTHORITY,
Contract.LockScreenQuickAffordances.qualifiedTablePath(
- Contract.LockScreenQuickAffordances.SlotTable.TABLE_NAME,
+ Contract.LockScreenQuickAffordances.SlotTable.TABLE_NAME
),
MATCH_CODE_ALL_SLOTS,
)
addURI(
Contract.AUTHORITY,
Contract.LockScreenQuickAffordances.qualifiedTablePath(
- Contract.LockScreenQuickAffordances.AffordanceTable.TABLE_NAME,
+ Contract.LockScreenQuickAffordances.AffordanceTable.TABLE_NAME
),
MATCH_CODE_ALL_AFFORDANCES,
)
addURI(
Contract.AUTHORITY,
Contract.LockScreenQuickAffordances.qualifiedTablePath(
- Contract.LockScreenQuickAffordances.SelectionTable.TABLE_NAME,
+ Contract.LockScreenQuickAffordances.SelectionTable.TABLE_NAME
),
MATCH_CODE_ALL_SELECTIONS,
)
- addURI(
- Contract.AUTHORITY,
- Contract.FlagsTable.TABLE_NAME,
- MATCH_CODE_ALL_FLAGS,
- )
+ addURI(Contract.AUTHORITY, Contract.FlagsTable.TABLE_NAME, MATCH_CODE_ALL_FLAGS)
}
override fun onCreate(): Boolean {
@@ -106,15 +102,15 @@
when (uriMatcher.match(uri)) {
MATCH_CODE_ALL_SLOTS ->
Contract.LockScreenQuickAffordances.qualifiedTablePath(
- Contract.LockScreenQuickAffordances.SlotTable.TABLE_NAME,
+ Contract.LockScreenQuickAffordances.SlotTable.TABLE_NAME
)
MATCH_CODE_ALL_AFFORDANCES ->
Contract.LockScreenQuickAffordances.qualifiedTablePath(
- Contract.LockScreenQuickAffordances.AffordanceTable.TABLE_NAME,
+ Contract.LockScreenQuickAffordances.AffordanceTable.TABLE_NAME
)
MATCH_CODE_ALL_SELECTIONS ->
Contract.LockScreenQuickAffordances.qualifiedTablePath(
- Contract.LockScreenQuickAffordances.SelectionTable.TABLE_NAME,
+ Contract.LockScreenQuickAffordances.SelectionTable.TABLE_NAME
)
MATCH_CODE_ALL_FLAGS -> Contract.FlagsTable.TABLE_NAME
else -> null
@@ -128,6 +124,7 @@
}
override fun insert(uri: Uri, values: ContentValues?): Uri? {
+ if (!::mainDispatcher.isInitialized) return null
if (uriMatcher.match(uri) != MATCH_CODE_ALL_SELECTIONS) {
throw UnsupportedOperationException()
}
@@ -142,6 +139,7 @@
selectionArgs: Array<out String>?,
sortOrder: String?,
): Cursor? {
+ if (!::mainDispatcher.isInitialized) return null
return runBlocking("$TAG#query", mainDispatcher) {
when (uriMatcher.match(uri)) {
MATCH_CODE_ALL_AFFORDANCES -> queryAffordances()
@@ -163,11 +161,8 @@
return 0
}
- override fun delete(
- uri: Uri,
- selection: String?,
- selectionArgs: Array<out String>?,
- ): Int {
+ override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
+ if (!::mainDispatcher.isInitialized) return 0
if (uriMatcher.match(uri) != MATCH_CODE_ALL_SELECTIONS) {
throw UnsupportedOperationException()
}
@@ -232,11 +227,7 @@
throw IllegalArgumentException("Cannot insert selection, affordance ID was empty!")
}
- val success =
- interactor.select(
- slotId = slotId,
- affordanceId = affordanceId,
- )
+ val success = interactor.select(slotId = slotId, affordanceId = affordanceId)
return if (success) {
Log.d(TAG, "Successfully selected $affordanceId for slot $slotId")
@@ -318,22 +309,14 @@
)
.apply {
interactor.getSlotPickerRepresentations().forEach { representation ->
- addRow(
- arrayOf(
- representation.id,
- representation.maxSelectedAffordances,
- )
- )
+ addRow(arrayOf(representation.id, representation.maxSelectedAffordances))
}
}
}
private suspend fun queryFlags(): Cursor {
return MatrixCursor(
- arrayOf(
- Contract.FlagsTable.Columns.NAME,
- Contract.FlagsTable.Columns.VALUE,
- )
+ arrayOf(Contract.FlagsTable.Columns.NAME, Contract.FlagsTable.Columns.VALUE)
)
.apply {
interactor.getPickerFlags().forEach { flag ->
@@ -351,10 +334,7 @@
}
}
- private suspend fun deleteSelection(
- uri: Uri,
- selectionArgs: Array<out String>?,
- ): Int {
+ private suspend fun deleteSelection(uri: Uri, selectionArgs: Array<out String>?): Int {
if (selectionArgs == null) {
throw IllegalArgumentException(
"Cannot delete selection, selection arguments not included!"
@@ -372,11 +352,7 @@
)
}
- val deleted =
- interactor.unselect(
- slotId = slotId,
- affordanceId = affordanceId,
- )
+ val deleted = interactor.unselect(slotId = slotId, affordanceId = affordanceId)
return if (deleted) {
Log.d(TAG, "Successfully unselected $affordanceId for slot $slotId")
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 3b1569d..1a0525d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -42,6 +42,7 @@
import static com.android.systemui.DejankUtils.whitelistIpcs;
import static com.android.systemui.Flags.notifyPowerManagerUserActivityBackground;
import static com.android.systemui.Flags.relockWithPowerButtonImmediately;
+import static com.android.systemui.Flags.simPinBouncerReset;
import static com.android.systemui.Flags.translucentOccludingActivityFix;
import static com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel.DREAMING_ANIMATION_DURATION_MS;
@@ -238,7 +239,6 @@
private static final long KEYGUARD_DONE_PENDING_TIMEOUT_MS = 3000;
private static final boolean DEBUG = KeyguardConstants.DEBUG;
- private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;
private final static String TAG = "KeyguardViewMediator";
@@ -649,11 +649,8 @@
@Override
public void onSimStateChanged(int subId, int slotId, int simState) {
-
- if (DEBUG_SIM_STATES) {
- Log.d(TAG, "onSimStateChanged(subId=" + subId + ", slotId=" + slotId
- + ",state=" + simState + ")");
- }
+ Log.d(TAG, "onSimStateChanged(subId=" + subId + ", slotId=" + slotId
+ + ",state=" + TelephonyManager.simStateToString(simState) + ")");
int size = mKeyguardStateCallbacks.size();
boolean simPinSecure = mUpdateMonitor.isSimPinSecure();
@@ -686,7 +683,7 @@
synchronized (KeyguardViewMediator.this) {
if (shouldWaitForProvisioning()) {
if (!mShowing) {
- if (DEBUG_SIM_STATES) Log.d(TAG, "ICC_ABSENT isn't showing,"
+ Log.d(TAG, "ICC_ABSENT isn't showing,"
+ " we need to show the keyguard since the "
+ "device isn't provisioned yet.");
doKeyguardLocked(null);
@@ -698,11 +695,21 @@
// MVNO SIMs can become transiently NOT_READY when switching networks,
// so we should only lock when they are ABSENT.
if (lastSimStateWasLocked) {
- if (DEBUG_SIM_STATES) Log.d(TAG, "SIM moved to ABSENT when the "
+ Log.d(TAG, "SIM moved to ABSENT when the "
+ "previous state was locked. Reset the state.");
resetStateLocked();
}
mSimWasLocked.append(slotId, false);
+ } else if (simState == TelephonyManager.SIM_STATE_NOT_READY) {
+ if (simPinBouncerReset()) {
+ // Support eSIM disablement, and do not clear `mSimWasLocked`.
+ // NOT_READY could just be a temporary state
+ if (lastSimStateWasLocked) {
+ Log.d(TAG, "SIM moved to NOT_READY when the "
+ + "previous state was locked. Reset the state.");
+ resetStateLocked();
+ }
+ }
}
}
break;
@@ -712,7 +719,7 @@
mSimWasLocked.append(slotId, true);
mPendingPinLock = true;
if (!mShowing) {
- if (DEBUG_SIM_STATES) Log.d(TAG,
+ Log.d(TAG,
"INTENT_VALUE_ICC_LOCKED and keygaurd isn't "
+ "showing; need to show keyguard so user can enter sim pin");
doKeyguardLocked(null);
@@ -724,11 +731,11 @@
case TelephonyManager.SIM_STATE_PERM_DISABLED:
synchronized (KeyguardViewMediator.this) {
if (!mShowing) {
- if (DEBUG_SIM_STATES) Log.d(TAG, "PERM_DISABLED and "
+ Log.d(TAG, "PERM_DISABLED and "
+ "keygaurd isn't showing.");
doKeyguardLocked(null);
} else {
- if (DEBUG_SIM_STATES) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
+ Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
+ "show permanently disabled message in lockscreen.");
resetStateLocked();
}
@@ -736,9 +743,9 @@
break;
case TelephonyManager.SIM_STATE_READY:
synchronized (KeyguardViewMediator.this) {
- if (DEBUG_SIM_STATES) Log.d(TAG, "READY, reset state? " + mShowing);
+ Log.d(TAG, "READY, reset state? " + mShowing);
if (mShowing && mSimWasLocked.get(slotId, false)) {
- if (DEBUG_SIM_STATES) Log.d(TAG, "SIM moved to READY when the "
+ Log.d(TAG, "SIM moved to READY when the "
+ "previously was locked. Reset the state.");
mSimWasLocked.append(slotId, false);
resetStateLocked();
@@ -746,7 +753,7 @@
}
break;
default:
- if (DEBUG_SIM_STATES) Log.v(TAG, "Unspecific state: " + simState);
+ Log.v(TAG, "Unspecific state: " + simState);
break;
}
}
@@ -1682,6 +1689,12 @@
});
mJavaAdapter.alwaysCollectFlow(communalViewModel.getTransitionFromOccludedEnded(),
getFinishedCallbackConsumer());
+
+ // System ready can be invoked in the middle of user switching, so check for this state
+ // and issue the call manually as that important event was missed.
+ if (mUserTracker.isUserSwitching()) {
+ mUpdateCallback.onUserSwitching(mUserTracker.getUserId());
+ }
}
// Most services aren't available until the system reaches the ready state, so we
// send it here when the device first boots.
diff --git a/packages/SystemUI/src/com/android/systemui/settings/MultiUserUtilsModule.java b/packages/SystemUI/src/com/android/systemui/settings/MultiUserUtilsModule.java
index b9f9b92..05f19ef 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/MultiUserUtilsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/MultiUserUtilsModule.java
@@ -16,6 +16,7 @@
package com.android.systemui.settings;
+import android.app.ActivityManager;
import android.app.IActivityManager;
import android.content.Context;
import android.hardware.display.DisplayManager;
@@ -66,7 +67,7 @@
@Background CoroutineDispatcher backgroundDispatcher,
@Background Handler handler
) {
- int startingUser = userManager.getBootUser().getIdentifier();
+ int startingUser = ActivityManager.getCurrentUser();
UserTrackerImpl tracker = new UserTrackerImpl(context, featureFlagsProvider, userManager,
iActivityManager, dumpManager, appScope, backgroundDispatcher, handler);
tracker.initialize(startingUser);
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
index 1a997a7..e1631cc 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
@@ -16,11 +16,10 @@
package com.android.systemui.settings
-import com.android.systemui.util.annotations.WeaklyReferencedCallback
-
import android.content.Context
import android.content.pm.UserInfo
import android.os.UserHandle
+import com.android.systemui.util.annotations.WeaklyReferencedCallback
import java.util.concurrent.Executor
/**
@@ -31,19 +30,13 @@
*/
interface UserTracker : UserContentResolverProvider, UserContextProvider {
- /**
- * Current user's id.
- */
+ /** Current user's id. */
val userId: Int
- /**
- * [UserHandle] for current user
- */
+ /** [UserHandle] for current user */
val userHandle: UserHandle
- /**
- * [UserInfo] for current user
- */
+ /** [UserInfo] for current user */
val userInfo: UserInfo
/**
@@ -56,39 +49,33 @@
*/
val userProfiles: List<UserInfo>
- /**
- * Add a [Callback] to be notified of chances, on a particular [Executor]
- */
+ /** Is the system in the process of switching users? */
+ val isUserSwitching: Boolean
+
+ /** Add a [Callback] to be notified of chances, on a particular [Executor] */
fun addCallback(callback: Callback, executor: Executor)
- /**
- * Remove a [Callback] previously added.
- */
+ /** Remove a [Callback] previously added. */
fun removeCallback(callback: Callback)
- /**
- * Callback for notifying of changes.
- */
+ /** Callback for notifying of changes. */
@WeaklyReferencedCallback
interface Callback {
- /**
- * Notifies that the current user will be changed.
- */
+ /** Notifies that the current user will be changed. */
fun onBeforeUserSwitching(newUser: Int) {}
/**
- * Same as {@link onUserChanging(Int, Context, Runnable)} but the callback will be
- * called automatically after the completion of this method.
+ * Same as {@link onUserChanging(Int, Context, Runnable)} but the callback will be called
+ * automatically after the completion of this method.
*/
fun onUserChanging(newUser: Int, userContext: Context) {}
/**
- * Notifies that the current user is being changed.
- * Override this method to run things while the screen is frozen for the user switch.
- * Please use {@link #onUserChanged} if the task doesn't need to push the unfreezing of the
- * screen further. Please be aware that code executed in this callback will lengthen the
- * user switch duration. When overriding this method, resultCallback#run() MUST be called
- * once the execution is complete.
+ * Notifies that the current user is being changed. Override this method to run things while
+ * the screen is frozen for the user switch. Please use {@link #onUserChanged} if the task
+ * doesn't need to push the unfreezing of the screen further. Please be aware that code
+ * executed in this callback will lengthen the user switch duration. When overriding this
+ * method, resultCallback#run() MUST be called once the execution is complete.
*/
fun onUserChanging(newUser: Int, userContext: Context, resultCallback: Runnable) {
onUserChanging(newUser, userContext)
@@ -96,15 +83,13 @@
}
/**
- * Notifies that the current user has changed.
- * Override this method to run things after the screen is unfrozen for the user switch.
- * Please see {@link #onUserChanging} if you need to hide jank.
+ * Notifies that the current user has changed. Override this method to run things after the
+ * screen is unfrozen for the user switch. Please see {@link #onUserChanging} if you need to
+ * hide jank.
*/
fun onUserChanged(newUser: Int, userContext: Context) {}
- /**
- * Notifies that the current user's profiles have changed.
- */
+ /** Notifies that the current user's profiles have changed. */
fun onProfilesChanged(profiles: List<@JvmSuppressWildcards UserInfo>) {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 553d1f5..1863e12 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -106,6 +106,9 @@
override var userInfo: UserInfo by SynchronizedDelegate(UserInfo(context.userId, "", 0))
protected set
+ override var isUserSwitching = false
+ protected set
+
/**
* Returns a [List<UserInfo>] of all profiles associated with the current user.
*
@@ -197,6 +200,7 @@
}
override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback?) {
+ isUserSwitching = true
if (isBackgroundUserSwitchEnabled) {
userSwitchingJob?.cancel()
userSwitchingJob =
@@ -210,6 +214,7 @@
}
override fun onUserSwitchComplete(newUserId: Int) {
+ isUserSwitching = false
if (isBackgroundUserSwitchEnabled) {
afterUserSwitchingJob?.cancel()
afterUserSwitchingJob =
@@ -221,7 +226,7 @@
}
}
},
- TAG
+ TAG,
)
}
@@ -349,7 +354,7 @@
private data class DataItem(
val callback: WeakReference<UserTracker.Callback>,
- val executor: Executor
+ val executor: Executor,
) {
fun sameOrEmpty(other: UserTracker.Callback): Boolean {
return callback.get()?.equals(other) ?: true
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 52fde7e..4005e10 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -494,7 +494,7 @@
@Test
public void testIgnoresSimStateCallback_rebroadcast() {
- Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+ Intent intent = defaultSimStateChangedIntent();
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(), intent);
mTestableLooper.processAllMessages();
@@ -515,7 +515,8 @@
@Test
public void testTelephonyCapable_SimState_Absent() {
- Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+
+ Intent intent = defaultSimStateChangedIntent();
intent.putExtra(Intent.EXTRA_SIM_STATE,
Intent.SIM_STATE_ABSENT);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
@@ -526,7 +527,7 @@
@Test
public void testTelephonyCapable_SimState_CardIOError() {
- Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+ Intent intent = defaultSimStateChangedIntent();
intent.putExtra(Intent.EXTRA_SIM_STATE,
Intent.SIM_STATE_CARD_IO_ERROR);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext(),
@@ -593,7 +594,7 @@
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_OUT_OF_SERVICE);
state.fillInNotifierBundle(data);
- Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+ Intent intent = defaultSimStateChangedIntent();
intent.putExtra(Intent.EXTRA_SIM_STATE
, Intent.SIM_STATE_NOT_READY);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
@@ -608,7 +609,7 @@
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_OUT_OF_SERVICE);
state.fillInNotifierBundle(data);
- Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+ Intent intent = defaultSimStateChangedIntent();
intent.putExtra(Intent.EXTRA_SIM_STATE
, Intent.SIM_STATE_READY);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
@@ -649,7 +650,7 @@
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_IN_SERVICE);
state.fillInNotifierBundle(data);
- Intent intentSimState = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+ Intent intentSimState = defaultSimStateChangedIntent();
intentSimState.putExtra(Intent.EXTRA_SIM_STATE
, Intent.SIM_STATE_LOADED);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
@@ -2256,6 +2257,12 @@
Assert.assertFalse(mKeyguardUpdateMonitor.forceIsDismissibleIsKeepingDeviceUnlocked());
}
+ private Intent defaultSimStateChangedIntent() {
+ Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+ intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 0);
+ return intent;
+ }
+
private void verifyFingerprintAuthenticateNeverCalled() {
verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), any());
verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 597ffef..9e0d358 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -26,6 +26,7 @@
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
import static com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR;
+import static com.android.systemui.Flags.FLAG_SIM_PIN_BOUNCER_RESET;
import static com.android.systemui.keyguard.KeyguardViewMediator.DELAYED_KEYGUARD_ACTION;
import static com.android.systemui.keyguard.KeyguardViewMediator.KEYGUARD_LOCK_AFTER_DELAY_DEFAULT;
import static com.android.systemui.keyguard.KeyguardViewMediator.REBOOT_MAINLINE_UPDATE;
@@ -62,6 +63,7 @@
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.RemoteException;
+import android.platform.test.annotations.EnableFlags;
import android.telephony.TelephonyManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -588,6 +590,35 @@
@Test
@TestableLooper.RunWithLooper(setAsMainLooper = true)
+ @EnableFlags(FLAG_SIM_PIN_BOUNCER_RESET)
+ public void resetStateLocked_whenSimNotReadyAndWasLockedPrior() {
+ // When showing and provisioned
+ mViewMediator.onSystemReady();
+ when(mUpdateMonitor.isDeviceProvisioned()).thenReturn(true);
+ mViewMediator.setShowingLocked(true, "");
+
+ // and a SIM becomes locked and requires a PIN
+ mViewMediator.mUpdateCallback.onSimStateChanged(
+ 1 /* subId */,
+ 0 /* slotId */,
+ TelephonyManager.SIM_STATE_PIN_REQUIRED);
+ TestableLooper.get(this).processAllMessages();
+
+ reset(mStatusBarKeyguardViewManager);
+
+ // but then disabled by a NOT_READY
+ mViewMediator.mUpdateCallback.onSimStateChanged(
+ 1 /* subId */,
+ 0 /* slotId */,
+ TelephonyManager.SIM_STATE_NOT_READY);
+ TestableLooper.get(this).processAllMessages();
+
+ // A call to reset the keyguard and bouncer was invoked
+ verify(mStatusBarKeyguardViewManager).reset(true);
+ }
+
+ @Test
+ @TestableLooper.RunWithLooper(setAsMainLooper = true)
public void restoreBouncerWhenSimLockedAndKeyguardIsGoingAway_initiallyNotShowing() {
// When showing and provisioned
mViewMediator.onSystemReady();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
index 2e2ac3e..a0ecb80 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
@@ -231,7 +231,7 @@
"",
"",
UserInfo.FLAG_MANAGED_PROFILE,
- UserManager.USER_TYPE_PROFILE_MANAGED
+ UserManager.USER_TYPE_PROFILE_MANAGED,
)
infoProfile.profileGroupId = id
listOf(info, infoProfile)
@@ -261,7 +261,7 @@
"",
"",
UserInfo.FLAG_MANAGED_PROFILE or UserInfo.FLAG_QUIET_MODE,
- UserManager.USER_TYPE_PROFILE_MANAGED
+ UserManager.USER_TYPE_PROFILE_MANAGED,
)
infoProfile.profileGroupId = id
listOf(info, infoProfile)
@@ -291,7 +291,7 @@
"",
"",
UserInfo.FLAG_MANAGED_PROFILE,
- UserManager.USER_TYPE_PROFILE_MANAGED
+ UserManager.USER_TYPE_PROFILE_MANAGED,
)
infoProfile.profileGroupId = id
listOf(info, infoProfile)
@@ -423,7 +423,7 @@
"",
"",
UserInfo.FLAG_MANAGED_PROFILE,
- UserManager.USER_TYPE_PROFILE_MANAGED
+ UserManager.USER_TYPE_PROFILE_MANAGED,
)
infoProfile.profileGroupId = id
listOf(info, infoProfile)
@@ -469,6 +469,24 @@
assertThat(callback.calledOnProfilesChanged).isEqualTo(0)
}
+ @Test
+ fun testisUserSwitching() =
+ testScope.runTest {
+ tracker.initialize(0)
+ val newID = 5
+ val profileID = newID + 10
+
+ val captor = ArgumentCaptor.forClass(IUserSwitchObserver::class.java)
+ verify(iActivityManager).registerUserSwitchObserver(capture(captor), anyString())
+ assertThat(tracker.isUserSwitching).isFalse()
+
+ captor.value.onUserSwitching(newID, userSwitchingReply)
+ assertThat(tracker.isUserSwitching).isTrue()
+
+ captor.value.onUserSwitchComplete(newID)
+ assertThat(tracker.isUserSwitching).isFalse()
+ }
+
private class TestCallback : UserTracker.Callback {
var calledOnUserChanging = 0
var calledOnUserChanged = 0
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
index f3d5b7d..cd76a74 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
@@ -33,6 +33,7 @@
private var _userHandle: UserHandle = UserHandle.of(_userId),
private var _userInfo: UserInfo = mock(),
private var _userProfiles: List<UserInfo> = emptyList(),
+ private var _isUserSwitching: Boolean = false,
userContentResolverProvider: () -> ContentResolver = { MockContentResolver() },
userContext: Context = mock(),
private val onCreateCurrentUserContext: (Context) -> Context = { mock() },
@@ -51,6 +52,9 @@
override val userProfiles: List<UserInfo>
get() = _userProfiles
+ override val isUserSwitching: Boolean
+ get() = _isUserSwitching
+
// userContentResolver is lazy because Ravenwood doesn't support MockContentResolver()
// and we still want to allow people use this class for tests that don't use it.
override val userContentResolver: ContentResolver by lazy { userContentResolverProvider() }
@@ -86,11 +90,13 @@
}
fun onUserChanging(userId: Int = _userId) {
+ _isUserSwitching = true
val copy = callbacks.toList()
copy.forEach { it.onUserChanging(userId, userContext) {} }
}
fun onUserChanged(userId: Int = _userId) {
+ _isUserSwitching = false
val copy = callbacks.toList()
copy.forEach { it.onUserChanged(userId, userContext) }
}