1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.server.devicepolicy; 17 18 import static android.os.UserHandle.USER_SYSTEM; 19 20 import static com.android.server.devicepolicy.DpmTestUtils.writeInputStreamToFile; 21 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; 22 23 import static com.google.common.truth.Truth.assertThat; 24 import static com.google.common.truth.Truth.assertWithMessage; 25 26 import static org.mockito.ArgumentMatchers.anyBoolean; 27 import static org.mockito.Matchers.any; 28 import static org.mockito.Matchers.anyInt; 29 import static org.mockito.Matchers.eq; 30 import static org.mockito.Mockito.never; 31 import static org.mockito.Mockito.verify; 32 import static org.mockito.Mockito.when; 33 34 import android.app.admin.DevicePolicyManager; 35 import android.content.ComponentName; 36 import android.content.Intent; 37 import android.content.pm.PackageManager; 38 import android.os.Build; 39 import android.os.IpcDataCache; 40 import android.os.UserHandle; 41 import android.os.UserManager; 42 import android.platform.test.annotations.Presubmit; 43 import android.provider.Settings; 44 45 import androidx.test.filters.SmallTest; 46 import androidx.test.runner.AndroidJUnit4; 47 48 import com.android.frameworks.servicestests.R; 49 import com.android.server.SystemService; 50 51 import org.junit.Before; 52 import org.junit.Ignore; 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 56 import java.io.File; 57 import java.util.Set; 58 59 @Presubmit 60 @RunWith(AndroidJUnit4.class) 61 public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { 62 63 private static final int COPE_ADMIN1_APP_ID = 123; 64 private static final int COPE_ANOTHER_ADMIN_APP_ID = 125; 65 private static final int COPE_PROFILE_USER_ID = 11; 66 67 private DpmMockContext mContext; 68 69 @Before setUp()70 public void setUp() throws Exception { 71 72 // Disable caches in this test process. This must happen early, since some of the 73 // following initialization steps invalidate caches. 74 IpcDataCache.disableForTestMode(); 75 76 mContext = getContext(); 77 78 // Make createContextAsUser to work. 79 mContext.packageName = "com.android.frameworks.servicestests"; 80 getServices().addPackageContext(UserHandle.of(0), mContext); 81 82 when(getServices().packageManager.hasSystemFeature(eq(PackageManager.FEATURE_DEVICE_ADMIN))) 83 .thenReturn(true); 84 when(getServices().userManagerInternal.getUserIds()).thenReturn(new int[]{0}); 85 } 86 87 // Test setting default restrictions for managed profile. 88 @Test 89 @Ignore("b/277916462") testMigration_managedProfileOwner()90 public void testMigration_managedProfileOwner() throws Exception { 91 // Create a managed profile user. 92 final File user10dir = getServices().addUser(10, 0, 93 UserManager.USER_TYPE_PROFILE_MANAGED); 94 // Profile owner package for managed profile user. 95 setUpPackageManagerForAdmin(admin1, UserHandle.getUid(10, 123)); 96 // Set up fake UserManager to make it look like a managed profile. 97 when(getServices().userManager.isManagedProfile(eq(10))).thenReturn(true); 98 // Set up fake Settings to make it look like INSTALL_NON_MARKET_APPS was reversed. 99 when(getServices().settings.settingsSecureGetIntForUser( 100 eq(Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED), 101 eq(0), eq(10))).thenReturn(1); 102 // Write policy and owners files. 103 DpmTestUtils.writeToFile( 104 (new File(getServices().systemUserDataDir, "device_policies.xml")).getAbsoluteFile(), 105 DpmTestUtils.readAsset(mRealTestContext, 106 "DevicePolicyManagerServiceMigrationTest3/system_device_policies.xml")); 107 DpmTestUtils.writeToFile( 108 (new File(user10dir, "device_policies.xml")).getAbsoluteFile(), 109 DpmTestUtils.readAsset(mRealTestContext, 110 "DevicePolicyManagerServiceMigrationTest3/profile_device_policies.xml")); 111 DpmTestUtils.writeToFile( 112 (new File(user10dir, "profile_owner.xml")).getAbsoluteFile(), 113 DpmTestUtils.readAsset(mRealTestContext, 114 "DevicePolicyManagerServiceMigrationTest3/profile_owner.xml")); 115 116 final DevicePolicyManagerServiceTestable dpms; 117 118 // Initialize DPM/DPMS and let it migrate the persisted information. 119 // (Need clearCallingIdentity() to pass permission checks.) 120 final long ident = mContext.binder.clearCallingIdentity(); 121 try { 122 dpms = new DevicePolicyManagerServiceTestable(getServices(), mContext); 123 124 dpms.systemReady(SystemService.PHASE_LOCK_SETTINGS_READY); 125 dpms.systemReady(SystemService.PHASE_BOOT_COMPLETED); 126 } finally { 127 mContext.binder.restoreCallingIdentity(ident); 128 } 129 130 assertThat(dpms.mOwners.hasDeviceOwner()).isFalse(); 131 assertThat(dpms.mOwners.hasProfileOwner(10)).isTrue(); 132 133 // Check that default restrictions were applied. 134 DpmTestUtils.assertRestrictions( 135 DpmTestUtils.newRestrictions( 136 UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, 137 UserManager.DISALLOW_BLUETOOTH_SHARING 138 ), 139 dpms.getProfileOwnerAdminLocked(10).ensureUserRestrictions()); 140 141 final Set<String> alreadySet = 142 dpms.getProfileOwnerAdminLocked(10).defaultEnabledRestrictionsAlreadySet; 143 assertThat(alreadySet).hasSize(1); 144 assertThat(alreadySet.contains(UserManager.DISALLOW_BLUETOOTH_SHARING)).isTrue(); 145 } 146 147 @SmallTest 148 @Test testCompMigrationUnAffiliated_skipped()149 public void testCompMigrationUnAffiliated_skipped() throws Exception { 150 prepareAdmin1AsDo(); 151 prepareAdminAnotherPackageAsPo(COPE_PROFILE_USER_ID); 152 153 final DevicePolicyManagerServiceTestable dpms = bootDpmsUp(); 154 155 // DO should still be DO since no migration should happen. 156 assertThat(dpms.mOwners.hasDeviceOwner()).isTrue(); 157 } 158 159 @SmallTest 160 @Test 161 @Ignore("b/269249457") testCompMigrationAffiliated()162 public void testCompMigrationAffiliated() throws Exception { 163 prepareAdmin1AsDo(); 164 prepareAdmin1AsPo(COPE_PROFILE_USER_ID, Build.VERSION_CODES.R); 165 166 // Secure lock screen is needed for password policy APIs to work. 167 when(getServices().lockPatternUtils.hasSecureLockScreen()).thenReturn(true); 168 169 final DevicePolicyManagerServiceTestable dpms = bootDpmsUp(); 170 171 // DO should cease to be DO. 172 assertThat(dpms.mOwners.hasDeviceOwner()).isFalse(); 173 174 final DpmMockContext poContext = new DpmMockContext(getServices(), mRealTestContext); 175 poContext.binder.callingUid = UserHandle.getUid(COPE_PROFILE_USER_ID, COPE_ADMIN1_APP_ID); 176 177 runAsCaller(poContext, dpms, dpm -> { 178 assertWithMessage("Password history policy wasn't migrated to PO parent instance") 179 .that(dpm.getParentProfileInstance(admin1).getPasswordHistoryLength(admin1)) 180 .isEqualTo(33); 181 assertWithMessage("Password history policy was put into non-parent PO instance") 182 .that(dpm.getPasswordHistoryLength(admin1)).isEqualTo(0); 183 assertWithMessage("Screen capture restriction wasn't migrated to PO parent instance") 184 .that(dpm.getParentProfileInstance(admin1).getScreenCaptureDisabled(admin1)) 185 .isTrue(); 186 187 assertWithMessage("Accounts with management disabled weren't migrated to PO parent") 188 .that(dpm.getParentProfileInstance(admin1) 189 .getAccountTypesWithManagementDisabled()).asList() 190 .containsExactly("com.google-primary"); 191 192 assertWithMessage("Accounts with management disabled for profile were lost") 193 .that(dpm.getAccountTypesWithManagementDisabled()).asList() 194 .containsExactly("com.google-profile"); 195 196 assertWithMessage("User restriction wasn't migrated to PO parent instance") 197 .that(dpm.getParentProfileInstance(admin1).getUserRestrictions(admin1).keySet()) 198 .contains(UserManager.DISALLOW_BLUETOOTH); 199 200 assertWithMessage("User restriction was put into non-parent PO instance").that( 201 dpm.getUserRestrictions(admin1).keySet()) 202 .doesNotContain(UserManager.DISALLOW_BLUETOOTH); 203 204 assertWithMessage("User restriction wasn't migrated to PO parent instance") 205 .that(dpms.getProfileOwnerAdminLocked(COPE_PROFILE_USER_ID) 206 .getParentActiveAdmin().getEffectiveRestrictions().keySet()) 207 .contains(UserManager.DISALLOW_CONFIG_DATE_TIME); 208 assertWithMessage("User restriction was put into non-parent PO instance") 209 .that(dpms.getProfileOwnerAdminLocked(COPE_PROFILE_USER_ID) 210 .getEffectiveRestrictions().keySet()) 211 .doesNotContain(UserManager.DISALLOW_CONFIG_DATE_TIME); 212 assertWithMessage("Personal apps suspension wasn't migrated") 213 .that(dpm.getPersonalAppsSuspendedReasons(admin1)) 214 .isEqualTo(DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED); 215 }); 216 } 217 218 @SmallTest 219 @Test testCompMigration_keepSuspendedAppsWhenDpcIsRPlus()220 public void testCompMigration_keepSuspendedAppsWhenDpcIsRPlus() throws Exception { 221 prepareAdmin1AsDo(); 222 prepareAdmin1AsPo(COPE_PROFILE_USER_ID, Build.VERSION_CODES.R); 223 224 // Pretend some packages are suspended. 225 when(getServices().packageManagerInternal.isSuspendingAnyPackages( 226 PLATFORM_PACKAGE_NAME, USER_SYSTEM)).thenReturn(true); 227 228 final DevicePolicyManagerServiceTestable dpms = bootDpmsUp(); 229 230 verify(getServices().packageManagerInternal, never()) 231 .unsuspendForSuspendingPackage(PLATFORM_PACKAGE_NAME, USER_SYSTEM); 232 233 sendBroadcastWithUser(dpms, Intent.ACTION_USER_STARTED, USER_SYSTEM); 234 235 // Verify that actual package suspension state is not modified after user start 236 verify(getServices().packageManagerInternal, never()) 237 .unsuspendForSuspendingPackage(PLATFORM_PACKAGE_NAME, USER_SYSTEM); 238 verify(getServices().ipackageManager, never()).setPackagesSuspendedAsUser( 239 any(), anyBoolean(), any(), any(), any(), any(), anyInt()); 240 241 final DpmMockContext poContext = new DpmMockContext(getServices(), mRealTestContext); 242 poContext.binder.callingUid = UserHandle.getUid(COPE_PROFILE_USER_ID, COPE_ADMIN1_APP_ID); 243 244 runAsCaller(poContext, dpms, dpm -> { 245 assertWithMessage("Personal apps suspension wasn't migrated") 246 .that(dpm.getPersonalAppsSuspendedReasons(admin1)) 247 .isEqualTo(DevicePolicyManager.PERSONAL_APPS_SUSPENDED_EXPLICITLY); 248 }); 249 } 250 251 @SmallTest 252 @Test testCompMigration_unsuspendAppsWhenDpcNotRPlus()253 public void testCompMigration_unsuspendAppsWhenDpcNotRPlus() throws Exception { 254 prepareAdmin1AsDo(); 255 prepareAdmin1AsPo(COPE_PROFILE_USER_ID, Build.VERSION_CODES.Q); 256 257 // Pretend some packages are suspended. 258 when(getServices().packageManagerInternal.isSuspendingAnyPackages( 259 PLATFORM_PACKAGE_NAME, USER_SYSTEM)).thenReturn(true); 260 261 final DevicePolicyManagerServiceTestable dpms = bootDpmsUp(); 262 263 // Verify that apps get unsuspended. 264 verify(getServices().packageManagerInternal) 265 .unsuspendForSuspendingPackage(PLATFORM_PACKAGE_NAME, USER_SYSTEM); 266 267 final DpmMockContext poContext = new DpmMockContext(getServices(), mRealTestContext); 268 poContext.binder.callingUid = UserHandle.getUid(COPE_PROFILE_USER_ID, COPE_ADMIN1_APP_ID); 269 270 runAsCaller(poContext, dpms, dpm -> { 271 assertWithMessage("Personal apps weren't unsuspended") 272 .that(dpm.getPersonalAppsSuspendedReasons(admin1)) 273 .isEqualTo(DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED); 274 }); 275 } 276 bootDpmsUp()277 private DevicePolicyManagerServiceTestable bootDpmsUp() { 278 DevicePolicyManagerServiceTestable dpms; 279 final long ident = mContext.binder.clearCallingIdentity(); 280 try { 281 dpms = new DevicePolicyManagerServiceTestable(getServices(), mContext); 282 283 dpms.systemReady(SystemService.PHASE_LOCK_SETTINGS_READY); 284 dpms.systemReady(SystemService.PHASE_ACTIVITY_MANAGER_READY); 285 dpms.systemReady(SystemService.PHASE_BOOT_COMPLETED); 286 } finally { 287 mContext.binder.restoreCallingIdentity(ident); 288 } 289 return dpms; 290 } 291 prepareAdmin1AsDo()292 private void prepareAdmin1AsDo() throws Exception { 293 setUpPackageManagerForAdmin(admin1, UserHandle.getUid(USER_SYSTEM, COPE_ADMIN1_APP_ID)); 294 final int xmlResource = R.raw.comp_policies_primary; 295 File dataSystemDirectory = getServices().pathProvider.getDataSystemDirectory(); 296 writeInputStreamToFile(getRawStream(xmlResource), 297 (new File(dataSystemDirectory, "device_policies.xml")).getAbsoluteFile()); 298 writeInputStreamToFile(getRawStream(R.raw.comp_device_owner), 299 (new File(dataSystemDirectory, "device_owner_2.xml")).getAbsoluteFile()); 300 } 301 prepareAdmin1AsPo(int profileUserId, int targetSdk)302 private void prepareAdmin1AsPo(int profileUserId, int targetSdk) throws Exception { 303 preparePo(profileUserId, admin1, R.raw.comp_profile_owner_same_package, 304 R.raw.comp_policies_profile_same_package, COPE_ADMIN1_APP_ID, targetSdk); 305 } 306 prepareAdminAnotherPackageAsPo(int profileUserId)307 private void prepareAdminAnotherPackageAsPo(int profileUserId) throws Exception { 308 preparePo(profileUserId, adminAnotherPackage, R.raw.comp_profile_owner_another_package, 309 R.raw.comp_policies_profile_another_package, COPE_ANOTHER_ADMIN_APP_ID, 310 Build.VERSION.SDK_INT); 311 } 312 preparePo(int profileUserId, ComponentName admin, int profileOwnerXmlResId, int policyXmlResId, int adminAppId, int targetSdk)313 private void preparePo(int profileUserId, ComponentName admin, int profileOwnerXmlResId, 314 int policyXmlResId, int adminAppId, int targetSdk) throws Exception { 315 final File profileDir = getServices().addUser(profileUserId, 0, 316 UserManager.USER_TYPE_PROFILE_MANAGED, USER_SYSTEM /* profile group */); 317 setUpPackageManagerForFakeAdmin(admin, UserHandle.getUid(profileUserId, adminAppId), 318 /* enabledSetting =*/ null, targetSdk, admin1); 319 writeInputStreamToFile(getRawStream(policyXmlResId), 320 (new File(profileDir, "device_policies.xml")).getAbsoluteFile()); 321 writeInputStreamToFile(getRawStream(profileOwnerXmlResId), 322 (new File(profileDir, "profile_owner.xml")).getAbsoluteFile()); 323 } 324 325 } 326