summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java59
-rw-r--r--services/java/com/android/server/PackageManagerService.java92
2 files changed, 118 insertions, 33 deletions
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index a236a3c..cc6e739 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -18,9 +18,11 @@ package com.android.commands.pm;
import com.android.internal.content.PackageHelper;
+import android.app.ActivityManagerNative;
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
import android.content.pm.FeatureInfo;
+import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageInstallObserver;
import android.content.pm.IPackageManager;
@@ -100,6 +102,11 @@ public final class Pm {
return;
}
+ if ("clear".equals(op)) {
+ runClear();
+ return;
+ }
+
if ("enable".equals(op)) {
runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
return;
@@ -811,6 +818,55 @@ public final class Pm {
return obs.result;
}
+ class ClearDataObserver extends IPackageDataObserver.Stub {
+ boolean finished;
+ boolean result;
+
+ @Override
+ public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
+ synchronized (this) {
+ finished = true;
+ result = succeeded;
+ notifyAll();
+ }
+ }
+
+ }
+
+ private void runClear() {
+ String pkg = nextArg();
+ if (pkg == null) {
+ System.err.println("Error: no package specified");
+ showUsage();
+ return;
+ }
+
+ ClearDataObserver obs = new ClearDataObserver();
+ try {
+ if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs)) {
+ System.err.println("Failed");
+ }
+
+ synchronized (obs) {
+ while (!obs.finished) {
+ try {
+ obs.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ if (obs.result) {
+ System.err.println("Success");
+ } else {
+ System.err.println("Failed");
+ }
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(PM_NOT_RUNNING_ERR);
+ }
+ }
+
private static String enabledSettingToString(int state) {
switch (state) {
case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
@@ -946,6 +1002,7 @@ public final class Pm {
System.err.println(" pm path PACKAGE");
System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH");
System.err.println(" pm uninstall [-k] PACKAGE");
+ System.err.println(" pm clear PACKAGE");
System.err.println(" pm enable PACKAGE_OR_COMPONENT");
System.err.println(" pm disable PACKAGE_OR_COMPONENT");
System.err.println(" pm setInstallLocation [0/auto] [1/internal] [2/external]");
@@ -991,6 +1048,8 @@ public final class Pm {
System.err.println(" -k: keep the data and cache directories around.");
System.err.println("after the package removal.");
System.err.println("");
+ System.err.println("The clear command deletes all data associated with a package.");
+ System.err.println("");
System.err.println("The enable and disable commands change the enabled state of");
System.err.println("a given package or component (written as \"package/class\").");
System.err.println("");
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 79ec920..435a2a5 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -3663,17 +3663,6 @@ class PackageManagerService extends IPackageManager.Stub {
mAppDirs.remove(pkg.mPath);
}
- PackageSetting ps = (PackageSetting)pkg.mExtras;
- if (ps != null && ps.sharedUser != null) {
- // XXX don't do this until the data is removed.
- if (false) {
- ps.sharedUser.packages.remove(ps);
- if (ps.sharedUser.packages.size() == 0) {
- // Remove.
- }
- }
- }
-
int N = pkg.providers.size();
StringBuilder r = null;
int i;
@@ -5769,12 +5758,26 @@ class PackageManagerService extends IPackageManager.Stub {
return;
}
}
+
+ killApplication(packageName, oldPkg.applicationInfo.uid);
+
res.removedInfo.uid = oldPkg.applicationInfo.uid;
res.removedInfo.removedPackage = packageName;
// Remove existing system package
removePackageLI(oldPkg, true);
synchronized (mPackages) {
- mSettings.disableSystemPackageLP(packageName);
+ if (!mSettings.disableSystemPackageLP(packageName) && deletedPackage != null) {
+ // We didn't need to disable the .apk as a current system package,
+ // which means we are replacing another update that is already
+ // installed. We need to make sure to delete the older one's .apk.
+ res.removedInfo.args = createInstallArgs(isExternal(pkg)
+ ? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL,
+ deletedPackage.applicationInfo.sourceDir,
+ deletedPackage.applicationInfo.publicSourceDir,
+ deletedPackage.applicationInfo.nativeLibraryDir);
+ } else {
+ res.removedInfo.args = null;
+ }
}
// Successfully disabled the old package. Now proceed with re-installation
@@ -5813,17 +5816,6 @@ class PackageManagerService extends IPackageManager.Stub {
}
mSettings.writeLP();
}
- } else {
- // If this is an update to an existing update, setup
- // to remove the existing update.
- synchronized (mPackages) {
- PackageSetting ps = mSettings.getDisabledSystemPkg(packageName);
- if (ps != null && ps.codePathString != null &&
- !ps.codePathString.equals(oldPkgSetting.codePathString)) {
- res.removedInfo.args = createInstallArgs(0, oldPkgSetting.codePathString,
- oldPkgSetting.resourcePathString, oldPkgSetting.nativeLibraryPathString);
- }
- }
}
}
@@ -6326,24 +6318,21 @@ class PackageManagerService extends IPackageManager.Stub {
ps = mSettings.getDisabledSystemPkg(p.packageName);
}
if (ps == null) {
- Slog.w(TAG, "Attempt to delete system package "+ p.packageName);
+ Slog.w(TAG, "Attempt to delete unknown system package "+ p.packageName);
return false;
} else {
Log.i(TAG, "Deleting system pkg from data partition");
}
// Delete the updated package
outInfo.isRemovedPackageSystemUpdate = true;
- final boolean deleteCodeAndResources;
if (ps.versionCode < p.mVersionCode) {
- // Delete code and resources for downgrades
- deleteCodeAndResources = true;
+ // Delete data for downgrades
flags &= ~PackageManager.DONT_DELETE_DATA;
} else {
// Preserve data by setting flag
- deleteCodeAndResources = false;
flags |= PackageManager.DONT_DELETE_DATA;
}
- boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo,
+ boolean ret = deleteInstalledPackageLI(p, true, flags, outInfo,
writeSettings);
if (!ret) {
return false;
@@ -7931,6 +7920,12 @@ class PackageManagerService extends IPackageManager.Stub {
pkgFlags);
}
+ PackageSetting(PackageSetting orig) {
+ super(orig.name, orig.realName, orig.codePath, orig.resourcePath,
+ orig.nativeLibraryPathString, orig.versionCode, orig.pkgFlags);
+ copyFrom(orig);
+ }
+
@Override
public String toString() {
return "PackageSetting{"
@@ -8143,21 +8138,29 @@ class PackageManagerService extends IPackageManager.Stub {
return s;
}
- int disableSystemPackageLP(String name) {
+ boolean disableSystemPackageLP(String name) {
PackageSetting p = mPackages.get(name);
if(p == null) {
Log.w(TAG, "Package:"+name+" is not an installed package");
- return -1;
+ return false;
}
PackageSetting dp = mDisabledSysPackages.get(name);
// always make sure the system package code and resource paths dont change
- if(dp == null) {
+ if (dp == null) {
if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
mDisabledSysPackages.put(name, p);
+
+ // a little trick... when we install the new package, we don't
+ // want to modify the existing PackageSetting for the built-in
+ // version. so at this point we need a new PackageSetting that
+ // is okay to much with.
+ PackageSetting newp = new PackageSetting(p);
+ replacePackageLP(name, newp);
+ return true;
}
- return removePackageLP(name);
+ return false;
}
PackageSetting enableSystemPackageLP(String name) {
@@ -8491,6 +8494,19 @@ class PackageManagerService extends IPackageManager.Stub {
return -1;
}
+ private void replacePackageLP(String name, PackageSetting newp) {
+ PackageSetting p = mPackages.get(name);
+ if (p != null) {
+ if (p.sharedUser != null) {
+ p.sharedUser.packages.remove(p);
+ p.sharedUser.packages.add(newp);
+ } else {
+ replaceUserIdLP(p.userId, newp);
+ }
+ }
+ mPackages.put(name, newp);
+ }
+
private boolean addUserIdLP(int uid, Object obj, Object name) {
if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
return false;
@@ -8553,6 +8569,16 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
+ private void replaceUserIdLP(int uid, Object obj) {
+ if (uid >= FIRST_APPLICATION_UID) {
+ int N = mUserIds.size();
+ final int index = uid - FIRST_APPLICATION_UID;
+ if (index < N) mUserIds.set(index, obj);
+ } else {
+ mOtherUserIds.put(uid, obj);
+ }
+ }
+
void writeLP() {
//Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);