Home | History | Annotate | Download | only in pm
      1 package com.android.server.pm;
      2 
      3 import static com.google.common.truth.Truth.assertThat;
      4 
      5 import static org.mockito.ArgumentMatchers.any;
      6 import static org.mockito.ArgumentMatchers.anyInt;
      7 import static org.mockito.ArgumentMatchers.anyString;
      8 import static org.mockito.ArgumentMatchers.eq;
      9 import static org.mockito.ArgumentMatchers.nullable;
     10 import static org.mockito.Mockito.doAnswer;
     11 import static org.mockito.Mockito.never;
     12 import static org.mockito.Mockito.verify;
     13 import static org.mockito.Mockito.when;
     14 import static org.testng.Assert.assertThrows;
     15 
     16 import android.app.ActivityManagerInternal;
     17 import android.app.AppOpsManager;
     18 import android.app.IApplicationThread;
     19 import android.content.ComponentName;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.pm.ActivityInfo;
     23 import android.content.pm.ApplicationInfo;
     24 import android.content.pm.PackageInfo;
     25 import android.content.pm.PackageManager;
     26 import android.content.pm.PackageManagerInternal;
     27 import android.content.pm.ResolveInfo;
     28 import android.os.Bundle;
     29 import android.os.UserHandle;
     30 import android.os.UserManager;
     31 import android.platform.test.annotations.Presubmit;
     32 import android.util.SparseArray;
     33 
     34 import org.junit.Before;
     35 import org.junit.Test;
     36 import org.junit.runner.RunWith;
     37 import org.mockito.Mock;
     38 import org.mockito.junit.MockitoJUnitRunner;
     39 
     40 import java.util.ArrayList;
     41 import java.util.Collections;
     42 import java.util.List;
     43 
     44 /**
     45  * Build/Install/Run:
     46  * atest FrameworksServicesTests:com.android.server.pm.CrossProfileAppsServiceImplTest
     47  */
     48 @Presubmit
     49 @RunWith(MockitoJUnitRunner.class)
     50 public class CrossProfileAppsServiceImplTest {
     51     private static final String PACKAGE_ONE = "com.one";
     52     private static final int PACKAGE_ONE_UID = 1111;
     53     private static final ComponentName ACTIVITY_COMPONENT =
     54             new ComponentName("com.one", "test");
     55 
     56     private static final String PACKAGE_TWO = "com.two";
     57     private static final int PACKAGE_TWO_UID = 2222;
     58 
     59     private static final int PRIMARY_USER = 0;
     60     private static final int PROFILE_OF_PRIMARY_USER = 10;
     61     private static final int SECONDARY_USER = 11;
     62 
     63     @Mock
     64     private Context mContext;
     65     @Mock
     66     private UserManager mUserManager;
     67     @Mock
     68     private PackageManager mPackageManager;
     69     @Mock
     70     private PackageManagerInternal mPackageManagerInternal;
     71     @Mock
     72     private AppOpsManager mAppOpsManager;
     73     @Mock
     74     private ActivityManagerInternal mActivityManagerInternal;
     75 
     76     private TestInjector mTestInjector;
     77     private ActivityInfo mActivityInfo;
     78     private CrossProfileAppsServiceImpl mCrossProfileAppsServiceImpl;
     79     private IApplicationThread mIApplicationThread;
     80 
     81     private SparseArray<Boolean> mUserEnabled = new SparseArray<>();
     82 
     83     @Before
     84     public void initCrossProfileAppsServiceImpl() {
     85         mTestInjector = new TestInjector();
     86         mCrossProfileAppsServiceImpl = new CrossProfileAppsServiceImpl(mContext, mTestInjector);
     87     }
     88 
     89     @Before
     90     public void setupEnabledProfiles() {
     91         mUserEnabled.put(PRIMARY_USER, true);
     92         mUserEnabled.put(PROFILE_OF_PRIMARY_USER, true);
     93         mUserEnabled.put(SECONDARY_USER, true);
     94 
     95         when(mUserManager.getEnabledProfileIds(anyInt())).thenAnswer(
     96                 invocation -> {
     97                     List<Integer> users = new ArrayList<>();
     98                     final int targetUser = invocation.getArgument(0);
     99                     users.add(targetUser);
    100 
    101                     int profileUserId = -1;
    102                     if (targetUser == PRIMARY_USER) {
    103                         profileUserId = PROFILE_OF_PRIMARY_USER;
    104                     } else if (targetUser == PROFILE_OF_PRIMARY_USER) {
    105                         profileUserId = PRIMARY_USER;
    106                     }
    107 
    108                     if (profileUserId != -1 && mUserEnabled.get(profileUserId)) {
    109                         users.add(profileUserId);
    110                     }
    111                     return users.stream().mapToInt(i -> i).toArray();
    112                 });
    113     }
    114 
    115     @Before
    116     public void setupCaller() {
    117         mTestInjector.setCallingUid(PACKAGE_ONE_UID);
    118         mTestInjector.setCallingUserId(PRIMARY_USER);
    119     }
    120 
    121     @Before
    122     public void setupPackage() throws Exception {
    123         // PACKAGE_ONE are installed in all users.
    124         mockAppsInstalled(PACKAGE_ONE, PRIMARY_USER, true);
    125         mockAppsInstalled(PACKAGE_ONE, PROFILE_OF_PRIMARY_USER, true);
    126         mockAppsInstalled(PACKAGE_ONE, SECONDARY_USER, true);
    127 
    128         // Packages are resolved to their corresponding UID.
    129         doAnswer(invocation -> {
    130             final int uid = invocation.getArgument(0);
    131             final String packageName = invocation.getArgument(1);
    132             if (uid == PACKAGE_ONE_UID && PACKAGE_ONE.equals(packageName)) {
    133                 return null;
    134             } else if (uid ==PACKAGE_TWO_UID && PACKAGE_TWO.equals(packageName)) {
    135                 return null;
    136             }
    137             throw new SecurityException("Not matching");
    138         }).when(mAppOpsManager).checkPackage(anyInt(), anyString());
    139 
    140         // The intent is resolved to the ACTIVITY_COMPONENT.
    141         mockActivityLaunchIntentResolvedTo(ACTIVITY_COMPONENT);
    142     }
    143 
    144     @Test
    145     public void getTargetUserProfiles_fromPrimaryUser_installed() throws Exception {
    146         List<UserHandle> targetProfiles =
    147                 mCrossProfileAppsServiceImpl.getTargetUserProfiles(PACKAGE_ONE);
    148         assertThat(targetProfiles).containsExactly(UserHandle.of(PROFILE_OF_PRIMARY_USER));
    149     }
    150 
    151     @Test
    152     public void getTargetUserProfiles_fromPrimaryUser_notInstalled() throws Exception {
    153         mockAppsInstalled(PACKAGE_ONE, PROFILE_OF_PRIMARY_USER, false);
    154 
    155         List<UserHandle> targetProfiles =
    156                 mCrossProfileAppsServiceImpl.getTargetUserProfiles(PACKAGE_ONE);
    157         assertThat(targetProfiles).isEmpty();
    158     }
    159 
    160     @Test
    161     public void getTargetUserProfiles_fromPrimaryUser_userNotEnabled() throws Exception {
    162         mUserEnabled.put(PROFILE_OF_PRIMARY_USER, false);
    163 
    164         List<UserHandle> targetProfiles =
    165                 mCrossProfileAppsServiceImpl.getTargetUserProfiles(PACKAGE_ONE);
    166         assertThat(targetProfiles).isEmpty();
    167     }
    168 
    169     @Test
    170     public void getTargetUserProfiles_fromSecondaryUser() throws Exception {
    171         mTestInjector.setCallingUserId(SECONDARY_USER);
    172 
    173         List<UserHandle> targetProfiles =
    174                 mCrossProfileAppsServiceImpl.getTargetUserProfiles(PACKAGE_ONE);
    175         assertThat(targetProfiles).isEmpty();
    176     }
    177 
    178     @Test
    179     public void getTargetUserProfiles_fromProfile_installed() throws Exception {
    180         mTestInjector.setCallingUserId(PROFILE_OF_PRIMARY_USER);
    181 
    182         List<UserHandle> targetProfiles =
    183                 mCrossProfileAppsServiceImpl.getTargetUserProfiles(PACKAGE_ONE);
    184         assertThat(targetProfiles).containsExactly(UserHandle.of(PRIMARY_USER));
    185     }
    186 
    187     @Test
    188     public void getTargetUserProfiles_fromProfile_notInstalled() throws Exception {
    189         mTestInjector.setCallingUserId(PROFILE_OF_PRIMARY_USER);
    190         mockAppsInstalled(PACKAGE_ONE, PRIMARY_USER, false);
    191 
    192         List<UserHandle> targetProfiles =
    193                 mCrossProfileAppsServiceImpl.getTargetUserProfiles(PACKAGE_ONE);
    194         assertThat(targetProfiles).isEmpty();
    195     }
    196 
    197     @Test(expected = SecurityException.class)
    198     public void getTargetUserProfiles_fakeCaller() throws Exception {
    199         mCrossProfileAppsServiceImpl.getTargetUserProfiles(PACKAGE_TWO);
    200     }
    201 
    202     @Test
    203     public void startActivityAsUser_currentUser() throws Exception {
    204         assertThrows(
    205                 SecurityException.class,
    206                 () ->
    207                         mCrossProfileAppsServiceImpl.startActivityAsUser(
    208                                 mIApplicationThread,
    209                                 PACKAGE_ONE,
    210                                 ACTIVITY_COMPONENT,
    211                                 UserHandle.of(PRIMARY_USER)));
    212 
    213         verify(mActivityManagerInternal, never())
    214                 .startActivityAsUser(
    215                         nullable(IApplicationThread.class),
    216                         anyString(),
    217                         any(Intent.class),
    218                         nullable(Bundle.class),
    219                         anyInt());
    220     }
    221 
    222     @Test
    223     public void startActivityAsUser_profile_notInstalled() throws Exception {
    224         mockAppsInstalled(PACKAGE_ONE, PROFILE_OF_PRIMARY_USER, false);
    225 
    226         assertThrows(
    227                 SecurityException.class,
    228                 () ->
    229                         mCrossProfileAppsServiceImpl.startActivityAsUser(
    230                                 mIApplicationThread,
    231                                 PACKAGE_ONE,
    232                                 ACTIVITY_COMPONENT,
    233                                 UserHandle.of(PROFILE_OF_PRIMARY_USER)));
    234 
    235         verify(mActivityManagerInternal, never())
    236                 .startActivityAsUser(
    237                         nullable(IApplicationThread.class),
    238                         anyString(),
    239                         any(Intent.class),
    240                         nullable(Bundle.class),
    241                         anyInt());
    242     }
    243 
    244     @Test
    245     public void startActivityAsUser_profile_fakeCaller() throws Exception {
    246         assertThrows(
    247                 SecurityException.class,
    248                 () ->
    249                         mCrossProfileAppsServiceImpl.startActivityAsUser(
    250                                 mIApplicationThread,
    251                                 PACKAGE_TWO,
    252                                 ACTIVITY_COMPONENT,
    253                                 UserHandle.of(PROFILE_OF_PRIMARY_USER)));
    254 
    255         verify(mActivityManagerInternal, never())
    256                 .startActivityAsUser(
    257                         nullable(IApplicationThread.class),
    258                         anyString(),
    259                         any(Intent.class),
    260                         nullable(Bundle.class),
    261                         anyInt());
    262     }
    263 
    264     @Test
    265     public void startActivityAsUser_profile_notExported() throws Exception {
    266         mActivityInfo.exported = false;
    267 
    268         assertThrows(
    269                 SecurityException.class,
    270                 () ->
    271                         mCrossProfileAppsServiceImpl.startActivityAsUser(
    272                                 mIApplicationThread,
    273                                 PACKAGE_ONE,
    274                                 ACTIVITY_COMPONENT,
    275                                 UserHandle.of(PROFILE_OF_PRIMARY_USER)));
    276 
    277         verify(mActivityManagerInternal, never())
    278                 .startActivityAsUser(
    279                         nullable(IApplicationThread.class),
    280                         anyString(),
    281                         any(Intent.class),
    282                         nullable(Bundle.class),
    283                         anyInt());
    284     }
    285 
    286     @Test
    287     public void startActivityAsUser_profile_anotherPackage() throws Exception {
    288         assertThrows(
    289                 SecurityException.class,
    290                 () ->
    291                         mCrossProfileAppsServiceImpl.startActivityAsUser(
    292                                 mIApplicationThread,
    293                                 PACKAGE_ONE,
    294                                 new ComponentName(PACKAGE_TWO, "test"),
    295                                 UserHandle.of(PROFILE_OF_PRIMARY_USER)));
    296 
    297         verify(mActivityManagerInternal, never())
    298                 .startActivityAsUser(
    299                         nullable(IApplicationThread.class),
    300                         anyString(),
    301                         any(Intent.class),
    302                         nullable(Bundle.class),
    303                         anyInt());
    304     }
    305 
    306     @Test
    307     public void startActivityAsUser_secondaryUser() throws Exception {
    308         assertThrows(
    309                 SecurityException.class,
    310                 () ->
    311                         mCrossProfileAppsServiceImpl.startActivityAsUser(
    312                                 mIApplicationThread,
    313                                 PACKAGE_ONE,
    314                                 ACTIVITY_COMPONENT,
    315                                 UserHandle.of(SECONDARY_USER)));
    316 
    317         verify(mActivityManagerInternal, never())
    318                 .startActivityAsUser(
    319                         nullable(IApplicationThread.class),
    320                         anyString(),
    321                         any(Intent.class),
    322                         nullable(Bundle.class),
    323                         anyInt());
    324     }
    325 
    326     @Test
    327     public void startActivityAsUser_fromProfile_success() throws Exception {
    328         mTestInjector.setCallingUserId(PROFILE_OF_PRIMARY_USER);
    329 
    330         mCrossProfileAppsServiceImpl.startActivityAsUser(
    331                 mIApplicationThread,
    332                 PACKAGE_ONE,
    333                 ACTIVITY_COMPONENT,
    334                 UserHandle.of(PRIMARY_USER));
    335 
    336         verify(mActivityManagerInternal)
    337                 .startActivityAsUser(
    338                         nullable(IApplicationThread.class),
    339                         eq(PACKAGE_ONE),
    340                         any(Intent.class),
    341                         nullable(Bundle.class),
    342                         eq(PRIMARY_USER));
    343     }
    344 
    345     private void mockAppsInstalled(String packageName, int user, boolean installed) {
    346         when(mPackageManagerInternal.getPackageInfo(
    347                 eq(packageName),
    348                 anyInt(),
    349                 anyInt(),
    350                 eq(user)))
    351                 .thenReturn(installed ? createInstalledPackageInfo() : null);
    352     }
    353 
    354     private PackageInfo createInstalledPackageInfo() {
    355         PackageInfo packageInfo = new PackageInfo();
    356         packageInfo.applicationInfo = new ApplicationInfo();
    357         packageInfo.applicationInfo.enabled = true;
    358         return packageInfo;
    359     }
    360 
    361     private void mockActivityLaunchIntentResolvedTo(ComponentName componentName) {
    362         ResolveInfo resolveInfo = new ResolveInfo();
    363         ActivityInfo activityInfo = new ActivityInfo();
    364         activityInfo.packageName = componentName.getPackageName();
    365         activityInfo.name = componentName.getClassName();
    366         activityInfo.exported = true;
    367         resolveInfo.activityInfo = activityInfo;
    368         mActivityInfo = activityInfo;
    369 
    370         when(mPackageManagerInternal.queryIntentActivities(
    371                 any(Intent.class), anyInt(), anyInt(), anyInt()))
    372                 .thenReturn(Collections.singletonList(resolveInfo));
    373     }
    374 
    375     private class TestInjector implements CrossProfileAppsServiceImpl.Injector {
    376         private int mCallingUid;
    377         private int mCallingUserId;
    378 
    379         public void setCallingUid(int uid) {
    380             mCallingUid = uid;
    381         }
    382 
    383         public void setCallingUserId(int userId) {
    384             mCallingUserId = userId;
    385         }
    386 
    387         @Override
    388         public int getCallingUid() {
    389             return mCallingUid;
    390         }
    391 
    392         @Override
    393         public int getCallingUserId() {
    394             return mCallingUserId;
    395         }
    396 
    397         @Override
    398         public UserHandle getCallingUserHandle() {
    399             return UserHandle.of(mCallingUserId);
    400         }
    401 
    402         @Override
    403         public long clearCallingIdentity() {
    404             return 0;
    405         }
    406 
    407         @Override
    408         public void restoreCallingIdentity(long token) {
    409         }
    410 
    411         @Override
    412         public UserManager getUserManager() {
    413             return mUserManager;
    414         }
    415 
    416         @Override
    417         public PackageManagerInternal getPackageManagerInternal() {
    418             return mPackageManagerInternal;
    419         }
    420 
    421         @Override
    422         public PackageManager getPackageManager() {
    423             return mPackageManager;
    424         }
    425 
    426         @Override
    427         public AppOpsManager getAppOpsManager() {
    428             return mAppOpsManager;
    429         }
    430 
    431         @Override
    432         public ActivityManagerInternal getActivityManagerInternal() {
    433             return mActivityManagerInternal;
    434         }
    435     }
    436 }
    437