diff options
author | Alex Kershaw <alexkershaw@google.com> | 2020-01-15 20:00:05 +0000 |
---|---|---|
committer | Alex Kershaw <alexkershaw@google.com> | 2020-01-22 13:20:24 +0000 |
commit | 4b0197d8ba2cacaed1a2b6a774c78774fdeeffdc (patch) | |
tree | e3933f538532e6aee103e81a1ef0b8171bd0aa9c /services/robotests/src | |
parent | a263d01c447f4bf5d946dfb4361ad78a5ecce7b1 (diff) |
Reset unset app-ops when the admin sets cross-profile packages.
When the admin unsets cross-profile packages, reset the
INTERACT_ACROSS_PROFILES app-op back to the default if it is no longer
configurable by the user.
Other minor changes:
- Remove the explicit app-op permission check from
setInteractAcrossProfilesAppOp, since AppOpManager performs that check
when required.
- Fix the broadcasting logic in CrossProfileAppsServiceImpl to correctly
set the component and flags.
Bug: 136249261
Bug: 148010178
Test: atest CtsDevicePolicyManagerTestCases:com.android.cts.devicepolicy.ManagedProfileCrossProfileTest
Change-Id: Ib8b5f331fb92fc475bc95ad039adf93fac04da37
Diffstat (limited to 'services/robotests/src')
2 files changed, 104 insertions, 22 deletions
diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java index 96ff9c1ba726..1a7b1d3f6039 100644 --- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java +++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java @@ -18,6 +18,8 @@ package com.android.server.pm; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.OP_INTERACT_ACROSS_PROFILES; +import static android.content.Intent.FLAG_RECEIVER_FOREGROUND; +import static android.content.Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND; import static android.content.Intent.FLAG_RECEIVER_REGISTERED_ONLY; import static android.content.pm.CrossProfileApps.ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED; @@ -37,11 +39,13 @@ import android.app.AppOpsManager.Mode; import android.app.admin.DevicePolicyManagerInternal; import android.content.ContextWrapper; import android.content.Intent; +import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; +import android.content.pm.ResolveInfo; import android.content.pm.parsing.AndroidPackage; import android.content.pm.parsing.PackageImpl; import android.os.Process; @@ -70,6 +74,7 @@ import org.robolectric.shadow.api.Shadow; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -106,6 +111,7 @@ public class CrossProfileAppsServiceImplRoboTest { MockitoAnnotations.initMocks(this); mockCrossProfileAppInstalledAndEnabledOnEachProfile(); mockCrossProfileAppRequestsInteractAcrossProfiles(); + mockCrossProfileAppRegistersBroadcastReceiver(); mockCrossProfileAppWhitelisted(); } @@ -113,19 +119,21 @@ public class CrossProfileAppsServiceImplRoboTest { // They are enabled by default, so we simply have to ensure that a package info with an // application info is returned. final PackageInfo packageInfo = buildTestPackageInfo(); + mockCrossProfileAppInstalledOnProfile( + packageInfo, PERSONAL_PROFILE_USER_ID, PERSONAL_PROFILE_UID); + mockCrossProfileAppInstalledOnProfile(packageInfo, WORK_PROFILE_USER_ID, WORK_PROFILE_UID); + } + + private void mockCrossProfileAppInstalledOnProfile( + PackageInfo packageInfo, @UserIdInt int userId, int uid) { when(mPackageManagerInternal.getPackageInfo( eq(CROSS_PROFILE_APP_PACKAGE_NAME), /* flags= */ anyInt(), /* filterCallingUid= */ anyInt(), - eq(PERSONAL_PROFILE_USER_ID))) + eq(userId))) .thenReturn(packageInfo); - when(mPackageManagerInternal.getPackageInfo( - eq(CROSS_PROFILE_APP_PACKAGE_NAME), - /* flags= */ anyInt(), - /* filterCallingUid= */ anyInt(), - eq(WORK_PROFILE_USER_ID))) - .thenReturn(packageInfo); - mockCrossProfileAndroidPackage(PackageImpl.forParsing(CROSS_PROFILE_APP_PACKAGE_NAME)); + when(mPackageManagerInternal.getPackage(uid)) + .thenReturn(PackageImpl.forParsing(CROSS_PROFILE_APP_PACKAGE_NAME)); } private PackageInfo buildTestPackageInfo() { @@ -140,6 +148,31 @@ public class CrossProfileAppsServiceImplRoboTest { .thenReturn(new String[] {CROSS_PROFILE_APP_PACKAGE_NAME}); } + private void mockCrossProfileAppRegistersBroadcastReceiver() { + final ShadowApplicationPackageManager shadowApplicationPackageManager = + Shadow.extract(mPackageManager); + final Intent baseIntent = + new Intent(ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED) + .setPackage(CROSS_PROFILE_APP_PACKAGE_NAME); + final Intent manifestIntent = + new Intent(baseIntent) + .setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND + | Intent.FLAG_RECEIVER_FOREGROUND); + final Intent registeredIntent = + new Intent(baseIntent).setFlags(FLAG_RECEIVER_REGISTERED_ONLY); + final List<ResolveInfo> resolveInfos = Lists.newArrayList(buildTestResolveInfo()); + shadowApplicationPackageManager.setResolveInfosForIntent(manifestIntent, resolveInfos); + shadowApplicationPackageManager.setResolveInfosForIntent(registeredIntent, resolveInfos); + } + + private ResolveInfo buildTestResolveInfo() { + final ResolveInfo resolveInfo = new ResolveInfo(); + resolveInfo.activityInfo = new ActivityInfo(); + resolveInfo.activityInfo.packageName = CROSS_PROFILE_APP_PACKAGE_NAME; + resolveInfo.activityInfo.name = CROSS_PROFILE_APP_PACKAGE_NAME + ".Receiver"; + return resolveInfo; + } + private void mockCrossProfileAppWhitelisted() { when(mDevicePolicyManagerInternal.getAllCrossProfilePackages()) .thenReturn(Lists.newArrayList(CROSS_PROFILE_APP_PACKAGE_NAME)); @@ -191,16 +224,6 @@ public class CrossProfileAppsServiceImplRoboTest { } @Test - public void setInteractAcrossProfilesAppOp_missingManageAppOpsModes_throwsSecurityException() { - denyPermissions(Manifest.permission.MANAGE_APP_OPS_MODES); - try { - mCrossProfileAppsServiceImpl.setInteractAcrossProfilesAppOp( - CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED); - fail(); - } catch (SecurityException expected) {} - } - - @Test public void setInteractAcrossProfilesAppOp_setsAppOp() { mCrossProfileAppsServiceImpl.setInteractAcrossProfilesAppOp( CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED); @@ -294,6 +317,54 @@ public class CrossProfileAppsServiceImplRoboTest { assertThat(receivedManifestCanInteractAcrossProfilesChangedBroadcast()).isTrue(); } + @Test + public void canConfigureInteractAcrossProfiles_packageNotInstalledInProfile_returnsFalse() { + mockUninstallCrossProfileAppFromWorkProfile(); + assertThat(mCrossProfileAppsServiceImpl + .canConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME)) + .isFalse(); + } + + private void mockUninstallCrossProfileAppFromWorkProfile() { + when(mPackageManagerInternal.getPackageInfo( + eq(CROSS_PROFILE_APP_PACKAGE_NAME), + /* flags= */ anyInt(), + /* filterCallingUid= */ anyInt(), + eq(WORK_PROFILE_USER_ID))) + .thenReturn(null); + when(mPackageManagerInternal.getPackage(WORK_PROFILE_UID)).thenReturn(null); + } + + @Test + public void canConfigureInteractAcrossProfiles_packageDoesNotRequestInteractAcrossProfiles_returnsFalse() + throws Exception { + mockCrossProfileAppDoesNotRequestInteractAcrossProfiles(); + assertThat(mCrossProfileAppsServiceImpl + .canConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME)) + .isFalse(); + } + + private void mockCrossProfileAppDoesNotRequestInteractAcrossProfiles() throws Exception { + final String permissionName = Manifest.permission.INTERACT_ACROSS_PROFILES; + when(mIPackageManager.getAppOpPermissionPackages(permissionName)) + .thenReturn(new String[] {}); + } + + @Test + public void canConfigureInteractAcrossProfiles_packageNotWhitelisted_returnsFalse() { + mockCrossProfileAppNotWhitelisted(); + assertThat(mCrossProfileAppsServiceImpl + .canConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME)) + .isFalse(); + } + + @Test + public void canConfigureInteractAcrossProfiles_returnsTrue() { + assertThat(mCrossProfileAppsServiceImpl + .canConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME)) + .isTrue(); + } + private void explicitlySetInteractAcrossProfilesAppOp(@Mode int mode) { explicitlySetInteractAcrossProfilesAppOp(PERSONAL_PROFILE_UID, mode); } @@ -311,7 +382,6 @@ public class CrossProfileAppsServiceImplRoboTest { shadowOf(mContext).denyPermissions(Process.myPid(), CALLING_UID, permissions); } - private @Mode int getCrossProfileAppOp() { return getCrossProfileAppOp(PERSONAL_PROFILE_UID); } @@ -365,10 +435,12 @@ public class CrossProfileAppsServiceImplRoboTest { } private boolean isBroadcastManifestCanInteractAcrossProfilesChanged(Intent intent) { - // The manifest check is negative since the FLAG_RECEIVER_REGISTERED_ONLY flag means that - // manifest receivers can NOT receive the broadcast. return isBroadcastCanInteractAcrossProfilesChanged(intent) - && (intent.getFlags() & FLAG_RECEIVER_REGISTERED_ONLY) == 0; + && (intent.getFlags() & FLAG_RECEIVER_REGISTERED_ONLY) == 0 + && (intent.getFlags() & FLAG_RECEIVER_INCLUDE_BACKGROUND) != 0 + && (intent.getFlags() & FLAG_RECEIVER_FOREGROUND) != 0 + && intent.getComponent() != null + && intent.getComponent().getPackageName().equals(CROSS_PROFILE_APP_PACKAGE_NAME); } private void declareCrossProfileAttributeOnCrossProfileApp(boolean value) { diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java b/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java index 1443eabf07d5..aea36e555ad7 100644 --- a/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java +++ b/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java @@ -19,7 +19,10 @@ package com.android.server.testing.shadows; import static android.content.pm.PackageManager.NameNotFoundException; import android.app.ApplicationPackageManager; +import android.content.Intent; import android.content.pm.PackageInfo; +import android.content.pm.ResolveInfo; +import android.os.UserHandle; import android.util.ArrayMap; import org.robolectric.annotation.Implements; @@ -100,6 +103,13 @@ public class ShadowApplicationPackageManager return sPackageUids.get(packageName); } + @Override + protected List<ResolveInfo> queryBroadcastReceiversAsUser( + Intent intent, int flags, UserHandle userHandle) { + // Currently does not handle multi-user. + return queryBroadcastReceivers(intent, flags); + } + /** Clear package state. */ @Resetter public static void reset() { |