Merge "Using UserManagerInternal for access control instead of UserManager" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
9015d24332
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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 -> {
|
||||
when(mMockUserManagerInternal.isUserUnlockingOrUnlocked(anyInt()))
|
||||
.thenAnswer(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 -> {
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user