forceUpdateUserSetupComplete should have no effect in user build
Bug:30031808
Change-Id: I908a495633e03ace770a8ec19196841d19dfd41d
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b28843a..f87f723 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1392,6 +1392,10 @@
return IAudioService.Stub.asInterface(ServiceManager.getService(Context.AUDIO_SERVICE));
}
+ boolean isBuildDebuggable() {
+ return Build.IS_DEBUGGABLE;
+ }
+
LockPatternUtils newLockPatternUtils() {
return new LockPatternUtils(mContext);
}
@@ -8978,6 +8982,14 @@
android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null);
}
+ private void enforceCallerSystemUserHandle() {
+ final int callingUid = mInjector.binderGetCallingUid();
+ final int userId = UserHandle.getUserId(callingUid);
+ if (userId != UserHandle.USER_SYSTEM) {
+ throw new SecurityException("Caller has to be in user 0");
+ }
+ }
+
@Override
public boolean isUninstallInQueue(final String packageName) {
enforceCanManageDeviceAdmin();
@@ -9142,17 +9154,18 @@
@Override
public void forceUpdateUserSetupComplete() {
enforceCanManageProfileAndDeviceOwners();
- List<UserInfo> users = mUserManager.getUsers(true);
- final int N = users.size();
- for (int i = 0; i < N; i++) {
- int userHandle = users.get(i).id;
- boolean isUserCompleted = mInjector.settingsSecureGetIntForUser(
- Settings.Secure.USER_SETUP_COMPLETE, 0, userHandle) != 0;
- DevicePolicyData policy = getUserData(userHandle);
- policy.mUserSetupComplete = isUserCompleted;
- synchronized (this) {
- saveSettingsLocked(userHandle);
- }
+ enforceCallerSystemUserHandle();
+ // no effect if it's called from user build
+ if (!mInjector.isBuildDebuggable()) {
+ return;
+ }
+ final int userId = UserHandle.USER_SYSTEM;
+ boolean isUserCompleted = mInjector.settingsSecureGetIntForUser(
+ Settings.Secure.USER_SETUP_COMPLETE, 0, userId) != 0;
+ DevicePolicyData policy = getUserData(userId);
+ policy.mUserSetupComplete = isUserCompleted;
+ synchronized (this) {
+ saveSettingsLocked(userId);
}
}
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index 6cb4a82..80be62b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -357,5 +357,10 @@
TelephonyManager getTelephonyManager() {
return context.telephonyManager;
}
+
+ @Override
+ boolean isBuildDebuggable() {
+ return context.buildMock.isDebuggable;
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 2d96bff..0fd1286 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -2117,6 +2117,76 @@
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
}
+ public void testForceUpdateUserSetupComplete_permission() {
+ // GIVEN the permission MANAGE_PROFILE_AND_DEVICE_OWNERS is not granted
+ try {
+ dpm.forceUpdateUserSetupComplete();
+ fail("Didn't throw SecurityException");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ public void testForceUpdateUserSetupComplete_systemUser() {
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ // GIVEN calling from user 20
+ mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ try {
+ dpm.forceUpdateUserSetupComplete();
+ fail("Didn't throw SecurityException");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ public void testForceUpdateUserSetupComplete_userbuild() {
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+
+ final int userId = UserHandle.USER_SYSTEM;
+ // GIVEN userComplete is false in SettingsProvider
+ setUserSetupCompleteForUser(false, userId);
+
+ // GIVEN userComplete is true in DPM
+ DevicePolicyManagerService.DevicePolicyData userData =
+ new DevicePolicyManagerService.DevicePolicyData(userId);
+ userData.mUserSetupComplete = true;
+ dpms.mUserData.put(UserHandle.USER_SYSTEM, userData);
+
+ // GIVEN it's user build
+ mContext.buildMock.isDebuggable = false;
+
+ assertTrue(dpms.hasUserSetupCompleted());
+
+ dpm.forceUpdateUserSetupComplete();
+
+ // THEN the state in dpms is not changed
+ assertTrue(dpms.hasUserSetupCompleted());
+ }
+
+ public void testForceUpdateUserSetupComplete_userDebugbuild() {
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+
+ final int userId = UserHandle.USER_SYSTEM;
+ // GIVEN userComplete is false in SettingsProvider
+ setUserSetupCompleteForUser(false, userId);
+
+ // GIVEN userComplete is true in DPM
+ DevicePolicyManagerService.DevicePolicyData userData =
+ new DevicePolicyManagerService.DevicePolicyData(userId);
+ userData.mUserSetupComplete = true;
+ dpms.mUserData.put(UserHandle.USER_SYSTEM, userData);
+
+ // GIVEN it's userdebug build
+ mContext.buildMock.isDebuggable = true;
+
+ assertTrue(dpms.hasUserSetupCompleted());
+
+ dpm.forceUpdateUserSetupComplete();
+
+ // THEN the state in dpms is not changed
+ assertFalse(dpms.hasUserSetupCompleted());
+ }
+
private void setUserSetupCompleteForUser(boolean isUserSetupComplete, int userhandle) {
when(mContext.settings.settingsSecureGetIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 0,
userhandle)).thenReturn(isUserSetupComplete ? 1 : 0);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 0783afc..37430ad 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -132,6 +132,10 @@
}
}
+ public static class BuildMock {
+ public boolean isDebuggable = true;
+ }
+
public static class PowerManagerForMock {
public WakeLock newWakeLock(int levelAndFlags, String tag) {
return null;
@@ -272,6 +276,8 @@
private final ArrayList<UserInfo> mUserInfos = new ArrayList<>();
+ public final BuildMock buildMock = new BuildMock();
+
public DpmMockContext(Context context, File dataDir) {
realTestContext = context;