summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java228
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java161
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);