diff options
| -rw-r--r-- | services/core/java/com/android/server/pm/UserManagerService.java | 228 | ||||
| -rw-r--r-- | services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java | 161 |
2 files changed, 386 insertions, 3 deletions
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 7b0a69bc6786..948e9cd9b32f 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -16,6 +16,8 @@ package com.android.server.pm; +import static android.content.Intent.ACTION_SCREEN_OFF; +import static android.content.Intent.ACTION_SCREEN_ON; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.os.UserManager.DEV_CREATE_OVERRIDE_PROPERTY; @@ -41,6 +43,7 @@ import android.annotation.ColorRes; import android.annotation.DrawableRes; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.StringRes; import android.annotation.UserIdInt; import android.app.ActivityManager; @@ -74,8 +77,10 @@ import android.content.pm.UserProperties; import android.content.pm.parsing.FrameworkParsingPackageUtils; import android.content.res.Configuration; import android.content.res.Resources; +import android.database.ContentObserver; import android.graphics.Bitmap; import android.multiuser.Flags; +import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; @@ -83,6 +88,7 @@ import android.os.Debug; import android.os.Environment; import android.os.FileUtils; import android.os.Handler; +import android.os.HandlerExecutor; import android.os.IBinder; import android.os.IProgressListener; import android.os.IUserManager; @@ -91,6 +97,7 @@ import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.Parcelable; import android.os.PersistableBundle; +import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; @@ -296,6 +303,12 @@ public class UserManagerService extends IUserManager.Stub { private static final long BOOT_USER_SET_TIMEOUT_MS = 300_000; + /** + * The time duration (in milliseconds) post device inactivity after which the private space + * should be auto-locked if the corresponding settings option is selected by the user. + */ + private static final long PRIVATE_SPACE_AUTO_LOCK_INACTIVITY_TIMEOUT_MS = 5 * 60 * 1000; + // Tron counters private static final String TRON_GUEST_CREATED = "users_guest_created"; private static final String TRON_USER_CREATED = "users_user_created"; @@ -522,6 +535,36 @@ public class UserManagerService extends IUserManager.Stub { private final LockPatternUtils mLockPatternUtils; + private KeyguardManager.KeyguardLockedStateListener mKeyguardLockedStateListener; + + /** Token to identify and remove already scheduled private space auto-lock messages */ + private static final Object PRIVATE_SPACE_AUTO_LOCK_MESSAGE_TOKEN = new Object(); + + /** Content observer to get callbacks for privte space autolock settings changes */ + private final SettingsObserver mPrivateSpaceAutoLockSettingsObserver; + + private final class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + if (isAutoLockForPrivateSpaceEnabled()) { + final String path = uri.getLastPathSegment(); + if (TextUtils.equals(path, Settings.Secure.PRIVATE_SPACE_AUTO_LOCK)) { + int autoLockPreference = + Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.PRIVATE_SPACE_AUTO_LOCK, + Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_NEVER, + getMainUserIdUnchecked()); + Slog.i(LOG_TAG, "Auto-lock settings changed to " + autoLockPreference); + setOrUpdateAutoLockPreferenceForPrivateProfile(autoLockPreference); + } + } + } + } + private final String ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK = "com.android.server.pm.DISABLE_QUIET_MODE_AFTER_UNLOCK"; @@ -534,12 +577,159 @@ public class UserManagerService extends IUserManager.Stub { final IntentSender target = intent.getParcelableExtra(Intent.EXTRA_INTENT, android.content.IntentSender.class); final int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL); final String callingPackage = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); - // Call setQuietModeEnabled on bg thread to avoid ANR - BackgroundThread.getHandler().post(() -> - setQuietModeEnabled(userId, false, target, callingPackage)); + setQuietModeEnabledAsync(userId, false, target, callingPackage); + } + }; + + /** Checks if the device inactivity broadcast receiver is already registered*/ + private boolean mIsDeviceInactivityBroadcastReceiverRegistered = false; + + private final BroadcastReceiver mDeviceInactivityBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (isAutoLockForPrivateSpaceEnabled()) { + if (ACTION_SCREEN_OFF.equals(intent.getAction())) { + maybeScheduleMessageToAutoLockPrivateSpace(); + } else if (ACTION_SCREEN_ON.equals(intent.getAction())) { + // Remove any queued messages since the device is interactive again + mHandler.removeCallbacksAndMessages(PRIVATE_SPACE_AUTO_LOCK_MESSAGE_TOKEN); + } + } } }; + @VisibleForTesting + void maybeScheduleMessageToAutoLockPrivateSpace() { + // No action needed if auto-lock on inactivity not selected + int privateSpaceAutoLockPreference = + Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.PRIVATE_SPACE_AUTO_LOCK, + Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_NEVER, + getMainUserIdUnchecked()); + if (privateSpaceAutoLockPreference + != Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_AFTER_INACTIVITY) { + return; + } + int privateProfileUserId = getPrivateProfileUserId(); + if (privateProfileUserId != UserHandle.USER_NULL) { + scheduleMessageToAutoLockPrivateSpace(privateProfileUserId, + PRIVATE_SPACE_AUTO_LOCK_MESSAGE_TOKEN, + PRIVATE_SPACE_AUTO_LOCK_INACTIVITY_TIMEOUT_MS); + } + } + + @VisibleForTesting + void scheduleMessageToAutoLockPrivateSpace(int userId, Object token, + long delayInMillis) { + mHandler.postDelayed(() -> { + final PowerManager powerManager = mContext.getSystemService(PowerManager.class); + if (powerManager != null && !powerManager.isInteractive()) { + Slog.i(LOG_TAG, "Auto-locking private space with user-id " + userId); + setQuietModeEnabledAsync(userId, true, + /* target */ null, mContext.getPackageName()); + } else { + Slog.i(LOG_TAG, "Device is interactive, skipping auto-lock"); + } + }, token, delayInMillis); + } + + @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) + private void initializeAndRegisterKeyguardLockedStateListener() { + mKeyguardLockedStateListener = this::tryAutoLockingPrivateSpaceOnKeyguardChanged; + // Register with keyguard to send locked state events to the listener initialized above + try { + final KeyguardManager keyguardManager = + mContext.getSystemService(KeyguardManager.class); + Slog.i(LOG_TAG, "Adding keyguard locked state listener"); + keyguardManager.addKeyguardLockedStateListener(new HandlerExecutor(mHandler), + mKeyguardLockedStateListener); + } catch (Exception e) { + Slog.e(LOG_TAG, "Error adding keyguard locked listener ", e); + } + } + + @VisibleForTesting + @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE) + void setOrUpdateAutoLockPreferenceForPrivateProfile( + @Settings.Secure.PrivateSpaceAutoLockOption int autoLockPreference) { + int privateProfileUserId = getPrivateProfileUserId(); + if (privateProfileUserId == UserHandle.USER_NULL) { + Slog.e(LOG_TAG, "Auto-lock preference updated but private space user not found"); + return; + } + + if (autoLockPreference == Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_AFTER_INACTIVITY) { + // Register inactivity broadcast + if (!mIsDeviceInactivityBroadcastReceiverRegistered) { + Slog.i(LOG_TAG, "Registering device inactivity broadcast receivers"); + mContext.registerReceiver(mDeviceInactivityBroadcastReceiver, + new IntentFilter(ACTION_SCREEN_OFF), + null, mHandler); + + mContext.registerReceiver(mDeviceInactivityBroadcastReceiver, + new IntentFilter(ACTION_SCREEN_ON), + null, mHandler); + + mIsDeviceInactivityBroadcastReceiverRegistered = true; + } + } else { + // Unregister device inactivity broadcasts + if (mIsDeviceInactivityBroadcastReceiverRegistered) { + Slog.i(LOG_TAG, "Removing device inactivity broadcast receivers"); + mHandler.removeCallbacksAndMessages(PRIVATE_SPACE_AUTO_LOCK_MESSAGE_TOKEN); + mContext.unregisterReceiver(mDeviceInactivityBroadcastReceiver); + mIsDeviceInactivityBroadcastReceiverRegistered = false; + } + } + + if (autoLockPreference == Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_ON_DEVICE_LOCK) { + // Initialize and add keyguard state listener + initializeAndRegisterKeyguardLockedStateListener(); + } else { + // Remove keyguard state listener + try { + final KeyguardManager keyguardManager = + mContext.getSystemService(KeyguardManager.class); + Slog.i(LOG_TAG, "Removing keyguard locked state listener"); + keyguardManager.removeKeyguardLockedStateListener(mKeyguardLockedStateListener); + } catch (Exception e) { + Slog.e(LOG_TAG, "Error adding keyguard locked state listener ", e); + } + } + } + + @VisibleForTesting + void tryAutoLockingPrivateSpaceOnKeyguardChanged(boolean isKeyguardLocked) { + if (isAutoLockForPrivateSpaceEnabled()) { + int autoLockPreference = Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.PRIVATE_SPACE_AUTO_LOCK, + Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_NEVER, + getMainUserIdUnchecked()); + boolean isAutoLockOnDeviceLockSelected = + autoLockPreference == Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_ON_DEVICE_LOCK; + if (isKeyguardLocked && isAutoLockOnDeviceLockSelected) { + int privateProfileUserId = getPrivateProfileUserId(); + if (privateProfileUserId != UserHandle.USER_NULL) { + Slog.i(LOG_TAG, "Auto-locking private space with user-id " + + privateProfileUserId); + setQuietModeEnabledAsync(privateProfileUserId, + /* enableQuietMode */true, /* target */ null, + mContext.getPackageName()); + } + } + } + } + + @VisibleForTesting + void setQuietModeEnabledAsync(@UserIdInt int userId, boolean enableQuietMode, + IntentSender target, @Nullable String callingPackage) { + // Call setQuietModeEnabled on bg thread to avoid ANR + BackgroundThread.getHandler().post( + () -> setQuietModeEnabled(userId, enableQuietMode, target, + callingPackage) + ); + } + /** * Cache the owner name string, since it could be read repeatedly on a critical code path * but hit by slow IO. This could be eliminated once we have the cached UserInfo in place. @@ -790,9 +980,15 @@ public class UserManagerService extends IUserManager.Stub { mLockPatternUtils = new LockPatternUtils(mContext); mUserStates.put(UserHandle.USER_SYSTEM, UserState.STATE_BOOTING); mUser0Allocations = DBG_ALLOCATION ? new AtomicInteger() : null; + mPrivateSpaceAutoLockSettingsObserver = new SettingsObserver(mHandler); emulateSystemUserModeIfNeeded(); } + private static boolean isAutoLockForPrivateSpaceEnabled() { + return android.os.Flags.allowPrivateProfile() + && Flags.supportAutolockForPrivateSpace(); + } + void systemReady() { mAppOpsService = IAppOpsService.Stub.asInterface( ServiceManager.getService(Context.APP_OPS_SERVICE)); @@ -809,6 +1005,20 @@ public class UserManagerService extends IUserManager.Stub { new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED), null, mHandler); + if (isAutoLockForPrivateSpaceEnabled()) { + + int mainUserId = getMainUserIdUnchecked(); + + mContext.getContentResolver().registerContentObserverAsUser(Settings.Secure.getUriFor( + Settings.Secure.PRIVATE_SPACE_AUTO_LOCK), false, + mPrivateSpaceAutoLockSettingsObserver, UserHandle.of(mainUserId)); + + setOrUpdateAutoLockPreferenceForPrivateProfile( + Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.PRIVATE_SPACE_AUTO_LOCK, + Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_NEVER, mainUserId)); + } + markEphemeralUsersForRemoval(); } @@ -973,6 +1183,18 @@ public class UserManagerService extends IUserManager.Stub { return UserHandle.USER_NULL; } + private @UserIdInt int getPrivateProfileUserId() { + synchronized (mUsersLock) { + for (int userId : getUserIds()) { + UserInfo userInfo = getUserInfoLU(userId); + if (userInfo != null && userInfo.isPrivateProfile()) { + return userInfo.id; + } + } + } + return UserHandle.USER_NULL; + } + @Override public void setBootUser(@UserIdInt int userId) { checkCreateUsersPermission("Set boot user"); diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java index fd6aa0c1ffab..e6298eeccafb 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java @@ -19,9 +19,11 @@ import static android.os.UserManager.DISALLOW_OUTGOING_CALLS; import static android.os.UserManager.DISALLOW_SMS; import static android.os.UserManager.DISALLOW_USER_SWITCH; import static android.os.UserManager.USER_TYPE_FULL_SECONDARY; +import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; @@ -30,20 +32,27 @@ import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; import android.annotation.UserIdInt; import android.app.ActivityManagerInternal; +import android.app.KeyguardManager; import android.content.Context; import android.content.pm.PackageManagerInternal; import android.content.pm.UserInfo; +import android.multiuser.Flags; +import android.os.PowerManager; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.util.Log; import android.util.Pair; @@ -52,6 +61,7 @@ import android.util.Xml; import androidx.test.annotation.UiThreadTest; +import com.android.dx.mockito.inline.extended.MockedVoidMethod; import com.android.internal.widget.LockSettingsInternal; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.testing.ExtendedMockitoRule; @@ -65,6 +75,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; +import org.mockito.Mockito; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -115,8 +126,11 @@ public final class UserManagerServiceTest { .spyStatic(LocalServices.class) .spyStatic(SystemProperties.class) .mockStatic(Settings.Global.class) + .mockStatic(Settings.Secure.class) .build(); + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + private final Object mPackagesLock = new Object(); private final Context mRealContext = androidx.test.InstrumentationRegistry.getInstrumentation() .getTargetContext(); @@ -133,6 +147,8 @@ public final class UserManagerServiceTest { private @Mock StorageManager mStorageManager; private @Mock LockSettingsInternal mLockSettingsInternal; private @Mock PackageManagerInternal mPackageManagerInternal; + private @Mock KeyguardManager mKeyguardManager; + private @Mock PowerManager mPowerManager; /** * Reference to the {@link UserManagerService} being tested. @@ -156,6 +172,8 @@ public final class UserManagerServiceTest { when(mDeviceStorageMonitorInternal.isMemoryLow()).thenReturn(false); mockGetLocalService(DeviceStorageMonitorInternal.class, mDeviceStorageMonitorInternal); when(mSpiedContext.getSystemService(StorageManager.class)).thenReturn(mStorageManager); + when(mSpiedContext.getSystemService(KeyguardManager.class)).thenReturn(mKeyguardManager); + when(mSpiedContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager); mockGetLocalService(LockSettingsInternal.class, mLockSettingsInternal); mockGetLocalService(PackageManagerInternal.class, mPackageManagerInternal); doNothing().when(mSpiedContext).sendBroadcastAsUser(any(), any(), any()); @@ -550,6 +568,143 @@ public final class UserManagerServiceTest { assertTrue(hasRestrictionsInUserXMLFile(user.id)); } + @Test + public void testAutoLockOnDeviceLockForPrivateProfile() { + mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE); + UserManagerService mSpiedUms = spy(mUms); + UserInfo privateProfileUser = + mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow("TestPrivateProfile", + USER_TYPE_PROFILE_PRIVATE, 0, 0, null); + mockAutoLockForPrivateSpace(Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_ON_DEVICE_LOCK); + Mockito.doNothing().when(mSpiedUms).setQuietModeEnabledAsync( + eq(privateProfileUser.getUserHandle().getIdentifier()), eq(true), any(), + any()); + + mSpiedUms.tryAutoLockingPrivateSpaceOnKeyguardChanged(true); + + Mockito.verify(mSpiedUms).setQuietModeEnabledAsync( + eq(privateProfileUser.getUserHandle().getIdentifier()), eq(true), + any(), any()); + } + + @Test + public void testAutoLockOnDeviceLockForPrivateProfile_keyguardUnlocked() { + mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE); + UserManagerService mSpiedUms = spy(mUms); + UserInfo privateProfileUser = + mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow("TestPrivateProfile", + USER_TYPE_PROFILE_PRIVATE, 0, 0, null); + mockAutoLockForPrivateSpace(Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_ON_DEVICE_LOCK); + + mSpiedUms.tryAutoLockingPrivateSpaceOnKeyguardChanged(false); + + // Verify that no operation to disable quiet mode is not called + Mockito.verify(mSpiedUms, never()).setQuietModeEnabledAsync( + eq(privateProfileUser.getUserHandle().getIdentifier()), eq(true), + any(), any()); + } + + @Test + public void testAutoLockOnDeviceLockForPrivateProfile_flagDisabled() { + mSetFlagsRule.disableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE); + UserManagerService mSpiedUms = spy(mUms); + UserInfo privateProfileUser = + mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow("TestPrivateProfile", + USER_TYPE_PROFILE_PRIVATE, 0, 0, null); + + mSpiedUms.tryAutoLockingPrivateSpaceOnKeyguardChanged(true); + + // Verify that no auto-lock operations take place + verify((MockedVoidMethod) () -> Settings.Secure.getInt(any(), + eq(Settings.Secure.PRIVATE_SPACE_AUTO_LOCK), anyInt()), never()); + Mockito.verify(mSpiedUms, never()).setQuietModeEnabledAsync( + eq(privateProfileUser.getUserHandle().getIdentifier()), eq(true), + any(), any()); + } + + @Test + public void testAutoLockAfterInactityForPrivateProfile() { + mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE); + UserManagerService mSpiedUms = spy(mUms); + mockAutoLockForPrivateSpace(Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_AFTER_INACTIVITY); + when(mPowerManager.isInteractive()).thenReturn(false); + + UserInfo privateProfileUser = + mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow("TestPrivateProfile", + USER_TYPE_PROFILE_PRIVATE, 0, 0, null); + Mockito.doNothing().when(mSpiedUms).scheduleMessageToAutoLockPrivateSpace( + eq(privateProfileUser.getUserHandle().getIdentifier()), any(), + anyLong()); + + + mSpiedUms.maybeScheduleMessageToAutoLockPrivateSpace(); + + Mockito.verify(mSpiedUms).scheduleMessageToAutoLockPrivateSpace( + eq(privateProfileUser.getUserHandle().getIdentifier()), any(), anyLong()); + } + + @Test + public void testSetOrUpdateAutoLockPreference_noPrivateProfile() { + mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE); + + mUms.setOrUpdateAutoLockPreferenceForPrivateProfile( + Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_AFTER_INACTIVITY); + + Mockito.verify(mSpiedContext, never()).registerReceiver(any(), any(), any(), any()); + Mockito.verify(mSpiedContext, never()).unregisterReceiver(any()); + Mockito.verify(mKeyguardManager, never()).removeKeyguardLockedStateListener((any())); + Mockito.verify(mKeyguardManager, never()).addKeyguardLockedStateListener(any(), any()); + } + + @Test + public void testSetOrUpdateAutoLockPreference() { + mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE); + mUms.createProfileForUserEvenWhenDisallowedWithThrow("TestPrivateProfile", + USER_TYPE_PROFILE_PRIVATE, 0, 0, null); + + // Set the preference to auto lock on device lock + mUms.setOrUpdateAutoLockPreferenceForPrivateProfile( + Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_ON_DEVICE_LOCK); + + // Verify that keyguard state listener was added + Mockito.verify(mKeyguardManager).addKeyguardLockedStateListener(any(), any()); + //Verity that keyguard state listener was not removed + Mockito.verify(mKeyguardManager, never()).removeKeyguardLockedStateListener(any()); + // Broadcasts are already unregistered when UserManagerService starts and the flag + // isDeviceInactivityBroadcastReceiverRegistered is false + Mockito.verify(mSpiedContext, never()).registerReceiver(any(), any(), any(), any()); + Mockito.verify(mSpiedContext, never()).unregisterReceiver(any()); + + Mockito.clearInvocations(mKeyguardManager); + Mockito.clearInvocations(mSpiedContext); + + // Now set the preference to auto-lock on inactivity + mUms.setOrUpdateAutoLockPreferenceForPrivateProfile( + Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_AFTER_INACTIVITY); + + // Verify that inactivity broadcasts are registered + Mockito.verify(mSpiedContext, times(2)).registerReceiver(any(), any(), any(), any()); + // Verify that keyguard state listener is removed + Mockito.verify(mKeyguardManager).removeKeyguardLockedStateListener(any()); + // Verify that all other operations don't take place + Mockito.verify(mSpiedContext, never()).unregisterReceiver(any()); + Mockito.verify(mKeyguardManager, never()).addKeyguardLockedStateListener(any(), any()); + + Mockito.clearInvocations(mKeyguardManager); + Mockito.clearInvocations(mSpiedContext); + + // Finally, set the preference to don't auto-lock + mUms.setOrUpdateAutoLockPreferenceForPrivateProfile( + Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_NEVER); + + // Verify that inactivity broadcasts are unregistered and keyguard listener was removed + Mockito.verify(mSpiedContext).unregisterReceiver(any()); + Mockito.verify(mKeyguardManager).removeKeyguardLockedStateListener(any()); + // Verify that no broadcasts were registered and no listeners were added + Mockito.verify(mSpiedContext, never()).registerReceiver(any(), any(), any(), any()); + Mockito.verify(mKeyguardManager, never()).addKeyguardLockedStateListener(any(), any()); + } + /** * Returns true if the user's XML file has Default restrictions * @param userId Id of the user. @@ -632,6 +787,12 @@ public final class UserManagerServiceTest { SystemProperties.getBoolean(eq("fw.show_multiuserui"), anyBoolean())); } + private void mockAutoLockForPrivateSpace(int val) { + doReturn(val).when(() -> + Settings.Secure.getIntForUser(any(), eq(Settings.Secure.PRIVATE_SPACE_AUTO_LOCK), + anyInt(), anyInt())); + } + private void mockCurrentUser(@UserIdInt int userId) { mockGetLocalService(ActivityManagerInternal.class, mActivityManagerInternal); |