summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/UserManagerInternal.java20
-rw-r--r--services/core/java/com/android/server/pm/LauncherAppsService.java173
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java22
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java59
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java89
5 files changed, 147 insertions, 216 deletions
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index 6c9f1b25bf66..f09d5cee4e61 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -186,4 +186,24 @@ public abstract class UserManagerInternal {
* @return the array of user ids.
*/
public abstract int[] getUserIds();
+
+ /**
+ * Checks if the {@code callingUserId} and {@code targetUserId} are same or in same group
+ * and that the {@code callingUserId} is not a managed profile and
+ * {@code targetUserId} is enabled.
+ *
+ * @return TRUE if the {@code callingUserId} can access {@code targetUserId}. FALSE
+ * otherwise
+ *
+ * @throws SecurityException if the calling user and {@code targetUser} are not in the same
+ * group and {@code throwSecurityException} is true, otherwise if will simply return false.
+ */
+ public abstract boolean isProfileAccessible(int callingUserId, int targetUserId,
+ String debugMsg, boolean throwSecurityException);
+
+ /**
+ * If {@code userId} is of a managed profile, return the parent user ID. Otherwise return
+ * itself.
+ */
+ public abstract int getProfileParentId(int userId);
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 14995b3827e1..fb3839805b1a 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -39,7 +39,6 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutServiceInternal;
import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
-import android.content.pm.UserInfo;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
@@ -50,7 +49,7 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.os.UserManager;
+import android.os.UserManagerInternal;
import android.provider.Settings;
import android.util.Log;
import android.util.Slog;
@@ -102,7 +101,7 @@ public class LauncherAppsService extends SystemService {
private static final boolean DEBUG = false;
private static final String TAG = "LauncherAppsService";
private final Context mContext;
- private final UserManager mUm;
+ private final UserManagerInternal mUserManagerInternal;
private final ActivityManagerInternal mActivityManagerInternal;
private final ShortcutServiceInternal mShortcutServiceInternal;
private final PackageCallbackList<IOnAppsChangedListener> mListeners
@@ -114,7 +113,8 @@ public class LauncherAppsService extends SystemService {
public LauncherAppsImpl(Context context) {
mContext = context;
- mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mUserManagerInternal = Preconditions.checkNotNull(
+ LocalServices.getService(UserManagerInternal.class));
mActivityManagerInternal = Preconditions.checkNotNull(
LocalServices.getService(ActivityManagerInternal.class));
mShortcutServiceInternal = Preconditions.checkNotNull(
@@ -222,12 +222,6 @@ public class LauncherAppsService extends SystemService {
}
}
- /** See {@link #canAccessProfile(String, int, String)} */
- private boolean canAccessProfile(
- String callingPackage, UserHandle targetUser, String message) {
- return canAccessProfile(callingPackage, targetUser.getIdentifier(), message);
- }
-
/**
* Checks if the calling user is in the same group as {@code targetUser}, and allowed
* to access it.
@@ -238,30 +232,9 @@ public class LauncherAppsService extends SystemService {
* @throws SecurityException if the calling user and {@code targetUser} are not in the same
* group.
*/
- private boolean canAccessProfile(String callingPackage, int targetUserId, String message) {
- final int callingUserId = injectCallingUserId();
-
- if (targetUserId == callingUserId) return true;
-
- long ident = injectClearCallingIdentity();
- try {
- UserInfo callingUserInfo = mUm.getUserInfo(callingUserId);
- if (callingUserInfo.isManagedProfile()) {
- Slog.w(TAG, message + " by " + callingPackage + " for another profile "
- + targetUserId + " from " + callingUserId);
- return false;
- }
-
- UserInfo targetUserInfo = mUm.getUserInfo(targetUserId);
- if (targetUserInfo == null
- || targetUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID
- || targetUserInfo.profileGroupId != callingUserInfo.profileGroupId) {
- throw new SecurityException(message + " for unrelated profile " + targetUserId);
- }
- } finally {
- injectRestoreCallingIdentity(ident);
- }
- return true;
+ private boolean canAccessProfile(int targetUserId, String message) {
+ return mUserManagerInternal.isProfileAccessible(injectCallingUserId(), targetUserId,
+ message, true);
}
@VisibleForTesting // We override it in unit tests
@@ -283,23 +256,6 @@ public class LauncherAppsService extends SystemService {
}
}
- /**
- * Checks if the user is enabled.
- */
- private boolean isUserEnabled(UserHandle user) {
- return isUserEnabled(user.getIdentifier());
- }
-
- private boolean isUserEnabled(int userId) {
- long ident = injectClearCallingIdentity();
- try {
- UserInfo targetUserInfo = mUm.getUserInfo(userId);
- return targetUserInfo != null && targetUserInfo.isEnabled();
- } finally {
- injectRestoreCallingIdentity(ident);
- }
- }
-
@Override
public ParceledListSlice<ResolveInfo> getLauncherActivities(String callingPackage,
String packageName, UserHandle user)
@@ -315,10 +271,7 @@ public class LauncherAppsService extends SystemService {
public ActivityInfo resolveActivity(
String callingPackage, ComponentName component, UserHandle user)
throws RemoteException {
- if (!canAccessProfile(callingPackage, user, "Cannot resolve activity")) {
- return null;
- }
- if (!isUserEnabled(user)) {
+ if (!canAccessProfile(user.getIdentifier(), "Cannot resolve activity")) {
return null;
}
@@ -346,10 +299,7 @@ public class LauncherAppsService extends SystemService {
private ParceledListSlice<ResolveInfo> queryActivitiesForUser(String callingPackage,
Intent intent, UserHandle user) {
- if (!canAccessProfile(callingPackage, user, "Cannot retrieve activities")) {
- return null;
- }
- if (!isUserEnabled(user)) {
+ if (!canAccessProfile(user.getIdentifier(), "Cannot retrieve activities")) {
return null;
}
@@ -372,11 +322,10 @@ public class LauncherAppsService extends SystemService {
public IntentSender getShortcutConfigActivityIntent(String callingPackage,
ComponentName component, UserHandle user) throws RemoteException {
ensureShortcutPermission(callingPackage);
- if (!canAccessProfile(callingPackage, user, "Cannot check package")) {
+ if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
return null;
}
Preconditions.checkNotNull(component);
- Preconditions.checkArgument(isUserEnabled(user), "User not enabled");
// All right, create the sender.
Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT).setComponent(component);
@@ -395,10 +344,7 @@ public class LauncherAppsService extends SystemService {
@Override
public boolean isPackageEnabled(String callingPackage, String packageName, UserHandle user)
throws RemoteException {
- if (!canAccessProfile(callingPackage, user, "Cannot check package")) {
- return false;
- }
- if (!isUserEnabled(user)) {
+ if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
return false;
}
@@ -421,10 +367,7 @@ public class LauncherAppsService extends SystemService {
public ApplicationInfo getApplicationInfo(
String callingPackage, String packageName, int flags, UserHandle user)
throws RemoteException {
- if (!canAccessProfile(callingPackage, user, "Cannot check package")) {
- return null;
- }
- if (!isUserEnabled(user)) {
+ if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
return null;
}
@@ -454,8 +397,7 @@ public class LauncherAppsService extends SystemService {
String packageName, List shortcutIds, ComponentName componentName, int flags,
UserHandle targetUser) {
ensureShortcutPermission(callingPackage);
- if (!canAccessProfile(callingPackage, targetUser, "Cannot get shortcuts")
- || !isUserEnabled(targetUser)) {
+ if (!canAccessProfile(targetUser.getIdentifier(), "Cannot get shortcuts")) {
return new ParceledListSlice<>(Collections.EMPTY_LIST);
}
if (shortcutIds != null && packageName == null) {
@@ -475,13 +417,9 @@ public class LauncherAppsService extends SystemService {
public void pinShortcuts(String callingPackage, String packageName, List<String> ids,
UserHandle targetUser) {
ensureShortcutPermission(callingPackage);
- if (!canAccessProfile(callingPackage, targetUser, "Cannot pin shortcuts")) {
+ if (!canAccessProfile(targetUser.getIdentifier(), "Cannot pin shortcuts")) {
return;
}
- if (!isUserEnabled(targetUser)) {
- throw new IllegalStateException("Cannot pin shortcuts for disabled profile "
- + targetUser);
- }
mShortcutServiceInternal.pinShortcuts(getCallingUserId(),
callingPackage, packageName, ids, targetUser.getIdentifier());
@@ -491,10 +429,7 @@ public class LauncherAppsService extends SystemService {
public int getShortcutIconResId(String callingPackage, String packageName, String id,
int targetUserId) {
ensureShortcutPermission(callingPackage);
- if (!canAccessProfile(callingPackage, targetUserId, "Cannot access shortcuts")) {
- return 0;
- }
- if (!isUserEnabled(targetUserId)) {
+ if (!canAccessProfile(targetUserId, "Cannot access shortcuts")) {
return 0;
}
@@ -506,10 +441,7 @@ public class LauncherAppsService extends SystemService {
public ParcelFileDescriptor getShortcutIconFd(String callingPackage,
String packageName, String id, int targetUserId) {
ensureShortcutPermission(callingPackage);
- if (!canAccessProfile(callingPackage, targetUserId, "Cannot access shortcuts")) {
- return null;
- }
- if (!isUserEnabled(targetUserId)) {
+ if (!canAccessProfile(targetUserId, "Cannot access shortcuts")) {
return null;
}
@@ -528,13 +460,9 @@ public class LauncherAppsService extends SystemService {
public boolean startShortcut(String callingPackage, String packageName, String shortcutId,
Rect sourceBounds, Bundle startActivityOptions, int targetUserId) {
verifyCallingPackage(callingPackage);
- if (!canAccessProfile(callingPackage, targetUserId, "Cannot start activity")) {
+ if (!canAccessProfile(targetUserId, "Cannot start activity")) {
return false;
}
- if (!isUserEnabled(targetUserId)) {
- throw new IllegalStateException("Cannot start a shortcut for disabled profile "
- + targetUserId);
- }
// Even without the permission, pinned shortcuts are always launchable.
if (!mShortcutServiceInternal.isPinnedByCaller(getCallingUserId(),
@@ -581,10 +509,7 @@ public class LauncherAppsService extends SystemService {
public boolean isActivityEnabled(
String callingPackage, ComponentName component, UserHandle user)
throws RemoteException {
- if (!canAccessProfile(callingPackage , user, "Cannot check component")) {
- return false;
- }
- if (!isUserEnabled(user)) {
+ if (!canAccessProfile(user.getIdentifier(), "Cannot check component")) {
return false;
}
@@ -607,12 +532,9 @@ public class LauncherAppsService extends SystemService {
public void startActivityAsUser(String callingPackage,
ComponentName component, Rect sourceBounds,
Bundle opts, UserHandle user) throws RemoteException {
- if (!canAccessProfile(callingPackage, user, "Cannot start activity")) {
+ if (!canAccessProfile(user.getIdentifier(), "Cannot start activity")) {
return;
}
- if (!isUserEnabled(user)) {
- throw new IllegalStateException("Cannot start activity for disabled profile " + user);
- }
Intent launchIntent = new Intent(Intent.ACTION_MAIN);
launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
@@ -665,13 +587,9 @@ public class LauncherAppsService extends SystemService {
@Override
public void showAppDetailsAsUser(String callingPackage, ComponentName component,
Rect sourceBounds, Bundle opts, UserHandle user) throws RemoteException {
- if (!canAccessProfile(callingPackage, user, "Cannot show app details")) {
+ if (!canAccessProfile(user.getIdentifier(), "Cannot show app details")) {
return;
}
- if (!isUserEnabled(user)) {
- throw new IllegalStateException("Cannot show app details for disabled profile "
- + user);
- }
long ident = Binder.clearCallingIdentity();
try {
@@ -688,39 +606,10 @@ public class LauncherAppsService extends SystemService {
/** Checks if user is a profile of or same as listeningUser.
* and the user is enabled. */
- private boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser,
+ private boolean isEnabledProfileOf(UserHandle listeningUser, UserHandle user,
String debugMsg) {
- if (user.getIdentifier() == listeningUser.getIdentifier()) {
- if (DEBUG) Log.d(TAG, "Delivering msg to same user: " + debugMsg);
- return true;
- }
- if (mUm.isManagedProfile(listeningUser.getIdentifier())) {
- if (DEBUG) Log.d(TAG, "Managed profile can't see other profiles: " + debugMsg);
- return false;
- }
- long ident = injectClearCallingIdentity();
- try {
- UserInfo userInfo = mUm.getUserInfo(user.getIdentifier());
- UserInfo listeningUserInfo = mUm.getUserInfo(listeningUser.getIdentifier());
- if (userInfo == null || listeningUserInfo == null
- || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID
- || userInfo.profileGroupId != listeningUserInfo.profileGroupId
- || !userInfo.isEnabled()) {
- if (DEBUG) {
- Log.d(TAG, "Not delivering msg from " + user + " to " + listeningUser + ":"
- + debugMsg);
- }
- return false;
- } else {
- if (DEBUG) {
- Log.d(TAG, "Delivering msg from " + user + " to " + listeningUser + ":"
- + debugMsg);
- }
- return true;
- }
- } finally {
- injectRestoreCallingIdentity(ident);
- }
+ return mUserManagerInternal.isProfileAccessible(listeningUser.getIdentifier(),
+ user.getIdentifier(), debugMsg, false);
}
@VisibleForTesting
@@ -740,7 +629,7 @@ public class LauncherAppsService extends SystemService {
for (int i = 0; i < n; i++) {
IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
- if (!isEnabledProfileOf(user, cookie.user, "onPackageAdded")) continue;
+ if (!isEnabledProfileOf(cookie.user, user, "onPackageAdded")) continue;
try {
listener.onPackageAdded(user, packageName);
} catch (RemoteException re) {
@@ -762,7 +651,7 @@ public class LauncherAppsService extends SystemService {
for (int i = 0; i < n; i++) {
IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
- if (!isEnabledProfileOf(user, cookie.user, "onPackageRemoved")) continue;
+ if (!isEnabledProfileOf(cookie.user, user, "onPackageRemoved")) continue;
try {
listener.onPackageRemoved(user, packageName);
} catch (RemoteException re) {
@@ -784,7 +673,7 @@ public class LauncherAppsService extends SystemService {
for (int i = 0; i < n; i++) {
IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
- if (!isEnabledProfileOf(user, cookie.user, "onPackageModified")) continue;
+ if (!isEnabledProfileOf(cookie.user, user, "onPackageModified")) continue;
try {
listener.onPackageChanged(user, packageName);
} catch (RemoteException re) {
@@ -806,7 +695,7 @@ public class LauncherAppsService extends SystemService {
for (int i = 0; i < n; i++) {
IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
- if (!isEnabledProfileOf(user, cookie.user, "onPackagesAvailable")) continue;
+ if (!isEnabledProfileOf(cookie.user, user, "onPackagesAvailable")) continue;
try {
listener.onPackagesAvailable(user, packages, isReplacing());
} catch (RemoteException re) {
@@ -828,7 +717,7 @@ public class LauncherAppsService extends SystemService {
for (int i = 0; i < n; i++) {
IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
- if (!isEnabledProfileOf(user, cookie.user, "onPackagesUnavailable")) continue;
+ if (!isEnabledProfileOf(cookie.user, user, "onPackagesUnavailable")) continue;
try {
listener.onPackagesUnavailable(user, packages, isReplacing());
} catch (RemoteException re) {
@@ -850,7 +739,7 @@ public class LauncherAppsService extends SystemService {
for (int i = 0; i < n; i++) {
IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
- if (!isEnabledProfileOf(user, cookie.user, "onPackagesSuspended")) continue;
+ if (!isEnabledProfileOf(cookie.user, user, "onPackagesSuspended")) continue;
try {
listener.onPackagesSuspended(user, packages);
} catch (RemoteException re) {
@@ -872,7 +761,7 @@ public class LauncherAppsService extends SystemService {
for (int i = 0; i < n; i++) {
IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
- if (!isEnabledProfileOf(user, cookie.user, "onPackagesUnsuspended")) continue;
+ if (!isEnabledProfileOf(cookie.user, user, "onPackagesUnsuspended")) continue;
try {
listener.onPackagesUnsuspended(user, packages);
} catch (RemoteException re) {
@@ -901,7 +790,7 @@ public class LauncherAppsService extends SystemService {
for (int i = 0; i < n; i++) {
IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
- if (!isEnabledProfileOf(user, cookie.user, "onShortcutChanged")) continue;
+ if (!isEnabledProfileOf(cookie.user, user, "onShortcutChanged")) continue;
final int launcherUserId = cookie.user.getIdentifier();
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 8c3518831b7b..265cc8ebe4d3 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -77,7 +77,7 @@ import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.UserHandle;
-import android.os.UserManager;
+import android.os.UserManagerInternal;
import android.text.TextUtils;
import android.text.format.Time;
import android.util.ArraySet;
@@ -315,7 +315,7 @@ public class ShortcutService extends IShortcutService.Stub {
private final IPackageManager mIPackageManager;
private final PackageManagerInternal mPackageManagerInternal;
- private final UserManager mUserManager;
+ private final UserManagerInternal mUserManagerInternal;
private final UsageStatsManagerInternal mUsageStatsManagerInternal;
private final ActivityManagerInternal mActivityManagerInternal;
@@ -430,7 +430,8 @@ public class ShortcutService extends IShortcutService.Stub {
mIPackageManager = AppGlobals.getPackageManager();
mPackageManagerInternal = Preconditions.checkNotNull(
LocalServices.getService(PackageManagerInternal.class));
- mUserManager = Preconditions.checkNotNull(context.getSystemService(UserManager.class));
+ mUserManagerInternal = Preconditions.checkNotNull(
+ LocalServices.getService(UserManagerInternal.class));
mUsageStatsManagerInternal = Preconditions.checkNotNull(
LocalServices.getService(UsageStatsManagerInternal.class));
mActivityManagerInternal = Preconditions.checkNotNull(
@@ -1176,12 +1177,7 @@ public class ShortcutService extends IShortcutService.Stub {
// the user might just have been unlocked.
// Note we just don't use isUserUnlockingOrUnlocked() here, because it'll return false
// when the user is STOPPING, which we still want to consider as "unlocked".
- final long token = injectClearCallingIdentity();
- try {
- return mUserManager.isUserUnlockingOrUnlocked(userId);
- } finally {
- injectRestoreCallingIdentity(token);
- }
+ return mUserManagerInternal.isUserUnlockingOrUnlocked(userId);
}
// Requires mLock held, but "Locked" prefix would look weired so we jsut say "L".
@@ -3493,13 +3489,7 @@ public class ShortcutService extends IShortcutService.Stub {
* itself.
*/
int getParentOrSelfUserId(int userId) {
- final long token = injectClearCallingIdentity();
- try {
- final UserInfo parent = mUserManager.getProfileParent(userId);
- return (parent != null) ? parent.id : userId;
- } finally {
- injectRestoreCallingIdentity(token);
- }
+ return mUserManagerInternal.getProfileParentId(userId);
}
void injectSendIntentSender(IntentSender intentSender, Intent extras) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 2c7df6c31bed..ced2a7e48e44 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -781,14 +781,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public int getProfileParentId(int userHandle) {
checkManageUsersPermission("get the profile parent");
- synchronized (mUsersLock) {
- UserInfo profileParent = getProfileParentLU(userHandle);
- if (profileParent == null) {
- return userHandle;
- }
-
- return profileParent.id;
- }
+ return mLocalService.getProfileParentId(userHandle);
}
private UserInfo getProfileParentLU(int userHandle) {
@@ -3928,6 +3921,56 @@ public class UserManagerService extends IUserManager.Stub {
public boolean exists(int userId) {
return getUserInfoNoChecks(userId) != null;
}
+
+ @Override
+ public boolean isProfileAccessible(int callingUserId, int targetUserId, String debugMsg,
+ boolean throwSecurityException) {
+ if (targetUserId == callingUserId) {
+ return true;
+ }
+ synchronized (mUsersLock) {
+ UserInfo callingUserInfo = getUserInfoLU(callingUserId);
+ if (callingUserInfo == null || callingUserInfo.isManagedProfile()) {
+ if (throwSecurityException) {
+ throw new SecurityException(
+ debugMsg + " for another profile "
+ + targetUserId + " from " + callingUserId);
+ }
+ }
+
+ UserInfo targetUserInfo = getUserInfoLU(targetUserId);
+ if (targetUserInfo == null || !targetUserInfo.isEnabled()) {
+ // Do not throw any exception here as this could happen due to race conditions
+ // between the system updating its state and the client getting notified.
+ if (throwSecurityException) {
+ Slog.w(LOG_TAG, debugMsg + " for disabled profile "
+ + targetUserId + " from " + callingUserId);
+ }
+ return false;
+ }
+
+ if (targetUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID ||
+ targetUserInfo.profileGroupId != callingUserInfo.profileGroupId) {
+ if (throwSecurityException) {
+ throw new SecurityException(
+ debugMsg + " for unrelated profile " + targetUserId);
+ }
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int getProfileParentId(int userId) {
+ synchronized (mUsersLock) {
+ UserInfo profileParent = getProfileParentLU(userId);
+ if (profileParent == null) {
+ return userId;
+ }
+ return profileParent.id;
+ }
+ }
}
/* Remove all the users except of the system one. */
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 4ca1647ef415..51d27fe016f0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -23,6 +23,7 @@ import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.makeBundle;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.set;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
@@ -76,6 +77,7 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.UserManagerInternal;
import android.test.InstrumentationTestCase;
import android.test.mock.MockContext;
import android.util.ArrayMap;
@@ -90,8 +92,6 @@ import com.android.server.pm.ShortcutUser.PackageWithUser;
import org.junit.Assert;
import org.mockito.ArgumentCaptor;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
@@ -111,7 +111,6 @@ import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
-import java.util.function.Function;
public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected static final String TAG = "ShortcutManagerTest";
@@ -604,6 +603,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected PackageManager mMockPackageManager;
protected PackageManagerInternal mMockPackageManagerInternal;
protected UserManager mMockUserManager;
+ protected UserManagerInternal mMockUserManagerInternal;
protected UsageStatsManagerInternal mMockUsageStatsManagerInternal;
protected ActivityManagerInternal mMockActivityManagerInternal;
@@ -742,6 +742,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
mMockPackageManager = mock(PackageManager.class);
mMockPackageManagerInternal = mock(PackageManagerInternal.class);
mMockUserManager = mock(UserManager.class);
+ mMockUserManagerInternal = mock(UserManagerInternal.class);
mMockUsageStatsManagerInternal = mock(UsageStatsManagerInternal.class);
mMockActivityManagerInternal = mock(ActivityManagerInternal.class);
@@ -751,6 +752,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
LocalServices.addService(UsageStatsManagerInternal.class, mMockUsageStatsManagerInternal);
LocalServices.removeServiceForTest(ActivityManagerInternal.class);
LocalServices.addService(ActivityManagerInternal.class, mMockActivityManagerInternal);
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
+ LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal);
// Prepare injection values.
@@ -782,50 +785,54 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
deleteAllSavedFiles();
// Set up users.
- when(mMockUserManager.getUserInfo(anyInt())).thenAnswer(new AnswerWithSystemCheck<>(
- inv -> mUserInfos.get((Integer) inv.getArguments()[0])));
-
mUserInfos.put(USER_0, USER_INFO_0);
mUserInfos.put(USER_10, USER_INFO_10);
mUserInfos.put(USER_11, USER_INFO_11);
mUserInfos.put(USER_P0, USER_INFO_P0);
mUserInfos.put(USER_P1, USER_INFO_P1);
- // Set up isUserRunning and isUserUnlocked.
- when(mMockUserManager.isUserRunning(anyInt())).thenAnswer(new AnswerWithSystemCheck<>(
- inv -> b(mRunningUsers.get((Integer) inv.getArguments()[0]))));
-
- when(mMockUserManager.isUserUnlocked(anyInt()))
- .thenAnswer(new AnswerWithSystemCheck<>(inv -> {
- final int userId = (Integer) inv.getArguments()[0];
- return b(mRunningUsers.get(userId)) && b(mUnlockedUsers.get(userId));
- }));
- // isUserUnlockingOrUnlocked() return the same value as isUserUnlocked().
- when(mMockUserManager.isUserUnlockingOrUnlocked(anyInt()))
- .thenAnswer(new AnswerWithSystemCheck<>(inv -> {
+ when(mMockUserManagerInternal.isUserUnlockingOrUnlocked(anyInt()))
+ .thenAnswer(inv -> {
final int userId = (Integer) inv.getArguments()[0];
return b(mRunningUsers.get(userId)) && b(mUnlockedUsers.get(userId));
- }));
-
- when(mMockUserManager.getProfileParent(anyInt()))
- .thenAnswer(new AnswerWithSystemCheck<>(inv -> {
+ });
+ when(mMockUserManagerInternal.getProfileParentId(anyInt()))
+ .thenAnswer(inv -> {
final int userId = (Integer) inv.getArguments()[0];
final UserInfo ui = mUserInfos.get(userId);
assertNotNull(ui);
if (ui.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
- return null;
+ return userId;
}
final UserInfo parent = mUserInfos.get(ui.profileGroupId);
assertNotNull(parent);
- return parent;
- }));
- when(mMockUserManager.isManagedProfile(anyInt()))
- .thenAnswer(new AnswerWithSystemCheck<>(inv -> {
- final int userId = (Integer) inv.getArguments()[0];
- final UserInfo ui = mUserInfos.get(userId);
- assertNotNull(ui);
- return ui.isManagedProfile();
- }));
+ return parent.id;
+ });
+
+ when(mMockUserManagerInternal.isProfileAccessible(anyInt(), anyInt(), anyString(),
+ anyBoolean())).thenAnswer(inv -> {
+ final int callingUserId = (Integer) inv.getArguments()[0];
+ final int targetUserId = (Integer) inv.getArguments()[1];
+ if (targetUserId == callingUserId) {
+ return true;
+ }
+ final UserInfo callingUserInfo = mUserInfos.get(callingUserId);
+ final UserInfo targetUserInfo = mUserInfos.get(targetUserId);
+ if (callingUserInfo == null || callingUserInfo.isManagedProfile()
+ || targetUserInfo == null || !targetUserInfo.isEnabled()) {
+ return false;
+ }
+ if (targetUserInfo.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
+ && targetUserInfo.profileGroupId == callingUserInfo.profileGroupId) {
+ return true;
+ }
+ final boolean isExternal = (Boolean) inv.getArguments()[3];
+ if (!isExternal) {
+ return false;
+ }
+ throw new SecurityException(inv.getArguments()[2] + " for unrelated profile "
+ + targetUserId);
+ });
when(mMockActivityManagerInternal.getUidProcessState(anyInt())).thenReturn(
ActivityManager.PROCESS_STATE_CACHED_EMPTY);
@@ -860,24 +867,6 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
return (value != null && value);
}
- /**
- * Returns a boolean but also checks if the current UID is SYSTEM_UID.
- */
- protected class AnswerWithSystemCheck<T> implements Answer<T> {
- private final Function<InvocationOnMock, T> mChecker;
-
- public AnswerWithSystemCheck(Function<InvocationOnMock, T> checker) {
- mChecker = checker;
- }
-
- @Override
- public T answer(InvocationOnMock invocation) throws Throwable {
- assertEquals("Must be called on SYSTEM UID.",
- Process.SYSTEM_UID, mInjectedCallingUid);
- return mChecker.apply(invocation);
- }
- }
-
protected void setUpAppResources() throws Exception {
setUpAppResources(/* offset = */ 0);
}