Allow cross user SessionCallback support
Bug: 31929647
Test: Manually tests on device and added CTS tests
Change-Id: I083435c12ce56a675ccf2cb5e00c76fbaace6c65
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index d0ef4f1..597ba63 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -34,9 +34,11 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.ILauncherApps;
import android.content.pm.IOnAppsChangedListener;
+import android.content.pm.IPackageInstallerCallback;
import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
@@ -56,6 +58,7 @@
import android.os.ParcelFileDescriptor;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
@@ -153,6 +156,8 @@
private final Object mVouchedSignaturesLocked = new Object();
+ private PackageInstallerService mPackageInstallerService;
+
public LauncherAppsImpl(Context context) {
mContext = context;
mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
@@ -204,8 +209,7 @@
}
/*
- * @see android.content.pm.ILauncherApps#addOnAppsChangedListener(
- * android.content.pm.IOnAppsChangedListener)
+ * @see android.content.pm.ILauncherApps#addOnAppsChangedListener
*/
@Override
public void addOnAppsChangedListener(String callingPackage, IOnAppsChangedListener listener)
@@ -228,8 +232,7 @@
}
/*
- * @see android.content.pm.ILauncherApps#removeOnAppsChangedListener(
- * android.content.pm.IOnAppsChangedListener)
+ * @see android.content.pm.ILauncherApps#removeOnAppsChangedListener
*/
@Override
public void removeOnAppsChangedListener(IOnAppsChangedListener listener)
@@ -246,6 +249,44 @@
}
/**
+ * @see android.content.pm.ILauncherApps#registerPackageInstallerCallback
+ */
+ @Override
+ public void registerPackageInstallerCallback(String callingPackage,
+ IPackageInstallerCallback callback) {
+ verifyCallingPackage(callingPackage);
+ UserHandle callingIdUserHandle = new UserHandle(getCallingUserId());
+ getPackageInstallerService().registerCallback(callback, eventUserId ->
+ isEnabledProfileOf(callingIdUserHandle,
+ new UserHandle(eventUserId), "shouldReceiveEvent"));
+ }
+
+ @Override
+ public ParceledListSlice<SessionInfo> getAllSessions(String callingPackage) {
+ verifyCallingPackage(callingPackage);
+ List<SessionInfo> sessionInfos = new ArrayList<>();
+ int[] userIds = mUm.getEnabledProfileIds(getCallingUserId());
+ long token = Binder.clearCallingIdentity();
+ try {
+ for (int userId : userIds) {
+ sessionInfos.addAll(getPackageInstallerService().getAllSessions(userId)
+ .getList());
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return new ParceledListSlice<>(sessionInfos);
+ }
+
+ private PackageInstallerService getPackageInstallerService() {
+ if (mPackageInstallerService == null) {
+ mPackageInstallerService = ((PackageInstallerService) ((PackageManagerService)
+ ServiceManager.getService("package")).getPackageInstaller());
+ }
+ return mPackageInstallerService;
+ }
+
+ /**
* Register a receiver to watch for package broadcasts
*/
private void startWatchingPackageBroadcasts() {
@@ -844,6 +885,29 @@
}
@Override
+ public void startSessionDetailsActivityAsUser(IApplicationThread caller,
+ String callingPackage, SessionInfo sessionInfo, Rect sourceBounds,
+ Bundle opts, UserHandle userHandle) throws RemoteException {
+ int userId = userHandle.getIdentifier();
+ if (!canAccessProfile(userId, "Cannot start details activity")) {
+ return;
+ }
+
+ Intent i = new Intent(Intent.ACTION_VIEW)
+ .setData(new Uri.Builder()
+ .scheme("market")
+ .authority("details")
+ .appendQueryParameter("id", sessionInfo.appPackageName)
+ .build())
+ .putExtra(Intent.EXTRA_REFERRER, new Uri.Builder().scheme("android-app")
+ .authority(callingPackage).build());
+ i.setSourceBounds(sourceBounds);
+
+ mActivityTaskManagerInternal.startActivityAsUser(caller, callingPackage, i, opts,
+ userId);
+ }
+
+ @Override
public void startActivityAsUser(IApplicationThread caller, String callingPackage,
ComponentName component, Rect sourceBounds,
Bundle opts, UserHandle user) throws RemoteException {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 146a2f3..a3e0d8d 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -59,7 +59,6 @@
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SELinux;
-import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.system.ErrnoException;
@@ -107,6 +106,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Random;
+import java.util.function.IntPredicate;
/** The service responsible for installing packages. */
public class PackageInstallerService extends IPackageInstaller.Stub implements
@@ -804,7 +804,14 @@
public void registerCallback(IPackageInstallerCallback callback, int userId) {
mPermissionManager.enforceCrossUserPermission(
Binder.getCallingUid(), userId, true, false, "registerCallback");
- mCallbacks.register(callback, userId);
+ registerCallback(callback, eventUserId -> userId == eventUserId);
+ }
+
+ /**
+ * Assume permissions already checked and caller's identity cleared
+ */
+ public void registerCallback(IPackageInstallerCallback callback, IntPredicate userCheck) {
+ mCallbacks.register(callback, userCheck);
}
@Override
@@ -1026,8 +1033,8 @@
super(looper);
}
- public void register(IPackageInstallerCallback callback, int userId) {
- mCallbacks.register(callback, new UserHandle(userId));
+ public void register(IPackageInstallerCallback callback, IntPredicate userCheck) {
+ mCallbacks.register(callback, userCheck);
}
public void unregister(IPackageInstallerCallback callback) {
@@ -1040,9 +1047,8 @@
final int n = mCallbacks.beginBroadcast();
for (int i = 0; i < n; i++) {
final IPackageInstallerCallback callback = mCallbacks.getBroadcastItem(i);
- final UserHandle user = (UserHandle) mCallbacks.getBroadcastCookie(i);
- // TODO: dispatch notifications for slave profiles
- if (userId == user.getIdentifier()) {
+ final IntPredicate userCheck = (IntPredicate) mCallbacks.getBroadcastCookie(i);
+ if (userCheck.test(userId)) {
try {
invokeCallback(callback, msg);
} catch (RemoteException ignored) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 494ec3f..de0849f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -473,6 +473,7 @@
final SessionInfo info = new SessionInfo();
synchronized (mLock) {
info.sessionId = sessionId;
+ info.userId = userId;
info.installerPackageName = mInstallerPackageName;
info.resolvedBaseCodePath = (mResolvedBaseFile != null) ?
mResolvedBaseFile.getAbsolutePath() : null;
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 4f20590..d0f192d 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1109,14 +1109,7 @@
@Override
public int getManagedProfileBadge(@UserIdInt int userId) {
- int callingUserId = UserHandle.getCallingUserId();
- if (callingUserId != userId && !hasManageUsersPermission()) {
- if (!isSameProfileGroupNoChecks(callingUserId, userId)) {
- throw new SecurityException(
- "You need MANAGE_USERS permission to: check if specified user a " +
- "managed profile outside your profile group");
- }
- }
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "getManagedProfileBadge");
synchronized (mUsersLock) {
UserInfo userInfo = getUserInfoLU(userId);
return userInfo != null ? userInfo.profileBadge : 0;
@@ -1125,14 +1118,7 @@
@Override
public boolean isManagedProfile(int userId) {
- int callingUserId = UserHandle.getCallingUserId();
- if (callingUserId != userId && !hasManageUsersPermission()) {
- if (!isSameProfileGroupNoChecks(callingUserId, userId)) {
- throw new SecurityException(
- "You need MANAGE_USERS permission to: check if specified user a " +
- "managed profile outside your profile group");
- }
- }
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isManagedProfile");
synchronized (mUsersLock) {
UserInfo userInfo = getUserInfoLU(userId);
return userInfo != null && userInfo.isManagedProfile();