diff options
-rw-r--r-- | api/current.xml | 4 | ||||
-rw-r--r-- | cmds/pm/src/com/android/commands/pm/Pm.java | 14 | ||||
-rw-r--r-- | core/java/android/app/ApplicationContext.java | 15 | ||||
-rw-r--r-- | core/java/android/content/pm/IPackageManager.aidl | 7 | ||||
-rw-r--r-- | core/java/android/content/pm/PackageManager.java | 42 | ||||
-rw-r--r-- | services/java/com/android/server/PackageManagerService.java | 93 | ||||
-rw-r--r-- | test-runner/android/test/mock/MockPackageManager.java | 10 |
7 files changed, 160 insertions, 25 deletions
diff --git a/api/current.xml b/api/current.xml index 40fe8e7..71b5bc2 100644 --- a/api/current.xml +++ b/api/current.xml @@ -33542,7 +33542,7 @@ </method> <method name="installPackage" return="void" - abstract="true" + abstract="false" native="false" synchronized="false" static="false" @@ -112339,6 +112339,8 @@ </parameter> <parameter name="flags" type="int"> </parameter> +<parameter name="installerPackageName" type="java.lang.String"> +</parameter> </method> <method name="isSafeMode" return="boolean" diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index 04e69e3..ac62757 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -579,6 +579,7 @@ public final class Pm { private void runInstall() { int installFlags = 0; + String installerPackageName = null; String opt; while ((opt=nextOption()) != null) { @@ -586,6 +587,13 @@ public final class Pm { installFlags |= PackageManager.FORWARD_LOCK_PACKAGE; } else if (opt.equals("-r")) { installFlags |= PackageManager.REPLACE_EXISTING_PACKAGE; + } else if (opt.equals("-i")) { + installerPackageName = nextOptionData(); + if (installerPackageName == null) { + System.err.println("Error: no value specified for -i"); + showUsage(); + return; + } } else { System.err.println("Error: Unknown option: " + opt); showUsage(); @@ -603,7 +611,8 @@ public final class Pm { PackageInstallObserver obs = new PackageInstallObserver(); try { - mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags); + mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags, + installerPackageName); synchronized (obs) { while (!obs.finished) { @@ -812,7 +821,7 @@ public final class Pm { System.err.println(" pm list permissions [-g] [-f] [-d] [-u] [GROUP]"); System.err.println(" pm list instrumentation [-f] [TARGET-PACKAGE]"); System.err.println(" pm path PACKAGE"); - System.err.println(" pm install [-l] [-r] PATH"); + System.err.println(" pm install [-l] [-r] [-i INSTALLER_PACKAGE_NAME] PATH"); System.err.println(" pm uninstall [-k] PACKAGE"); System.err.println(" pm enable PACKAGE_OR_COMPONENT"); System.err.println(" pm disable PACKAGE_OR_COMPONENT"); @@ -840,6 +849,7 @@ public final class Pm { System.err.println("The install command installs a package to the system. Use"); System.err.println("the -l option to install the package with FORWARD_LOCK. Use"); System.err.println("the -r option to reinstall an exisiting app, keeping its data."); + System.err.println("the -i option to specify the installer package name."); System.err.println(""); System.err.println("The uninstall command removes a package from the system. Use"); System.err.println("the -k option to keep the data and cache directories around"); diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java index a1f5a58..bb17dc3 100644 --- a/core/java/android/app/ApplicationContext.java +++ b/core/java/android/app/ApplicationContext.java @@ -2310,15 +2310,26 @@ class ApplicationContext extends Context { } @Override - public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags) { + public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags, + String installerPackageName) { try { - mPM.installPackage(packageURI, observer, flags); + mPM.installPackage(packageURI, observer, flags, installerPackageName); } catch (RemoteException e) { // Should never happen! } } @Override + public String getInstallerPackageName(String packageName) { + try { + return mPM.getInstallerPackageName(packageName); + } catch (RemoteException e) { + // Should never happen! + } + return null; + } + + @Override public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) { try { mPM.deletePackage(packageName, observer, flags); diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index d3f6f3c..c199619 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -139,8 +139,11 @@ interface IPackageManager { * @param observer a callback to use to notify when the package installation in finished. * @param flags - possible values: {@link #FORWARD_LOCK_PACKAGE}, * {@link #REPLACE_EXISITING_PACKAGE} + * @param installerPackageName Optional package name of the application that is performing the + * installation. This identifies which market the package came from. */ - void installPackage(in Uri packageURI, IPackageInstallObserver observer, int flags); + void installPackage(in Uri packageURI, IPackageInstallObserver observer, int flags, + in String installerPackageName); /** * Delete a package. @@ -151,6 +154,8 @@ interface IPackageManager { */ void deletePackage(in String packageName, IPackageDeleteObserver observer, int flags); + String getInstallerPackageName(in String packageName); + void addPackageToPreferred(String packageName); void removePackageFromPreferred(String packageName); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e2f0ce4..3695516 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1354,8 +1354,35 @@ public abstract class PackageManager { * * @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 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); + Uri packageURI, IPackageInstallObserver observer, int flags, + String installerPackageName); /** * Attempts to delete a package. Since this may take a little while, the result will @@ -1374,6 +1401,17 @@ public abstract class PackageManager { */ public abstract void deletePackage( String packageName, IPackageDeleteObserver observer, int flags); + + /** + * Retrieve the package name of the application that installed a package. This identifies + * which market the package came from. + * + * @param packageName The name of the package to query + * + * @hide + */ + public abstract String getInstallerPackageName(String packageName); + /** * Attempts to clear the user data directory of an application. * Since this may take a little while, the result will @@ -1483,7 +1521,7 @@ public abstract class PackageManager { * * @param packageURI The location of the package file to install * - * @see #installPackage(android.net.Uri, IPackageInstallObserver, int) + * @see #installPackage(android.net.Uri, IPackageInstallObserver, int, String) */ public void installPackage(Uri packageURI) { installPackage(packageURI, null, 0); diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 237b70d..b17a941 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -3231,20 +3231,27 @@ class PackageManagerService extends IPackageManager.Stub { private final String mRootDir; private final boolean mIsRom; } - + /* Called when a downloaded package installation has been confirmed by the user */ public void installPackage( final Uri packageURI, final IPackageInstallObserver observer, final int flags) { + installPackage(packageURI, observer, flags, null); + } + + /* Called when a downloaded package installation has been confirmed by the user */ + public void installPackage( + final Uri packageURI, final IPackageInstallObserver observer, final int flags, + final String installerPackageName) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INSTALL_PACKAGES, null); - + // Queue up an async operation since the package installation may take a little while. mHandler.post(new Runnable() { public void run() { mHandler.removeCallbacks(this); PackageInstalledInfo res; synchronized (mInstallLock) { - res = installPackageLI(packageURI, flags, true); + res = installPackageLI(packageURI, flags, true, installerPackageName); } if (observer != null) { try { @@ -3292,7 +3299,7 @@ class PackageManagerService extends IPackageManager.Stub { File tmpPackageFile, String destFilePath, File destPackageFile, File destResourceFile, PackageParser.Package pkg, boolean forwardLocked, boolean newInstall, - PackageInstalledInfo res) { + String installerPackageName, PackageInstalledInfo res) { // Remember this for later, in case we need to rollback this install boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists(); res.name = pkgName; @@ -3328,7 +3335,8 @@ class PackageManagerService extends IPackageManager.Stub { destResourceFile, pkg, newPackage, true, - forwardLocked, + forwardLocked, + installerPackageName, res); // delete the partially installed application. the data directory will have to be // restored if it was already existing @@ -3349,7 +3357,8 @@ class PackageManagerService extends IPackageManager.Stub { File tmpPackageFile, String destFilePath, File destPackageFile, File destResourceFile, PackageParser.Package pkg, boolean forwardLocked, boolean newInstall, - PackageInstalledInfo res) { + String installerPackageName, PackageInstalledInfo res) { + PackageParser.Package oldPackage; // First find the old package info and check signatures synchronized(mPackages) { @@ -3364,11 +3373,11 @@ class PackageManagerService extends IPackageManager.Stub { replaceSystemPackageLI(oldPackage, tmpPackageFile, destFilePath, destPackageFile, destResourceFile, pkg, forwardLocked, - newInstall, res); + newInstall, installerPackageName, res); } else { replaceNonSystemPackageLI(oldPackage, tmpPackageFile, destFilePath, destPackageFile, destResourceFile, pkg, forwardLocked, - newInstall, res); + newInstall, installerPackageName, res); } } @@ -3376,11 +3385,17 @@ class PackageManagerService extends IPackageManager.Stub { File tmpPackageFile, String destFilePath, File destPackageFile, File destResourceFile, PackageParser.Package pkg, boolean forwardLocked, boolean newInstall, - PackageInstalledInfo res) { + String installerPackageName, PackageInstalledInfo res) { PackageParser.Package newPackage = null; String pkgName = deletedPackage.packageName; boolean deletedPkg = true; boolean updatedSettings = false; + + String oldInstallerPackageName = null; + synchronized (mPackages) { + oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName); + } + int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE; // First delete the existing package while retaining the data directory if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA, @@ -3409,6 +3424,7 @@ class PackageManagerService extends IPackageManager.Stub { newPackage, true, forwardLocked, + installerPackageName, res); updatedSettings = true; } @@ -3453,7 +3469,7 @@ class PackageManagerService extends IPackageManager.Stub { Uri.fromFile(new File(deletedPackage.mPath)), isForwardLocked(deletedPackage) ? PackageManager.FORWARD_LOCK_PACKAGE - : 0, false); + : 0, false, oldInstallerPackageName); } } } @@ -3462,7 +3478,7 @@ class PackageManagerService extends IPackageManager.Stub { File tmpPackageFile, String destFilePath, File destPackageFile, File destResourceFile, PackageParser.Package pkg, boolean forwardLocked, boolean newInstall, - PackageInstalledInfo res) { + String installerPackageName, PackageInstalledInfo res) { PackageParser.Package newPackage = null; boolean updatedSettings = false; int parseFlags = PackageManager.REPLACE_EXISTING_PACKAGE | @@ -3512,7 +3528,8 @@ class PackageManagerService extends IPackageManager.Stub { destResourceFile, pkg, newPackage, true, - forwardLocked, + forwardLocked, + installerPackageName, res); updatedSettings = true; } @@ -3539,6 +3556,8 @@ class PackageManagerService extends IPackageManager.Stub { synchronized(mPackages) { if(updatedSettings) { mSettings.enableSystemPackageLP(packageName); + mSettings.setInstallerPackageName(packageName, + oldPkgSetting.installerPackageName); } mSettings.writeLP(); } @@ -3552,7 +3571,7 @@ class PackageManagerService extends IPackageManager.Stub { PackageParser.Package newPackage, boolean replacingExistingPackage, boolean forwardLocked, - PackageInstalledInfo res) { + String installerPackageName, PackageInstalledInfo res) { synchronized (mPackages) { //write settings. the installStatus will be incomplete at this stage. //note that the new package setting would have already been @@ -3599,6 +3618,7 @@ class PackageManagerService extends IPackageManager.Stub { res.uid = newPackage.applicationInfo.uid; res.pkg = newPackage; mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE); + mSettings.setInstallerPackageName(pkgName, installerPackageName); res.returnCode = PackageManager.INSTALL_SUCCEEDED; //to update install status mSettings.writeLP(); @@ -3606,7 +3626,7 @@ class PackageManagerService extends IPackageManager.Stub { } private PackageInstalledInfo installPackageLI(Uri pPackageURI, - int pFlags, boolean newInstall) { + int pFlags, boolean newInstall, String installerPackageName) { File tmpPackageFile = null; String pkgName = null; boolean forwardLocked = false; @@ -3719,13 +3739,13 @@ class PackageManagerService extends IPackageManager.Stub { replacePackageLI(pkgName, tmpPackageFile, destFilePath, destPackageFile, destResourceFile, - pkg, forwardLocked, newInstall, + pkg, forwardLocked, newInstall, installerPackageName, res); } else { installNewPackageLI(pkgName, tmpPackageFile, destFilePath, destPackageFile, destResourceFile, - pkg, forwardLocked, newInstall, + pkg, forwardLocked, newInstall, installerPackageName, res); } } finally { @@ -4543,6 +4563,16 @@ class PackageManagerService extends IPackageManager.Stub { } } + public String getInstallerPackageName(String packageName) { + synchronized (mPackages) { + PackageSetting pkg = mSettings.mPackages.get(packageName); + if (pkg == null) { + throw new IllegalArgumentException("Unknown package: " + packageName); + } + return pkg.installerPackageName; + } + } + public int getApplicationEnabledSetting(String appPackageName) { synchronized (mPackages) { PackageSetting pkg = mSettings.mPackages.get(appPackageName); @@ -5192,6 +5222,9 @@ class PackageManagerService extends IPackageManager.Stub { HashSet<String> enabledComponents = new HashSet<String>(0); int enabled = COMPONENT_ENABLED_STATE_DEFAULT; int installStatus = PKG_INSTALL_COMPLETE; + + /* package name of the app that installed this package */ + String installerPackageName; PackageSettingBase(String name, File codePath, File resourcePath, int pVersionCode, int pkgFlags) { @@ -5204,6 +5237,14 @@ class PackageManagerService extends IPackageManager.Stub { this.versionCode = pVersionCode; } + public void setInstallerPackageName(String packageName) { + installerPackageName = packageName; + } + + String getInstallerPackageName() { + return installerPackageName; + } + public void setInstallStatus(int newStatus) { installStatus = newStatus; } @@ -5434,6 +5475,19 @@ class PackageManagerService extends IPackageManager.Stub { } } + void setInstallerPackageName(String pkgName, + String installerPkgName) { + PackageSetting p = mPackages.get(pkgName); + if(p != null) { + p.setInstallerPackageName(installerPkgName); + } + } + + String getInstallerPackageName(String pkgName) { + PackageSetting p = mPackages.get(pkgName); + return (p == null) ? null : p.getInstallerPackageName(); + } + int getInstallStatus(String pkgName) { PackageSetting p = mPackages.get(pkgName); if(p != null) { @@ -5909,6 +5963,9 @@ class PackageManagerService extends IPackageManager.Stub { if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) { serializer.attribute(null, "installStatus", "false"); } + if (pkg.installerPackageName != null) { + serializer.attribute(null, "installer", pkg.installerPackageName); + } pkg.signatures.writeXml(serializer, "sigs", mPastSignatures); if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) { serializer.startTag(null, "perms"); @@ -5943,6 +6000,7 @@ class PackageManagerService extends IPackageManager.Stub { } serializer.endTag(null, "enabled-components"); } + serializer.endTag(null, "package"); } @@ -6264,6 +6322,7 @@ class PackageManagerService extends IPackageManager.Stub { String codePathStr = null; String resourcePathStr = null; String systemStr = null; + String installerPackageName = null; int pkgFlags = 0; String timeStampStr; long timeStamp = 0; @@ -6284,6 +6343,7 @@ class PackageManagerService extends IPackageManager.Stub { } } systemStr = parser.getAttributeValue(null, "system"); + installerPackageName = parser.getAttributeValue(null, "installer"); if (systemStr != null) { if ("true".equals(systemStr)) { pkgFlags |= ApplicationInfo.FLAG_SYSTEM; @@ -6357,6 +6417,7 @@ class PackageManagerService extends IPackageManager.Stub { + parser.getPositionDescription()); } if (packageSetting != null) { + packageSetting.installerPackageName = installerPackageName; final String enabledStr = parser.getAttributeValue(null, "enabled"); if (enabledStr != null) { if (enabledStr.equalsIgnoreCase("true")) { diff --git a/test-runner/android/test/mock/MockPackageManager.java b/test-runner/android/test/mock/MockPackageManager.java index ea190e2..4769057 100644 --- a/test-runner/android/test/mock/MockPackageManager.java +++ b/test-runner/android/test/mock/MockPackageManager.java @@ -286,7 +286,15 @@ public class MockPackageManager extends PackageManager { @Override public void installPackage(Uri packageURI, IPackageInstallObserver observer, - int flags) { + int flags, String installerPackageName) { + throw new UnsupportedOperationException(); + } + + /** + * @hide - to match hiding in superclass + */ + @Override + public String getInstallerPackageName(String packageName) { throw new UnsupportedOperationException(); } |