Home | History | Annotate | Download | only in pm
      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 com.android.server.pm;
     18 
     19 import android.content.Context;
     20 import android.content.pm.ApplicationInfo;
     21 import android.content.pm.PackageManager;
     22 import android.content.pm.PackageStats;
     23 import android.os.SystemClock;
     24 import android.os.UserHandle;
     25 import android.support.test.InstrumentationRegistry;
     26 import android.support.test.runner.AndroidJUnit4;
     27 import android.util.Log;
     28 
     29 import com.android.internal.util.ArrayUtils;
     30 
     31 import org.junit.After;
     32 import org.junit.Before;
     33 import org.junit.Ignore;
     34 import org.junit.Test;
     35 import org.junit.runner.RunWith;
     36 
     37 import java.util.Arrays;
     38 
     39 @RunWith(AndroidJUnit4.class)
     40 public class InstallerTest {
     41     private static final String TAG = "InstallerTest";
     42 
     43     private Installer mInstaller;
     44 
     45     private final Timer mManual = new Timer("Manual");
     46     private final Timer mQuota = new Timer("Quota");
     47 
     48     private static class Timer {
     49         private final String mTitle;
     50         private long mStart;
     51         private long mTotal;
     52 
     53         public Timer(String title) {
     54             mTitle = title;
     55         }
     56 
     57         public void start() {
     58             mStart = SystemClock.currentTimeMicro();
     59         }
     60 
     61         public void stop() {
     62             mTotal += SystemClock.currentTimeMicro() - mStart;
     63         }
     64 
     65         public void reset() {
     66             mStart = 0;
     67             mTotal = 0;
     68         }
     69 
     70         @Override
     71         public String toString() {
     72             return mTitle + ": " + (mTotal / 1000) + "ms";
     73         }
     74     }
     75 
     76     @Before
     77     public void setUp() throws Exception {
     78         mInstaller = new Installer(getContext());
     79         mInstaller.onStart();
     80         mManual.reset();
     81         mQuota.reset();
     82     }
     83 
     84     @After
     85     public void tearDown() throws Exception {
     86         Log.i(TAG, mManual.toString());
     87         Log.i(TAG, mQuota.toString());
     88         mInstaller = null;
     89     }
     90 
     91     @Test
     92     @Ignore("b/68819006")
     93     public void testGetAppSize() throws Exception {
     94         int[] appIds = null;
     95 
     96         final PackageManager pm = getContext().getPackageManager();
     97         for (ApplicationInfo app : pm.getInstalledApplications(0)) {
     98             final int userId = UserHandle.getUserId(app.uid);
     99             final int appId = UserHandle.getAppId(app.uid);
    100 
    101             if (ArrayUtils.contains(appIds, appId)) {
    102                 continue;
    103             } else {
    104                 appIds = ArrayUtils.appendInt(appIds, appId);
    105             }
    106 
    107             final String[] packageNames = pm.getPackagesForUid(app.uid);
    108             final long[] ceDataInodes = new long[packageNames.length];
    109             final String[] codePaths = new String[packageNames.length];
    110 
    111             for (int i = 0; i < packageNames.length; i++) {
    112                 final ApplicationInfo info = pm.getApplicationInfo(packageNames[i], 0);
    113                 codePaths[i] = info.getCodePath();
    114             }
    115 
    116             final PackageStats stats = new PackageStats(app.packageName);
    117             final PackageStats quotaStats = new PackageStats(app.packageName);
    118 
    119             mManual.start();
    120             mInstaller.getAppSize(app.volumeUuid, packageNames, userId, 0,
    121                     appId, ceDataInodes, codePaths, stats);
    122             mManual.stop();
    123 
    124             mQuota.start();
    125             mInstaller.getAppSize(app.volumeUuid, packageNames, userId, Installer.FLAG_USE_QUOTA,
    126                     appId, ceDataInodes, codePaths, quotaStats);
    127             mQuota.stop();
    128 
    129             checkEquals(Arrays.toString(packageNames) + " UID=" + app.uid, stats, quotaStats);
    130         }
    131     }
    132 
    133     @Test
    134     @Ignore("b/68819006")
    135     public void testGetUserSize() throws Exception {
    136         final int[] appIds = getAppIds(UserHandle.USER_SYSTEM);
    137 
    138         final PackageStats stats = new PackageStats("android");
    139         final PackageStats quotaStats = new PackageStats("android");
    140 
    141         mManual.start();
    142         mInstaller.getUserSize(null, UserHandle.USER_SYSTEM, 0,
    143                 appIds, stats);
    144         mManual.stop();
    145 
    146         mQuota.start();
    147         mInstaller.getUserSize(null, UserHandle.USER_SYSTEM, Installer.FLAG_USE_QUOTA,
    148                 appIds, quotaStats);
    149         mQuota.stop();
    150 
    151         checkEquals(Arrays.toString(appIds), stats, quotaStats);
    152     }
    153 
    154     @Test
    155     @Ignore("b/68819006")
    156     public void testGetExternalSize() throws Exception {
    157         final int[] appIds = getAppIds(UserHandle.USER_SYSTEM);
    158 
    159         mManual.start();
    160         final long[] stats = mInstaller.getExternalSize(null, UserHandle.USER_SYSTEM, 0, appIds);
    161         mManual.stop();
    162 
    163         mQuota.start();
    164         final long[] quotaStats = mInstaller.getExternalSize(null, UserHandle.USER_SYSTEM,
    165                 Installer.FLAG_USE_QUOTA, appIds);
    166         mQuota.stop();
    167 
    168         for (int i = 0; i < stats.length; i++) {
    169             checkEquals("#" + i, stats[i], quotaStats[i]);
    170         }
    171     }
    172 
    173     private int[] getAppIds(int userId) {
    174         int[] appIds = null;
    175         for (ApplicationInfo app : getContext().getPackageManager().getInstalledApplicationsAsUser(
    176                 PackageManager.MATCH_UNINSTALLED_PACKAGES, userId)) {
    177             final int appId = UserHandle.getAppId(app.uid);
    178             if (!ArrayUtils.contains(appIds, appId)) {
    179                 appIds = ArrayUtils.appendInt(appIds, appId);
    180             }
    181         }
    182         return appIds;
    183     }
    184 
    185     private static Context getContext() {
    186         return InstrumentationRegistry.getContext();
    187     }
    188 
    189     private static void checkEquals(String msg, PackageStats a, PackageStats b) {
    190         checkEquals(msg + " codeSize", a.codeSize, b.codeSize);
    191         checkEquals(msg + " dataSize", a.dataSize, b.dataSize);
    192         checkEquals(msg + " cacheSize", a.cacheSize, b.cacheSize);
    193         checkEquals(msg + " externalCodeSize", a.externalCodeSize, b.externalCodeSize);
    194         checkEquals(msg + " externalDataSize", a.externalDataSize, b.externalDataSize);
    195         checkEquals(msg + " externalCacheSize", a.externalCacheSize, b.externalCacheSize);
    196     }
    197 
    198     private static void checkEquals(String msg, long expected, long actual) {
    199         if (expected != actual) {
    200             Log.e(TAG, msg + " expected " + expected + " actual " + actual);
    201         }
    202     }
    203 }
    204