summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.xml56
-rw-r--r--core/java/android/app/ContextImpl.java14
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl3
-rw-r--r--core/java/android/content/pm/PackageManager.java25
-rwxr-xr-xcore/tests/coretests/src/android/content/pm/PackageManagerTests.java159
-rw-r--r--services/java/com/android/server/PackageManagerService.java96
-rw-r--r--test-runner/src/android/test/mock/MockPackageManager.java11
7 files changed, 342 insertions, 22 deletions
diff --git a/api/current.xml b/api/current.xml
index 85b367d..c0dcfe6 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -45952,6 +45952,19 @@
<exception name="PackageManager.NameNotFoundException" type="android.content.pm.PackageManager.NameNotFoundException">
</exception>
</method>
+<method name="getPackageObbPaths"
+ return="java.lang.String[]"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+</method>
<method name="getPackagesForUid"
return="java.lang.String[]"
abstract="true"
@@ -46423,6 +46436,21 @@
<parameter name="flags" type="int">
</parameter>
</method>
+<method name="setPackageObbPaths"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+<parameter name="paths" type="java.lang.String[]">
+</parameter>
+</method>
<field name="COMPONENT_ENABLED_STATE_DEFAULT"
type="int"
transient="false"
@@ -159105,6 +159133,19 @@
<exception name="PackageManager.NameNotFoundException" type="android.content.pm.PackageManager.NameNotFoundException">
</exception>
</method>
+<method name="getPackageObbPaths"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+</method>
<method name="getPackagesForUid"
return="java.lang.String[]"
abstract="false"
@@ -159589,6 +159630,21 @@
<parameter name="path" type="java.lang.String">
</parameter>
</method>
+<method name="setPackageObbPaths"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+<parameter name="paths" type="java.lang.String[]">
+</parameter>
+</method>
</class>
<class name="MockResources"
extends="android.content.res.Resources"
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 7e7cd7a..18ab478 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2700,14 +2700,24 @@ class ContextImpl extends Context {
}
@Override
- public void setPackageObbPath(String packageName, String path) {
+ public void setPackageObbPaths(String packageName, String[] paths) {
try {
- mPM.setPackageObbPath(packageName, path);
+ mPM.setPackageObbPaths(packageName, paths);
} catch (RemoteException e) {
// Should never happen!
}
}
+ @Override
+ public String[] getPackageObbPaths(String packageName) {
+ try {
+ return mPM.getPackageObbPaths(packageName);
+ } catch (RemoteException e) {
+ // Should never happen!
+ }
+ return null;
+ }
+
private final ContextImpl mContext;
private final IPackageManager mPM;
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 4cff3bb..44b0c96 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -322,5 +322,6 @@ interface IPackageManager {
boolean setInstallLocation(int loc);
int getInstallLocation();
- void setPackageObbPath(String packageName, String path);
+ void setPackageObbPaths(in String packageName, in String[] paths);
+ String[] getPackageObbPaths(in String packageName);
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index b5d1653..a1c29f7 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2273,15 +2273,30 @@ public abstract class PackageManager {
String packageName, IPackageMoveObserver observer, int flags);
/**
- * Sets the Opaque Binary Blob (OBB) file location.
+ * Sets the Opaque Binary Blob (OBB) file path associated with a package
+ * name. The caller must have the
+ * {@link android.Manifest.permission#INSTALL_PACKAGES} permission.
* <p>
* NOTE: The existence or format of this file is not currently checked, but
* it may be in the future.
*
* @param packageName Name of the package with which to associate the .obb
- * file
- * @param path Path on the filesystem to the .obb file
- * @hide
+ * file.
+ * @param paths Arrays of paths on the filesystem to the .obb files
+ * associated with the package.
+ * @see #getPackageObbPaths(String)
+ */
+ public abstract void setPackageObbPaths(String packageName, String[] paths);
+
+ /**
+ * Gets the Opaque Binary Blob (OBB) file path associated with the package.
+ * The caller must be the owner of the package queried or have the
+ * {@link android.Manifest.permission#INSTALL_PACKAGES} permission.
+ *
+ * @param packageName Name of the package with which to associate the .obb
+ * file.
+ * @return array of paths to .obb files associated with the package
+ * @see #setPackageObbPaths(String, String[])
*/
- public abstract void setPackageObbPath(String packageName, String path);
+ public abstract String[] getPackageObbPaths(String packageName);
}
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index d5f385b..c8a4593 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -47,6 +47,7 @@ import android.util.Log;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Arrays;
public class PackageManagerTests extends AndroidTestCase {
private static final boolean localLOGV = true;
@@ -2838,6 +2839,164 @@ public class PackageManagerTests extends AndroidTestCase {
installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
+
+ @LargeTest
+ public void testPackageObbPaths_Nonexistent() {
+ try {
+ final PackageManager pm = getPm();
+
+ // Invalid Java package name.
+ pm.getPackageObbPaths("=non-existent");
+
+ fail("Should not be able to get package OBB paths for non-existent package");
+ } catch (IllegalArgumentException e) {
+ // pass
+ }
+ }
+
+ @LargeTest
+ public void testPackageObbPaths_Initial() {
+ InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+ try {
+ final PackageManager pm = getPm();
+
+ assertEquals("Initial obb paths should be null",
+ null, pm.getPackageObbPaths(ip.pkg.packageName));
+ } finally {
+ cleanUpInstall(ip);
+ }
+ }
+
+ @LargeTest
+ public void testPackageObbPaths_Null() {
+ InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+ try {
+ final PackageManager pm = getPm();
+
+ pm.setPackageObbPaths(ip.pkg.packageName, null);
+
+ assertEquals("Returned paths should be null",
+ null, pm.getPackageObbPaths(ip.pkg.packageName));
+ } finally {
+ cleanUpInstall(ip);
+ }
+ }
+
+ @LargeTest
+ public void testPackageObbPaths_Empty() {
+ InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+ try {
+ final PackageManager pm = getPm();
+
+ final String[] paths = new String[0];
+
+ pm.setPackageObbPaths(ip.pkg.packageName, paths);
+
+ assertEquals("Empty list should be interpreted as null",
+ null, pm.getPackageObbPaths(ip.pkg.packageName));
+ } finally {
+ cleanUpInstall(ip);
+ }
+ }
+
+ @LargeTest
+ public void testPackageObbPaths_Single() {
+ InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+ try {
+ final PackageManager pm = getPm();
+
+ final String[] paths = new String[] {
+ "/example/test",
+ };
+
+ pm.setPackageObbPaths(ip.pkg.packageName, paths.clone());
+
+ assertTrue("Previously set paths should be the same as the returned paths.",
+ Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName)));
+ } finally {
+ cleanUpInstall(ip);
+ }
+ }
+
+ @LargeTest
+ public void testPackageObbPaths_Multiple() {
+ InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+ try {
+ final PackageManager pm = getPm();
+
+ final String[] paths = new String[] {
+ "/example/test1",
+ "/example/test2",
+ };
+
+ pm.setPackageObbPaths(ip.pkg.packageName, paths.clone());
+
+ assertTrue("Previously set paths should be the same as the returned paths.",
+ Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName)));
+ } finally {
+ cleanUpInstall(ip);
+ }
+ }
+
+ @LargeTest
+ public void testPackageObbPaths_Twice() {
+ InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+ try {
+ final PackageManager pm = getPm();
+
+ final String[] paths = new String[] {
+ "/example/test1",
+ "/example/test2",
+ };
+
+ pm.setPackageObbPaths(ip.pkg.packageName, paths.clone());
+
+ assertTrue("Previously set paths should be the same as the returned paths.",
+ Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName)));
+
+ paths[0] = "/example/test3";
+ pm.setPackageObbPaths(ip.pkg.packageName, paths.clone());
+
+ assertTrue("Previously set paths should be the same as the returned paths.",
+ Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName)));
+ } finally {
+ cleanUpInstall(ip);
+ }
+ }
+
+ @LargeTest
+ public void testPackageObbPaths_ReplacePackage() {
+ InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+ try {
+ final PackageManager pm = getPm();
+
+ final String[] paths = new String[] {
+ "/example/test1",
+ "/example/test2",
+ };
+
+ pm.setPackageObbPaths(ip.pkg.packageName, paths.clone());
+
+ Log.i(TAG, "Creating replaceReceiver");
+ final GenericReceiver receiver = new ReplaceReceiver(ip.pkg.packageName);
+
+ final int flags = PackageManager.INSTALL_REPLACE_EXISTING;
+ invokeInstallPackage(ip.packageURI, flags, receiver);
+ assertInstall(ip.pkg, flags, ip.pkg.installLocation);
+
+ assertTrue("Previously set paths should be the same as the returned paths.",
+ Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName)));
+ } finally {
+ cleanUpInstall(ip);
+ }
+ }
/*---------- Recommended install location tests ----*/
/*
* TODO's
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index b0f3a23..ead9f22 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -102,6 +102,7 @@ import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
+import java.lang.reflect.Array;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -4577,16 +4578,52 @@ class PackageManagerService extends IPackageManager.Stub {
mHandler.sendMessage(msg);
}
- 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) {
- pkgSetting = mSettings.mPackages.get(packageName);
+ 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) {
+ final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
if (pkgSetting == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
@@ -4595,8 +4632,7 @@ class PackageManagerService extends IPackageManager.Stub {
+ Binder.getCallingPid() + ", uid=" + uid + ", package uid="
+ pkgSetting.userId);
}
- pkgSetting.obbPathString = path;
- mSettings.writeLP();
+ return pkgSetting.obbPathStrings;
}
}
@@ -7165,7 +7201,7 @@ class PackageManagerService extends IPackageManager.Stub {
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);
@@ -7728,7 +7764,7 @@ class PackageManagerService extends IPackageManager.Stub {
File resourcePath;
String resourcePathString;
String nativeLibraryPathString;
- String obbPathString;
+ String[] obbPathStrings;
long timeStamp;
long firstInstallTime;
long lastUpdateTime;
@@ -8749,8 +8785,15 @@ class PackageManagerService extends IPackageManager.Stub {
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) {
@@ -9154,7 +9197,6 @@ class PackageManagerService extends IPackageManager.Stub {
String codePathStr = null;
String resourcePathStr = null;
String nativeLibraryPathStr = null;
- String obbPathStr = null;
String systemStr = null;
String installerPackageName = null;
String uidError = null;
@@ -9174,7 +9216,6 @@ class PackageManagerService extends IPackageManager.Stub {
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 {
@@ -9299,7 +9340,6 @@ class PackageManagerService extends IPackageManager.Stub {
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")) {
@@ -9347,6 +9387,8 @@ class PackageManagerService extends IPackageManager.Stub {
readGrantedPermissionsLP(parser,
packageSetting.grantedPermissions);
packageSetting.permissionsFixed = true;
+ } else if (tagName.equals("obbs")) {
+ readObbPathsLP(packageSetting, parser);
} else {
reportSettingsProblem(Log.WARN,
"Unknown element under <package>: "
@@ -9551,6 +9593,34 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
+ 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...
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index f0cbaa0..4a18b3e 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -490,8 +490,17 @@ public class MockPackageManager extends PackageManager {
throw new UnsupportedOperationException();
}
- @Override
public void setPackageObbPath(String packageName, String path) {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public void setPackageObbPaths(String packageName, String[] paths) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String[] getPackageObbPaths(String packageName) {
+ throw new UnsupportedOperationException();
+ }
}