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