Loading services/core/java/com/android/server/pm/Installer.java +32 −4 Original line number Diff line number Diff line Loading @@ -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); } Loading services/core/java/com/android/server/pm/PackageManagerService.java +5 −33 Original line number Diff line number Diff line Loading @@ -16872,11 +16872,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) { Loading @@ -16887,44 +16882,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)); services/tests/servicestests/src/com/android/server/pm/InstallerTest.java 0 → 100644 +123 −0 Original line number Diff line number Diff line /* * 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); } } } Loading
services/core/java/com/android/server/pm/Installer.java +32 −4 Original line number Diff line number Diff line Loading @@ -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); } Loading
services/core/java/com/android/server/pm/PackageManagerService.java +5 −33 Original line number Diff line number Diff line Loading @@ -16872,11 +16872,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) { Loading @@ -16887,44 +16882,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));
services/tests/servicestests/src/com/android/server/pm/InstallerTest.java 0 → 100644 +123 −0 Original line number Diff line number Diff line /* * 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); } } }