diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index 8e78703f37c2f..595de9e35a7f7 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -39,6 +39,7 @@ 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; @@ -49,6 +50,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; @@ -101,6 +103,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; @@ -113,6 +116,7 @@ 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( @@ -233,6 +237,22 @@ public class LauncherAppsService extends SystemService { * group. */ private boolean canAccessProfile(int targetUserId, String message) { + final int callingUserId = injectCallingUserId(); + + if (targetUserId == callingUserId) return true; + + long ident = injectClearCallingIdentity(); + try { + final UserInfo callingUserInfo = mUm.getUserInfo(callingUserId); + if (callingUserInfo != null && callingUserInfo.isManagedProfile()) { + Slog.w(TAG, message + " for another profile " + + targetUserId + " from " + callingUserId + " not allowed"); + return false; + } + } finally { + injectRestoreCallingIdentity(ident); + } + return mUserManagerInternal.isProfileAccessible(injectCallingUserId(), targetUserId, message, true); } 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 197475032ea87..a6e0a662ffbcf 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java @@ -92,6 +92,8 @@ 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,6 +113,7 @@ 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"; @@ -834,6 +837,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { + targetUserId); }); + when(mMockUserManager.getUserInfo(anyInt())).thenAnswer(new AnswerWithSystemCheck<>( + inv -> mUserInfos.get((Integer) inv.getArguments()[0]))); when(mMockActivityManagerInternal.getUidProcessState(anyInt())).thenReturn( ActivityManager.PROCESS_STATE_CACHED_EMPTY); @@ -863,6 +868,24 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { } } + /** + * Returns a boolean but also checks if the current UID is SYSTEM_UID. + */ + protected class AnswerWithSystemCheck implements Answer { + private final Function mChecker; + + public AnswerWithSystemCheck(Function 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); + } + } + private static boolean b(Boolean value) { return (value != null && value); }