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