Plumb information from the framework about asec container size.

Change-Id: Ie0ec3cb6d463aefa341a8cbea80be790451ba5e3
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index d3244ec..54e5432 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -1626,6 +1626,30 @@
         }
     }
 
+    public String getSecureContainerFilesystemPath(String id) {
+        validatePermission(android.Manifest.permission.ASEC_ACCESS);
+        waitForReady();
+        warnOnNotMounted();
+
+        try {
+            ArrayList<String> rsp = mConnector.doCommand(String.format("asec fspath %s", id));
+            String []tok = rsp.get(0).split(" ");
+            int code = Integer.parseInt(tok[0]);
+            if (code != VoldResponseCode.AsecPathResult) {
+                throw new IllegalStateException(String.format("Unexpected response code %d", code));
+            }
+            return tok[1];
+        } catch (NativeDaemonConnectorException e) {
+            int code = e.getCode();
+            if (code == VoldResponseCode.OpFailedStorageNotFound) {
+                Slog.i(TAG, String.format("Container '%s' not found", id));
+                return null;
+            } else {
+                throw new IllegalStateException(String.format("Unexpected response code %d", code));
+            }
+        }
+    }
+
     public void finishMediaUpdate() {
         mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE);
     }
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index d10aa97..11ccd60 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -307,7 +307,7 @@
     }
 
     public int getSizeInfo(String pkgName, String apkPath, String fwdLockApkPath,
-            PackageStats pStats) {
+            String asecPath, PackageStats pStats) {
         StringBuilder builder = new StringBuilder("getsize");
         builder.append(' ');
         builder.append(pkgName);
@@ -315,17 +315,20 @@
         builder.append(apkPath);
         builder.append(' ');
         builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
+        builder.append(' ');
+        builder.append(asecPath != null ? asecPath : "!");
 
         String s = transaction(builder.toString());
         String res[] = s.split(" ");
 
-        if ((res == null) || (res.length != 4)) {
+        if ((res == null) || (res.length != 5)) {
             return -1;
         }
         try {
             pStats.codeSize = Long.parseLong(res[1]);
             pStats.dataSize = Long.parseLong(res[2]);
             pStats.cacheSize = Long.parseLong(res[3]);
+            pStats.externalCodeSize = Long.parseLong(res[4]);
             return Integer.parseInt(res[0]);
         } catch (NumberFormatException e) {
             return -1;
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 5a9dae9..22e2dde 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -75,6 +75,7 @@
 import android.os.Environment;
 import android.os.FileObserver;
 import android.os.FileUtils;
+import android.os.FileUtils.FileStatus;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -4887,8 +4888,7 @@
 
         private final IPackageStatsObserver mObserver;
 
-        public MeasureParams(PackageStats stats, boolean success,
-                IPackageStatsObserver observer) {
+        public MeasureParams(PackageStats stats, boolean success, IPackageStatsObserver observer) {
             mObserver = observer;
             mStats = stats;
             mSuccess = success;
@@ -5480,6 +5480,17 @@
         }
     }
 
+    /**
+     * Extract the MountService "container ID" from the full code path of an
+     * .apk.
+     */
+    static String cidFromCodePath(String fullCodePath) {
+        int eidx = fullCodePath.lastIndexOf("/");
+        String subStr1 = fullCodePath.substring(0, eidx);
+        int sidx = subStr1.lastIndexOf("/");
+        return subStr1.substring(sidx+1, eidx);
+    }
+
     class SdInstallArgs extends InstallArgs {
         static final String RES_FILE_NAME = "pkg.apk";
 
@@ -6831,6 +6842,7 @@
         }
         PackageParser.Package p;
         boolean dataOnly = false;
+        String asecPath = null;
         synchronized (mPackages) {
             p = mPackages.get(packageName);
             if(p == null) {
@@ -6842,6 +6854,12 @@
                 }
                 p = ps.pkg;
             }
+            if (p != null && isExternal(p)) {
+                String secureContainerId = cidFromCodePath(p.applicationInfo.sourceDir);
+                if (secureContainerId != null) {
+                    asecPath = PackageHelper.getSdFilesystem(secureContainerId);
+                }
+            }
         }
         String publicSrcDir = null;
         if(!dataOnly) {
@@ -6850,10 +6868,13 @@
                 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
                 return false;
             }
-            publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
+            if (isForwardLocked(p)) {
+                publicSrcDir = applicationInfo.publicSourceDir;
+            }
         }
         if (mInstaller != null) {
-            int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir, pStats);
+            int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir,
+                    asecPath, pStats);
             if (res < 0) {
                 return false;
             } else {