Add the {get,set}PackageObbPaths calls to API

Add getPackageObbPaths() and setPackageObbPaths() to the public API.

Bug: 3214719
Change-Id: I8627b5f674a795d5780eb5c08911419110670a41
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 26060e6..1837166 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -4646,16 +4646,52 @@
         }
     }
 
-    public void setPackageObbPath(String packageName, String path) {
+    public void setPackageObbPaths(String packageName, String[] paths) {
         if (DEBUG_OBB)
-            Log.v(TAG, "Setting .obb path for " + packageName + " to: " + path);
-        PackageSetting pkgSetting;
+            Log.v(TAG, "Setting .obb paths for " + packageName + " to: " + Arrays.toString(paths));
+        final int uid = Binder.getCallingUid();
+        final int permission = mContext.checkCallingPermission(
+                android.Manifest.permission.INSTALL_PACKAGES);
+        final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
+        if (!allowedByPermission) {
+            throw new SecurityException("Permission denial: attempt to set .obb file from pid="
+                    + Binder.getCallingPid());
+        }
+        synchronized (mPackages) {
+            final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
+            if (pkgSetting == null) {
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
+
+            if (paths != null) {
+                if (paths.length == 0) {
+                    // Don't bother storing an empty array.
+                    paths = null;
+                } else {
+                    // Don't allow the caller to manipulate our copy of the
+                    // list.
+                    paths = paths.clone();
+                }
+            }
+
+            // Only write settings file if the new and old settings are not the
+            // same.
+            if (!Arrays.equals(paths, pkgSetting.obbPathStrings)) {
+                pkgSetting.obbPathStrings = paths;
+                mSettings.writeLP();
+            }
+        }
+    }
+
+    public String[] getPackageObbPaths(String packageName) {
+        if (DEBUG_OBB)
+            Log.v(TAG, "Getting .obb paths for " + packageName);
         final int uid = Binder.getCallingUid();
         final int permission = mContext.checkCallingPermission(
                 android.Manifest.permission.INSTALL_PACKAGES);
         final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
         synchronized (mPackages) {
-            pkgSetting = mSettings.mPackages.get(packageName);
+            final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
             if (pkgSetting == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
@@ -4664,8 +4700,7 @@
                         + Binder.getCallingPid() + ", uid=" + uid + ", package uid="
                         + pkgSetting.userId);
             }
-            pkgSetting.obbPathString = path;
-            mSettings.writeLP();
+            return pkgSetting.obbPathStrings;
         }
     }
 
@@ -7238,7 +7273,7 @@
                     pw.print("    codePath="); pw.println(ps.codePathString);
                     pw.print("    resourcePath="); pw.println(ps.resourcePathString);
                     pw.print("    nativeLibraryPath="); pw.println(ps.nativeLibraryPathString);
-                    pw.print("    obbPath="); pw.println(ps.obbPathString);
+                    pw.print("    obbPaths="); pw.println(Arrays.toString(ps.obbPathStrings));
                     pw.print("    versionCode="); pw.println(ps.versionCode);
                     if (ps.pkg != null) {
                         pw.print("    versionName="); pw.println(ps.pkg.mVersionName);
@@ -7818,7 +7853,7 @@
         File resourcePath;
         String resourcePathString;
         String nativeLibraryPathString;
-        String obbPathString;
+        String[] obbPathStrings;
         long timeStamp;
         long firstInstallTime;
         long lastUpdateTime;
@@ -7864,7 +7899,11 @@
             resourcePath = base.resourcePath;
             resourcePathString = base.resourcePathString;
             nativeLibraryPathString = base.nativeLibraryPathString;
-            obbPathString = base.obbPathString;
+
+            if (base.obbPathStrings != null) {
+                obbPathStrings = base.obbPathStrings.clone();
+            }
+
             timeStamp = base.timeStamp;
             firstInstallTime = base.firstInstallTime;
             lastUpdateTime = base.lastUpdateTime;
@@ -8923,8 +8962,15 @@
             if (pkg.installerPackageName != null) {
                 serializer.attribute(null, "installer", pkg.installerPackageName);
             }
-            if (pkg.obbPathString != null) {
-                serializer.attribute(null, "obbPath", pkg.obbPathString);
+            if (pkg.obbPathStrings != null && pkg.obbPathStrings.length > 0) {
+                int N = pkg.obbPathStrings.length;
+                serializer.startTag(null, "obbs");
+                for (int i = 0; i < N; i++) {
+                    serializer.startTag(null, "obb");
+                    serializer.attribute(null, "path", pkg.obbPathStrings[i]);
+                    serializer.endTag(null, "obb");
+                }
+                serializer.endTag(null, "obbs");
             }
             pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
             if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
@@ -9328,7 +9374,6 @@
             String codePathStr = null;
             String resourcePathStr = null;
             String nativeLibraryPathStr = null;
-            String obbPathStr = null;
             String systemStr = null;
             String installerPackageName = null;
             String uidError = null;
@@ -9348,7 +9393,6 @@
                 codePathStr = parser.getAttributeValue(null, "codePath");
                 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
                 nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
-                obbPathStr = parser.getAttributeValue(null, "obbPath");
                 version = parser.getAttributeValue(null, "version");
                 if (version != null) {
                     try {
@@ -9473,7 +9517,6 @@
                 packageSetting.uidError = "true".equals(uidError);
                 packageSetting.installerPackageName = installerPackageName;
                 packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
-                packageSetting.obbPathString = obbPathStr;
                 final String enabledStr = parser.getAttributeValue(null, "enabled");
                 if (enabledStr != null) {
                     if (enabledStr.equalsIgnoreCase("true")) {
@@ -9521,6 +9564,8 @@
                         readGrantedPermissionsLP(parser,
                                 packageSetting.grantedPermissions);
                         packageSetting.permissionsFixed = true;
+                    } else if (tagName.equals("obbs")) {
+                        readObbPathsLP(packageSetting, parser);
                     } else {
                         reportSettingsProblem(Log.WARN,
                                 "Unknown element under <package>: "
@@ -9725,6 +9770,34 @@
             }
         }
 
+        private void readObbPathsLP(PackageSettingBase packageSetting, XmlPullParser parser)
+                throws XmlPullParserException, IOException {
+            final List<String> obbPaths = new ArrayList<String>();
+            final int outerDepth = parser.getDepth();
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                    continue;
+                }
+
+                final String tagName = parser.getName();
+                if (tagName.equals("obb")) {
+                    final String path = parser.getAttributeValue(null, "path");
+                    obbPaths.add(path);
+                } else {
+                    reportSettingsProblem(Log.WARN, "Unknown element under <obbs>: "
+                            + parser.getName());
+                }
+                XmlUtils.skipCurrentTag(parser);
+            }
+            if (obbPaths.size() == 0) {
+                return;
+            } else {
+                packageSetting.obbPathStrings = obbPaths.toArray(new String[obbPaths.size()]);
+            }
+        }
+
         // Returns -1 if we could not find an available UserId to assign
         private int newUserIdLP(Object obj) {
             // Let's be stupidly inefficient for now...