blob: 0da459dab0d603fd6c185840f23aecd58c8eed33 [file] [log] [blame]
Makoto Onukicc4bbeb2015-09-17 10:28:24 -07001/*
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 */
Makoto Onukicc4bbeb2015-09-17 10:28:24 -070016package com.android.server.devicepolicy;
17
18import com.android.server.LocalServices;
19
Makoto Onukif76b06a2015-09-22 15:03:44 -070020import android.Manifest.permission;
21import android.app.Activity;
Makoto Onukicc4bbeb2015-09-17 10:28:24 -070022import android.app.admin.DeviceAdminReceiver;
23import android.app.admin.DevicePolicyManager;
24import android.app.admin.DevicePolicyManagerInternal;
Makoto Onukif76b06a2015-09-22 15:03:44 -070025import android.content.BroadcastReceiver;
Makoto Onukicc4bbeb2015-09-17 10:28:24 -070026import android.content.ComponentName;
27import android.content.Intent;
Makoto Onukif76b06a2015-09-22 15:03:44 -070028import android.content.pm.ApplicationInfo;
29import android.content.pm.IPackageManager;
Makoto Onukicc4bbeb2015-09-17 10:28:24 -070030import android.content.pm.PackageManager;
31import android.content.pm.ResolveInfo;
Makoto Onukif76b06a2015-09-22 15:03:44 -070032import android.os.Bundle;
Makoto Onukicc4bbeb2015-09-17 10:28:24 -070033
34import org.mockito.ArgumentCaptor;
35
36import java.util.List;
37
38import static org.mockito.Matchers.any;
Makoto Onukif76b06a2015-09-22 15:03:44 -070039import static org.mockito.Matchers.anyString;
Makoto Onukicc4bbeb2015-09-17 10:28:24 -070040import static org.mockito.Matchers.eq;
Makoto Onukif76b06a2015-09-22 15:03:44 -070041import static org.mockito.Matchers.isNull;
Makoto Onukicc4bbeb2015-09-17 10:28:24 -070042import static org.mockito.Mockito.doReturn;
43import static org.mockito.Mockito.times;
44import static org.mockito.Mockito.verify;
45import static org.mockito.Mockito.when;
46
47/**
Makoto Onukif76b06a2015-09-22 15:03:44 -070048 * Tests for DevicePolicyManager( and DevicePolicyManagerService).
Makoto Onukicc4bbeb2015-09-17 10:28:24 -070049 *
50 m FrameworksServicesTests &&
51 adb install \
52 -r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
53 adb shell am instrument -e class com.android.server.devicepolicy.DevicePolicyManagerTest \
54 -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
55
56 (mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
57 */
58public class DevicePolicyManagerTest extends DpmTestBase {
59
Makoto Onukif76b06a2015-09-22 15:03:44 -070060
Makoto Onukicc4bbeb2015-09-17 10:28:24 -070061 private DpmMockContext mContext;
62 public DevicePolicyManager dpm;
63 public DevicePolicyManagerServiceTestable dpms;
Makoto Onukif76b06a2015-09-22 15:03:44 -070064 public ComponentName admin1;
65 public ComponentName admin2;
66 public ComponentName admin3;
Makoto Onukicc4bbeb2015-09-17 10:28:24 -070067
68 @Override
69 protected void setUp() throws Exception {
70 super.setUp();
71
72 mContext = getContext();
73
74 when(mContext.packageManager.hasSystemFeature(eq(PackageManager.FEATURE_DEVICE_ADMIN)))
75 .thenReturn(true);
76
77 LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
78 dpms = new DevicePolicyManagerServiceTestable(mContext, dataDir);
79 dpm = new DevicePolicyManagerTestable(mContext, dpms);
Makoto Onukif76b06a2015-09-22 15:03:44 -070080
81 admin1 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin1.class);
82 admin2 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin2.class);
83 admin3 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin3.class);
84
85 setUpPackageManagerForAdmin(admin1);
86 setUpPackageManagerForAdmin(admin2);
87 setUpPackageManagerForAdmin(admin3);
88
89 setUpApplicationInfo(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
90 }
91
92 /**
93 * Set up a mock result for {@link PackageManager#queryBroadcastReceivers}. We'll return
94 * the actual ResolveInfo for the admin component, but we need to mock PM so it'll return
95 * it for user {@link DpmMockContext#CALLER_USER_HANDLE}.
96 */
97 private void setUpPackageManagerForAdmin(ComponentName admin) {
98 final Intent resolveIntent = new Intent();
99 resolveIntent.setComponent(admin);
100 final List<ResolveInfo> realResolveInfo =
101 mRealTestContext.getPackageManager().queryBroadcastReceivers(
102 resolveIntent,
103 PackageManager.GET_META_DATA);
104 assertNotNull(realResolveInfo);
105 assertEquals(1, realResolveInfo.size());
106
107 // We need to rewrite the UID in the activity info.
108 realResolveInfo.get(0).activityInfo.applicationInfo.uid = DpmMockContext.CALLER_UID;
109
110 doReturn(realResolveInfo).when(mContext.packageManager).queryBroadcastReceivers(
111 MockUtils.checkIntentComponent(admin),
112 eq(PackageManager.GET_META_DATA
113 | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
114 eq(DpmMockContext.CALLER_USER_HANDLE)
115 );
116 }
117
118 /**
119 * Set up a mock result for {@link IPackageManager#getApplicationInfo} for user
120 * {@link DpmMockContext#CALLER_USER_HANDLE}.
121 */
122 private void setUpApplicationInfo(int enabledSetting) throws Exception {
123 final ApplicationInfo ai = mRealTestContext.getPackageManager().getApplicationInfo(
124 admin1.getPackageName(),
125 PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
126
127 ai.enabledSetting = enabledSetting;
128
129 doReturn(ai).when(mContext.ipackageManager).getApplicationInfo(
130 eq(admin1.getPackageName()),
131 eq(PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
132 eq(DpmMockContext.CALLER_USER_HANDLE));
Makoto Onukicc4bbeb2015-09-17 10:28:24 -0700133 }
134
135 public void testHasNoFeature() {
136 when(mContext.packageManager.hasSystemFeature(eq(PackageManager.FEATURE_DEVICE_ADMIN)))
137 .thenReturn(false);
138
139 LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
140 new DevicePolicyManagerServiceTestable(mContext, dataDir);
141
142 // If the device has no DPMS feature, it shouldn't register the local service.
143 assertNull(LocalServices.getService(DevicePolicyManagerInternal.class));
144 }
145
146 /**
147 * Caller doesn't have proper permissions.
148 */
149 public void testSetActiveAdmin_SecurityException() {
Makoto Onukicc4bbeb2015-09-17 10:28:24 -0700150 // 1. Failure cases.
151
152 // Caller doesn't have MANAGE_DEVICE_ADMINS.
153 try {
Makoto Onukif76b06a2015-09-22 15:03:44 -0700154 dpm.setActiveAdmin(admin1, false);
Makoto Onukicc4bbeb2015-09-17 10:28:24 -0700155 fail("Didn't throw SecurityException");
156 } catch (SecurityException expected) {
157 }
158
159 // Caller has MANAGE_DEVICE_ADMINS, but for different user.
160 mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
161 try {
Makoto Onukif76b06a2015-09-22 15:03:44 -0700162 dpm.setActiveAdmin(admin1, false, DpmMockContext.CALLER_USER_HANDLE + 1);
Makoto Onukicc4bbeb2015-09-17 10:28:24 -0700163 fail("Didn't throw SecurityException");
164 } catch (SecurityException expected) {
165 }
166 }
167
Makoto Onukif76b06a2015-09-22 15:03:44 -0700168 /**
169 * Test for:
170 * {@link DevicePolicyManager#setActiveAdmin}
171 * with replace=false and replace=true
172 * {@link DevicePolicyManager#isAdminActive}
173 * {@link DevicePolicyManager#isAdminActiveAsUser}
174 * {@link DevicePolicyManager#getActiveAdmins}
175 * {@link DevicePolicyManager#getActiveAdminsAsUser}
176 */
177 public void testSetActiveAdmin() throws Exception {
178 // 1. Make sure the caller has proper permissions.
Makoto Onukicc4bbeb2015-09-17 10:28:24 -0700179 mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
180
Makoto Onukif76b06a2015-09-22 15:03:44 -0700181 // 2. Call the API.
182 dpm.setActiveAdmin(admin1, /* replace =*/ false);
Makoto Onukicc4bbeb2015-09-17 10:28:24 -0700183
184 // 3. Verify internal calls.
185
186 // Check if the boradcast is sent.
Makoto Onukif76b06a2015-09-22 15:03:44 -0700187 verify(mContext.spiedContext).sendBroadcastAsUser(
188 MockUtils.checkIntentAction(
189 DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
190 MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
191 verify(mContext.spiedContext).sendBroadcastAsUser(
192 MockUtils.checkIntentAction(
193 DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED),
Makoto Onukicc4bbeb2015-09-17 10:28:24 -0700194 MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
195
Makoto Onukif76b06a2015-09-22 15:03:44 -0700196 verify(mContext.ipackageManager, times(1)).setApplicationEnabledSetting(
197 eq(admin1.getPackageName()),
198 eq(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT),
199 eq(PackageManager.DONT_KILL_APP),
200 eq(DpmMockContext.CALLER_USER_HANDLE),
201 anyString());
Makoto Onukicc4bbeb2015-09-17 10:28:24 -0700202
203 // TODO Verify other calls too.
Makoto Onukif76b06a2015-09-22 15:03:44 -0700204
205 // Make sure it's active admin1.
206 assertTrue(dpm.isAdminActive(admin1));
207 assertFalse(dpm.isAdminActive(admin2));
208 assertFalse(dpm.isAdminActive(admin3));
209
210 // But not admin1 for a different user.
211
212 // For this to work, caller needs android.permission.INTERACT_ACROSS_USERS_FULL.
213 // (Because we're checking a different user's status from CALLER_USER_HANDLE.)
214 mContext.callerPermissions.add("android.permission.INTERACT_ACROSS_USERS_FULL");
215
216 assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE + 1));
217 assertFalse(dpm.isAdminActiveAsUser(admin2, DpmMockContext.CALLER_USER_HANDLE + 1));
218
219 mContext.callerPermissions.remove("android.permission.INTERACT_ACROSS_USERS_FULL");
220
221 // Next, add one more admin.
222 // Before doing so, update the application info, now it's enabled.
223 setUpApplicationInfo(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
224
225 dpm.setActiveAdmin(admin2, /* replace =*/ false);
226
227 // Now we have two admins.
228 assertTrue(dpm.isAdminActive(admin1));
229 assertTrue(dpm.isAdminActive(admin2));
230 assertFalse(dpm.isAdminActive(admin3));
231
232 // Admin2 was already enabled, so setApplicationEnabledSetting() shouldn't have called
233 // again. (times(1) because it was previously called for admin1)
234 verify(mContext.ipackageManager, times(1)).setApplicationEnabledSetting(
235 eq(admin1.getPackageName()),
236 eq(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT),
237 eq(PackageManager.DONT_KILL_APP),
238 eq(DpmMockContext.CALLER_USER_HANDLE),
239 anyString());
240
241 // 4. Add the same admin1 again without replace, which should throw.
242 try {
243 dpm.setActiveAdmin(admin1, /* replace =*/ false);
244 fail("Didn't throw");
245 } catch (IllegalArgumentException expected) {
246 }
247
248 // 5. Add the same admin1 again with replace, which should succeed.
249 dpm.setActiveAdmin(admin1, /* replace =*/ true);
250
251 // TODO make sure it's replaced.
252
253 // 6. Test getActiveAdmins()
254 List<ComponentName> admins = dpm.getActiveAdmins();
255 assertEquals(2, admins.size());
256 assertEquals(admin1, admins.get(0));
257 assertEquals(admin2, admins.get(1));
258
259 // Another user has no admins.
260 mContext.callerPermissions.add("android.permission.INTERACT_ACROSS_USERS_FULL");
261
262 assertEquals(0, DpmTestUtils.getListSizeAllowingNull(
263 dpm.getActiveAdminsAsUser(DpmMockContext.CALLER_USER_HANDLE + 1)));
264
265 mContext.callerPermissions.remove("android.permission.INTERACT_ACROSS_USERS_FULL");
266 }
267
268 /**
269 * Test for:
270 * {@link DevicePolicyManager#setActiveAdmin}
271 * with replace=false
272 */
273 public void testSetActiveAdmin_twiceWithoutReplace() throws Exception {
274 // 1. Make sure the caller has proper permissions.
275 mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
276
277 dpm.setActiveAdmin(admin1, /* replace =*/ false);
278 assertTrue(dpm.isAdminActive(admin1));
279
280 // Add the same admin1 again without replace, which should throw.
281 try {
282 dpm.setActiveAdmin(admin1, /* replace =*/ false);
283 fail("Didn't throw");
284 } catch (IllegalArgumentException expected) {
285 }
286 }
287
288 /**
289 * Test for:
290 * {@link DevicePolicyManager#removeActiveAdmin}
291 */
292 public void testRemoveActiveAdmin_SecurityException() {
293 mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
294
295 // Add admin.
296
297 dpm.setActiveAdmin(admin1, /* replace =*/ false);
298
299 assertTrue(dpm.isAdminActive(admin1));
300
301 assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
302
303 // Directly call the DPMS method with a different userid, which should fail.
304 try {
305 dpms.removeActiveAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE + 1);
306 fail("Didn't throw SecurityException");
307 } catch (SecurityException expected) {
308 }
309
310 // Try to remove active admin with a different caller userid should fail too, without
311 // having MANAGE_DEVICE_ADMINS.
312 mContext.callerPermissions.clear();
313
314 mContext.binder.callingUid = 1234567;
315 try {
316 dpm.removeActiveAdmin(admin1);
317 fail("Didn't throw SecurityException");
318 } catch (SecurityException expected) {
319 }
320 }
321
322 /**
323 * Test for:
324 * {@link DevicePolicyManager#removeActiveAdmin}
325 */
326 public void testRemoveActiveAdmin_fromDifferentUserWithMINTERACT_ACROSS_USERS_FULL() {
327 mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
328
329 // Add admin1.
330
331 dpm.setActiveAdmin(admin1, /* replace =*/ false);
332
333 assertTrue(dpm.isAdminActive(admin1));
334 assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
335
336 // Different user, but should work, because caller has proper permissions.
337 mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
338 mContext.binder.callingUid = 1234567;
339 dpm.removeActiveAdmin(admin1);
340
341 assertTrue(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
342
343 // TODO DO Still can't be removed in this case.
344 }
345
346 /**
347 * Test for:
348 * {@link DevicePolicyManager#removeActiveAdmin}
349 */
350 public void testRemoveActiveAdmin_sameUserNoMANAGE_DEVICE_ADMINS() {
351 // Need MANAGE_DEVICE_ADMINS for setActiveAdmin. We'll remove it later.
352 mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
353
354 // Add admin1.
355
356 dpm.setActiveAdmin(admin1, /* replace =*/ false);
357
358 assertTrue(dpm.isAdminActive(admin1));
359 assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
360
361 // Broadcast from saveSettingsLocked().
362 verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
363 MockUtils.checkIntentAction(
364 DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
365 MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
366
367 // Remove. No permissions, but same user, so it'll work.
368 mContext.callerPermissions.clear();
369 dpm.removeActiveAdmin(admin1);
370
371 final ArgumentCaptor<BroadcastReceiver> brCap =
372 ArgumentCaptor.forClass(BroadcastReceiver.class);
373
374 // Is removing now, but not removed yet.
375 assertTrue(dpm.isAdminActive(admin1));
376 assertTrue(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
377
378 verify(mContext.spiedContext).sendOrderedBroadcastAsUser(
379 MockUtils.checkIntentAction(
380 DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED),
381 MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE),
382 isNull(String.class),
383 brCap.capture(),
384 eq(dpms.mHandler),
385 eq(Activity.RESULT_OK),
386 isNull(String.class),
387 isNull(Bundle.class));
388
389 brCap.getValue().onReceive(mContext, null);
390
391 assertFalse(dpm.isAdminActive(admin1));
392 assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
393
394 // Again broadcast from saveSettingsLocked().
395 verify(mContext.spiedContext, times(2)).sendBroadcastAsUser(
396 MockUtils.checkIntentAction(
397 DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
398 MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
399
400 // TODO Check other internal calls.
Makoto Onukicc4bbeb2015-09-17 10:28:24 -0700401 }
402}
403
Makoto Onukif76b06a2015-09-22 15:03:44 -0700404