diff options
13 files changed, 182 insertions, 124 deletions
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index 02e8cd6c398d..7974f9222a0c 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -1313,6 +1313,16 @@ flag { } 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 a5b62b6e7c64..b16c683a1b6c 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java @@ -28,5 +28,4 @@ public class KeyguardConstants { * 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 1c1acf83fa12..52c93f72206b 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java @@ -53,7 +53,6 @@ public class KeyguardSimPinViewController 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 @@ public class KeyguardSimPinViewController 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 @@ public class KeyguardSimPinViewController @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 @@ public class KeyguardSimPinViewController 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 @@ public class KeyguardSimPinViewController 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 @@ public class KeyguardSimPinViewController @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 f731186f6d01..22130f827841 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.STR 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 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab 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 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } 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 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab 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 342325ffee91..6df8355550a0 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 @@ class CustomizationProvider : 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 @@ class CustomizationProvider : 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 @@ class CustomizationProvider : } 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 @@ class CustomizationProvider : 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 @@ class CustomizationProvider : 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 @@ class CustomizationProvider : 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 @@ class CustomizationProvider : ) .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 @@ class CustomizationProvider : } } - 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 @@ class CustomizationProvider : ) } - 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 3b1569d7f79b..1a0525d97d30 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.internal.widget.LockPatternUtils.StrongAuthTracker.STR 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 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, 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 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, @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 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, 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 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, // 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 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, 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 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, 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 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, 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 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } break; default: - if (DEBUG_SIM_STATES) Log.v(TAG, "Unspecific state: " + simState); + Log.v(TAG, "Unspecific state: " + simState); break; } } @@ -1682,6 +1689,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, }); 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 b9f9b929d962..05f19ef2f043 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 @@ public abstract class MultiUserUtilsModule { @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 1a997a764055..e1631ccdcb06 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 @@ import java.util.concurrent.Executor */ 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 @@ interface UserTracker : UserContentResolverProvider, UserContextProvider { */ 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 @@ interface UserTracker : UserContentResolverProvider, UserContextProvider { } /** - * 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 553d1f51a198..1863e12187cd 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 @@ internal constructor( 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 @@ internal constructor( } override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback?) { + isUserSwitching = true if (isBackgroundUserSwitchEnabled) { userSwitchingJob?.cancel() userSwitchingJob = @@ -210,6 +214,7 @@ internal constructor( } override fun onUserSwitchComplete(newUserId: Int) { + isUserSwitching = false if (isBackgroundUserSwitchEnabled) { afterUserSwitchingJob?.cancel() afterUserSwitchingJob = @@ -221,7 +226,7 @@ internal constructor( } } }, - TAG + TAG, ) } @@ -349,7 +354,7 @@ internal constructor( 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 52fde7ed72c9..4005e104108d 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 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { @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 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { @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 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { @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 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { 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 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { 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 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { 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 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { 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 597ffef20ace..9e0d35883dee 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.STR 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.content.Context; 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 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { @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 2e2ac3eb7183..a0ecb802dd61 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 @@ class UserTrackerImplTest : SysuiTestCase() { "", "", UserInfo.FLAG_MANAGED_PROFILE, - UserManager.USER_TYPE_PROFILE_MANAGED + UserManager.USER_TYPE_PROFILE_MANAGED, ) infoProfile.profileGroupId = id listOf(info, infoProfile) @@ -261,7 +261,7 @@ class UserTrackerImplTest : SysuiTestCase() { "", "", 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 @@ class UserTrackerImplTest : SysuiTestCase() { "", "", UserInfo.FLAG_MANAGED_PROFILE, - UserManager.USER_TYPE_PROFILE_MANAGED + UserManager.USER_TYPE_PROFILE_MANAGED, ) infoProfile.profileGroupId = id listOf(info, infoProfile) @@ -423,7 +423,7 @@ class UserTrackerImplTest : SysuiTestCase() { "", "", UserInfo.FLAG_MANAGED_PROFILE, - UserManager.USER_TYPE_PROFILE_MANAGED + UserManager.USER_TYPE_PROFILE_MANAGED, ) infoProfile.profileGroupId = id listOf(info, infoProfile) @@ -469,6 +469,24 @@ class UserTrackerImplTest : SysuiTestCase() { 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 f3d5b7d77669..cd76a749cc9a 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 @@ class FakeUserTracker( 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 @@ class FakeUserTracker( 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 @@ class FakeUserTracker( } 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) } } |