From ade3ecad94d1f4431576f53bae26c35efbf7a2c9 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Mon, 11 May 2009 18:54:45 -0700 Subject: [PATCH] Implement issue #1783881 (manifest option for adb-install-only apps) You can now use android:testOnly="true" to not allow your .apk to be installed as a normal app. The only way to do so is with the pm command and giving the -t option, which sets a new INSTALL_ALLOW_TEST flag when installing. I also used this to clean up the install API... actually, mostly to hide it, since it is not accessible to apps so shouldn't be in the SDK. We will be doing some more work on it, so this will prevent adding yet another backwards-compatibility-for-no-reason version. --- api/4.xml | 424 ---------------- api/current.xml | 459 +----------------- cmds/pm/src/com/android/commands/pm/Pm.java | 44 +- .../android/content/pm/ApplicationInfo.java | 6 + .../content/pm/IPackageInstallObserver.aidl | 2 +- .../android/content/pm/PackageManager.java | 96 ++-- .../android/content/pm/PackageParser.java | 6 + core/res/res/values/attrs_manifest.xml | 8 + core/res/res/values/public.xml | 1 + .../android/server/PackageManagerService.java | 18 +- .../android/test/mock/MockPackageManager.java | 8 +- 11 files changed, 137 insertions(+), 935 deletions(-) diff --git a/api/4.xml b/api/4.xml index ab93a47c90b93..893301e100099 100644 --- a/api/4.xml +++ b/api/4.xml @@ -31801,97 +31801,6 @@ > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - = the current SDK version. + */ + public static final int FLAG_TEST_ONLY = 1<<9; + /** * Flags associated with the application. Any combination of * {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE}, diff --git a/core/java/android/content/pm/IPackageInstallObserver.aidl b/core/java/android/content/pm/IPackageInstallObserver.aidl index e83bbc67d117a..6133365373178 100644 --- a/core/java/android/content/pm/IPackageInstallObserver.aidl +++ b/core/java/android/content/pm/IPackageInstallObserver.aidl @@ -19,7 +19,7 @@ package android.content.pm; /** * API for installation callbacks from the Package Manager. - * + * @hide */ oneway interface IPackageInstallObserver { void packageInstalled(in String packageName, int returnCode); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 3695516aa4f14..3a192f7eb7493 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -235,14 +235,24 @@ public abstract class PackageManager { * Flag parameter for {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} to * indicate that this package should be installed as forward locked, i.e. only the app itself * should have access to it's code and non-resource assets. + * @hide */ - public static final int FORWARD_LOCK_PACKAGE = 0x00000001; + public static final int INSTALL_FORWARD_LOCK = 0x00000001; /** * Flag parameter for {@link #installPackage} to indicate that you want to replace an already - * installed package, if one exists + * installed package, if one exists. + * @hide */ - public static final int REPLACE_EXISTING_PACKAGE = 0x00000002; + public static final int INSTALL_REPLACE_EXISTING = 0x00000002; + + /** + * Flag parameter for {@link #installPackage} to indicate that you want to + * allow test packages (those that have set android:testOnly in their + * manifest) to be installed. + * @hide + */ + public static final int INSTALL_ALLOW_TEST = 0x00000004; /** * Flag parameter for @@ -255,6 +265,7 @@ public abstract class PackageManager { /** * Installation return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} on success. + * @hide */ public static final int INSTALL_SUCCEEDED = 1; @@ -262,6 +273,7 @@ public abstract class PackageManager { * Installation return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package is * already installed. + * @hide */ public static final int INSTALL_FAILED_ALREADY_EXISTS = -1; @@ -269,6 +281,7 @@ public abstract class PackageManager { * Installation return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package archive * file is invalid. + * @hide */ public static final int INSTALL_FAILED_INVALID_APK = -2; @@ -276,13 +289,15 @@ public abstract class PackageManager { * Installation return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the URI passed in * is invalid. + * @hide */ public static final int INSTALL_FAILED_INVALID_URI = -3; /** * Installation return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package manager - * service found that the device didn't have enough storage space to install the app + * service found that the device didn't have enough storage space to install the app. + * @hide */ public static final int INSTALL_FAILED_INSUFFICIENT_STORAGE = -4; @@ -290,6 +305,7 @@ public abstract class PackageManager { * Installation return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if a * package is already installed with the same name. + * @hide */ public static final int INSTALL_FAILED_DUPLICATE_PACKAGE = -5; @@ -297,6 +313,7 @@ public abstract class PackageManager { * Installation return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if * the requested shared user does not exist. + * @hide */ public static final int INSTALL_FAILED_NO_SHARED_USER = -6; @@ -305,6 +322,7 @@ public abstract class PackageManager { * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if * a previously installed package of the same name has a different signature * than the new package (and the old package's data was not removed). + * @hide */ public static final int INSTALL_FAILED_UPDATE_INCOMPATIBLE = -7; @@ -313,6 +331,7 @@ public abstract class PackageManager { * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if * the new package is requested a shared user which is already installed on the * device and does not have matching signature. + * @hide */ public static final int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE = -8; @@ -320,6 +339,7 @@ public abstract class PackageManager { * Installation return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if * the new package uses a shared library that is not available. + * @hide */ public static final int INSTALL_FAILED_MISSING_SHARED_LIBRARY = -9; @@ -327,6 +347,7 @@ public abstract class PackageManager { * Installation return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if * the new package uses a shared library that is not available. + * @hide */ public static final int INSTALL_FAILED_REPLACE_COULDNT_DELETE = -10; @@ -335,6 +356,7 @@ public abstract class PackageManager { * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if * the new package failed while optimizing and validating its dex files, * either because there was not enough storage or the validation failed. + * @hide */ public static final int INSTALL_FAILED_DEXOPT = -11; @@ -343,6 +365,7 @@ public abstract class PackageManager { * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if * the new package failed because the current SDK version is older than * that required by the package. + * @hide */ public static final int INSTALL_FAILED_OLDER_SDK = -12; @@ -351,6 +374,7 @@ public abstract class PackageManager { * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if * the new package failed because it contains a content provider with the * same authority as a provider already installed in the system. + * @hide */ public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13; @@ -359,14 +383,26 @@ public abstract class PackageManager { * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if * the new package failed because the current SDK version is newer than * that required by the package. + * @hide */ public static final int INSTALL_FAILED_NEWER_SDK = -14; + /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if + * the new package failed because it has specified that it is a test-only + * package and the caller has not supplied the {@link #INSTALL_ALLOW_TEST} + * flag. + * @hide + */ + public static final int INSTALL_FAILED_TEST_ONLY = -15; + /** * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} * if the parser was given a path that is not a file, or does not end with the expected * '.apk' extension. + * @hide */ public static final int INSTALL_PARSE_FAILED_NOT_APK = -100; @@ -374,6 +410,7 @@ public abstract class PackageManager { * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} * if the parser was unable to retrieve the AndroidManifest.xml file. + * @hide */ public static final int INSTALL_PARSE_FAILED_BAD_MANIFEST = -101; @@ -381,6 +418,7 @@ public abstract class PackageManager { * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} * if the parser encountered an unexpected exception. + * @hide */ public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102; @@ -388,6 +426,7 @@ public abstract class PackageManager { * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} * if the parser did not find any certificates in the .apk. + * @hide */ public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103; @@ -395,6 +434,7 @@ public abstract class PackageManager { * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} * if the parser found inconsistent certificates on the files in the .apk. + * @hide */ public static final int INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES = -104; @@ -403,6 +443,7 @@ public abstract class PackageManager { * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} * if the parser encountered a CertificateEncodingException in one of the * files in the .apk. + * @hide */ public static final int INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING = -105; @@ -410,6 +451,7 @@ public abstract class PackageManager { * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} * if the parser encountered a bad or missing package name in the manifest. + * @hide */ public static final int INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME = -106; @@ -417,6 +459,7 @@ public abstract class PackageManager { * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} * if the parser encountered a bad shared user id name in the manifest. + * @hide */ public static final int INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID = -107; @@ -424,6 +467,7 @@ public abstract class PackageManager { * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} * if the parser encountered some structural problem in the manifest. + * @hide */ public static final int INSTALL_PARSE_FAILED_MANIFEST_MALFORMED = -108; @@ -432,6 +476,7 @@ public abstract class PackageManager { * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} * if the parser did not find any actionable tags (instrumentation or application) * in the manifest. + * @hide */ public static final int INSTALL_PARSE_FAILED_MANIFEST_EMPTY = -109; @@ -1338,6 +1383,8 @@ public abstract class PackageManager { } /** + * @hide + * * Install a package. Since this may take a little while, the result will * be posted back to the given observer. An installation will fail if the calling context * lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the @@ -1349,36 +1396,10 @@ public abstract class PackageManager { * @param observer An observer callback to get notified when the package installation is * complete. {@link IPackageInstallObserver#packageInstalled(String, int)} will be * called when that happens. observer may be null to indicate that no callback is desired. - * @param flags - possible values: {@link #FORWARD_LOCK_PACKAGE}, - * {@link #REPLACE_EXISTING_PACKAGE} - * - * @see #installPackage(android.net.Uri) - */ - public void installPackage( - Uri packageURI, IPackageInstallObserver observer, int flags) { - installPackage(packageURI, observer, flags, null); - } - - /** - * Install a package. Since this may take a little while, the result will - * be posted back to the given observer. An installation will fail if the calling context - * lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the - * package named in the package file's manifest is already installed, or if there's no space - * available on the device. - * - * @param packageURI The location of the package file to install. This can be a 'file:' or a - * 'content:' URI. - * @param observer An observer callback to get notified when the package installation is - * complete. {@link IPackageInstallObserver#packageInstalled(String, int)} will be - * called when that happens. observer may be null to indicate that no callback is desired. - * @param flags - possible values: {@link #FORWARD_LOCK_PACKAGE}, - * {@link #REPLACE_EXISTING_PACKAGE} + * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK}, + * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}. * @param installerPackageName Optional package name of the application that is performing the * installation. This identifies which market the package came from. - * - * @see #installPackage(android.net.Uri) - * - * @hide */ public abstract void installPackage( Uri packageURI, IPackageInstallObserver observer, int flags, @@ -1516,17 +1537,6 @@ public abstract class PackageManager { public abstract void getPackageSizeInfo(String packageName, IPackageStatsObserver observer); - /** - * Install a package. - * - * @param packageURI The location of the package file to install - * - * @see #installPackage(android.net.Uri, IPackageInstallObserver, int, String) - */ - public void installPackage(Uri packageURI) { - installPackage(packageURI, null, 0); - } - /** * Add a new package to the list of preferred packages. This new package * will be added to the front of the list (removed from its current location diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 12df5bd8e5fc8..a1c0f487626cb 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1187,6 +1187,12 @@ public class PackageParser { ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA; } + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestApplication_testOnly, + true)) { + ai.flags |= ApplicationInfo.FLAG_TEST_ONLY; + } + String str; str = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestApplication_permission); diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 1319c77cdc53f..7b48267045faa 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -79,6 +79,13 @@ by applications. --> + + + @@ -635,6 +642,7 @@ +