Put externalSize measurements in PackageStats

When measuring a package's usage, put the external size in the
PackageStats as well. This will allow programs using a lot of space on
the external card to be held accountable.

Bug: 3308791
Change-Id: If2df07bdbf6ffb31577074fad8f4a87ca4e89086
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 1c3967d..19667d4 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -4806,6 +4806,74 @@
         abstract void handleReturnCode();
     }
 
+    class MeasureParams extends HandlerParams {
+        private final PackageStats mStats;
+        private boolean mSuccess;
+
+        private final IPackageStatsObserver mObserver;
+
+        public MeasureParams(PackageStats stats, boolean success,
+                IPackageStatsObserver observer) {
+            mObserver = observer;
+            mStats = stats;
+            mSuccess = success;
+        }
+
+        @Override
+        void handleStartCopy() throws RemoteException {
+            final boolean mounted;
+
+            if (Environment.isExternalStorageEmulated()) {
+                mounted = true;
+            } else {
+                final String status = Environment.getExternalStorageState();
+
+                mounted = status.equals(Environment.MEDIA_MOUNTED)
+                        || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
+            }
+
+            if (mounted) {
+                final File externalCacheDir = Environment
+                        .getExternalStorageAppCacheDirectory(mStats.packageName);
+                final long externalCacheSize = mContainerService
+                        .calculateDirectorySize(externalCacheDir.getPath());
+                mStats.externalCacheSize = externalCacheSize;
+
+                final File externalDataDir = Environment
+                        .getExternalStorageAppDataDirectory(mStats.packageName);
+                long externalDataSize = mContainerService.calculateDirectorySize(externalDataDir
+                        .getPath());
+
+                if (externalCacheDir.getParentFile().equals(externalDataDir)) {
+                    externalDataSize -= externalCacheSize;
+                }
+                mStats.externalDataSize = externalDataSize;
+
+                final File externalMediaDir = Environment
+                        .getExternalStorageAppMediaDirectory(mStats.packageName);
+                mStats.externalMediaSize = mContainerService
+                        .calculateDirectorySize(externalCacheDir.getPath());
+            }
+        }
+
+        @Override
+        void handleReturnCode() {
+            if (mObserver != null) {
+                try {
+                    mObserver.onGetStatsCompleted(mStats, mSuccess);
+                } catch (RemoteException e) {
+                    Slog.i(TAG, "Observer no longer exists.");
+                }
+            }
+        }
+
+        @Override
+        void handleServiceError() {
+            Slog.e(TAG, "Could not measure application " + mStats.packageName
+                            + " external storage");
+        }
+    }
+
     class InstallParams extends HandlerParams {
         final IPackageInstallObserver observer;
         int flags;
@@ -6619,18 +6687,16 @@
         mHandler.post(new Runnable() {
             public void run() {
                 mHandler.removeCallbacks(this);
-                PackageStats lStats = new PackageStats(packageName);
-                final boolean succeded;
+                PackageStats stats = new PackageStats(packageName);
+
+                final boolean success;
                 synchronized (mInstallLock) {
-                    succeded = getPackageSizeInfoLI(packageName, lStats);
+                    success = getPackageSizeInfoLI(packageName, stats);
                 }
-                if(observer != null) {
-                    try {
-                        observer.onGetStatsCompleted(lStats, succeded);
-                    } catch (RemoteException e) {
-                        Log.i(TAG, "Observer no longer exists.");
-                    }
-                } //end if observer
+
+                Message msg = mHandler.obtainMessage(INIT_COPY);
+                msg.obj = new MeasureParams(stats, success, observer);
+                mHandler.sendMessage(msg);
             } //end run
         });
     }