Home | History | Annotate | Download | only in storage
      1 /*
      2  * Copyright (C) 2016 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 com.android.server.storage;
     18 
     19 import android.app.usage.StorageStats;
     20 import android.app.usage.StorageStatsManager;
     21 import android.content.pm.UserInfo;
     22 import android.content.Context;
     23 import android.content.pm.ApplicationInfo;
     24 import android.content.pm.IPackageStatsObserver;
     25 import android.content.pm.PackageManager;
     26 import android.content.pm.PackageStats;
     27 import android.os.UserHandle;
     28 import android.os.UserManager;
     29 import android.os.storage.VolumeInfo;
     30 import android.test.AndroidTestCase;
     31 import android.util.ArrayMap;
     32 import android.util.Log;
     33 
     34 import org.junit.Before;
     35 import org.junit.Test;
     36 import org.junit.runner.RunWith;
     37 import org.junit.runners.JUnit4;
     38 import org.mockito.Mock;
     39 import org.mockito.Mockito;
     40 import org.mockito.MockitoAnnotations;
     41 import org.mockito.invocation.InvocationOnMock;
     42 import org.mockito.stubbing.Answer;
     43 
     44 import java.util.ArrayList;
     45 import java.util.List;
     46 import java.util.Map;
     47 import java.util.concurrent.CountDownLatch;
     48 import java.util.concurrent.TimeUnit;
     49 
     50 import static com.google.common.truth.Truth.assertThat;
     51 import static org.mockito.Matchers.any;
     52 import static org.mockito.Matchers.anyInt;
     53 import static org.mockito.Matchers.anyString;
     54 import static org.mockito.Matchers.eq;
     55 import static org.mockito.Mockito.doAnswer;
     56 import static org.mockito.Mockito.when;
     57 
     58 @RunWith(JUnit4.class)
     59 public class AppCollectorTest extends AndroidTestCase {
     60     private static final long TIMEOUT = TimeUnit.MINUTES.toMillis(1);
     61     @Mock private Context mContext;
     62     @Mock private PackageManager mPm;
     63     @Mock private UserManager mUm;
     64     @Mock private StorageStatsManager mSsm;
     65     private List<UserInfo> mUsers;
     66     private Map<Integer, List<ApplicationInfo>> mUserApps;
     67 
     68     @Before
     69     public void setUp() throws Exception {
     70         super.setUp();
     71         MockitoAnnotations.initMocks(this);
     72         when(mContext.getPackageManager()).thenReturn(mPm);
     73         when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUm);
     74         when(mContext.getSystemService(Context.STORAGE_STATS_SERVICE)).thenReturn(mSsm);
     75 
     76         // Set up the app list.
     77         doAnswer((InvocationOnMock invocation) -> {
     78             Integer userId = (Integer) invocation.getArguments()[1];
     79             return mUserApps.get(userId);
     80         }).when(mPm).getInstalledApplicationsAsUser(anyInt(), anyInt());
     81 
     82         // Set up the user list with a single user (0).
     83         mUsers = new ArrayList<>();
     84         mUsers.add(new UserInfo(0, "", 0));
     85 
     86         mUserApps = new ArrayMap<>();
     87         mUserApps.put(0, new ArrayList<>());
     88         when(mUm.getUsers()).thenReturn(mUsers);
     89     }
     90 
     91     @Test
     92     public void testNoApps() throws Exception {
     93         VolumeInfo volume = new VolumeInfo("testuuid", 0, null, null);
     94         volume.fsUuid = "testuuid";
     95         AppCollector collector = new AppCollector(mContext, volume);
     96 
     97         assertThat(collector.getPackageStats(TIMEOUT)).isEmpty();
     98     }
     99 
    100     @Test
    101     public void testAppOnExternalVolume() throws Exception {
    102         addApplication("com.test.app", "differentuuid", 0);
    103         VolumeInfo volume = new VolumeInfo("testuuid", 0, null, null);
    104         volume.fsUuid = "testuuid";
    105         AppCollector collector = new AppCollector(mContext, volume);
    106 
    107         assertThat(collector.getPackageStats(TIMEOUT)).isEmpty();
    108     }
    109 
    110     @Test
    111     public void testOneValidApp() throws Exception {
    112         addApplication("com.test.app", "testuuid", 0);
    113         VolumeInfo volume = new VolumeInfo("testuuid", 0, null, null);
    114         volume.fsUuid = "testuuid";
    115         AppCollector collector = new AppCollector(mContext, volume);
    116         PackageStats stats = new PackageStats("com.test.app");
    117 
    118         when(mSsm.queryStatsForPackage(eq("testuuid"),
    119                 eq("com.test.app"), eq(UserHandle.of(0)))).thenReturn(new StorageStats());
    120         assertThat(collector.getPackageStats(TIMEOUT)).containsExactly(stats);
    121     }
    122 
    123     @Test
    124     public void testMultipleUsersOneApp() throws Exception {
    125         addApplication("com.test.app", "testuuid", 0);
    126         mUserApps.put(1, new ArrayList<>());
    127         addApplication("com.test.app", "testuuid", 1);
    128         mUsers.add(new UserInfo(1, "", 0));
    129 
    130         VolumeInfo volume = new VolumeInfo("testuuid", 0, null, null);
    131         volume.fsUuid = "testuuid";
    132         AppCollector collector = new AppCollector(mContext, volume);
    133         PackageStats stats = new PackageStats("com.test.app");
    134         PackageStats otherStats = new PackageStats("com.test.app");
    135         otherStats.userHandle = 1;
    136 
    137         when(mSsm.queryStatsForPackage(eq("testuuid"),
    138                 eq("com.test.app"), eq(UserHandle.of(0)))).thenReturn(new StorageStats());
    139         when(mSsm.queryStatsForPackage(eq("testuuid"),
    140                 eq("com.test.app"), eq(UserHandle.of(1)))).thenReturn(new StorageStats());
    141         assertThat(collector.getPackageStats(TIMEOUT)).containsExactly(stats, otherStats);
    142     }
    143 
    144     @Test(expected=NullPointerException.class)
    145     public void testNullVolumeShouldCauseNPE() throws Exception {
    146         AppCollector collector = new AppCollector(mContext, null);
    147     }
    148 
    149     @Test
    150     public void testAppNotFoundDoesntCauseCrash() throws Exception {
    151         VolumeInfo volume = new VolumeInfo("testuuid", 0, null, null);
    152         addApplication("com.test.app", "uuid", 0);
    153         mUsers.add(new UserInfo(1, "", 0));
    154         mUserApps.put(1, new ArrayList<>());
    155         AppCollector collector = new AppCollector(mContext, volume);
    156         when(mSsm.queryStatsForPackage(anyString(), anyString(), any(UserHandle.class))).thenThrow(
    157                 new IllegalStateException());
    158 
    159         assertThat(collector.getPackageStats(TIMEOUT)).isEmpty();
    160     }
    161 
    162     private void addApplication(String packageName, String uuid, int userId) {
    163         ApplicationInfo info = new ApplicationInfo();
    164         info.packageName = packageName;
    165         info.volumeUuid = uuid;
    166         List<ApplicationInfo> userApps = mUserApps.get(userId);
    167         if (userApps == null) {
    168             userApps = new ArrayList<>();
    169             mUserApps.put(userId, userApps);
    170         }
    171         userApps.add(info);
    172     }
    173 }
    174