Merge "Add hidden API to clear all cross-profile app-ops" into rvc-dev
This commit is contained in:
@@ -487,6 +487,34 @@ public class CrossProfileApps {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the app-op for {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES} back to
|
||||
* its default value for every package on the device.
|
||||
*
|
||||
* <p>This method can be used to ensure that app-op state is not left around on existing users
|
||||
* for previously-configured profiles.
|
||||
*
|
||||
* <p>If the caller does not have the {@link android.Manifest.permission
|
||||
* #CONFIGURE_INTERACT_ACROSS_PROFILES} permission, then they must have the permissions that
|
||||
* would have been required to call {@link android.app.AppOpsManager#setMode(int, int, String,
|
||||
* int)}, which includes {@link android.Manifest.permission#MANAGE_APP_OPS_MODES}.
|
||||
*
|
||||
* <p>Also requires either {@link android.Manifest.permission#INTERACT_ACROSS_USERS} or {@link
|
||||
* android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(
|
||||
allOf={android.Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES,
|
||||
android.Manifest.permission.INTERACT_ACROSS_USERS})
|
||||
public void clearInteractAcrossProfilesAppOps() {
|
||||
try {
|
||||
mService.clearInteractAcrossProfilesAppOps();
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyCanAccessUser(UserHandle userHandle) {
|
||||
if (!getTargetUserProfiles().contains(userHandle)) {
|
||||
throw new SecurityException("Not allowed to access " + userHandle);
|
||||
|
||||
@@ -40,4 +40,5 @@ interface ICrossProfileApps {
|
||||
boolean canConfigureInteractAcrossProfiles(in String packageName);
|
||||
boolean canUserAttemptToConfigureInteractAcrossProfiles(in String packageName);
|
||||
void resetInteractAcrossProfilesAppOps(in List<String> packageNames);
|
||||
void clearInteractAcrossProfilesAppOps();
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ import com.android.server.wm.ActivityTaskManagerInternal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
|
||||
private static final String TAG = "CrossProfileAppsService";
|
||||
@@ -447,7 +448,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
|
||||
final int uid = mInjector.getPackageManager()
|
||||
.getPackageUidAsUser(packageName, /* flags= */ 0, userId);
|
||||
if (currentModeEquals(newMode, packageName, uid)) {
|
||||
Slog.w(TAG, "Attempt to set mode to existing value of " + newMode + " for "
|
||||
Slog.i(TAG, "Attempt to set mode to existing value of " + newMode + " for "
|
||||
+ packageName + " on user ID " + userId);
|
||||
return;
|
||||
}
|
||||
@@ -577,6 +578,24 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
|
||||
setInteractAcrossProfilesAppOp(packageName, AppOpsManager.opToDefaultMode(op));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearInteractAcrossProfilesAppOps() {
|
||||
final int defaultMode =
|
||||
AppOpsManager.opToDefaultMode(
|
||||
AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES));
|
||||
findAllPackageNames()
|
||||
.forEach(packageName -> setInteractAcrossProfilesAppOp(packageName, defaultMode));
|
||||
}
|
||||
|
||||
private List<String> findAllPackageNames() {
|
||||
return mInjector.getPackageManagerInternal()
|
||||
.getInstalledApplications(
|
||||
/* flags= */ 0, mInjector.getCallingUserId(), mInjector.getCallingUid())
|
||||
.stream()
|
||||
.map(applicationInfo -> applicationInfo.packageName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
CrossProfileAppsInternal getLocalService() {
|
||||
return mLocalService;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.pm;
|
||||
|
||||
import static android.app.AppOpsManager.MODE_ALLOWED;
|
||||
import static android.app.AppOpsManager.MODE_DEFAULT;
|
||||
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;
|
||||
@@ -104,6 +105,7 @@ public class CrossProfileAppsServiceImplRoboTest {
|
||||
private final CrossProfileAppsServiceImpl mCrossProfileAppsServiceImpl =
|
||||
new CrossProfileAppsServiceImpl(mContext, mInjector);
|
||||
private final Map<UserHandle, Set<Intent>> mSentUserBroadcasts = new HashMap<>();
|
||||
private final Map<Integer, List<ApplicationInfo>> installedApplications = new HashMap<>();
|
||||
|
||||
@Mock private PackageManagerInternal mPackageManagerInternal;
|
||||
@Mock private IPackageManager mIPackageManager;
|
||||
@@ -112,12 +114,18 @@ public class CrossProfileAppsServiceImplRoboTest {
|
||||
@Before
|
||||
public void initializeMocks() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
initializeInstalledApplicationsMock();
|
||||
mockCrossProfileAppInstalledAndEnabledOnEachProfile();
|
||||
mockCrossProfileAppRequestsInteractAcrossProfiles();
|
||||
mockCrossProfileAppRegistersBroadcastReceiver();
|
||||
mockCrossProfileAppWhitelisted();
|
||||
}
|
||||
|
||||
private void initializeInstalledApplicationsMock() {
|
||||
when(mPackageManagerInternal.getInstalledApplications(anyInt(), anyInt(), eq(CALLING_UID)))
|
||||
.thenAnswer(invocation -> installedApplications.get(invocation.getArgument(1)));
|
||||
}
|
||||
|
||||
private void mockCrossProfileAppInstalledAndEnabledOnEachProfile() {
|
||||
// They are enabled by default, so we simply have to ensure that a package info with an
|
||||
// application info is returned.
|
||||
@@ -138,11 +146,14 @@ public class CrossProfileAppsServiceImplRoboTest {
|
||||
when(mPackageManagerInternal.getPackage(uid))
|
||||
.thenReturn(((ParsedPackage) PackageImpl.forTesting(CROSS_PROFILE_APP_PACKAGE_NAME)
|
||||
.hideAsParsed()).hideAsFinal());
|
||||
installedApplications.putIfAbsent(userId, new ArrayList<>());
|
||||
installedApplications.get(userId).add(packageInfo.applicationInfo);
|
||||
}
|
||||
|
||||
private PackageInfo buildTestPackageInfo() {
|
||||
PackageInfo packageInfo = new PackageInfo();
|
||||
packageInfo.applicationInfo = new ApplicationInfo();
|
||||
packageInfo.applicationInfo.packageName = CROSS_PROFILE_APP_PACKAGE_NAME;
|
||||
return packageInfo;
|
||||
}
|
||||
|
||||
@@ -451,6 +462,13 @@ public class CrossProfileAppsServiceImplRoboTest {
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearInteractAcrossProfilesAppOps() {
|
||||
explicitlySetInteractAcrossProfilesAppOp(MODE_ALLOWED);
|
||||
mCrossProfileAppsServiceImpl.clearInteractAcrossProfilesAppOps();
|
||||
assertThat(getCrossProfileAppOp()).isEqualTo(MODE_DEFAULT);
|
||||
}
|
||||
|
||||
private void explicitlySetInteractAcrossProfilesAppOp(@Mode int mode) {
|
||||
explicitlySetInteractAcrossProfilesAppOp(PERSONAL_PROFILE_UID, mode);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user