Merge "Exempt the default browser from trampoline restrictions" into sc-dev

This commit is contained in:
Bernardo Rufino
2021-05-04 16:15:24 +00:00
committed by Android (Google) Code Review
3 changed files with 195 additions and 48 deletions

View File

@@ -123,7 +123,7 @@ import static com.android.server.utils.PriorityDump.PRIORITY_ARG_NORMAL;
import android.Manifest; import android.Manifest;
import android.Manifest.permission; import android.Manifest.permission;
import android.annotation.CallbackExecutor; import android.annotation.MainThread;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.annotation.RequiresPermission; import android.annotation.RequiresPermission;
@@ -492,7 +492,7 @@ public class NotificationManagerService extends SystemService {
private DeviceIdleManager mDeviceIdleManager; private DeviceIdleManager mDeviceIdleManager;
private IUriGrantsManager mUgm; private IUriGrantsManager mUgm;
private UriGrantsManagerInternal mUgmInternal; private UriGrantsManagerInternal mUgmInternal;
private RoleObserver mRoleObserver; private volatile RoleObserver mRoleObserver;
private UserManager mUm; private UserManager mUm;
private IPlatformCompat mPlatformCompat; private IPlatformCompat mPlatformCompat;
private ShortcutHelper mShortcutHelper; private ShortcutHelper mShortcutHelper;
@@ -2651,6 +2651,11 @@ public class NotificationManagerService extends SystemService {
@Override @Override
public void onBootPhase(int phase) { public void onBootPhase(int phase) {
onBootPhase(phase, Looper.getMainLooper());
}
@VisibleForTesting
void onBootPhase(int phase, Looper mainLooper) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
// no beeping until we're basically done booting // no beeping until we're basically done booting
mSystemReady = true; mSystemReady = true;
@@ -2660,9 +2665,11 @@ public class NotificationManagerService extends SystemService {
mAudioManagerInternal = getLocalService(AudioManagerInternal.class); mAudioManagerInternal = getLocalService(AudioManagerInternal.class);
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mZenModeHelper.onSystemReady(); mZenModeHelper.onSystemReady();
mRoleObserver = new RoleObserver(getContext().getSystemService(RoleManager.class), RoleObserver roleObserver = new RoleObserver(getContext(),
mPackageManager, getContext().getMainExecutor()); getContext().getSystemService(RoleManager.class),
mRoleObserver.init(); mPackageManager, mainLooper);
roleObserver.init();
mRoleObserver = roleObserver;
LauncherApps launcherApps = LauncherApps launcherApps =
(LauncherApps) getContext().getSystemService(Context.LAUNCHER_APPS_SERVICE); (LauncherApps) getContext().getSystemService(Context.LAUNCHER_APPS_SERVICE);
mShortcutHelper = new ShortcutHelper(launcherApps, mShortcutListener, getLocalService( mShortcutHelper = new ShortcutHelper(launcherApps, mShortcutListener, getLocalService(
@@ -10688,26 +10695,40 @@ public class NotificationManagerService extends SystemService {
// Role name : user id : list of approved packages // Role name : user id : list of approved packages
private ArrayMap<String, ArrayMap<Integer, ArraySet<String>>> mNonBlockableDefaultApps; private ArrayMap<String, ArrayMap<Integer, ArraySet<String>>> mNonBlockableDefaultApps;
/**
* Writes should be pretty rare (only when default browser changes) and reads are done
* during activity start code-path, so we're optimizing for reads. This means this set is
* immutable once written and we'll recreate the set every time there is a role change and
* then assign that new set to the volatile below, so reads can be done without needing to
* hold a lock. Every write is done on the main-thread, so write atomicity is guaranteed.
*
* Didn't use unmodifiable set to enforce immutability to avoid iterating via iterators.
*/
private volatile ArraySet<Integer> mTrampolineExemptUids = new ArraySet<>();
private final RoleManager mRm; private final RoleManager mRm;
private final IPackageManager mPm; private final IPackageManager mPm;
private final Executor mExecutor; private final Executor mExecutor;
private final Looper mMainLooper;
RoleObserver(@NonNull RoleManager roleManager, RoleObserver(Context context, @NonNull RoleManager roleManager,
@NonNull IPackageManager pkgMgr, @NonNull IPackageManager pkgMgr, @NonNull Looper mainLooper) {
@NonNull @CallbackExecutor Executor executor) {
mRm = roleManager; mRm = roleManager;
mPm = pkgMgr; mPm = pkgMgr;
mExecutor = executor; mExecutor = context.getMainExecutor();
mMainLooper = mainLooper;
} }
/** Should be called from the main-thread. */
@MainThread
public void init() { public void init() {
List<UserInfo> users = mUm.getUsers(); List<UserHandle> users = mUm.getUserHandles(/* excludeDying */ true);
mNonBlockableDefaultApps = new ArrayMap<>(); mNonBlockableDefaultApps = new ArrayMap<>();
for (int i = 0; i < NON_BLOCKABLE_DEFAULT_ROLES.length; i++) { for (int i = 0; i < NON_BLOCKABLE_DEFAULT_ROLES.length; i++) {
final ArrayMap<Integer, ArraySet<String>> userToApprovedList = new ArrayMap<>(); final ArrayMap<Integer, ArraySet<String>> userToApprovedList = new ArrayMap<>();
mNonBlockableDefaultApps.put(NON_BLOCKABLE_DEFAULT_ROLES[i], userToApprovedList); mNonBlockableDefaultApps.put(NON_BLOCKABLE_DEFAULT_ROLES[i], userToApprovedList);
for (int j = 0; j < users.size(); j++) { for (int j = 0; j < users.size(); j++) {
Integer userId = users.get(j).getUserHandle().getIdentifier(); Integer userId = users.get(j).getIdentifier();
ArraySet<String> approvedForUserId = new ArraySet<>(mRm.getRoleHoldersAsUser( ArraySet<String> approvedForUserId = new ArraySet<>(mRm.getRoleHoldersAsUser(
NON_BLOCKABLE_DEFAULT_ROLES[i], UserHandle.of(userId))); NON_BLOCKABLE_DEFAULT_ROLES[i], UserHandle.of(userId)));
ArraySet<Pair<String, Integer>> approvedAppUids = new ArraySet<>(); ArraySet<Pair<String, Integer>> approvedAppUids = new ArraySet<>();
@@ -10718,7 +10739,7 @@ public class NotificationManagerService extends SystemService {
mPreferencesHelper.updateDefaultApps(userId, null, approvedAppUids); mPreferencesHelper.updateDefaultApps(userId, null, approvedAppUids);
} }
} }
updateTrampolineExemptUidsForUsers(users.toArray(new UserHandle[0]));
mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.ALL); mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.ALL);
} }
@@ -10727,6 +10748,11 @@ public class NotificationManagerService extends SystemService {
return mNonBlockableDefaultApps.get(role).get(userId).contains(pkg); return mNonBlockableDefaultApps.get(role).get(userId).contains(pkg);
} }
@VisibleForTesting
public boolean isUidExemptFromTrampolineRestrictions(int uid) {
return mTrampolineExemptUids.contains(uid);
}
/** /**
* Convert the assistant-role holder into settings. The rest of the system uses the * Convert the assistant-role holder into settings. The rest of the system uses the
* settings. * settings.
@@ -10736,6 +10762,12 @@ public class NotificationManagerService extends SystemService {
*/ */
@Override @Override
public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) { public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
onRoleHoldersChangedForNonBlockableDefaultApps(roleName, user);
onRoleHoldersChangedForTrampolines(roleName, user);
}
private void onRoleHoldersChangedForNonBlockableDefaultApps(@NonNull String roleName,
@NonNull UserHandle user) {
// we only care about a couple of the roles they'll tell us about // we only care about a couple of the roles they'll tell us about
boolean relevantChange = false; boolean relevantChange = false;
for (int i = 0; i < NON_BLOCKABLE_DEFAULT_ROLES.length; i++) { for (int i = 0; i < NON_BLOCKABLE_DEFAULT_ROLES.length; i++) {
@@ -10783,6 +10815,41 @@ public class NotificationManagerService extends SystemService {
// write of the notification policy xml for this change // write of the notification policy xml for this change
} }
private void onRoleHoldersChangedForTrampolines(@NonNull String roleName,
@NonNull UserHandle user) {
if (!RoleManager.ROLE_BROWSER.equals(roleName)) {
return;
}
updateTrampolineExemptUidsForUsers(user);
}
private void updateTrampolineExemptUidsForUsers(UserHandle... users) {
Preconditions.checkState(mMainLooper.isCurrentThread());
ArraySet<Integer> oldUids = mTrampolineExemptUids;
ArraySet<Integer> newUids = new ArraySet<>();
// Add the uids from previous set for the users that we won't update.
for (int i = 0, n = oldUids.size(); i < n; i++) {
int uid = oldUids.valueAt(i);
UserHandle user = UserHandle.of(UserHandle.getUserId(uid));
if (!ArrayUtils.contains(users, user)) {
newUids.add(uid);
}
}
// Now lookup the new uids for the users that we want to update.
for (int i = 0, n = users.length; i < n; i++) {
UserHandle user = users[i];
for (String pkg : mRm.getRoleHoldersAsUser(RoleManager.ROLE_BROWSER, user)) {
int uid = getUidForPackage(pkg, user.getIdentifier());
if (uid != -1) {
newUids.add(uid);
} else {
Slog.e(TAG, "Bad uid (-1) for browser package " + pkg);
}
}
}
mTrampolineExemptUids = newUids;
}
private int getUidForPackage(String pkg, int userId) { private int getUidForPackage(String pkg, int userId) {
try { try {
return mPm.getPackageUid(pkg, MATCH_ALL, userId); return mPm.getPackageUid(pkg, MATCH_ALL, userId);
@@ -10947,7 +11014,7 @@ public class NotificationManagerService extends SystemService {
} }
String logcatMessage = String logcatMessage =
"Indirect notification activity start (trampoline) from " + packageName; "Indirect notification activity start (trampoline) from " + packageName;
if (CompatChanges.isChangeEnabled(NOTIFICATION_TRAMPOLINE_BLOCK, uid)) { if (blockTrampoline(uid)) {
// Post toast() call to mHandler to offload PM lookup from the activity start path // Post toast() call to mHandler to offload PM lookup from the activity start path
mHandler.post(() -> toast(packageName, uid)); mHandler.post(() -> toast(packageName, uid));
Slog.e(TAG, logcatMessage + " blocked"); Slog.e(TAG, logcatMessage + " blocked");
@@ -10958,6 +11025,13 @@ public class NotificationManagerService extends SystemService {
} }
} }
private boolean blockTrampoline(int uid) {
if (mRoleObserver != null && mRoleObserver.isUidExemptFromTrampolineRestrictions(uid)) {
return false;
}
return CompatChanges.isChangeEnabled(NOTIFICATION_TRAMPOLINE_BLOCK, uid);
}
@Override @Override
public boolean canCloseSystemDialogs(Collection<IBinder> tokens, int uid) { public boolean canCloseSystemDialogs(Collection<IBinder> tokens, int uid) {
// If the start is allowed via notification, we allow the app to close system dialogs // If the start is allowed via notification, we allow the app to close system dialogs

View File

@@ -141,6 +141,7 @@ import android.os.Binder;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper;
import android.os.Parcel; import android.os.Parcel;
import android.os.Process; import android.os.Process;
import android.os.RemoteException; import android.os.RemoteException;
@@ -267,6 +268,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
RankingHandler mRankingHandler; RankingHandler mRankingHandler;
@Mock @Mock
ActivityManagerInternal mAmi; ActivityManagerInternal mAmi;
@Mock
private Looper mMainLooper;
@Mock @Mock
IIntentSender pi1; IIntentSender pi1;
@@ -514,7 +517,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mAppUsageStats, mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal, mAppUsageStats, mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
mAppOpsManager, mUm, mHistoryManager, mStatsManager, mock(TelephonyManager.class), mAppOpsManager, mUm, mHistoryManager, mStatsManager, mock(TelephonyManager.class),
mAmi, mToastRateLimiter); mAmi, mToastRateLimiter);
mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); // Return first true for RoleObserver main-thread check
when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false);
mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper);
mService.setAudioManager(mAudioManager); mService.setAudioManager(mAudioManager);

View File

@@ -16,6 +16,7 @@
package com.android.server.notification; package com.android.server.notification;
import static android.app.role.RoleManager.ROLE_BROWSER;
import static android.app.role.RoleManager.ROLE_DIALER; import static android.app.role.RoleManager.ROLE_DIALER;
import static android.app.role.RoleManager.ROLE_EMERGENCY; import static android.app.role.RoleManager.ROLE_EMERGENCY;
import static android.content.pm.PackageManager.MATCH_ALL; import static android.content.pm.PackageManager.MATCH_ALL;
@@ -23,6 +24,7 @@ import static android.content.pm.PackageManager.MATCH_ALL;
import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.any; import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@@ -31,6 +33,8 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static java.util.Arrays.asList;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.ActivityManagerInternal; import android.app.ActivityManagerInternal;
import android.app.AppOpsManager; import android.app.AppOpsManager;
@@ -44,7 +48,6 @@ import android.companion.ICompanionDeviceManager;
import android.content.Context; import android.content.Context;
import android.content.pm.IPackageManager; import android.content.pm.IPackageManager;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.Looper; import android.os.Looper;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
@@ -80,7 +83,6 @@ import org.mockito.MockitoAnnotations;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor;
@SmallTest @SmallTest
@RunWith(AndroidTestingRunner.class) @RunWith(AndroidTestingRunner.class)
@@ -98,13 +100,13 @@ public class RoleObserverTest extends UiServiceTestCase {
@Mock @Mock
private UserManager mUm; private UserManager mUm;
@Mock @Mock
private Executor mExecutor;
@Mock
private RoleManager mRoleManager; private RoleManager mRoleManager;
@Mock
private Looper mMainLooper;
NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake(); NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake( private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
1 << 30); 1 << 30);
private List<UserInfo> mUsers; private List<UserHandle> mUsers;
private static class TestableNotificationManagerService extends NotificationManagerService { private static class TestableNotificationManagerService extends NotificationManagerService {
TestableNotificationManagerService(Context context, TestableNotificationManagerService(Context context,
@@ -133,13 +135,15 @@ public class RoleObserverTest extends UiServiceTestCase {
mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class)); mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
mUsers = new ArrayList<>(); mUsers = new ArrayList<>();
mUsers.add(new UserInfo(0, "system", 0)); mUsers.add(new UserHandle(0));
mUsers.add(new UserInfo(10, "second", 0)); mUsers.add(new UserHandle(10));
when(mUm.getUsers()).thenReturn(mUsers); when(mUm.getUserHandles(anyBoolean())).thenReturn(mUsers);
when(mMainLooper.isCurrentThread()).thenReturn(true);
mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger, mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
mNotificationInstanceIdSequence); mNotificationInstanceIdSequence);
mRoleObserver = mService.new RoleObserver(mRoleManager, mPm, mExecutor); mRoleObserver = mService.new RoleObserver(mContext, mRoleManager, mPm, mMainLooper);
try { try {
mService.init(mService.new WorkerHandler(mock(Looper.class)), mService.init(mService.new WorkerHandler(mock(Looper.class)),
@@ -174,7 +178,7 @@ public class RoleObserverTest extends UiServiceTestCase {
} }
@Test @Test
public void testInit() throws Exception { public void testInit_forNonBlockableDefaultApps() throws Exception {
List<String> dialer0 = new ArrayList<>(); List<String> dialer0 = new ArrayList<>();
dialer0.add("dialer"); dialer0.add("dialer");
List<String> emer0 = new ArrayList<>(); List<String> emer0 = new ArrayList<>();
@@ -191,29 +195,29 @@ public class RoleObserverTest extends UiServiceTestCase {
when(mRoleManager.getRoleHoldersAsUser( when(mRoleManager.getRoleHoldersAsUser(
ROLE_DIALER, ROLE_DIALER,
mUsers.get(0).getUserHandle())). mUsers.get(0)))
thenReturn(dialer0); .thenReturn(dialer0);
when(mRoleManager.getRoleHoldersAsUser( when(mRoleManager.getRoleHoldersAsUser(
ROLE_EMERGENCY, ROLE_EMERGENCY,
mUsers.get(0).getUserHandle())). mUsers.get(0)))
thenReturn(emer0); .thenReturn(emer0);
mRoleObserver.init(); mRoleObserver.init();
// verify internal records of current state of the world // verify internal records of current state of the world
assertTrue(mRoleObserver.isApprovedPackageForRoleForUser( assertTrue(mRoleObserver.isApprovedPackageForRoleForUser(
ROLE_DIALER, dialer0.get(0), mUsers.get(0).id)); ROLE_DIALER, dialer0.get(0), mUsers.get(0).getIdentifier()));
assertFalse(mRoleObserver.isApprovedPackageForRoleForUser( assertFalse(mRoleObserver.isApprovedPackageForRoleForUser(
ROLE_DIALER, dialer0.get(0), mUsers.get(1).id)); ROLE_DIALER, dialer0.get(0), mUsers.get(1).getIdentifier()));
assertTrue(mRoleObserver.isApprovedPackageForRoleForUser( assertTrue(mRoleObserver.isApprovedPackageForRoleForUser(
ROLE_EMERGENCY, emer0.get(0), mUsers.get(0).id)); ROLE_EMERGENCY, emer0.get(0), mUsers.get(0).getIdentifier()));
assertFalse(mRoleObserver.isApprovedPackageForRoleForUser( assertFalse(mRoleObserver.isApprovedPackageForRoleForUser(
ROLE_EMERGENCY, emer0.get(0), mUsers.get(1).id)); ROLE_EMERGENCY, emer0.get(0), mUsers.get(1).getIdentifier()));
// make sure we're listening to updates // make sure we're listening to updates
verify(mRoleManager, times(1)).addOnRoleHoldersChangedListenerAsUser( verify(mRoleManager, times(1)).addOnRoleHoldersChangedListenerAsUser(
eq(mExecutor), any(), eq(UserHandle.ALL)); any(), any(), eq(UserHandle.ALL));
// make sure we told pref helper about the state of the world // make sure we told pref helper about the state of the world
verify(mPreferencesHelper, times(1)).updateDefaultApps(0, null, dialer0Pair); verify(mPreferencesHelper, times(1)).updateDefaultApps(0, null, dialer0Pair);
@@ -221,14 +225,31 @@ public class RoleObserverTest extends UiServiceTestCase {
} }
@Test @Test
public void testSwapDefault() throws Exception { public void testInit_forTrampolines() throws Exception {
when(mPm.getPackageUid("com.browser", MATCH_ALL, 0)).thenReturn(30);
when(mRoleManager.getRoleHoldersAsUser(
ROLE_BROWSER,
mUsers.get(0)))
.thenReturn(asList("com.browser"));
mRoleObserver.init();
assertTrue(mRoleObserver.isUidExemptFromTrampolineRestrictions(30));
// make sure we're listening to updates
verify(mRoleManager, times(1)).addOnRoleHoldersChangedListenerAsUser(any(), any(),
eq(UserHandle.ALL));
}
@Test
public void testSwapDefault_forNonBlockableDefaultApps() throws Exception {
List<String> dialer0 = new ArrayList<>(); List<String> dialer0 = new ArrayList<>();
dialer0.add("dialer"); dialer0.add("dialer");
when(mRoleManager.getRoleHoldersAsUser( when(mRoleManager.getRoleHoldersAsUser(
ROLE_DIALER, ROLE_DIALER,
mUsers.get(0).getUserHandle())). mUsers.get(0)))
thenReturn(dialer0); .thenReturn(dialer0);
mRoleObserver.init(); mRoleObserver.init();
@@ -241,8 +262,8 @@ public class RoleObserverTest extends UiServiceTestCase {
when(mRoleManager.getRoleHoldersAsUser( when(mRoleManager.getRoleHoldersAsUser(
ROLE_DIALER, ROLE_DIALER,
mUsers.get(0).getUserHandle())). mUsers.get(0)))
thenReturn(newDefault); .thenReturn(newDefault);
mRoleObserver.onRoleHoldersChanged(ROLE_DIALER, UserHandle.of(0)); mRoleObserver.onRoleHoldersChanged(ROLE_DIALER, UserHandle.of(0));
@@ -251,15 +272,39 @@ public class RoleObserverTest extends UiServiceTestCase {
} }
@Test @Test
public void testSwapDefault_multipleOverlappingApps() throws Exception { public void testSwapDefault_forTrampolines() throws Exception {
List<String> dialer0 = new ArrayList<>();
when(mPm.getPackageUid("com.browser", MATCH_ALL, 0)).thenReturn(30);
when(mPm.getPackageUid("com.browser2", MATCH_ALL, 0)).thenReturn(31);
when(mRoleManager.getRoleHoldersAsUser(
ROLE_BROWSER,
mUsers.get(0)))
.thenReturn(asList("com.browser"));
mRoleObserver.init();
assertTrue(mRoleObserver.isUidExemptFromTrampolineRestrictions(30));
assertFalse(mRoleObserver.isUidExemptFromTrampolineRestrictions(31));
// Default changed
when(mRoleManager.getRoleHoldersAsUser(
ROLE_BROWSER,
mUsers.get(0)))
.thenReturn(asList("com.browser2"));
mRoleObserver.onRoleHoldersChanged(ROLE_BROWSER, UserHandle.of(0));
assertFalse(mRoleObserver.isUidExemptFromTrampolineRestrictions(30));
assertTrue(mRoleObserver.isUidExemptFromTrampolineRestrictions(31));
}
@Test
public void testSwapDefault_multipleOverlappingApps_forNonBlockableDefaultApps()
throws Exception {
List<String> dialer0 = new ArrayList<>(); List<String> dialer0 = new ArrayList<>();
dialer0.add("dialer"); dialer0.add("dialer");
dialer0.add("phone"); dialer0.add("phone");
when(mRoleManager.getRoleHoldersAsUser( when(mRoleManager.getRoleHoldersAsUser(
ROLE_DIALER, ROLE_DIALER,
mUsers.get(0).getUserHandle())). mUsers.get(0)))
thenReturn(dialer0); .thenReturn(dialer0);
mRoleObserver.init(); mRoleObserver.init();
@@ -273,8 +318,8 @@ public class RoleObserverTest extends UiServiceTestCase {
when(mRoleManager.getRoleHoldersAsUser( when(mRoleManager.getRoleHoldersAsUser(
ROLE_DIALER, ROLE_DIALER,
mUsers.get(0).getUserHandle())). mUsers.get(0)))
thenReturn(newDefault); .thenReturn(newDefault);
ArraySet<String> expectedRemove = new ArraySet<>(); ArraySet<String> expectedRemove = new ArraySet<>();
expectedRemove.add("dialer"); expectedRemove.add("dialer");
@@ -294,14 +339,14 @@ public class RoleObserverTest extends UiServiceTestCase {
} }
@Test @Test
public void testSwapDefault_newUser() throws Exception { public void testSwapDefault_newUser_forNonBlockableDefaultApps() throws Exception {
List<String> dialer0 = new ArrayList<>(); List<String> dialer0 = new ArrayList<>();
dialer0.add("dialer"); dialer0.add("dialer");
when(mRoleManager.getRoleHoldersAsUser( when(mRoleManager.getRoleHoldersAsUser(
ROLE_DIALER, ROLE_DIALER,
mUsers.get(0).getUserHandle())). mUsers.get(0)))
thenReturn(dialer0); .thenReturn(dialer0);
mRoleObserver.init(); mRoleObserver.init();
@@ -310,8 +355,8 @@ public class RoleObserverTest extends UiServiceTestCase {
when(mRoleManager.getRoleHoldersAsUser( when(mRoleManager.getRoleHoldersAsUser(
ROLE_DIALER, ROLE_DIALER,
mUsers.get(1).getUserHandle())). mUsers.get(1)))
thenReturn(dialer10); .thenReturn(dialer10);
ArraySet<Pair<String, Integer>> expectedAddPair = new ArraySet<>(); ArraySet<Pair<String, Integer>> expectedAddPair = new ArraySet<>();
expectedAddPair.add(new Pair("phone", 30)); expectedAddPair.add(new Pair("phone", 30));
@@ -329,4 +374,27 @@ public class RoleObserverTest extends UiServiceTestCase {
assertTrue(mRoleObserver.isApprovedPackageForRoleForUser(ROLE_DIALER, "phone", 10)); assertTrue(mRoleObserver.isApprovedPackageForRoleForUser(ROLE_DIALER, "phone", 10));
assertTrue(mRoleObserver.isApprovedPackageForRoleForUser(ROLE_DIALER, "dialer", 0)); assertTrue(mRoleObserver.isApprovedPackageForRoleForUser(ROLE_DIALER, "dialer", 0));
} }
@Test
public void testSwapDefault_newUser_forTrampolines() throws Exception {
List<String> dialer0 = new ArrayList<>();
when(mPm.getPackageUid("com.browser", MATCH_ALL, 0)).thenReturn(30);
when(mPm.getPackageUid("com.browser2", MATCH_ALL, 10)).thenReturn(1031);
when(mRoleManager.getRoleHoldersAsUser(
ROLE_BROWSER,
mUsers.get(0)))
.thenReturn(asList("com.browser"));
mRoleObserver.init();
assertTrue(mRoleObserver.isUidExemptFromTrampolineRestrictions(30));
assertFalse(mRoleObserver.isUidExemptFromTrampolineRestrictions(1031));
// New user
when(mRoleManager.getRoleHoldersAsUser(
ROLE_BROWSER,
mUsers.get(1)))
.thenReturn(asList("com.browser2"));
mRoleObserver.onRoleHoldersChanged(ROLE_BROWSER, UserHandle.of(10));
assertTrue(mRoleObserver.isUidExemptFromTrampolineRestrictions(30));
assertTrue(mRoleObserver.isUidExemptFromTrampolineRestrictions(1031));
}
} }