Allow cross user SessionCallback support
Bug: 31929647
Test: Manually tests on device and added CTS tests
Change-Id: I083435c12ce56a675ccf2cb5e00c76fbaace6c65
diff --git a/api/current.txt b/api/current.txt
index 2692916..1d3a7a8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11224,6 +11224,7 @@
public class LauncherApps {
method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(String, android.os.UserHandle);
+ method @NonNull public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getAllPackageInstallerSessions();
method @Nullable public android.content.pm.LauncherApps.AppUsageLimit getAppUsageLimit(String, android.os.UserHandle);
method public android.content.pm.ApplicationInfo getApplicationInfo(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
method public android.content.pm.LauncherApps.PinItemRequest getPinItemRequest(android.content.Intent);
@@ -11240,13 +11241,16 @@
method public void pinShortcuts(@NonNull String, @NonNull java.util.List<java.lang.String>, @NonNull android.os.UserHandle);
method public void registerCallback(android.content.pm.LauncherApps.Callback);
method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
+ method public void registerPackageInstallerSessionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.content.pm.PackageInstaller.SessionCallback);
method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
method public boolean shouldHideFromSuggestions(@NonNull String, @NonNull android.os.UserHandle);
method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
+ method public void startPackageInstallerSessionDetailsActivity(android.content.pm.PackageInstaller.SessionInfo, android.graphics.Rect, android.os.Bundle);
method public void startShortcut(@NonNull String, @NonNull String, @Nullable android.graphics.Rect, @Nullable android.os.Bundle, @NonNull android.os.UserHandle);
method public void startShortcut(@NonNull android.content.pm.ShortcutInfo, @Nullable android.graphics.Rect, @Nullable android.os.Bundle);
method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
+ method public void unregisterPackageInstallerSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
field public static final String ACTION_CONFIRM_PIN_APPWIDGET = "android.content.pm.action.CONFIRM_PIN_APPWIDGET";
field public static final String ACTION_CONFIRM_PIN_SHORTCUT = "android.content.pm.action.CONFIRM_PIN_SHORTCUT";
field public static final String EXTRA_PIN_ITEM_REQUEST = "android.content.pm.extra.PIN_ITEM_REQUEST";
@@ -11436,6 +11440,7 @@
method public long getSize();
method public int getStagedSessionErrorCode();
method public String getStagedSessionErrorMessage();
+ method public android.os.UserHandle getUser();
method public boolean isActive();
method public boolean isMultiPackage();
method public boolean isSealed();
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index d1bc377..50bb3c7 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -24,6 +24,8 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IOnAppsChangedListener;
import android.content.pm.LauncherApps;
+import android.content.pm.IPackageInstallerCallback;
+import android.content.pm.PackageInstaller;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
@@ -44,6 +46,9 @@
String callingPackage, String packageName, in UserHandle user);
ActivityInfo resolveActivity(
String callingPackage, in ComponentName component, in UserHandle user);
+ void startSessionDetailsActivityAsUser(in IApplicationThread caller, String callingPackage,
+ in PackageInstaller.SessionInfo sessionInfo, in Rect sourceBounds, in Bundle opts,
+ in UserHandle user);
void startActivityAsUser(in IApplicationThread caller, String callingPackage,
in ComponentName component, in Rect sourceBounds,
in Bundle opts, in UserHandle user);
@@ -79,4 +84,9 @@
String callingPackage, String packageName, in UserHandle user);
IntentSender getShortcutConfigActivityIntent(String callingPackage, in ComponentName component,
in UserHandle user);
+
+ // Unregister is performed using package installer
+ void registerPackageInstallerCallback(String callingPackage,
+ in IPackageInstallerCallback callback);
+ ParceledListSlice getAllSessions(String callingPackage);
}
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 89630e1..5763440 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -16,6 +16,7 @@
package android.content.pm;
+import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -32,6 +33,9 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.PackageInstaller.SessionCallback;
+import android.content.pm.PackageInstaller.SessionCallbackDelegate;
+import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageManager.ApplicationInfoFlags;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
@@ -65,7 +69,9 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
+import java.util.concurrent.Executor;
/**
* Class for retrieving a list of launchable activities for the current user and any associated
@@ -154,8 +160,8 @@
private final PackageManager mPm;
private final UserManager mUserManager;
- private List<CallbackMessageHandler> mCallbacks
- = new ArrayList<CallbackMessageHandler>();
+ private final List<CallbackMessageHandler> mCallbacks = new ArrayList<>();
+ private final List<SessionCallbackDelegate> mDelegates = new ArrayList<>();
/**
* Callbacks for package changes to this and related managed profiles.
@@ -572,6 +578,24 @@
}
/**
+ * Starts an activity to show the details of the specified session.
+ *
+ * @param sessionInfo The SessionInfo of the session
+ * @param sourceBounds The Rect containing the source bounds of the clicked icon
+ * @param opts Options to pass to startActivity
+ */
+ public void startPackageInstallerSessionDetailsActivity(SessionInfo sessionInfo,
+ Rect sourceBounds, Bundle opts) {
+ try {
+ mService.startSessionDetailsActivityAsUser(mContext.getIApplicationThread(),
+ mContext.getPackageName(), sessionInfo, sourceBounds, opts,
+ sessionInfo.getUser());
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Starts the settings activity to show the application details for a
* package in the specified profile.
*
@@ -1128,7 +1152,7 @@
}
/**
- * Registers a callback for changes to packages in current and managed profiles.
+ * Registers a callback for changes to packages in this user and managed profiles.
*
* @param callback The callback to register.
*/
@@ -1137,7 +1161,7 @@
}
/**
- * Registers a callback for changes to packages in current and managed profiles.
+ * Registers a callback for changes to packages in this user and managed profiles.
*
* @param callback The callback to register.
* @param handler that should be used to post callbacks on, may be null.
@@ -1443,6 +1467,64 @@
}
/**
+ * Register a callback to watch for session lifecycle events in this user and managed profiles.
+ * @param callback The callback to register.
+ * @param executor {@link Executor} to handle the callbacks, cannot be null.
+ *
+ * @see PackageInstaller#registerSessionCallback(SessionCallback)
+ */
+ public void registerPackageInstallerSessionCallback(
+ @NonNull @CallbackExecutor Executor executor, @NonNull SessionCallback callback) {
+ if (executor == null) {
+ throw new NullPointerException("Executor must not be null");
+ }
+
+ synchronized (mDelegates) {
+ final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
+ executor);
+ try {
+ mService.registerPackageInstallerCallback(mContext.getPackageName(),
+ delegate);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ mDelegates.add(delegate);
+ }
+ }
+
+ /**
+ * Unregisters a callback that was previously registered.
+ *
+ * @param callback The callback to unregister.
+ * @see #registerPackageInstallerSessionCallback(Executor, SessionCallback)
+ */
+ public void unregisterPackageInstallerSessionCallback(SessionCallback callback) {
+ synchronized (mDelegates) {
+ for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
+ final SessionCallbackDelegate delegate = i.next();
+ if (delegate.mCallback == callback) {
+ mPm.getPackageInstaller().unregisterSessionCallback(delegate.mCallback);
+ i.remove();
+ }
+ }
+ }
+ }
+
+ /**
+ * Return list of all known install sessions in this user and managed profiles, regardless
+ * of the installer.
+ *
+ * @see PackageInstaller#getAllSessions()
+ */
+ public @NonNull List<SessionInfo> getAllPackageInstallerSessions() {
+ try {
+ return mService.getAllSessions(mContext.getPackageName()).getList();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* A helper method to extract a {@link PinItemRequest} set to
* the {@link #EXTRA_PIN_ITEM_REQUEST} extra.
*/
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 2dc014c..4f674bd 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -36,20 +36,21 @@
import android.os.Build;
import android.os.FileBridge;
import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
+import android.os.HandlerExecutor;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.ParcelableException;
import android.os.RemoteException;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.system.ErrnoException;
import android.system.Os;
import android.util.ExceptionUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.pooled.PooledLambda;
import java.io.Closeable;
import java.io.IOException;
@@ -61,6 +62,7 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.concurrent.Executor;
/**
* Offers the ability to install, upgrade, and remove applications on the
@@ -659,8 +661,7 @@
}
/** {@hide} */
- private static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub implements
- Handler.Callback {
+ static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub {
private static final int MSG_SESSION_CREATED = 1;
private static final int MSG_SESSION_BADGING_CHANGED = 2;
private static final int MSG_SESSION_ACTIVE_CHANGED = 3;
@@ -668,63 +669,41 @@
private static final int MSG_SESSION_FINISHED = 5;
final SessionCallback mCallback;
- final Handler mHandler;
+ final Executor mExecutor;
- public SessionCallbackDelegate(SessionCallback callback, Looper looper) {
+ SessionCallbackDelegate(SessionCallback callback, Executor executor) {
mCallback = callback;
- mHandler = new Handler(looper, this);
- }
-
- @Override
- public boolean handleMessage(Message msg) {
- final int sessionId = msg.arg1;
- switch (msg.what) {
- case MSG_SESSION_CREATED:
- mCallback.onCreated(sessionId);
- return true;
- case MSG_SESSION_BADGING_CHANGED:
- mCallback.onBadgingChanged(sessionId);
- return true;
- case MSG_SESSION_ACTIVE_CHANGED:
- final boolean active = msg.arg2 != 0;
- mCallback.onActiveChanged(sessionId, active);
- return true;
- case MSG_SESSION_PROGRESS_CHANGED:
- mCallback.onProgressChanged(sessionId, (float) msg.obj);
- return true;
- case MSG_SESSION_FINISHED:
- mCallback.onFinished(sessionId, msg.arg2 != 0);
- return true;
- }
- return false;
+ mExecutor = executor;
}
@Override
public void onSessionCreated(int sessionId) {
- mHandler.obtainMessage(MSG_SESSION_CREATED, sessionId, 0).sendToTarget();
+ mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onCreated, mCallback,
+ sessionId).recycleOnUse());
}
@Override
public void onSessionBadgingChanged(int sessionId) {
- mHandler.obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, 0).sendToTarget();
+ mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onBadgingChanged,
+ mCallback, sessionId).recycleOnUse());
}
@Override
public void onSessionActiveChanged(int sessionId, boolean active) {
- mHandler.obtainMessage(MSG_SESSION_ACTIVE_CHANGED, sessionId, active ? 1 : 0)
- .sendToTarget();
+ mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onActiveChanged,
+ mCallback, sessionId, active).recycleOnUse());
}
@Override
public void onSessionProgressChanged(int sessionId, float progress) {
- mHandler.obtainMessage(MSG_SESSION_PROGRESS_CHANGED, sessionId, 0, progress)
- .sendToTarget();
+ mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onProgressChanged,
+ mCallback, sessionId, progress).recycleOnUse());
}
@Override
public void onSessionFinished(int sessionId, boolean success) {
- mHandler.obtainMessage(MSG_SESSION_FINISHED, sessionId, success ? 1 : 0)
- .sendToTarget();
+ mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onFinished,
+ mCallback, sessionId, success).recycleOnUse());
}
}
@@ -758,7 +737,7 @@
public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
synchronized (mDelegates) {
final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
- handler.getLooper());
+ new HandlerExecutor(handler));
try {
mInstaller.registerCallback(delegate, mUserId);
} catch (RemoteException e) {
@@ -1649,6 +1628,8 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public int sessionId;
/** {@hide} */
+ public int userId;
+ /** {@hide} */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public String installerPackageName;
/** {@hide} */
@@ -1720,6 +1701,7 @@
/** {@hide} */
public SessionInfo(Parcel source) {
sessionId = source.readInt();
+ userId = source.readInt();
installerPackageName = source.readString();
resolvedBaseCodePath = source.readString();
progress = source.readFloat();
@@ -1761,6 +1743,13 @@
}
/**
+ * Return the user associated with this session.
+ */
+ public UserHandle getUser() {
+ return new UserHandle(userId);
+ }
+
+ /**
* Return the package name of the app that owns this session.
*/
public @Nullable String getInstallerPackageName() {
@@ -2091,6 +2080,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(sessionId);
+ dest.writeInt(userId);
dest.writeString(installerPackageName);
dest.writeString(resolvedBaseCodePath);
dest.writeFloat(progress);
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();