Tests for owner transfer atomicity.
Test: bit
FrameworksServicesTests:com.android.server.devicepolicy.TransferOwnershipMetadataManagerTest
Test: runtest -x
frameworks/base/services/tests/servicestests/src/com/android/server/devicepolicy/OwnerTransferParamsManagerTest.java
Test: bit
FrameworksServicesTests:com.android.server.devicepolicy.DevicePolicyManagerTest#testRevertDeviceOwnership_noMetadataFile
Test: bit
FrameworksServicesTests:com.android.server.devicepolicy.DevicePolicyManagerTest#testRevertDeviceOwnership_adminAndDeviceMigrated
Test: bit
FrameworksServicesTests:com.android.server.devicepolicy.DevicePolicyManagerTest#testRevertDeviceOwnership_deviceNotMigrated
Test: bit
FrameworksServicesTests:com.android.server.devicepolicy.DevicePolicyManagerTest#testRevertDeviceOwnership_adminAndDeviceNotMigrated
Test: bit
FrameworksServicesTests:com.android.server.devicepolicy.DevicePolicyManagerTest#testRevertProfileOwnership_noMetadataFile
Test: bit
FrameworksServicesTests:com.android.server.devicepolicy.DevicePolicyManagerTest#testRevertProfileOwnership_adminAndProfileMigrated
Test: bit
FrameworksServicesTests:com.android.server.devicepolicy.DevicePolicyManagerTest#testRevertProfileOwnership_profileNotMigrated
Test: bit
FrameworksServicesTests:com.android.server.devicepolicy.DevicePolicyManagerTest#testRevertProfileOwnership_adminAndProfileNotMigrated
Bug: 69543005
Change-Id: I2f0153819346cf5be8e5f966627e9cc7e8dba190
diff --git a/services/tests/servicestests/res/raw/active_admin_migrated.xml b/services/tests/servicestests/res/raw/active_admin_migrated.xml
new file mode 100644
index 0000000..47af30f
--- /dev/null
+++ b/services/tests/servicestests/res/raw/active_admin_migrated.xml
@@ -0,0 +1,11 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<policies setup-complete="true" provisioning-state="3">
+ <admin name="com.another.package.name/whatever.random.class">
+ <policies flags="991"/>
+ <strong-auth-unlock-timeout value="0"/>
+ <user-restrictions no_add_managed_profile="true"/>
+ <default-enabled-user-restrictions>
+ <restriction value="no_add_managed_profile"/>
+ </default-enabled-user-restrictions>
+ </admin>
+</policies>
\ No newline at end of file
diff --git a/services/tests/servicestests/res/raw/active_admin_not_migrated.xml b/services/tests/servicestests/res/raw/active_admin_not_migrated.xml
new file mode 100644
index 0000000..54eba4c
--- /dev/null
+++ b/services/tests/servicestests/res/raw/active_admin_not_migrated.xml
@@ -0,0 +1,11 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<policies setup-complete="true" provisioning-state="3">
+ <admin name="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin1">
+ <policies flags="991"/>
+ <strong-auth-unlock-timeout value="0"/>
+ <user-restrictions no_add_managed_profile="true"/>
+ <default-enabled-user-restrictions>
+ <restriction value="no_add_managed_profile"/>
+ </default-enabled-user-restrictions>
+ </admin>
+</policies>
\ No newline at end of file
diff --git a/services/tests/servicestests/res/raw/device_owner_migrated.xml b/services/tests/servicestests/res/raw/device_owner_migrated.xml
new file mode 100644
index 0000000..4ee05bf
--- /dev/null
+++ b/services/tests/servicestests/res/raw/device_owner_migrated.xml
@@ -0,0 +1,9 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<root>
+<device-owner
+ package="com.another.package.name"
+ name=""
+ component="com.another.package.name/whatever.random.class"
+ userRestrictionsMigrated="true" />
+<device-owner-context userId="0" />
+</root>
\ No newline at end of file
diff --git a/services/tests/servicestests/res/raw/device_owner_not_migrated.xml b/services/tests/servicestests/res/raw/device_owner_not_migrated.xml
new file mode 100644
index 0000000..3a532af
--- /dev/null
+++ b/services/tests/servicestests/res/raw/device_owner_not_migrated.xml
@@ -0,0 +1,9 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<root>
+<device-owner
+ package="com.android.frameworks.servicestests"
+ name=""
+ component="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin1"
+ userRestrictionsMigrated="true" />
+<device-owner-context userId="0" />
+</root>
\ No newline at end of file
diff --git a/services/tests/servicestests/res/raw/profile_owner_migrated.xml b/services/tests/servicestests/res/raw/profile_owner_migrated.xml
new file mode 100644
index 0000000..f73d2cd
--- /dev/null
+++ b/services/tests/servicestests/res/raw/profile_owner_migrated.xml
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<root>
+ <profile-owner package="com.another.package.name"
+ name="com.another.package.name"
+ component="com.another.package.name/whatever.random.class"
+ userRestrictionsMigrated="true"/>
+</root>
\ No newline at end of file
diff --git a/services/tests/servicestests/res/raw/profile_owner_not_migrated.xml b/services/tests/servicestests/res/raw/profile_owner_not_migrated.xml
new file mode 100644
index 0000000..1ce3a47
--- /dev/null
+++ b/services/tests/servicestests/res/raw/profile_owner_not_migrated.xml
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<root>
+ <profile-owner package="com.android.frameworks.servicestests"
+ name="com.android.frameworks.servicestests"
+ component="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin1"
+ userRestrictionsMigrated="true"/>
+</root>
\ No newline at end of file
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 bc65df8..6b87ea9 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -50,6 +50,7 @@
import static org.mockito.hamcrest.MockitoHamcrest.argThat;
import android.Manifest.permission;
+import android.annotation.RawRes;
import android.app.Activity;
import android.app.Notification;
import android.app.admin.DeviceAdminReceiver;
@@ -93,10 +94,13 @@
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import java.io.File;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -202,9 +206,14 @@
setUpUserManager();
}
+ private TransferOwnershipMetadataManager getMockTransferMetadataManager() {
+ return dpms.mTransferOwnershipMetadataManager;
+ }
+
@Override
protected void tearDown() throws Exception {
flushTasks();
+ getMockTransferMetadataManager().deleteMetadataFile();
super.tearDown();
}
@@ -4835,6 +4844,176 @@
AttestationUtils.ID_TYPE_MEID});
}
+ public void testRevertDeviceOwnership_noMetadataFile() throws Exception {
+ setDeviceOwner();
+ initializeDpms();
+ assertFalse(getMockTransferMetadataManager().metadataFileExists());
+ assertTrue(dpms.isDeviceOwner(admin1, UserHandle.USER_SYSTEM));
+ assertTrue(dpms.isAdminActive(admin1, UserHandle.USER_SYSTEM));
+ }
+
+ public void testRevertDeviceOwnership_adminAndDeviceMigrated() throws Exception {
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
+ getDeviceOwnerPoliciesFile());
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.device_owner_migrated),
+ getDeviceOwnerFile());
+ assertDeviceOwnershipRevertedWithFakeTransferMetadata();
+ }
+
+ public void testRevertDeviceOwnership_deviceNotMigrated()
+ throws Exception {
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
+ getDeviceOwnerPoliciesFile());
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.device_owner_not_migrated),
+ getDeviceOwnerFile());
+ assertDeviceOwnershipRevertedWithFakeTransferMetadata();
+ }
+
+ public void testRevertDeviceOwnership_adminAndDeviceNotMigrated()
+ throws Exception {
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_not_migrated),
+ getDeviceOwnerPoliciesFile());
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.device_owner_not_migrated),
+ getDeviceOwnerFile());
+ assertDeviceOwnershipRevertedWithFakeTransferMetadata();
+ }
+
+ public void testRevertProfileOwnership_noMetadataFile() throws Exception {
+ setupProfileOwner();
+ initializeDpms();
+ assertFalse(getMockTransferMetadataManager().metadataFileExists());
+ assertTrue(dpms.isProfileOwner(admin1, DpmMockContext.CALLER_USER_HANDLE));
+ assertTrue(dpms.isAdminActive(admin1, DpmMockContext.CALLER_USER_HANDLE));
+ UserHandle userHandle = UserHandle.of(DpmMockContext.CALLER_USER_HANDLE);
+ }
+
+ public void testRevertProfileOwnership_adminAndProfileMigrated() throws Exception {
+ getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, UserInfo.FLAG_MANAGED_PROFILE,
+ UserHandle.USER_SYSTEM);
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
+ getProfileOwnerPoliciesFile());
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.profile_owner_migrated),
+ getProfileOwnerFile());
+ assertProfileOwnershipRevertedWithFakeTransferMetadata();
+ }
+
+ public void testRevertProfileOwnership_profileNotMigrated() throws Exception {
+ getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, UserInfo.FLAG_MANAGED_PROFILE,
+ UserHandle.USER_SYSTEM);
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
+ getProfileOwnerPoliciesFile());
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.profile_owner_not_migrated),
+ getProfileOwnerFile());
+ assertProfileOwnershipRevertedWithFakeTransferMetadata();
+ }
+
+ public void testRevertProfileOwnership_adminAndProfileNotMigrated() throws Exception {
+ getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, UserInfo.FLAG_MANAGED_PROFILE,
+ UserHandle.USER_SYSTEM);
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_not_migrated),
+ getProfileOwnerPoliciesFile());
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.profile_owner_not_migrated),
+ getProfileOwnerFile());
+ assertProfileOwnershipRevertedWithFakeTransferMetadata();
+ }
+
+ // admin1 is the outgoing DPC, adminAnotherPakcage is the incoming one.
+ private void assertDeviceOwnershipRevertedWithFakeTransferMetadata() throws Exception {
+ writeFakeTransferMetadataFile(UserHandle.USER_SYSTEM,
+ TransferOwnershipMetadataManager.ADMIN_TYPE_DEVICE_OWNER);
+
+ final long ident = mServiceContext.binder.clearCallingIdentity();
+ setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
+ setUpPackageManagerForFakeAdmin(adminAnotherPackage,
+ DpmMockContext.CALLER_SYSTEM_USER_UID, admin1);
+ // To simulate a reboot, we just reinitialize dpms and call systemReady
+ initializeDpms();
+
+ assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
+ assertFalse(dpm.isDeviceOwnerApp(adminAnotherPackage.getPackageName()));
+ assertFalse(dpm.isAdminActive(adminAnotherPackage));
+ assertTrue(dpm.isAdminActive(admin1));
+ assertTrue(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+
+ assertTrue(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+ assertEquals(UserHandle.USER_SYSTEM, dpm.getDeviceOwnerUserId());
+ assertFalse(getMockTransferMetadataManager().metadataFileExists());
+
+ mServiceContext.binder.restoreCallingIdentity(ident);
+ }
+
+ // admin1 is the outgoing DPC, adminAnotherPakcage is the incoming one.
+ private void assertProfileOwnershipRevertedWithFakeTransferMetadata() throws Exception {
+ writeFakeTransferMetadataFile(DpmMockContext.CALLER_USER_HANDLE,
+ TransferOwnershipMetadataManager.ADMIN_TYPE_PROFILE_OWNER);
+
+ int uid = UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE,
+ DpmMockContext.CALLER_SYSTEM_USER_UID);
+ setUpPackageManagerForAdmin(admin1, uid);
+ setUpPackageManagerForFakeAdmin(adminAnotherPackage, uid, admin1);
+ // To simulate a reboot, we just reinitialize dpms and call systemReady
+ initializeDpms();
+
+ assertTrue(dpm.isProfileOwnerApp(admin1.getPackageName()));
+ assertTrue(dpm.isAdminActive(admin1));
+ assertFalse(dpm.isProfileOwnerApp(adminAnotherPackage.getPackageName()));
+ assertFalse(dpm.isAdminActive(adminAnotherPackage));
+ assertEquals(dpm.getProfileOwnerAsUser(DpmMockContext.CALLER_USER_HANDLE), admin1);
+ assertFalse(getMockTransferMetadataManager().metadataFileExists());
+ }
+
+ private void writeFakeTransferMetadataFile(int callerUserHandle, String adminType) {
+ TransferOwnershipMetadataManager metadataManager = getMockTransferMetadataManager();
+ metadataManager.deleteMetadataFile();
+
+ final TransferOwnershipMetadataManager.Metadata metadata =
+ new TransferOwnershipMetadataManager.Metadata(
+ admin1.flattenToString(), adminAnotherPackage.flattenToString(),
+ callerUserHandle,
+ adminType);
+ metadataManager.saveMetadataFile(metadata);
+ }
+
+ private File getDeviceOwnerFile() {
+ return dpms.mOwners.getDeviceOwnerFile();
+ }
+
+ private File getProfileOwnerFile() {
+ return dpms.mOwners.getProfileOwnerFile(DpmMockContext.CALLER_USER_HANDLE);
+ }
+
+ private File getProfileOwnerPoliciesFile() {
+ File parentDir = dpms.mMockInjector.environmentGetUserSystemDirectory(
+ DpmMockContext.CALLER_USER_HANDLE);
+ return getPoliciesFile(parentDir);
+ }
+
+ private File getDeviceOwnerPoliciesFile() {
+ return getPoliciesFile(getServices().systemUserDataDir);
+ }
+
+ private File getPoliciesFile(File parentDir) {
+ return new File(parentDir, "device_policies.xml");
+ }
+
+ private InputStream getRawStream(@RawRes int id) {
+ return mRealTestContext.getResources().openRawResource(id);
+ }
+
private void setUserSetupCompleteForUser(boolean isUserSetupComplete, int userhandle) {
when(getServices().settings.settingsSecureGetIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 0,
userhandle)).thenReturn(isUserSetupComplete ? 1 : 0);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java
index cceb2d2..2882b88 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java
@@ -16,9 +16,6 @@
package com.android.server.devicepolicy;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Sets;
-
import android.content.Context;
import android.os.Bundle;
import android.os.FileUtils;
@@ -28,21 +25,25 @@
import android.util.Log;
import android.util.Printer;
+import libcore.io.Streams;
+
+import com.google.android.collect.Lists;
+
+import junit.framework.AssertionFailedError;
+
import org.junit.Assert;
import java.io.BufferedReader;
import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-
-import junit.framework.AssertionFailedError;
public class DpmTestUtils extends AndroidTestCase {
public static void clearDir(File dir) {
@@ -136,6 +137,11 @@
}
}
+ public static void writeInputStreamToFile(InputStream stream, File file)
+ throws IOException {
+ Streams.copy(stream, new FileOutputStream(file));
+ }
+
private static boolean checkAssertRestrictions(Bundle a, Bundle b) {
try {
assertRestrictions(a, b);