Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.app;
     18 
     19 import android.content.Context;
     20 import android.content.pm.ApplicationInfo;
     21 import android.content.pm.IPackageManager;
     22 import android.content.pm.PackageInfo;
     23 import android.os.storage.StorageManager;
     24 import android.os.storage.VolumeInfo;
     25 import android.support.test.filters.LargeTest;
     26 
     27 import junit.framework.TestCase;
     28 
     29 import org.mockito.Mockito;
     30 
     31 import java.util.ArrayList;
     32 import java.util.Arrays;
     33 import java.util.List;
     34 
     35 import static android.os.storage.VolumeInfo.STATE_MOUNTED;
     36 import static android.os.storage.VolumeInfo.STATE_UNMOUNTED;
     37 
     38 @LargeTest
     39 public class ApplicationPackageManagerTest extends TestCase {
     40     private static final String sInternalVolPath = "/data";
     41     private static final String sAdoptedVolPath = "/mnt/expand/123";
     42     private static final String sPublicVolPath = "/emulated";
     43     private static final String sPrivateUnmountedVolPath = "/private";
     44 
     45     private static final String sInternalVolUuid = null; //StorageManager.UUID_PRIVATE_INTERNAL
     46     private static final String sAdoptedVolUuid = "adopted";
     47     private static final String sPublicVolUuid = "emulated";
     48     private static final String sPrivateUnmountedVolUuid = "private";
     49 
     50     private static final VolumeInfo sInternalVol = new VolumeInfo("private",
     51             VolumeInfo.TYPE_PRIVATE, null /*DiskInfo*/, null /*partGuid*/);
     52 
     53     private static final VolumeInfo sAdoptedVol = new VolumeInfo("adopted",
     54             VolumeInfo.TYPE_PRIVATE, null /*DiskInfo*/, null /*partGuid*/);
     55 
     56     private static final VolumeInfo sPublicVol = new VolumeInfo("public",
     57             VolumeInfo.TYPE_PUBLIC, null /*DiskInfo*/, null /*partGuid*/);
     58 
     59     private static final VolumeInfo sPrivateUnmountedVol = new VolumeInfo("private2",
     60             VolumeInfo.TYPE_PRIVATE, null /*DiskInfo*/, null /*partGuid*/);
     61 
     62     private static final List<VolumeInfo> sVolumes = new ArrayList<>();
     63 
     64     static {
     65         sInternalVol.path = sInternalVolPath;
     66         sInternalVol.state = STATE_MOUNTED;
     67         sInternalVol.fsUuid = sInternalVolUuid;
     68 
     69         sAdoptedVol.path = sAdoptedVolPath;
     70         sAdoptedVol.state = STATE_MOUNTED;
     71         sAdoptedVol.fsUuid = sAdoptedVolUuid;
     72 
     73         sPublicVol.state = STATE_MOUNTED;
     74         sPublicVol.path = sPublicVolPath;
     75         sPublicVol.fsUuid = sPublicVolUuid;
     76 
     77         sPrivateUnmountedVol.state = STATE_UNMOUNTED;
     78         sPrivateUnmountedVol.path = sPrivateUnmountedVolPath;
     79         sPrivateUnmountedVol.fsUuid = sPrivateUnmountedVolUuid;
     80 
     81         sVolumes.add(sInternalVol);
     82         sVolumes.add(sAdoptedVol);
     83         sVolumes.add(sPublicVol);
     84         sVolumes.add(sPrivateUnmountedVol);
     85     }
     86 
     87     private static final class MockedApplicationPackageManager extends ApplicationPackageManager {
     88         private boolean mForceAllowOnExternal = false;
     89         private boolean mAllow3rdPartyOnInternal = true;
     90 
     91         public MockedApplicationPackageManager() {
     92             super(null, null);
     93         }
     94 
     95         public void setForceAllowOnExternal(boolean forceAllowOnExternal) {
     96             mForceAllowOnExternal = forceAllowOnExternal;
     97         }
     98 
     99         public void setAllow3rdPartyOnInternal(boolean allow3rdPartyOnInternal) {
    100             mAllow3rdPartyOnInternal = allow3rdPartyOnInternal;
    101         }
    102 
    103         @Override
    104         public boolean isForceAllowOnExternal(Context context) {
    105             return mForceAllowOnExternal;
    106         }
    107 
    108         @Override
    109         public boolean isAllow3rdPartyOnInternal(Context context) {
    110             return mAllow3rdPartyOnInternal;
    111         }
    112     }
    113 
    114     private StorageManager getMockedStorageManager() {
    115         StorageManager storageManager = Mockito.mock(StorageManager.class);
    116         Mockito.when(storageManager.getVolumes()).thenReturn(sVolumes);
    117         Mockito.when(storageManager.findVolumeById(VolumeInfo.ID_PRIVATE_INTERNAL))
    118                 .thenReturn(sInternalVol);
    119         Mockito.when(storageManager.findVolumeByUuid(sAdoptedVolUuid))
    120                 .thenReturn(sAdoptedVol);
    121         Mockito.when(storageManager.findVolumeByUuid(sPublicVolUuid))
    122                 .thenReturn(sPublicVol);
    123         Mockito.when(storageManager.findVolumeByUuid(sPrivateUnmountedVolUuid))
    124                 .thenReturn(sPrivateUnmountedVol);
    125         return storageManager;
    126     }
    127 
    128     private void verifyReturnedVolumes(List<VolumeInfo> actualVols, VolumeInfo... exptectedVols) {
    129         boolean failed = false;
    130         if (actualVols.size() != exptectedVols.length) {
    131             failed = true;
    132         } else {
    133             for (VolumeInfo vol : exptectedVols) {
    134                 if (!actualVols.contains(vol)) {
    135                     failed = true;
    136                     break;
    137                 }
    138             }
    139         }
    140 
    141         if (failed) {
    142             fail("Wrong volumes returned.\n Expected: " + Arrays.toString(exptectedVols)
    143                     + "\n Actual: " + Arrays.toString(actualVols.toArray()));
    144         }
    145     }
    146 
    147     public void testGetCandidateVolumes_systemApp() throws Exception {
    148         ApplicationInfo sysAppInfo = new ApplicationInfo();
    149         sysAppInfo.flags = ApplicationInfo.FLAG_SYSTEM;
    150 
    151         StorageManager storageManager = getMockedStorageManager();
    152         IPackageManager pm = Mockito.mock(IPackageManager.class);
    153 
    154         MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
    155 
    156         appPkgMgr.setAllow3rdPartyOnInternal(true);
    157         appPkgMgr.setForceAllowOnExternal(true);
    158         List<VolumeInfo> candidates =
    159                 appPkgMgr.getPackageCandidateVolumes(sysAppInfo, storageManager, pm);
    160         verifyReturnedVolumes(candidates, sInternalVol);
    161 
    162         appPkgMgr.setAllow3rdPartyOnInternal(true);
    163         appPkgMgr.setForceAllowOnExternal(false);
    164         candidates = appPkgMgr.getPackageCandidateVolumes(sysAppInfo, storageManager, pm);
    165         verifyReturnedVolumes(candidates, sInternalVol);
    166 
    167         appPkgMgr.setAllow3rdPartyOnInternal(false);
    168         appPkgMgr.setForceAllowOnExternal(false);
    169         candidates = appPkgMgr.getPackageCandidateVolumes(sysAppInfo, storageManager, pm);
    170         verifyReturnedVolumes(candidates, sInternalVol);
    171 
    172         appPkgMgr.setAllow3rdPartyOnInternal(false);
    173         appPkgMgr.setForceAllowOnExternal(true);
    174         candidates = appPkgMgr.getPackageCandidateVolumes(sysAppInfo, storageManager, pm);
    175         verifyReturnedVolumes(candidates, sInternalVol);
    176     }
    177 
    178     public void testGetCandidateVolumes_3rdParty_internalOnly() throws Exception {
    179         ApplicationInfo appInfo = new ApplicationInfo();
    180         StorageManager storageManager = getMockedStorageManager();
    181 
    182         IPackageManager pm = Mockito.mock(IPackageManager.class);
    183         Mockito.when(pm.isPackageDeviceAdminOnAnyUser(Mockito.anyString())).thenReturn(false);
    184 
    185         MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
    186 
    187         // must allow 3rd party on internal, otherwise the app wouldn't have been installed before.
    188         appPkgMgr.setAllow3rdPartyOnInternal(true);
    189 
    190         // INSTALL_LOCATION_INTERNAL_ONLY AND INSTALL_LOCATION_UNSPECIFIED are treated the same.
    191         int[] locations = {PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY,
    192                 PackageInfo.INSTALL_LOCATION_UNSPECIFIED};
    193 
    194         for (int location : locations) {
    195             appInfo.installLocation = location;
    196             appPkgMgr.setForceAllowOnExternal(true);
    197             List<VolumeInfo> candidates = appPkgMgr.getPackageCandidateVolumes(
    198                     appInfo, storageManager, pm);
    199             verifyReturnedVolumes(candidates, sInternalVol, sAdoptedVol);
    200 
    201             appPkgMgr.setForceAllowOnExternal(false);
    202             candidates = appPkgMgr.getPackageCandidateVolumes(appInfo, storageManager, pm);
    203             verifyReturnedVolumes(candidates, sInternalVol);
    204         }
    205     }
    206 
    207     public void testGetCandidateVolumes_3rdParty_auto() throws Exception {
    208         ApplicationInfo appInfo = new ApplicationInfo();
    209         StorageManager storageManager = getMockedStorageManager();
    210 
    211         IPackageManager pm = Mockito.mock(IPackageManager.class);
    212 
    213         MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
    214         appPkgMgr.setForceAllowOnExternal(true);
    215 
    216         // INSTALL_LOCATION_AUTO AND INSTALL_LOCATION_PREFER_EXTERNAL are treated the same.
    217         int[] locations = {PackageInfo.INSTALL_LOCATION_AUTO,
    218                 PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL};
    219 
    220         for (int location : locations) {
    221             appInfo.installLocation = location;
    222             appInfo.flags = 0;
    223 
    224             appInfo.volumeUuid = sInternalVolUuid;
    225             Mockito.when(pm.isPackageDeviceAdminOnAnyUser(Mockito.anyString())).thenReturn(false);
    226             appPkgMgr.setAllow3rdPartyOnInternal(true);
    227             List<VolumeInfo> candidates = appPkgMgr.getPackageCandidateVolumes(
    228                     appInfo, storageManager, pm);
    229             verifyReturnedVolumes(candidates, sInternalVol, sAdoptedVol);
    230 
    231             appInfo.volumeUuid = sInternalVolUuid;
    232             appPkgMgr.setAllow3rdPartyOnInternal(true);
    233             Mockito.when(pm.isPackageDeviceAdminOnAnyUser(Mockito.anyString())).thenReturn(true);
    234             candidates = appPkgMgr.getPackageCandidateVolumes(appInfo, storageManager, pm);
    235             verifyReturnedVolumes(candidates, sInternalVol);
    236 
    237             appInfo.flags = ApplicationInfo.FLAG_EXTERNAL_STORAGE;
    238             appInfo.volumeUuid = sAdoptedVolUuid;
    239             appPkgMgr.setAllow3rdPartyOnInternal(false);
    240             candidates = appPkgMgr.getPackageCandidateVolumes(appInfo, storageManager, pm);
    241             verifyReturnedVolumes(candidates, sAdoptedVol);
    242         }
    243     }
    244 }
    245