diff options
3 files changed, 160 insertions, 37 deletions
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 605fa5d8d0c3..98249dd12634 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -199,16 +199,44 @@ public class Installer extends SystemService { } } - public void getAppSize(String uuid, String packageName, int userId, int flags, int appId, - long ceDataInode, String codePath, String externalUuid, PackageStats stats) + public void getAppSize(String uuid, String[] packageNames, int userId, int flags, int appId, + long[] ceDataInodes, String[] codePaths, PackageStats stats) throws InstallerException { if (!checkBeforeRemote()) return; try { - final long[] res = mInstalld.getAppSize(uuid, packageName, userId, flags, appId, - ceDataInode, codePath, externalUuid); + final long[] res = mInstalld.getAppSize(uuid, packageNames, userId, flags, + appId, ceDataInodes, codePaths); stats.codeSize += res[0]; stats.dataSize += res[1]; stats.cacheSize += res[2]; + stats.externalCodeSize += res[3]; + stats.externalDataSize += res[4]; + stats.externalCacheSize += res[5]; + } catch (Exception e) { + throw InstallerException.from(e); + } + } + + public void getUserSize(String uuid, int userId, int flags, int[] appIds, PackageStats stats) + throws InstallerException { + if (!checkBeforeRemote()) return; + try { + final long[] res = mInstalld.getUserSize(uuid, userId, flags, appIds); + stats.codeSize += res[0]; + stats.dataSize += res[1]; + stats.cacheSize += res[2]; + stats.externalCodeSize += res[3]; + stats.externalDataSize += res[4]; + stats.externalCacheSize += res[5]; + } catch (Exception e) { + throw InstallerException.from(e); + } + } + + public long[] getExternalSize(String uuid, int userId, int flags) throws InstallerException { + if (!checkBeforeRemote()) return new long[4]; + try { + return mInstalld.getExternalSize(uuid, userId, flags); } catch (Exception e) { throw InstallerException.from(e); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 37cca4492401..b9f1ab83714d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -16904,11 +16904,6 @@ public class PackageManagerService extends IPackageManager.Stub { mHandler.sendMessage(msg); } - private boolean equals(PackageStats a, PackageStats b) { - return (a.codeSize == b.codeSize) && (a.dataSize == b.dataSize) - && (a.cacheSize == b.cacheSize); - } - private boolean getPackageSizeInfoLI(String packageName, int userId, PackageStats stats) { final PackageSetting ps; synchronized (mPackages) { @@ -16919,44 +16914,21 @@ public class PackageManagerService extends IPackageManager.Stub { } } - final long ceDataInode = ps.getCeDataInode(userId); - final PackageStats quotaStats = new PackageStats(stats.packageName, stats.userHandle); + final String[] packageNames = { packageName }; + final long[] ceDataInodes = { ps.getCeDataInode(userId) }; + final String[] codePaths = { ps.codePathString }; - final StorageManager storage = mContext.getSystemService(StorageManager.class); - final String externalUuid = storage.getPrimaryStorageUuid(); try { - final long start = SystemClock.elapsedRealtimeNanos(); - mInstaller.getAppSize(ps.volumeUuid, packageName, userId, 0, - ps.appId, ceDataInode, ps.codePathString, externalUuid, stats); - final long stopManual = SystemClock.elapsedRealtimeNanos(); - if (ENABLE_QUOTA) { - mInstaller.getAppSize(ps.volumeUuid, packageName, userId, Installer.FLAG_USE_QUOTA, - ps.appId, ceDataInode, ps.codePathString, externalUuid, quotaStats); - } - final long stopQuota = SystemClock.elapsedRealtimeNanos(); + mInstaller.getAppSize(ps.volumeUuid, packageNames, userId, 0, + ps.appId, ceDataInodes, codePaths, stats); // For now, ignore code size of packages on system partition if (isSystemApp(ps) && !isUpdatedSystemApp(ps)) { stats.codeSize = 0; - quotaStats.codeSize = 0; - } - - if (ENABLE_QUOTA && Build.IS_ENG && !ps.isSharedUser()) { - if (!equals(stats, quotaStats)) { - Log.w(TAG, "Found discrepancy between statistics:"); - Log.w(TAG, "Manual: " + stats); - Log.w(TAG, "Quota: " + quotaStats); - } - final long manualTime = stopManual - start; - final long quotaTime = stopQuota - stopManual; - EventLogTags.writePmPackageStats(manualTime, quotaTime, - stats.dataSize, quotaStats.dataSize, - stats.cacheSize, quotaStats.cacheSize); } // External clients expect these to be tracked separately stats.dataSize -= stats.cacheSize; - quotaStats.dataSize -= quotaStats.cacheSize; } catch (InstallerException e) { Slog.w(TAG, String.valueOf(e)); diff --git a/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java new file mode 100644 index 000000000000..2a7cbc21137a --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageStats; +import android.os.UserHandle; +import android.test.AndroidTestCase; +import android.util.Log; + +import com.android.internal.util.ArrayUtils; + +import java.util.Arrays; + +public class InstallerTest extends AndroidTestCase { + private static final String TAG = "InstallerTest"; + + private Installer mInstaller; + + @Override + public void setUp() throws Exception { + mInstaller = new Installer(getContext()); + mInstaller.onStart(); + } + + @Override + public void tearDown() throws Exception { + mInstaller = null; + } + + public void testGetAppSize() throws Exception { + final PackageManager pm = getContext().getPackageManager(); + for (ApplicationInfo app : pm.getInstalledApplications(0)) { + final int userId = UserHandle.getUserId(app.uid); + final int appId = UserHandle.getAppId(app.uid); + + final String[] packageNames = pm.getPackagesForUid(app.uid); + final long[] ceDataInodes = new long[packageNames.length]; + final String[] codePaths = new String[packageNames.length]; + + for (int i = 0; i < packageNames.length; i++) { + final ApplicationInfo info = pm.getApplicationInfo(packageNames[i], 0); + codePaths[i] = info.getCodePath(); + } + + final PackageStats stats = new PackageStats(app.packageName); + final PackageStats quotaStats = new PackageStats(app.packageName); + + mInstaller.getAppSize(app.volumeUuid, packageNames, userId, 0, + appId, ceDataInodes, codePaths, stats); + + mInstaller.getAppSize(app.volumeUuid, packageNames, userId, Installer.FLAG_USE_QUOTA, + appId, ceDataInodes, codePaths, quotaStats); + + checkEquals(Arrays.toString(packageNames) + " UID=" + app.uid, stats, quotaStats); + } + } + + public void testGetUserSize() throws Exception { + int[] appIds = null; + + final PackageManager pm = getContext().getPackageManager(); + for (ApplicationInfo app : pm.getInstalledApplications(0)) { + final int appId = UserHandle.getAppId(app.uid); + if (!ArrayUtils.contains(appIds, appId)) { + appIds = ArrayUtils.appendInt(appIds, appId); + } + } + + final PackageStats stats = new PackageStats("android"); + final PackageStats quotaStats = new PackageStats("android"); + + mInstaller.getUserSize(null, UserHandle.USER_SYSTEM, 0, + appIds, stats); + + mInstaller.getUserSize(null, UserHandle.USER_SYSTEM, Installer.FLAG_USE_QUOTA, + appIds, quotaStats); + + checkEquals(Arrays.toString(appIds), stats, quotaStats); + } + + public void testGetExternalSize() throws Exception { + + final long[] stats = mInstaller.getExternalSize(null, UserHandle.USER_SYSTEM, 0); + + final long[] quotaStats = mInstaller.getExternalSize(null, UserHandle.USER_SYSTEM, + Installer.FLAG_USE_QUOTA); + + for (int i = 0; i < stats.length; i++) { + checkEquals("#" + i, stats[i], quotaStats[i]); + } + } + + private static void checkEquals(String msg, PackageStats a, PackageStats b) { + checkEquals(msg + " codeSize", a.codeSize, b.codeSize); + checkEquals(msg + " dataSize", a.dataSize, b.dataSize); + checkEquals(msg + " cacheSize", a.cacheSize, b.cacheSize); + checkEquals(msg + " externalCodeSize", a.externalCodeSize, b.externalCodeSize); + checkEquals(msg + " externalDataSize", a.externalDataSize, b.externalDataSize); + checkEquals(msg + " externalCacheSize", a.externalCacheSize, b.externalCacheSize); + } + + private static void checkEquals(String msg, long expected, long actual) { + if (expected != actual) { + Log.e(TAG, msg + " expected " + expected + " actual " + actual); + } + } +} |