blob: a4b9b256aa075f3eda4d2b612ce1eec4471bd684 [file] [log] [blame]
Julia Reynoldsb852e562017-06-06 16:14:18 -04001/*
2 * Copyright (C) 2017 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 */
16package com.android.server.notification;
17
18import static com.android.server.notification.ManagedServices.APPROVAL_BY_COMPONENT;
19import static com.android.server.notification.ManagedServices.APPROVAL_BY_PACKAGE;
20
21import static junit.framework.Assert.assertEquals;
22import static junit.framework.Assert.assertFalse;
23import static junit.framework.Assert.assertTrue;
24
25import static org.mockito.Matchers.any;
26import static org.mockito.Matchers.anyInt;
27import static org.mockito.Matchers.eq;
28import static org.mockito.Mockito.never;
29import static org.mockito.Mockito.times;
30import static org.mockito.Mockito.verify;
31import static org.mockito.Mockito.when;
32
33import android.content.ComponentName;
34import android.content.Context;
35import android.content.Intent;
36import android.content.pm.IPackageManager;
37import android.content.pm.PackageManager;
38import android.content.pm.ResolveInfo;
39import android.content.pm.ServiceInfo;
40import android.content.pm.UserInfo;
Julia Reynoldsfa206a42017-08-14 13:22:23 -040041import android.os.Build;
Julia Reynoldsb852e562017-06-06 16:14:18 -040042import android.os.IBinder;
43import android.os.IInterface;
44import android.os.UserHandle;
45import android.os.UserManager;
46import android.provider.Settings;
47import android.text.TextUtils;
48import android.util.ArrayMap;
49import android.util.Xml;
50
51import com.android.internal.util.FastXmlSerializer;
52
53import com.google.android.collect.Lists;
54
55import org.junit.Before;
56import org.junit.Test;
57import org.mockito.Mock;
58import org.mockito.MockitoAnnotations;
59import org.mockito.invocation.InvocationOnMock;
60import org.mockito.stubbing.Answer;
61import org.xmlpull.v1.XmlPullParser;
62import org.xmlpull.v1.XmlSerializer;
63
64import java.io.BufferedInputStream;
65import java.io.BufferedOutputStream;
66import java.io.ByteArrayInputStream;
67import java.io.ByteArrayOutputStream;
68import java.util.ArrayList;
69import java.util.List;
70
71public class ManagedServicesTest extends NotificationTestCase {
72
73 @Mock
74 private IPackageManager mIpm;
75 @Mock
76 private PackageManager mPm;
77 @Mock
78 private UserManager mUm;
79 @Mock
80 private ManagedServices.UserProfiles mUserProfiles;
81 Object mLock = new Object();
82
83 UserInfo mZero = new UserInfo(0, "zero", 0);
84 UserInfo mTen = new UserInfo(10, "ten", 0);
85
86 private static final String SETTING = "setting";
87 private static final String SECONDARY_SETTING = "secondary_setting";
88
89 private ArrayMap<Integer, String> mExpectedPrimaryPackages;
90 private ArrayMap<Integer, String> mExpectedPrimaryComponentNames;
91 private ArrayMap<Integer, String> mExpectedSecondaryPackages;
92 private ArrayMap<Integer, String> mExpectedSecondaryComponentNames;
93
Julia Reynolds5aa13a42017-08-24 09:10:23 -040094 // type : user : list of approved
Julia Reynoldsb852e562017-06-06 16:14:18 -040095 private ArrayMap<Integer, ArrayMap<Integer, String>> mExpectedPrimary = new ArrayMap<>();
96 private ArrayMap<Integer, ArrayMap<Integer, String>> mExpectedSecondary = new ArrayMap<>();
97
98 @Before
99 public void setUp() throws Exception {
100 MockitoAnnotations.initMocks(this);
101
102 getContext().setMockPackageManager(mPm);
103 getContext().addMockSystemService(Context.USER_SERVICE, mUm);
104
105 List<UserInfo> users = new ArrayList<>();
106 users.add(mZero);
107 users.add(mTen);
108 users.add(new UserInfo(11, "11", 0));
109 users.add(new UserInfo(12, "12", 0));
110 for (UserInfo user : users) {
111 when(mUm.getUserInfo(eq(user.id))).thenReturn(user);
112 }
113 when(mUm.getUsers()).thenReturn(users);
114 when(mUserProfiles.getCurrentProfileIds()).thenReturn(new int[] {0, 10, 11, 12});
115
116 mExpectedPrimaryPackages = new ArrayMap<>();
117 mExpectedPrimaryPackages.put(0, "this.is.a.package.name:another.package");
118 mExpectedPrimaryPackages.put(10, "this.is.another.package");
119 mExpectedPrimaryPackages.put(11, "");
120 mExpectedPrimaryPackages.put(12, "bananas!");
121 mExpectedPrimaryComponentNames = new ArrayMap<>();
122 mExpectedPrimaryComponentNames.put(0, "this.is.a.package.name/Ba:another.package/B1");
123 mExpectedPrimaryComponentNames.put(10, "this.is.another.package/M1");
124 mExpectedPrimaryComponentNames.put(11, "");
125 mExpectedPrimaryComponentNames.put(12, "bananas!/Bananas!");
126 mExpectedPrimary.put(APPROVAL_BY_PACKAGE, mExpectedPrimaryPackages);
127 mExpectedPrimary.put(APPROVAL_BY_COMPONENT, mExpectedPrimaryComponentNames);
128
129 mExpectedSecondaryComponentNames = new ArrayMap<>();
130 mExpectedSecondaryComponentNames.put(0, "secondary/component.Name");
131 mExpectedSecondaryComponentNames.put(10,
132 "this.is.another.package/with.Component:component/2:package/component2");
133 mExpectedSecondaryPackages = new ArrayMap<>();
134 mExpectedSecondaryPackages.put(0, "secondary");
135 mExpectedSecondaryPackages.put(10,
136 "this.is.another.package:component:package");
137 mExpectedSecondary.put(APPROVAL_BY_PACKAGE, mExpectedSecondaryPackages);
138 mExpectedSecondary.put(APPROVAL_BY_COMPONENT, mExpectedSecondaryComponentNames);
139 }
140
141 @Test
142 public void testBackupAndRestore_migration() throws Exception {
143 for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
144 ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
145 mIpm, approvalLevel);
146
147 for (int userId : mExpectedPrimary.get(approvalLevel).keySet()) {
148 service.onSettingRestored(
149 service.getConfig().secureSettingName,
150 mExpectedPrimary.get(approvalLevel).get(userId),
Julia Reynoldsfa206a42017-08-14 13:22:23 -0400151 Build.VERSION_CODES.O, userId);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400152 }
153 verifyExpectedApprovedEntries(service, true);
154
155 for (int userId : mExpectedSecondary.get(approvalLevel).keySet()) {
156 service.onSettingRestored(service.getConfig().secondarySettingName,
Julia Reynoldsfa206a42017-08-14 13:22:23 -0400157 mExpectedSecondary.get(approvalLevel).get(userId), Build.VERSION_CODES.O,
158 userId);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400159 }
160 verifyExpectedApprovedEntries(service);
161 }
162 }
163
164 @Test
Julia Reynoldsfa206a42017-08-14 13:22:23 -0400165 public void testBackupAndRestore_migration_preO() throws Exception {
166 ArrayMap backupPrimaryPackages = new ArrayMap<>();
167 backupPrimaryPackages.put(0, "backup.0:backup:0a");
168 backupPrimaryPackages.put(10, "10.backup");
169 backupPrimaryPackages.put(11, "eleven");
170 backupPrimaryPackages.put(12, "");
171 ArrayMap backupPrimaryComponentNames = new ArrayMap<>();
172 backupPrimaryComponentNames.put(0, "backup.first/whatever:a/b");
173 backupPrimaryComponentNames.put(10, "again/M1");
174 backupPrimaryComponentNames.put(11, "orange/youglad:itisnot/banana");
175 backupPrimaryComponentNames.put(12, "");
176 ArrayMap<Integer, ArrayMap<Integer, String>> backupPrimary = new ArrayMap<>();
177 backupPrimary.put(APPROVAL_BY_PACKAGE, backupPrimaryPackages);
178 backupPrimary.put(APPROVAL_BY_COMPONENT, backupPrimaryComponentNames);
179
180 ArrayMap backupSecondaryComponentNames = new ArrayMap<>();
181 backupSecondaryComponentNames.put(0, "secondary.1/component.Name");
182 backupSecondaryComponentNames.put(10,
183 "this.is.another.package.backup/with.Component:component.backup/2");
184 ArrayMap backupSecondaryPackages = new ArrayMap<>();
185 backupSecondaryPackages.put(0, "");
186 backupSecondaryPackages.put(10,
187 "this.is.another.package.backup:package.backup");
188 ArrayMap<Integer, ArrayMap<Integer, String>> backupSecondary = new ArrayMap<>();
189 backupSecondary.put(APPROVAL_BY_PACKAGE, backupSecondaryPackages);
190 backupSecondary.put(APPROVAL_BY_COMPONENT, backupSecondaryComponentNames);
191
192 for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
193 ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
194 mIpm, approvalLevel);
195
196 // not an expected flow but a way to get data into the settings
197 for (int userId : mExpectedPrimary.get(approvalLevel).keySet()) {
198 service.onSettingRestored(
199 service.getConfig().secureSettingName,
200 mExpectedPrimary.get(approvalLevel).get(userId),
201 Build.VERSION_CODES.O, userId);
202 }
203
204 for (int userId : mExpectedSecondary.get(approvalLevel).keySet()) {
205 service.onSettingRestored(service.getConfig().secondarySettingName,
206 mExpectedSecondary.get(approvalLevel).get(userId), Build.VERSION_CODES.O,
207 userId);
208 }
209
210 // actual test
211 for (int userId : backupPrimary.get(approvalLevel).keySet()) {
212 service.onSettingRestored(
213 service.getConfig().secureSettingName,
214 backupPrimary.get(approvalLevel).get(userId),
215 Build.VERSION_CODES.N_MR1, userId);
216 }
217 verifyExpectedApprovedEntries(service, true);
218
219 for (int userId : backupSecondary.get(approvalLevel).keySet()) {
220 service.onSettingRestored(service.getConfig().secondarySettingName,
221 backupSecondary.get(approvalLevel).get(userId),
222 Build.VERSION_CODES.N_MR1, userId);
223 }
224 verifyExpectedApprovedEntries(service);
225 verifyExpectedApprovedEntries(service, backupPrimary.get(approvalLevel));
226 verifyExpectedApprovedEntries(service, backupSecondary.get(approvalLevel));
227 }
228 }
229
230 @Test
Julia Reynoldsb852e562017-06-06 16:14:18 -0400231 public void testReadXml_migrationFromSettings() throws Exception {
232 for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
233 ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
234 mIpm, approvalLevel);
235
236 // approved services aren't in xml
237 XmlPullParser parser = Xml.newPullParser();
238 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(new byte[]{})),
239 null);
240 writeExpectedValuesToSettings(approvalLevel);
241
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400242 service.migrateToXml();
Julia Reynoldsb852e562017-06-06 16:14:18 -0400243
244 verifyExpectedApprovedEntries(service);
245 }
246 }
247
248 @Test
249 public void testReadXml() throws Exception {
250 for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
251 ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
252 mIpm, approvalLevel);
253
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400254 loadXml(service);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400255
256 verifyExpectedApprovedEntries(service);
Julia Reynolds45523002017-09-12 09:43:57 -0400257
258 int[] invalidUsers = new int[] {98, 99};
259 for (int invalidUser : invalidUsers) {
260 assertFalse("service type " + service.mApprovalLevel + ":"
261 + invalidUser + " is allowed for user " + invalidUser,
262 service.isPackageOrComponentAllowed(
263 String.valueOf(invalidUser), invalidUser));
264 }
Julia Reynoldsb852e562017-06-06 16:14:18 -0400265 }
266 }
267
268 @Test
269 public void testWriteXml_trimsMissingServices() throws Exception {
270 for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
271 ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
272 mIpm, approvalLevel);
273 loadXml(service);
274
275 // remove missing
276 mExpectedPrimaryPackages.put(0, "another.package");
277 mExpectedPrimaryPackages.remove(12);
278 mExpectedPrimaryComponentNames.put(0, "another.package/B1");
279 mExpectedPrimaryComponentNames.remove(12);
280 mExpectedSecondaryPackages.put(10, "this.is.another.package:component");
281 mExpectedSecondaryComponentNames.put(
282 10, "this.is.another.package/with.Component:component/2");
283
284 for (UserInfo userInfo : mUm.getUsers()) {
285 List<String> entriesExpectedToHaveServices = new ArrayList<>();
286 if (mExpectedPrimary.get(approvalLevel).containsKey(userInfo.id)) {
287 for (String packageOrComponent :
288 mExpectedPrimary.get(approvalLevel).get(userInfo.id).split(":")) {
289 if (!TextUtils.isEmpty(packageOrComponent)) {
290 entriesExpectedToHaveServices.add(
291 service.getPackageName(packageOrComponent));
292 }
293 }
294 }
295 if (mExpectedSecondary.get(approvalLevel).containsKey(userInfo.id)) {
296 for (String packageOrComponent :
297 mExpectedSecondary.get(approvalLevel).get(userInfo.id).split(":")) {
298 if (!TextUtils.isEmpty(packageOrComponent)) {
299 entriesExpectedToHaveServices.add(
300 service.getPackageName(packageOrComponent));
301 }
302 }
303 }
304 addExpectedServices(service, entriesExpectedToHaveServices, userInfo.id);
305 }
306
307 XmlSerializer serializer = new FastXmlSerializer();
308 ByteArrayOutputStream baos = new ByteArrayOutputStream();
309 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
310 serializer.startDocument(null, true);
311 service.writeXml(serializer, true);
312 serializer.endDocument();
313 serializer.flush();
314
315 XmlPullParser parser = Xml.newPullParser();
316 parser.setInput(new BufferedInputStream(
317 new ByteArrayInputStream(baos.toByteArray())), null);
318 parser.nextTag();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400319 service.readXml(parser);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400320
321 verifyExpectedApprovedEntries(service);
322 assertFalse(service.isPackageOrComponentAllowed("this.is.a.package.name", 0));
323 assertFalse(service.isPackageOrComponentAllowed("bananas!", 12));
324 assertFalse(service.isPackageOrComponentAllowed("package/component2", 10));
325 }
326 }
327
328 @Test
329 public void testWriteXml_writesSetting() throws Exception {
330 for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
331 ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
332 mIpm, approvalLevel);
333 loadXml(service);
334
335 XmlSerializer serializer = new FastXmlSerializer();
336 ByteArrayOutputStream baos = new ByteArrayOutputStream();
337 serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
338 serializer.startDocument(null, true);
339 service.writeXml(serializer, false);
340 serializer.endDocument();
341 serializer.flush();
342
343 for (int userId : mUserProfiles.getCurrentProfileIds()) {
344 List<String> expected =
345 stringToList(mExpectedPrimary.get(approvalLevel).get(userId));
346 List<String> actual = stringToList(Settings.Secure.getStringForUser(
347 getContext().getContentResolver(),
348 service.getConfig().secureSettingName, userId));
349 assertContentsInAnyOrder(actual, expected);
350 }
351 }
352 }
353
354 @Test
355 public void rebindServices_onlyBindsExactMatchesIfComponent() throws Exception {
356 // If the primary and secondary lists contain component names, only those components within
357 // the package should be matched
358 ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
359 mIpm,
360 ManagedServices.APPROVAL_BY_COMPONENT);
361
362 List<String> packages = new ArrayList<>();
363 packages.add("package");
364 packages.add("anotherPackage");
365 addExpectedServices(service, packages, 0);
366
367 // only 2 components are approved per package
368 mExpectedPrimaryComponentNames.clear();
369 mExpectedPrimaryComponentNames.put(0, "package/C1:package/C2");
370 mExpectedSecondaryComponentNames.clear();
371 mExpectedSecondaryComponentNames.put(0, "anotherPackage/C1:anotherPackage/C2");
372
373 loadXml(service);
374
375 // verify the 2 components per package are enabled (bound)
376 verifyExpectedBoundEntries(service, true);
377 verifyExpectedBoundEntries(service, false);
378
379 // verify the last component per package is not enabled/we don't try to bind to it
380 for (String pkg : packages) {
381 ComponentName unapprovedAdditionalComponent =
382 ComponentName.unflattenFromString(pkg + "/C3");
383 assertFalse(
384 service.isComponentEnabledForCurrentProfiles(
385 unapprovedAdditionalComponent));
386 verify(mIpm, never()).getServiceInfo(
387 eq(unapprovedAdditionalComponent), anyInt(), anyInt());
388 }
389 }
390
391 @Test
392 public void rebindServices_bindsEverythingInAPackage() throws Exception {
393 // If the primary and secondary lists contain packages, all components within those packages
394 // should be bound
395 ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
396 APPROVAL_BY_PACKAGE);
397
398 List<String> packages = new ArrayList<>();
399 packages.add("package");
400 packages.add("packagea");
401 addExpectedServices(service, packages, 0);
402
403 // 2 approved packages
404 mExpectedPrimaryPackages.clear();
405 mExpectedPrimaryPackages.put(0, "package");
406 mExpectedSecondaryPackages.clear();
407 mExpectedSecondaryPackages.put(0, "packagea");
408
409 loadXml(service);
410
411 // verify the 3 components per package are enabled (bound)
412 verifyExpectedBoundEntries(service, true);
413 verifyExpectedBoundEntries(service, false);
414 }
415
416 @Test
417 public void testPackageUninstall_packageNoLongerInApprovedList() throws Exception {
418 for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
419 ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
420 mIpm, approvalLevel);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400421 writeExpectedValuesToSettings(approvalLevel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400422 service.migrateToXml();
Julia Reynoldsb852e562017-06-06 16:14:18 -0400423
424 mExpectedPrimaryPackages.put(0, "another.package");
425 mExpectedPrimaryComponentNames.put(0, "another.package/B1");
426 service.onPackagesChanged(true, new String[]{"this.is.a.package.name"}, new int[]{103});
427
428 verifyExpectedApprovedEntries(service);
429 }
430 }
431
432 @Test
433 public void testPackageUninstall_componentNoLongerInApprovedList() throws Exception {
434 for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
435 ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
436 mIpm, approvalLevel);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400437 writeExpectedValuesToSettings(approvalLevel);
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400438 service.migrateToXml();
Julia Reynoldsb852e562017-06-06 16:14:18 -0400439
440 mExpectedSecondaryComponentNames.put(10, "component/2");
441 mExpectedSecondaryPackages.put(10, "component");
442 service.onPackagesChanged(true, new String[]{"this.is.another.package"}, new int[]{
443 UserHandle.PER_USER_RANGE + 1});
444
445 verifyExpectedApprovedEntries(service);
446 }
447 }
448
449 @Test
450 public void testSetPackageOrComponentEnabled() throws Exception {
451 for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
452 ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
453 mIpm, approvalLevel);
454 ArrayMap<Integer, ArrayList<String>> expectedEnabled = new ArrayMap<>();
455 expectedEnabled.put(0,
456 Lists.newArrayList(new String[]{"package/Comp", "package/C2", "again/M4"}));
457 expectedEnabled.put(10,
458 Lists.newArrayList(new String[]{"user10package/B", "user10/Component",
459 "user10package1/K", "user10.3/Component", "user10package2/L",
460 "user10.4/Component"}));
461
462 for (int userId : expectedEnabled.keySet()) {
463 ArrayList<String> expectedForUser = expectedEnabled.get(userId);
464 for (int i = 0; i < expectedForUser.size(); i++) {
465 boolean primary = i % 2 == 0;
466 service.setPackageOrComponentEnabled(expectedForUser.get(i), userId, primary,
467 true);
468 }
469 }
470
471 // verify everything added is approved
472 for (int userId : expectedEnabled.keySet()) {
473 ArrayList<String> expectedForUser = expectedEnabled.get(userId);
474 for (int i = 0; i < expectedForUser.size(); i++) {
475 String verifyValue = (approvalLevel == APPROVAL_BY_COMPONENT)
476 ? expectedForUser.get(i)
477 : service.getPackageName(expectedForUser.get(i));
478 assertTrue("Not allowed: user: " + userId + " entry: " + verifyValue
479 + " for approval level " + approvalLevel,
480 service.isPackageOrComponentAllowed(verifyValue, userId));
481 }
482 }
483
484 ArrayMap<Integer, ArrayList<String>> expectedNoAccess = new ArrayMap<>();
485 for (int userId : expectedEnabled.keySet()) {
486 ArrayList<String> expectedForUser = expectedEnabled.get(userId);
487 for (int i = expectedForUser.size() - 1; i >= 0; i--) {
488 ArrayList<String> removed = new ArrayList<>();
489 if (i % 3 == 0) {
490 String revokeAccessFor = expectedForUser.remove(i);
491 removed.add(revokeAccessFor);
492 service.setPackageOrComponentEnabled(
493 revokeAccessFor, userId, i % 2 == 0, false);
494 }
495 expectedNoAccess.put(userId, removed);
496 }
497 }
498
499 // verify everything still there is approved
500 for (int userId : expectedEnabled.keySet()) {
501 ArrayList<String> expectedForUser = expectedEnabled.get(userId);
502 for (int i = 0; i < expectedForUser.size(); i++) {
503 String verifyValue = (approvalLevel == APPROVAL_BY_COMPONENT)
504 ? expectedForUser.get(i)
505 : service.getPackageName(expectedForUser.get(i));
506 assertTrue("Not allowed: user: " + userId + " entry: " + verifyValue,
507 service.isPackageOrComponentAllowed(verifyValue, userId));
508 }
509 }
510 // verify everything removed isn't
511 for (int userId : expectedNoAccess.keySet()) {
512 ArrayList<String> notExpectedForUser = expectedNoAccess.get(userId);
513 for (int i = 0; i < notExpectedForUser.size(); i++) {
514 assertFalse(
515 "Is allowed: user: " + userId + " entry: " + notExpectedForUser.get(i),
516 service.isPackageOrComponentAllowed(notExpectedForUser.get(i), userId));
517 }
518 }
519 }
520 }
521
522 @Test
523 public void testGetAllowedPackages() throws Exception {
524 for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
525 ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
526 mIpm, approvalLevel);
527 loadXml(service);
528
529 List<String> allowedPackagesForUser0 = new ArrayList<>();
530 allowedPackagesForUser0.add("this.is.a.package.name");
531 allowedPackagesForUser0.add("another.package");
532 allowedPackagesForUser0.add("secondary");
533
534 List<String> actual = service.getAllowedPackages(0);
535 assertEquals(3, actual.size());
536 for (String pkg : allowedPackagesForUser0) {
537 assertTrue(actual.contains(pkg));
538 }
539
540 List<String> allowedPackagesForUser10 = new ArrayList<>();
541 allowedPackagesForUser10.add("this.is.another.package");
542 allowedPackagesForUser10.add("package");
543 allowedPackagesForUser10.add("this.is.another.package");
544 allowedPackagesForUser10.add("component");
545
546 actual = service.getAllowedPackages(10);
547 assertEquals(4, actual.size());
548 for (String pkg : allowedPackagesForUser10) {
549 assertTrue(actual.contains(pkg));
550 }
551 }
552 }
553
554 @Test
555 public void testGetAllowedComponents() throws Exception {
556 ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
557 APPROVAL_BY_COMPONENT);
558 loadXml(service);
559
560 List<ComponentName> expected = new ArrayList<>();
561 expected.add(ComponentName.unflattenFromString("this.is.another.package/M1"));
562 expected.add(ComponentName.unflattenFromString("this.is.another.package/with.Component"));
563 expected.add(ComponentName.unflattenFromString("component/2"));
564 expected.add(ComponentName.unflattenFromString("package/component2"));
565
566 List<ComponentName> actual = service.getAllowedComponents(10);
567
568 assertContentsInAnyOrder(expected, actual);
569
570 assertEquals(expected.size(), actual.size());
571
572 for (ComponentName cn : expected) {
573 assertTrue("Actual missing " + cn, actual.contains(cn));
574 }
575
576 for (ComponentName cn : actual) {
577 assertTrue("Actual contains extra " + cn, expected.contains(cn));
578 }
579 }
580
581 @Test
582 public void testGetAllowedComponents_approvalByPackage() throws Exception {
583 ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
584 APPROVAL_BY_PACKAGE);
585 loadXml(service);
586
587 assertEquals(0, service.getAllowedComponents(10).size());
588 }
589
Julia Reynolds5aa13a42017-08-24 09:10:23 -0400590 @Test
591 public void testOnUserRemoved() throws Exception {
592 for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
593 ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
594 mIpm, approvalLevel);
595 loadXml(service);
596
597 ArrayMap<Integer, String> verifyMap = mExpectedPrimary.get(service.mApprovalLevel);
598 String user0 = verifyMap.remove(0);
599 verifyMap = mExpectedSecondary.get(service.mApprovalLevel);
600 user0 = user0 + ":" + verifyMap.remove(0);
601
602 service.onUserRemoved(0);
603
604 for (String verifyValue : user0.split(":")) {
605 if (!TextUtils.isEmpty(verifyValue)) {
606 assertFalse("service type " + service.mApprovalLevel + ":" + verifyValue
607 + " is still allowed",
608 service.isPackageOrComponentAllowed(verifyValue, 0));
609 }
610 }
611
612 verifyExpectedApprovedEntries(service);
613 }
614 }
615
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400616 private void loadXml(ManagedServices service) throws Exception {
Julia Reynoldsb852e562017-06-06 16:14:18 -0400617 final StringBuffer xml = new StringBuffer();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400618 xml.append("<" + service.getConfig().xmlTag + ">\n");
Julia Reynoldsb852e562017-06-06 16:14:18 -0400619 for (int userId : mExpectedPrimary.get(service.mApprovalLevel).keySet()) {
620 xml.append(getXmlEntry(
621 mExpectedPrimary.get(service.mApprovalLevel).get(userId), userId, true));
622 }
623 for (int userId : mExpectedSecondary.get(service.mApprovalLevel).keySet()) {
624 xml.append(getXmlEntry(
625 mExpectedSecondary.get(service.mApprovalLevel).get(userId), userId, false));
626 }
Julia Reynolds45523002017-09-12 09:43:57 -0400627 xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " "
628 + ManagedServices.ATT_USER_ID + "=\"99\" "
629 + ManagedServices.ATT_IS_PRIMARY + "=\"true\" "
630 + ManagedServices.ATT_APPROVED_LIST + "=\"99\" />\n");
631 xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " "
632 + ManagedServices.ATT_USER_ID + "=\"98\" "
633 + ManagedServices.ATT_IS_PRIMARY + "=\"false\" "
634 + ManagedServices.ATT_APPROVED_LIST + "=\"98\" />\n");
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400635 xml.append("</" + service.getConfig().xmlTag + ">");
Julia Reynoldsb852e562017-06-06 16:14:18 -0400636
637 XmlPullParser parser = Xml.newPullParser();
638 parser.setInput(new BufferedInputStream(
639 new ByteArrayInputStream(xml.toString().getBytes())), null);
640 parser.nextTag();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400641 service.readXml(parser);
Julia Reynoldsb852e562017-06-06 16:14:18 -0400642 }
643
644 private void addExpectedServices(final ManagedServices service, final List<String> packages,
645 int userId) {
646 when(mPm.queryIntentServicesAsUser(any(), anyInt(), eq(userId))).
647 thenAnswer(new Answer<List<ResolveInfo>>() {
648 @Override
649 public List<ResolveInfo> answer(InvocationOnMock invocationOnMock)
650 throws Throwable {
651 Object[] args = invocationOnMock.getArguments();
652 Intent invocationIntent = (Intent) args[0];
653 if (invocationIntent != null) {
654 if (invocationIntent.getAction().equals(
655 service.getConfig().serviceInterface)
656 && packages.contains(invocationIntent.getPackage())) {
657 List<ResolveInfo> dummyServices = new ArrayList<>();
658 for (int i = 1; i <= 3; i ++) {
659 ResolveInfo resolveInfo = new ResolveInfo();
660 ServiceInfo serviceInfo = new ServiceInfo();
661 serviceInfo.packageName = invocationIntent.getPackage();
662 serviceInfo.name = "C"+i;
663 serviceInfo.permission = service.getConfig().bindPermission;
664 resolveInfo.serviceInfo = serviceInfo;
665 dummyServices.add(resolveInfo);
666 }
667 return dummyServices;
668 }
669 }
670 return new ArrayList<>();
671 }
672 });
673 }
674
675 private List<String> stringToList(String list) {
676 if (list == null) {
677 list = "";
678 }
679 return new ArrayList<>(Lists.newArrayList(list.split(
680 ManagedServices.ENABLED_SERVICES_SEPARATOR)));
681 }
682
683 private void assertContentsInAnyOrder(List<?> expected, List<?> actual) {
684 assertEquals(expected.size(), actual.size());
685
686 for (Object o : expected) {
687 assertTrue("Actual missing " + o, actual.contains(o));
688 }
689
690 for (Object o : actual) {
691 assertTrue("Actual contains extra " + o, expected.contains(o));
692 }
693 }
694
695 private void verifyExpectedBoundEntries(ManagedServices service, boolean primary)
696 throws Exception {
697 ArrayMap<Integer, String> verifyMap = primary ? mExpectedPrimary.get(service.mApprovalLevel)
698 : mExpectedSecondary.get(service.mApprovalLevel);
699 for (int userId : verifyMap.keySet()) {
700 for (String packageOrComponent : verifyMap.get(userId).split(":")) {
701 if (!TextUtils.isEmpty(packageOrComponent)) {
702 if (service.mApprovalLevel == APPROVAL_BY_PACKAGE) {
Julia Reynolds5aa13a42017-08-24 09:10:23 -0400703 assertTrue(packageOrComponent,
704 service.isComponentEnabledForPackage(packageOrComponent));
Julia Reynoldsb852e562017-06-06 16:14:18 -0400705 for (int i = 1; i <= 3; i ++) {
706 ComponentName componentName = ComponentName.unflattenFromString(
707 packageOrComponent +"/C" + i);
708 assertTrue(service.isComponentEnabledForCurrentProfiles(
709 componentName));
710 verify(mIpm, times(1)).getServiceInfo(
711 eq(componentName), anyInt(), anyInt());
712 }
713 } else {
714 ComponentName componentName =
715 ComponentName.unflattenFromString(packageOrComponent);
716 assertTrue(service.isComponentEnabledForCurrentProfiles(componentName));
717 verify(mIpm, times(1)).getServiceInfo(
718 eq(componentName), anyInt(), anyInt());
719 }
720 }
721 }
722 }
723 }
724
725 private void verifyExpectedApprovedEntries(ManagedServices service) {
726 verifyExpectedApprovedEntries(service, true);
727 verifyExpectedApprovedEntries(service, false);
728 }
729
730 private void verifyExpectedApprovedEntries(ManagedServices service, boolean primary) {
731 ArrayMap<Integer, String> verifyMap = primary
732 ? mExpectedPrimary.get(service.mApprovalLevel)
733 : mExpectedSecondary.get(service.mApprovalLevel);
Julia Reynoldsfa206a42017-08-14 13:22:23 -0400734 verifyExpectedApprovedEntries(service, verifyMap);
735 }
736
737 private void verifyExpectedApprovedEntries(ManagedServices service,
738 ArrayMap<Integer, String> verifyMap) {
Julia Reynoldsb852e562017-06-06 16:14:18 -0400739 for (int userId : verifyMap.keySet()) {
740 for (String verifyValue : verifyMap.get(userId).split(":")) {
741 if (!TextUtils.isEmpty(verifyValue)) {
742 assertTrue("service type " + service.mApprovalLevel + ":"
Julia Reynoldsfa206a42017-08-14 13:22:23 -0400743 + verifyValue + " is not allowed for user " + userId,
Julia Reynoldsb852e562017-06-06 16:14:18 -0400744 service.isPackageOrComponentAllowed(verifyValue, userId));
745 }
746 }
747 }
748 }
749
Julia Reynoldsb852e562017-06-06 16:14:18 -0400750 private void writeExpectedValuesToSettings(int approvalLevel) {
751 for (int userId : mExpectedPrimary.get(approvalLevel).keySet()) {
752 Settings.Secure.putStringForUser(getContext().getContentResolver(), SETTING,
753 mExpectedPrimary.get(approvalLevel).get(userId), userId);
754 }
755 for (int userId : mExpectedSecondary.get(approvalLevel).keySet()) {
756 Settings.Secure.putStringForUser(getContext().getContentResolver(), SECONDARY_SETTING,
757 mExpectedSecondary.get(approvalLevel).get(userId), userId);
758 }
759 }
760
761 private String getXmlEntry(String approved, int userId, boolean isPrimary) {
762 return "<" + ManagedServices.TAG_MANAGED_SERVICES + " "
763 + ManagedServices.ATT_USER_ID + "=\"" + userId +"\" "
764 + ManagedServices.ATT_IS_PRIMARY + "=\"" + isPrimary +"\" "
765 + ManagedServices.ATT_APPROVED_LIST + "=\"" + approved +"\" "
766 + "/>\n";
767 }
768
769 class TestManagedServices extends ManagedServices {
770
771 public TestManagedServices(Context context, Object mutex, UserProfiles userProfiles,
772 IPackageManager pm, int approvedServiceType) {
773 super(context, mutex, userProfiles, pm);
774 mApprovalLevel = approvedServiceType;
775 }
776
777 @Override
778 protected Config getConfig() {
779 final Config c = new Config();
Julia Reynoldsd1bf5f02017-07-11 10:39:58 -0400780 c.xmlTag = "test";
Julia Reynoldsb852e562017-06-06 16:14:18 -0400781 c.secureSettingName = SETTING;
782 c.secondarySettingName = SECONDARY_SETTING;
783 c.bindPermission = "permission";
784 c.serviceInterface = "serviceInterface";
785 return c;
786 }
787
788 @Override
789 protected IInterface asInterface(IBinder binder) {
790 return null;
791 }
792
793 @Override
794 protected boolean checkType(IInterface service) {
795 return false;
796 }
797
798 @Override
799 protected void onServiceAdded(ManagedServiceInfo info) {
800
801 }
802 }
803}