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