/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.notification; import static com.android.server.notification.ManagedServices.APPROVAL_BY_COMPONENT; import static com.android.server.notification.ManagedServices.APPROVAL_BY_PACKAGE; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; import android.os.Build; import android.os.IBinder; import android.os.IInterface; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Xml; import com.android.internal.util.FastXmlSerializer; import com.google.android.collect.Lists; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlSerializer; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.List; public class ManagedServicesTest extends NotificationTestCase { @Mock private IPackageManager mIpm; @Mock private PackageManager mPm; @Mock private UserManager mUm; @Mock private ManagedServices.UserProfiles mUserProfiles; Object mLock = new Object(); UserInfo mZero = new UserInfo(0, "zero", 0); UserInfo mTen = new UserInfo(10, "ten", 0); private static final String SETTING = "setting"; private static final String SECONDARY_SETTING = "secondary_setting"; private ArrayMap mExpectedPrimaryPackages; private ArrayMap mExpectedPrimaryComponentNames; private ArrayMap mExpectedSecondaryPackages; private ArrayMap mExpectedSecondaryComponentNames; // type : user : list of approved private ArrayMap> mExpectedPrimary = new ArrayMap<>(); private ArrayMap> mExpectedSecondary = new ArrayMap<>(); @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); getContext().setMockPackageManager(mPm); getContext().addMockSystemService(Context.USER_SERVICE, mUm); List users = new ArrayList<>(); users.add(mZero); users.add(mTen); users.add(new UserInfo(11, "11", 0)); users.add(new UserInfo(12, "12", 0)); for (UserInfo user : users) { when(mUm.getUserInfo(eq(user.id))).thenReturn(user); } when(mUm.getUsers()).thenReturn(users); when(mUserProfiles.getCurrentProfileIds()).thenReturn(new int[] {0, 10, 11, 12}); mExpectedPrimaryPackages = new ArrayMap<>(); mExpectedPrimaryPackages.put(0, "this.is.a.package.name:another.package"); mExpectedPrimaryPackages.put(10, "this.is.another.package"); mExpectedPrimaryPackages.put(11, ""); mExpectedPrimaryPackages.put(12, "bananas!"); mExpectedPrimaryComponentNames = new ArrayMap<>(); mExpectedPrimaryComponentNames.put(0, "this.is.a.package.name/Ba:another.package/B1"); mExpectedPrimaryComponentNames.put(10, "this.is.another.package/M1"); mExpectedPrimaryComponentNames.put(11, ""); mExpectedPrimaryComponentNames.put(12, "bananas!/Bananas!"); mExpectedPrimary.put(APPROVAL_BY_PACKAGE, mExpectedPrimaryPackages); mExpectedPrimary.put(APPROVAL_BY_COMPONENT, mExpectedPrimaryComponentNames); mExpectedSecondaryComponentNames = new ArrayMap<>(); mExpectedSecondaryComponentNames.put(0, "secondary/component.Name"); mExpectedSecondaryComponentNames.put(10, "this.is.another.package/with.Component:component/2:package/component2"); mExpectedSecondaryPackages = new ArrayMap<>(); mExpectedSecondaryPackages.put(0, "secondary"); mExpectedSecondaryPackages.put(10, "this.is.another.package:component:package"); mExpectedSecondary.put(APPROVAL_BY_PACKAGE, mExpectedSecondaryPackages); mExpectedSecondary.put(APPROVAL_BY_COMPONENT, mExpectedSecondaryComponentNames); } @Test public void testBackupAndRestore_migration() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, approvalLevel); for (int userId : mExpectedPrimary.get(approvalLevel).keySet()) { service.onSettingRestored( service.getConfig().secureSettingName, mExpectedPrimary.get(approvalLevel).get(userId), Build.VERSION_CODES.O, userId); } verifyExpectedApprovedEntries(service, true); for (int userId : mExpectedSecondary.get(approvalLevel).keySet()) { service.onSettingRestored(service.getConfig().secondarySettingName, mExpectedSecondary.get(approvalLevel).get(userId), Build.VERSION_CODES.O, userId); } verifyExpectedApprovedEntries(service); } } @Test public void testBackupAndRestore_migration_preO() throws Exception { ArrayMap backupPrimaryPackages = new ArrayMap<>(); backupPrimaryPackages.put(0, "backup.0:backup:0a"); backupPrimaryPackages.put(10, "10.backup"); backupPrimaryPackages.put(11, "eleven"); backupPrimaryPackages.put(12, ""); ArrayMap backupPrimaryComponentNames = new ArrayMap<>(); backupPrimaryComponentNames.put(0, "backup.first/whatever:a/b"); backupPrimaryComponentNames.put(10, "again/M1"); backupPrimaryComponentNames.put(11, "orange/youglad:itisnot/banana"); backupPrimaryComponentNames.put(12, ""); ArrayMap> backupPrimary = new ArrayMap<>(); backupPrimary.put(APPROVAL_BY_PACKAGE, backupPrimaryPackages); backupPrimary.put(APPROVAL_BY_COMPONENT, backupPrimaryComponentNames); ArrayMap backupSecondaryComponentNames = new ArrayMap<>(); backupSecondaryComponentNames.put(0, "secondary.1/component.Name"); backupSecondaryComponentNames.put(10, "this.is.another.package.backup/with.Component:component.backup/2"); ArrayMap backupSecondaryPackages = new ArrayMap<>(); backupSecondaryPackages.put(0, ""); backupSecondaryPackages.put(10, "this.is.another.package.backup:package.backup"); ArrayMap> backupSecondary = new ArrayMap<>(); backupSecondary.put(APPROVAL_BY_PACKAGE, backupSecondaryPackages); backupSecondary.put(APPROVAL_BY_COMPONENT, backupSecondaryComponentNames); for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, approvalLevel); // not an expected flow but a way to get data into the settings for (int userId : mExpectedPrimary.get(approvalLevel).keySet()) { service.onSettingRestored( service.getConfig().secureSettingName, mExpectedPrimary.get(approvalLevel).get(userId), Build.VERSION_CODES.O, userId); } for (int userId : mExpectedSecondary.get(approvalLevel).keySet()) { service.onSettingRestored(service.getConfig().secondarySettingName, mExpectedSecondary.get(approvalLevel).get(userId), Build.VERSION_CODES.O, userId); } // actual test for (int userId : backupPrimary.get(approvalLevel).keySet()) { service.onSettingRestored( service.getConfig().secureSettingName, backupPrimary.get(approvalLevel).get(userId), Build.VERSION_CODES.N_MR1, userId); } verifyExpectedApprovedEntries(service, true); for (int userId : backupSecondary.get(approvalLevel).keySet()) { service.onSettingRestored(service.getConfig().secondarySettingName, backupSecondary.get(approvalLevel).get(userId), Build.VERSION_CODES.N_MR1, userId); } verifyExpectedApprovedEntries(service); verifyExpectedApprovedEntries(service, backupPrimary.get(approvalLevel)); verifyExpectedApprovedEntries(service, backupSecondary.get(approvalLevel)); } } @Test public void testReadXml_migrationFromSettings() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, approvalLevel); // approved services aren't in xml XmlPullParser parser = Xml.newPullParser(); parser.setInput(new BufferedInputStream(new ByteArrayInputStream(new byte[]{})), null); writeExpectedValuesToSettings(approvalLevel); service.migrateToXml(); verifyExpectedApprovedEntries(service); } } @Test public void testReadXml() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, approvalLevel); loadXml(service); verifyExpectedApprovedEntries(service); int[] invalidUsers = new int[] {98, 99}; for (int invalidUser : invalidUsers) { assertFalse("service type " + service.mApprovalLevel + ":" + invalidUser + " is allowed for user " + invalidUser, service.isPackageOrComponentAllowed( String.valueOf(invalidUser), invalidUser)); } } } @Test public void testWriteXml_trimsMissingServices() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, approvalLevel); loadXml(service); // remove missing mExpectedPrimaryPackages.put(0, "another.package"); mExpectedPrimaryPackages.remove(12); mExpectedPrimaryComponentNames.put(0, "another.package/B1"); mExpectedPrimaryComponentNames.remove(12); mExpectedSecondaryPackages.put(10, "this.is.another.package:component"); mExpectedSecondaryComponentNames.put( 10, "this.is.another.package/with.Component:component/2"); for (UserInfo userInfo : mUm.getUsers()) { List entriesExpectedToHaveServices = new ArrayList<>(); if (mExpectedPrimary.get(approvalLevel).containsKey(userInfo.id)) { for (String packageOrComponent : mExpectedPrimary.get(approvalLevel).get(userInfo.id).split(":")) { if (!TextUtils.isEmpty(packageOrComponent)) { entriesExpectedToHaveServices.add( service.getPackageName(packageOrComponent)); } } } if (mExpectedSecondary.get(approvalLevel).containsKey(userInfo.id)) { for (String packageOrComponent : mExpectedSecondary.get(approvalLevel).get(userInfo.id).split(":")) { if (!TextUtils.isEmpty(packageOrComponent)) { entriesExpectedToHaveServices.add( service.getPackageName(packageOrComponent)); } } } addExpectedServices(service, entriesExpectedToHaveServices, userInfo.id); } XmlSerializer serializer = new FastXmlSerializer(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); serializer.startDocument(null, true); service.writeXml(serializer, true); serializer.endDocument(); serializer.flush(); XmlPullParser parser = Xml.newPullParser(); parser.setInput(new BufferedInputStream( new ByteArrayInputStream(baos.toByteArray())), null); parser.nextTag(); service.readXml(parser); verifyExpectedApprovedEntries(service); assertFalse(service.isPackageOrComponentAllowed("this.is.a.package.name", 0)); assertFalse(service.isPackageOrComponentAllowed("bananas!", 12)); assertFalse(service.isPackageOrComponentAllowed("package/component2", 10)); } } @Test public void testWriteXml_writesSetting() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, approvalLevel); loadXml(service); XmlSerializer serializer = new FastXmlSerializer(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); serializer.startDocument(null, true); service.writeXml(serializer, false); serializer.endDocument(); serializer.flush(); for (int userId : mUserProfiles.getCurrentProfileIds()) { List expected = stringToList(mExpectedPrimary.get(approvalLevel).get(userId)); List actual = stringToList(Settings.Secure.getStringForUser( getContext().getContentResolver(), service.getConfig().secureSettingName, userId)); assertContentsInAnyOrder(actual, expected); } } } @Test public void rebindServices_onlyBindsExactMatchesIfComponent() throws Exception { // If the primary and secondary lists contain component names, only those components within // the package should be matched ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, ManagedServices.APPROVAL_BY_COMPONENT); List packages = new ArrayList<>(); packages.add("package"); packages.add("anotherPackage"); addExpectedServices(service, packages, 0); // only 2 components are approved per package mExpectedPrimaryComponentNames.clear(); mExpectedPrimaryComponentNames.put(0, "package/C1:package/C2"); mExpectedSecondaryComponentNames.clear(); mExpectedSecondaryComponentNames.put(0, "anotherPackage/C1:anotherPackage/C2"); loadXml(service); // verify the 2 components per package are enabled (bound) verifyExpectedBoundEntries(service, true); verifyExpectedBoundEntries(service, false); // verify the last component per package is not enabled/we don't try to bind to it for (String pkg : packages) { ComponentName unapprovedAdditionalComponent = ComponentName.unflattenFromString(pkg + "/C3"); assertFalse( service.isComponentEnabledForCurrentProfiles( unapprovedAdditionalComponent)); verify(mIpm, never()).getServiceInfo( eq(unapprovedAdditionalComponent), anyInt(), anyInt()); } } @Test public void rebindServices_bindsEverythingInAPackage() throws Exception { // If the primary and secondary lists contain packages, all components within those packages // should be bound ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, APPROVAL_BY_PACKAGE); List packages = new ArrayList<>(); packages.add("package"); packages.add("packagea"); addExpectedServices(service, packages, 0); // 2 approved packages mExpectedPrimaryPackages.clear(); mExpectedPrimaryPackages.put(0, "package"); mExpectedSecondaryPackages.clear(); mExpectedSecondaryPackages.put(0, "packagea"); loadXml(service); // verify the 3 components per package are enabled (bound) verifyExpectedBoundEntries(service, true); verifyExpectedBoundEntries(service, false); } @Test public void testPackageUninstall_packageNoLongerInApprovedList() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, approvalLevel); writeExpectedValuesToSettings(approvalLevel); service.migrateToXml(); mExpectedPrimaryPackages.put(0, "another.package"); mExpectedPrimaryComponentNames.put(0, "another.package/B1"); service.onPackagesChanged(true, new String[]{"this.is.a.package.name"}, new int[]{103}); verifyExpectedApprovedEntries(service); } } @Test public void testPackageUninstall_componentNoLongerInApprovedList() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, approvalLevel); writeExpectedValuesToSettings(approvalLevel); service.migrateToXml(); mExpectedSecondaryComponentNames.put(10, "component/2"); mExpectedSecondaryPackages.put(10, "component"); service.onPackagesChanged(true, new String[]{"this.is.another.package"}, new int[]{ UserHandle.PER_USER_RANGE + 1}); verifyExpectedApprovedEntries(service); } } @Test public void testSetPackageOrComponentEnabled() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, approvalLevel); ArrayMap> expectedEnabled = new ArrayMap<>(); expectedEnabled.put(0, Lists.newArrayList(new String[]{"package/Comp", "package/C2", "again/M4"})); expectedEnabled.put(10, Lists.newArrayList(new String[]{"user10package/B", "user10/Component", "user10package1/K", "user10.3/Component", "user10package2/L", "user10.4/Component"})); for (int userId : expectedEnabled.keySet()) { ArrayList expectedForUser = expectedEnabled.get(userId); for (int i = 0; i < expectedForUser.size(); i++) { boolean primary = i % 2 == 0; service.setPackageOrComponentEnabled(expectedForUser.get(i), userId, primary, true); } } // verify everything added is approved for (int userId : expectedEnabled.keySet()) { ArrayList expectedForUser = expectedEnabled.get(userId); for (int i = 0; i < expectedForUser.size(); i++) { String verifyValue = (approvalLevel == APPROVAL_BY_COMPONENT) ? expectedForUser.get(i) : service.getPackageName(expectedForUser.get(i)); assertTrue("Not allowed: user: " + userId + " entry: " + verifyValue + " for approval level " + approvalLevel, service.isPackageOrComponentAllowed(verifyValue, userId)); } } ArrayMap> expectedNoAccess = new ArrayMap<>(); for (int userId : expectedEnabled.keySet()) { ArrayList expectedForUser = expectedEnabled.get(userId); for (int i = expectedForUser.size() - 1; i >= 0; i--) { ArrayList removed = new ArrayList<>(); if (i % 3 == 0) { String revokeAccessFor = expectedForUser.remove(i); removed.add(revokeAccessFor); service.setPackageOrComponentEnabled( revokeAccessFor, userId, i % 2 == 0, false); } expectedNoAccess.put(userId, removed); } } // verify everything still there is approved for (int userId : expectedEnabled.keySet()) { ArrayList expectedForUser = expectedEnabled.get(userId); for (int i = 0; i < expectedForUser.size(); i++) { String verifyValue = (approvalLevel == APPROVAL_BY_COMPONENT) ? expectedForUser.get(i) : service.getPackageName(expectedForUser.get(i)); assertTrue("Not allowed: user: " + userId + " entry: " + verifyValue, service.isPackageOrComponentAllowed(verifyValue, userId)); } } // verify everything removed isn't for (int userId : expectedNoAccess.keySet()) { ArrayList notExpectedForUser = expectedNoAccess.get(userId); for (int i = 0; i < notExpectedForUser.size(); i++) { assertFalse( "Is allowed: user: " + userId + " entry: " + notExpectedForUser.get(i), service.isPackageOrComponentAllowed(notExpectedForUser.get(i), userId)); } } } } @Test public void testGetAllowedPackages() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, approvalLevel); loadXml(service); List allowedPackagesForUser0 = new ArrayList<>(); allowedPackagesForUser0.add("this.is.a.package.name"); allowedPackagesForUser0.add("another.package"); allowedPackagesForUser0.add("secondary"); List actual = service.getAllowedPackages(0); assertEquals(3, actual.size()); for (String pkg : allowedPackagesForUser0) { assertTrue(actual.contains(pkg)); } List allowedPackagesForUser10 = new ArrayList<>(); allowedPackagesForUser10.add("this.is.another.package"); allowedPackagesForUser10.add("package"); allowedPackagesForUser10.add("this.is.another.package"); allowedPackagesForUser10.add("component"); actual = service.getAllowedPackages(10); assertEquals(4, actual.size()); for (String pkg : allowedPackagesForUser10) { assertTrue(actual.contains(pkg)); } } } @Test public void testGetAllowedComponents() throws Exception { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, APPROVAL_BY_COMPONENT); loadXml(service); List expected = new ArrayList<>(); expected.add(ComponentName.unflattenFromString("this.is.another.package/M1")); expected.add(ComponentName.unflattenFromString("this.is.another.package/with.Component")); expected.add(ComponentName.unflattenFromString("component/2")); expected.add(ComponentName.unflattenFromString("package/component2")); List actual = service.getAllowedComponents(10); assertContentsInAnyOrder(expected, actual); assertEquals(expected.size(), actual.size()); for (ComponentName cn : expected) { assertTrue("Actual missing " + cn, actual.contains(cn)); } for (ComponentName cn : actual) { assertTrue("Actual contains extra " + cn, expected.contains(cn)); } } @Test public void testGetAllowedComponents_approvalByPackage() throws Exception { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, APPROVAL_BY_PACKAGE); loadXml(service); assertEquals(0, service.getAllowedComponents(10).size()); } @Test public void testOnUserRemoved() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm, approvalLevel); loadXml(service); ArrayMap verifyMap = mExpectedPrimary.get(service.mApprovalLevel); String user0 = verifyMap.remove(0); verifyMap = mExpectedSecondary.get(service.mApprovalLevel); user0 = user0 + ":" + verifyMap.remove(0); service.onUserRemoved(0); for (String verifyValue : user0.split(":")) { if (!TextUtils.isEmpty(verifyValue)) { assertFalse("service type " + service.mApprovalLevel + ":" + verifyValue + " is still allowed", service.isPackageOrComponentAllowed(verifyValue, 0)); } } verifyExpectedApprovedEntries(service); } } private void loadXml(ManagedServices service) throws Exception { final StringBuffer xml = new StringBuffer(); xml.append("<" + service.getConfig().xmlTag + ">\n"); for (int userId : mExpectedPrimary.get(service.mApprovalLevel).keySet()) { xml.append(getXmlEntry( mExpectedPrimary.get(service.mApprovalLevel).get(userId), userId, true)); } for (int userId : mExpectedSecondary.get(service.mApprovalLevel).keySet()) { xml.append(getXmlEntry( mExpectedSecondary.get(service.mApprovalLevel).get(userId), userId, false)); } xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " " + ManagedServices.ATT_USER_ID + "=\"99\" " + ManagedServices.ATT_IS_PRIMARY + "=\"true\" " + ManagedServices.ATT_APPROVED_LIST + "=\"99\" />\n"); xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " " + ManagedServices.ATT_USER_ID + "=\"98\" " + ManagedServices.ATT_IS_PRIMARY + "=\"false\" " + ManagedServices.ATT_APPROVED_LIST + "=\"98\" />\n"); xml.append(""); XmlPullParser parser = Xml.newPullParser(); parser.setInput(new BufferedInputStream( new ByteArrayInputStream(xml.toString().getBytes())), null); parser.nextTag(); service.readXml(parser); } private void addExpectedServices(final ManagedServices service, final List packages, int userId) { when(mPm.queryIntentServicesAsUser(any(), anyInt(), eq(userId))). thenAnswer(new Answer>() { @Override public List answer(InvocationOnMock invocationOnMock) throws Throwable { Object[] args = invocationOnMock.getArguments(); Intent invocationIntent = (Intent) args[0]; if (invocationIntent != null) { if (invocationIntent.getAction().equals( service.getConfig().serviceInterface) && packages.contains(invocationIntent.getPackage())) { List dummyServices = new ArrayList<>(); for (int i = 1; i <= 3; i ++) { ResolveInfo resolveInfo = new ResolveInfo(); ServiceInfo serviceInfo = new ServiceInfo(); serviceInfo.packageName = invocationIntent.getPackage(); serviceInfo.name = "C"+i; serviceInfo.permission = service.getConfig().bindPermission; resolveInfo.serviceInfo = serviceInfo; dummyServices.add(resolveInfo); } return dummyServices; } } return new ArrayList<>(); } }); } private List stringToList(String list) { if (list == null) { list = ""; } return new ArrayList<>(Lists.newArrayList(list.split( ManagedServices.ENABLED_SERVICES_SEPARATOR))); } private void assertContentsInAnyOrder(List expected, List actual) { assertEquals(expected.size(), actual.size()); for (Object o : expected) { assertTrue("Actual missing " + o, actual.contains(o)); } for (Object o : actual) { assertTrue("Actual contains extra " + o, expected.contains(o)); } } private void verifyExpectedBoundEntries(ManagedServices service, boolean primary) throws Exception { ArrayMap verifyMap = primary ? mExpectedPrimary.get(service.mApprovalLevel) : mExpectedSecondary.get(service.mApprovalLevel); for (int userId : verifyMap.keySet()) { for (String packageOrComponent : verifyMap.get(userId).split(":")) { if (!TextUtils.isEmpty(packageOrComponent)) { if (service.mApprovalLevel == APPROVAL_BY_PACKAGE) { assertTrue(packageOrComponent, service.isComponentEnabledForPackage(packageOrComponent)); for (int i = 1; i <= 3; i ++) { ComponentName componentName = ComponentName.unflattenFromString( packageOrComponent +"/C" + i); assertTrue(service.isComponentEnabledForCurrentProfiles( componentName)); verify(mIpm, times(1)).getServiceInfo( eq(componentName), anyInt(), anyInt()); } } else { ComponentName componentName = ComponentName.unflattenFromString(packageOrComponent); assertTrue(service.isComponentEnabledForCurrentProfiles(componentName)); verify(mIpm, times(1)).getServiceInfo( eq(componentName), anyInt(), anyInt()); } } } } } private void verifyExpectedApprovedEntries(ManagedServices service) { verifyExpectedApprovedEntries(service, true); verifyExpectedApprovedEntries(service, false); } private void verifyExpectedApprovedEntries(ManagedServices service, boolean primary) { ArrayMap verifyMap = primary ? mExpectedPrimary.get(service.mApprovalLevel) : mExpectedSecondary.get(service.mApprovalLevel); verifyExpectedApprovedEntries(service, verifyMap); } private void verifyExpectedApprovedEntries(ManagedServices service, ArrayMap verifyMap) { for (int userId : verifyMap.keySet()) { for (String verifyValue : verifyMap.get(userId).split(":")) { if (!TextUtils.isEmpty(verifyValue)) { assertTrue("service type " + service.mApprovalLevel + ":" + verifyValue + " is not allowed for user " + userId, service.isPackageOrComponentAllowed(verifyValue, userId)); } } } } private void writeExpectedValuesToSettings(int approvalLevel) { for (int userId : mExpectedPrimary.get(approvalLevel).keySet()) { Settings.Secure.putStringForUser(getContext().getContentResolver(), SETTING, mExpectedPrimary.get(approvalLevel).get(userId), userId); } for (int userId : mExpectedSecondary.get(approvalLevel).keySet()) { Settings.Secure.putStringForUser(getContext().getContentResolver(), SECONDARY_SETTING, mExpectedSecondary.get(approvalLevel).get(userId), userId); } } private String getXmlEntry(String approved, int userId, boolean isPrimary) { return "<" + ManagedServices.TAG_MANAGED_SERVICES + " " + ManagedServices.ATT_USER_ID + "=\"" + userId +"\" " + ManagedServices.ATT_IS_PRIMARY + "=\"" + isPrimary +"\" " + ManagedServices.ATT_APPROVED_LIST + "=\"" + approved +"\" " + "/>\n"; } class TestManagedServices extends ManagedServices { public TestManagedServices(Context context, Object mutex, UserProfiles userProfiles, IPackageManager pm, int approvedServiceType) { super(context, mutex, userProfiles, pm); mApprovalLevel = approvedServiceType; } @Override protected Config getConfig() { final Config c = new Config(); c.xmlTag = "test"; c.secureSettingName = SETTING; c.secondarySettingName = SECONDARY_SETTING; c.bindPermission = "permission"; c.serviceInterface = "serviceInterface"; return c; } @Override protected IInterface asInterface(IBinder binder) { return null; } @Override protected boolean checkType(IInterface service) { return false; } @Override protected void onServiceAdded(ManagedServiceInfo info) { } } }