Add CrossProfileAppsInternal#getTargetUserProfiles

This will be used by the logic that updates the app bucket state of
cross-profile connected apps that declare the crossProfile manifest
attribute.

Also makes the following changes:
- Fixes CrossProfileAppsServiceImplRoboTest by registering the local
service in a different way.
- Removes some code duplication in CrossProfileAppsServiceImpl.
- Some clean-up.

Robolectric tests will be added later. Right now, there seems to be a
problem causing log messages not to appear, making debugging impossible.

Bug: 140808123
Bug: 136249261
Test: atest com.android.server.pm.CrossProfileAppsServiceImplRoboTest
Change-Id: Iefa6b2a7cb7535d5796d5ca8916c10b29c2e0661
This commit is contained in:
Alex Kershaw
2020-02-15 12:01:43 +00:00
parent efa8903567
commit 179ba0b4e4
3 changed files with 47 additions and 26 deletions

View File

@@ -17,6 +17,9 @@
package android.content.pm;
import android.annotation.UserIdInt;
import android.os.UserHandle;
import java.util.List;
/**
* Exposes internal methods from {@link com.android.server.pm.CrossProfileAppsServiceImpl} to other
@@ -52,4 +55,11 @@ public abstract class CrossProfileAppsInternal {
*/
public abstract boolean verifyUidHasInteractAcrossProfilePermission(String packageName,
int uid);
/**
* Returns the list of target user profiles for the given package on the given user. See {@link
* CrossProfileApps#getTargetUserProfiles()}.
*/
public abstract List<UserHandle> getTargetUserProfiles(
String packageName, @UserIdInt int userId);
}

View File

@@ -16,6 +16,7 @@
package com.android.server.pm;
import android.content.Context;
import android.content.pm.CrossProfileAppsInternal;
import com.android.server.SystemService;
@@ -30,5 +31,6 @@ public class CrossProfileAppsService extends SystemService {
@Override
public void onStart() {
publishBinderService(Context.CROSS_PROFILE_APPS_SERVICE, mServiceImpl);
publishLocalService(CrossProfileAppsInternal.class, mServiceImpl.getLocalService());
}
}

View File

@@ -66,6 +66,8 @@ import java.util.Objects;
public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
private static final String TAG = "CrossProfileAppsService";
private final LocalService mLocalService = new LocalService();
private Context mContext;
private Injector mInjector;
@@ -77,8 +79,6 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
CrossProfileAppsServiceImpl(Context context, Injector injector) {
mContext = context;
mInjector = injector;
LocalServices.addService(CrossProfileAppsInternal.class, new LocalService());
}
@Override
@@ -205,7 +205,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
}
if (callerUserId != userId) {
if (!hasInteractAcrossProfilesPermission(callingPackage)) {
if (!hasCallerGotInteractAcrossProfilesPermission(callingPackage)) {
throw new SecurityException("Attempt to launch activity without required "
+ android.Manifest.permission.INTERACT_ACROSS_PROFILES + " permission"
+ " or target user is not in the same profile group.");
@@ -268,20 +268,12 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
if (targetUserProfiles.isEmpty()) {
return false;
}
return hasInteractAcrossProfilesPermission(callingPackage);
return hasCallerGotInteractAcrossProfilesPermission(callingPackage);
}
private boolean hasInteractAcrossProfilesPermission(String callingPackage) {
final int callingUid = mInjector.getCallingUid();
final int callingPid = mInjector.getCallingPid();
return isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingUid)
|| isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS, callingUid)
|| PermissionChecker.checkPermissionForPreflight(
mContext,
Manifest.permission.INTERACT_ACROSS_PROFILES,
callingPid,
callingUid,
callingPackage) == PermissionChecker.PERMISSION_GRANTED;
private boolean hasCallerGotInteractAcrossProfilesPermission(String callingPackage) {
return hasInteractAcrossProfilesPermission(
callingPackage, mInjector.getCallingUid(), mInjector.getCallingPid());
}
private boolean isCrossProfilePackageWhitelisted(String packageName) {
@@ -563,6 +555,10 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
setInteractAcrossProfilesAppOp(packageName, AppOpsManager.opToDefaultMode(op));
}
CrossProfileAppsInternal getLocalService() {
return mLocalService;
}
private boolean isSameProfileGroup(@UserIdInt int callerUserId, @UserIdInt int userId) {
return mInjector.withCleanCallingIdentity(() ->
mInjector.getUserManager().isSameProfileGroup(callerUserId, userId));
@@ -589,6 +585,20 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
-> mContext.getSystemService(UserManager.class).isManagedProfile(userId));
}
private boolean hasInteractAcrossProfilesPermission(String packageName, int uid, int pid) {
if (isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, uid)
|| isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS, uid)) {
return true;
}
return PermissionChecker.PERMISSION_GRANTED
== PermissionChecker.checkPermissionForPreflight(
mContext,
Manifest.permission.INTERACT_ACROSS_PROFILES,
pid,
uid,
packageName);
}
private static class InjectorImpl implements Injector {
private Context mContext;
@@ -728,9 +738,11 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
}
class LocalService extends CrossProfileAppsInternal {
@Override
public boolean verifyPackageHasInteractAcrossProfilePermission(String packageName,
@UserIdInt int userId) throws PackageManager.NameNotFoundException {
public boolean verifyPackageHasInteractAcrossProfilePermission(
String packageName, @UserIdInt int userId)
throws PackageManager.NameNotFoundException {
final int uid = Objects.requireNonNull(
mInjector.getPackageManager().getApplicationInfoAsUser(
Objects.requireNonNull(packageName), /* flags= */ 0, userId)).uid;
@@ -740,16 +752,13 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
@Override
public boolean verifyUidHasInteractAcrossProfilePermission(String packageName, int uid) {
Objects.requireNonNull(packageName);
return hasInteractAcrossProfilesPermission(
packageName, uid, PermissionChecker.PID_UNKNOWN);
}
return isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, uid)
|| isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS, uid)
|| isPermissionGranted(Manifest.permission.INTERACT_ACROSS_PROFILES, uid)
|| PermissionChecker.checkPermissionForPreflight(
mContext,
Manifest.permission.INTERACT_ACROSS_PROFILES,
PermissionChecker.PID_UNKNOWN,
uid,
packageName) == PermissionChecker.PERMISSION_GRANTED;
@Override
public List<UserHandle> getTargetUserProfiles(String packageName, int userId) {
return getTargetUserProfilesUnchecked(packageName, userId);
}
}
}