Home | History | Annotate | Download | only in notification
      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 
     53 import com.google.android.collect.Lists;
     54 
     55 import org.junit.Before;
     56 import org.junit.Test;
     57 import org.mockito.Mock;
     58 import org.mockito.MockitoAnnotations;
     59 import org.mockito.invocation.InvocationOnMock;
     60 import org.mockito.stubbing.Answer;
     61 import org.xmlpull.v1.XmlPullParser;
     62 import org.xmlpull.v1.XmlSerializer;
     63 
     64 import java.io.BufferedInputStream;
     65 import java.io.BufferedOutputStream;
     66 import java.io.ByteArrayInputStream;
     67 import java.io.ByteArrayOutputStream;
     68 import java.util.ArrayList;
     69 import java.util.List;
     70 
     71 public 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 
     94     // type : user : list of approved
     95     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),
    151                         Build.VERSION_CODES.O, userId);
    152             }
    153             verifyExpectedApprovedEntries(service, true);
    154 
    155             for (int userId : mExpectedSecondary.get(approvalLevel).keySet()) {
    156                 service.onSettingRestored(service.getConfig().secondarySettingName,
    157                         mExpectedSecondary.get(approvalLevel).get(userId), Build.VERSION_CODES.O,
    158                         userId);
    159             }
    160             verifyExpectedApprovedEntries(service);
    161         }
    162     }
    163 
    164     @Test
    165     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
    231     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 
    242             service.migrateToXml();
    243 
    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 
    254             loadXml(service);
    255 
    256             verifyExpectedApprovedEntries(service);
    257 
    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             }
    265         }
    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();
    319             service.readXml(parser);
    320 
    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);
    421             writeExpectedValuesToSettings(approvalLevel);
    422             service.migrateToXml();
    423 
    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);
    437             writeExpectedValuesToSettings(approvalLevel);
    438             service.migrateToXml();
    439 
    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 
    590     @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 
    616     private void loadXml(ManagedServices service) throws Exception {
    617         final StringBuffer xml = new StringBuffer();
    618         xml.append("<" + service.getConfig().xmlTag + ">\n");
    619         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         }
    627         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");
    635         xml.append("</" + service.getConfig().xmlTag + ">");
    636 
    637         XmlPullParser parser = Xml.newPullParser();
    638         parser.setInput(new BufferedInputStream(
    639                 new ByteArrayInputStream(xml.toString().getBytes())), null);
    640         parser.nextTag();
    641         service.readXml(parser);
    642     }
    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) {
    703                         assertTrue(packageOrComponent,
    704                                 service.isComponentEnabledForPackage(packageOrComponent));
    705                         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);
    734         verifyExpectedApprovedEntries(service, verifyMap);
    735     }
    736 
    737     private void verifyExpectedApprovedEntries(ManagedServices service,
    738             ArrayMap<Integer, String> verifyMap) {
    739         for (int userId : verifyMap.keySet()) {
    740             for (String verifyValue : verifyMap.get(userId).split(":")) {
    741                 if (!TextUtils.isEmpty(verifyValue)) {
    742                     assertTrue("service type " + service.mApprovalLevel + ":"
    743                                     + verifyValue + " is not allowed for user " + userId,
    744                             service.isPackageOrComponentAllowed(verifyValue, userId));
    745                 }
    746             }
    747         }
    748     }
    749 
    750     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();
    780             c.xmlTag = "test";
    781             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 }
    804