summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt14
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java2
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java7
-rw-r--r--core/java/android/app/ActivityManagerNative.java12
-rw-r--r--core/java/android/app/ApplicationPackageManager.java16
-rw-r--r--core/java/android/app/ContextImpl.java16
-rw-r--r--core/java/android/app/IActivityManager.java4
-rw-r--r--core/java/android/content/Context.java10
-rw-r--r--core/java/android/content/ContextWrapper.java12
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java9
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl5
-rw-r--r--core/java/android/content/pm/ManifestDigest.java16
-rw-r--r--core/java/android/content/pm/PackageCleanItem.aidl18
-rw-r--r--core/java/android/content/pm/PackageCleanItem.java79
-rw-r--r--core/java/android/content/pm/PackageInfoLite.java7
-rw-r--r--core/java/android/content/pm/PackageManager.java50
-rw-r--r--core/java/android/content/pm/PackageParser.java149
-rw-r--r--core/java/android/content/pm/PackageUserState.java50
-rw-r--r--core/java/android/os/UserHandle.java3
-rw-r--r--core/java/com/android/internal/content/PackageHelper.java1
-rwxr-xr-xcore/tests/coretests/src/android/content/pm/PackageManagerTests.java12
-rw-r--r--packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java12
-rw-r--r--services/java/com/android/server/am/ActiveServices.java10
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java13
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java622
-rw-r--r--services/java/com/android/server/pm/PackageSettingBase.java189
-rw-r--r--services/java/com/android/server/pm/Settings.java249
-rw-r--r--services/java/com/android/server/pm/UserManagerService.java11
-rw-r--r--test-runner/src/android/test/mock/MockContext.java12
-rw-r--r--test-runner/src/android/test/mock/MockPackageManager.java10
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java12
31 files changed, 1176 insertions, 456 deletions
diff --git a/api/current.txt b/api/current.txt
index d053109..bcb6fab 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6293,6 +6293,7 @@ package android.content.pm {
field public static final int FLAG_EXTERNAL_STORAGE = 262144; // 0x40000
field public static final int FLAG_FACTORY_TEST = 16; // 0x10
field public static final int FLAG_HAS_CODE = 4; // 0x4
+ field public static final int FLAG_INSTALLED = 8388608; // 0x800000
field public static final int FLAG_KILL_AFTER_RESTORE = 65536; // 0x10000
field public static final int FLAG_LARGE_HEAP = 1048576; // 0x100000
field public static final int FLAG_PERSISTENT = 8; // 0x8
@@ -6629,6 +6630,17 @@ package android.content.pm {
field public java.lang.String packageName;
}
+ public class PackageUserState {
+ ctor public PackageUserState();
+ ctor public PackageUserState(android.content.pm.PackageUserState);
+ field public java.util.HashSet disabledComponents;
+ field public int enabled;
+ field public java.util.HashSet enabledComponents;
+ field public boolean installed;
+ field public boolean notLaunched;
+ field public boolean stopped;
+ }
+
public class PathPermission extends android.os.PatternMatcher {
ctor public PathPermission(java.lang.String, int, java.lang.String, java.lang.String);
ctor public PathPermission(android.os.Parcel);
@@ -26928,6 +26940,7 @@ package android.webkit {
method public synchronized int getDefaultFixedFontSize();
method public synchronized int getDefaultFontSize();
method public synchronized java.lang.String getDefaultTextEncodingName();
+ method public static java.lang.String getDefaultUserAgent(android.content.Context);
method public android.webkit.WebSettings.ZoomDensity getDefaultZoom();
method public boolean getDisplayZoomControls();
method public synchronized boolean getDomStorageEnabled();
@@ -26958,7 +26971,6 @@ package android.webkit {
method public synchronized boolean getUseWideViewPort();
method public deprecated synchronized int getUserAgent();
method public synchronized java.lang.String getUserAgentString();
- method public static java.lang.String getDefaultUserAgent(android.content.Context);
method public void setAllowContentAccess(boolean);
method public void setAllowFileAccess(boolean);
method public abstract void setAllowFileAccessFromFileURLs(boolean);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index a79eb14..22fc1ad 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -393,7 +393,7 @@ public class Am {
private void runStartService() throws Exception {
Intent intent = makeIntent();
System.out.println("Starting service: " + intent);
- ComponentName cn = mAm.startService(null, intent, intent.getType());
+ ComponentName cn = mAm.startService(null, intent, intent.getType(), 0);
if (cn == null) {
System.err.println("Error: Not found; no service started.");
}
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index b34fd05..32865a4 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -776,7 +776,7 @@ public final class Pm {
}
private void runInstall() {
- int installFlags = 0;
+ int installFlags = PackageManager.INSTALL_ALL_USERS;
String installerPackageName = null;
String opt;
@@ -811,6 +811,8 @@ public final class Pm {
} else if (opt.equals("-f")) {
// Override if -s option is specified.
installFlags |= PackageManager.INSTALL_INTERNAL;
+ } else if (opt.equals("-d")) {
+ installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
} else if (opt.equals("--algo")) {
algo = nextOptionData();
if (algo == null) {
@@ -1105,7 +1107,7 @@ public final class Pm {
String opt = nextOption();
if (opt != null && opt.equals("-k")) {
- unInstallFlags = PackageManager.DONT_DELETE_DATA;
+ unInstallFlags = PackageManager.DELETE_KEEP_DATA;
}
String pkg = nextArg();
@@ -1525,6 +1527,7 @@ public final class Pm {
System.err.println(" -i: specify the installer package name.");
System.err.println(" -s: install package on sdcard.");
System.err.println(" -f: install package on internal flash.");
+ System.err.println(" -d: allow version code downgrade.");
System.err.println("");
System.err.println("pm uninstall: removes a package from the system. Options:");
System.err.println(" -k: keep the data and cache directories around after package removal.");
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 3197a63..adc9434 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -697,7 +697,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
IApplicationThread app = ApplicationThreadNative.asInterface(b);
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
- ComponentName cn = startService(app, service, resolvedType);
+ int userId = data.readInt();
+ ComponentName cn = startService(app, service, resolvedType, userId);
reply.writeNoException();
ComponentName.writeToParcel(cn, reply);
return true;
@@ -709,7 +710,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
IApplicationThread app = ApplicationThreadNative.asInterface(b);
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
- int res = stopService(app, service, resolvedType);
+ int userId = data.readInt();
+ int res = stopService(app, service, resolvedType, userId);
reply.writeNoException();
reply.writeInt(res);
return true;
@@ -2523,7 +2525,7 @@ class ActivityManagerProxy implements IActivityManager
}
public ComponentName startService(IApplicationThread caller, Intent service,
- String resolvedType) throws RemoteException
+ String resolvedType, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -2531,6 +2533,7 @@ class ActivityManagerProxy implements IActivityManager
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
service.writeToParcel(data, 0);
data.writeString(resolvedType);
+ data.writeInt(userId);
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
ComponentName res = ComponentName.readFromParcel(reply);
@@ -2539,7 +2542,7 @@ class ActivityManagerProxy implements IActivityManager
return res;
}
public int stopService(IApplicationThread caller, Intent service,
- String resolvedType) throws RemoteException
+ String resolvedType, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -2547,6 +2550,7 @@ class ActivityManagerProxy implements IActivityManager
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
service.writeToParcel(data, 0);
data.writeString(resolvedType);
+ data.writeInt(userId);
mRemote.transact(STOP_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index f3f75ce..0f10c4f 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -45,6 +45,7 @@ import android.content.pm.ManifestDigest;
import android.content.pm.UserInfo;
import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
@@ -997,6 +998,21 @@ final class ApplicationPackageManager extends PackageManager {
}
@Override
+ public int installExistingPackage(String packageName)
+ throws NameNotFoundException {
+ try {
+ int res = mPM.installExistingPackage(packageName);
+ if (res == INSTALL_FAILED_INVALID_URI) {
+ throw new NameNotFoundException("Package " + packageName + " doesn't exist");
+ }
+ return res;
+ } catch (RemoteException e) {
+ // Should never happen!
+ throw new NameNotFoundException("Package " + packageName + " doesn't exist");
+ }
+ }
+
+ @Override
public void verifyPendingInstall(int id, int response) {
try {
mPM.verifyPendingInstall(id, response);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 0ae4d06..32086d7 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1220,11 +1220,21 @@ class ContextImpl extends Context {
@Override
public ComponentName startService(Intent service) {
+ return startServiceAsUser(service, Process.myUserHandle());
+ }
+
+ @Override
+ public boolean stopService(Intent service) {
+ return stopServiceAsUser(service, Process.myUserHandle());
+ }
+
+ @Override
+ public ComponentName startServiceAsUser(Intent service, UserHandle user) {
try {
service.setAllowFds(false);
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service,
- service.resolveTypeIfNeeded(getContentResolver()));
+ service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
if (cn != null && cn.getPackageName().equals("!")) {
throw new SecurityException(
"Not allowed to start service " + service
@@ -1237,12 +1247,12 @@ class ContextImpl extends Context {
}
@Override
- public boolean stopService(Intent service) {
+ public boolean stopServiceAsUser(Intent service, UserHandle user) {
try {
service.setAllowFds(false);
int res = ActivityManagerNative.getDefault().stopService(
mMainThread.getApplicationThread(), service,
- service.resolveTypeIfNeeded(getContentResolver()));
+ service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to stop service " + service);
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index a6d1995..c3e911e 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -133,9 +133,9 @@ public interface IActivityManager extends IInterface {
public PendingIntent getRunningServiceControlPanel(ComponentName service)
throws RemoteException;
public ComponentName startService(IApplicationThread caller, Intent service,
- String resolvedType) throws RemoteException;
+ String resolvedType, int userId) throws RemoteException;
public int stopService(IApplicationThread caller, Intent service,
- String resolvedType) throws RemoteException;
+ String resolvedType, int userId) throws RemoteException;
public boolean stopServiceToken(ComponentName className, IBinder token,
int startId) throws RemoteException;
public void setServiceForeground(ComponentName className, IBinder token,
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 1460bf5..dc6d93f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1414,6 +1414,16 @@ public abstract class Context {
public abstract boolean stopService(Intent service);
/**
+ * @hide like {@link #startService(Intent)} but for a specific user.
+ */
+ public abstract ComponentName startServiceAsUser(Intent service, UserHandle user);
+
+ /**
+ * @hide like {@link #stopService(Intent)} but for a specific user.
+ */
+ public abstract boolean stopServiceAsUser(Intent service, UserHandle user);
+
+ /**
* Connect to an application service, creating it if needed. This defines
* a dependency between your application and the service. The given
* <var>conn</var> will receive the service object when it is created and be
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 3a13725..4bbe44e 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -410,6 +410,18 @@ public class ContextWrapper extends Context {
return mBase.stopService(name);
}
+ /** @hide */
+ @Override
+ public ComponentName startServiceAsUser(Intent service, UserHandle user) {
+ return mBase.startServiceAsUser(service, user);
+ }
+
+ /** @hide */
+ @Override
+ public boolean stopServiceAsUser(Intent name, UserHandle user) {
+ return mBase.stopServiceAsUser(name, user);
+ }
+
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index cbabc7c..1a82d58 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -302,6 +302,12 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
public static final int FLAG_SUPPORTS_RTL = 1<<22;
/**
+ * Value for {@link #flags}: true if the application is currently
+ * installed for the calling user.
+ */
+ public static final int FLAG_INSTALLED = 1<<23;
+
+ /**
* Value for {@link #flags}: Set to true if the application has been
* installed using the forward lock option.
*
@@ -334,7 +340,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
* {@link #FLAG_SUPPORTS_NORMAL_SCREENS},
* {@link #FLAG_SUPPORTS_LARGE_SCREENS}, {@link #FLAG_SUPPORTS_XLARGE_SCREENS},
* {@link #FLAG_RESIZEABLE_FOR_SCREENS},
- * {@link #FLAG_SUPPORTS_SCREEN_DENSITIES}, {@link #FLAG_VM_SAFE_MODE}
+ * {@link #FLAG_SUPPORTS_SCREEN_DENSITIES}, {@link #FLAG_VM_SAFE_MODE},
+ * {@link #FLAG_INSTALLED}.
*/
public int flags = 0;
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 0be8b83..0e1fe3e 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -32,6 +32,7 @@ import android.content.pm.IPackageStatsObserver;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.ManifestDigest;
+import android.content.pm.PackageCleanItem;
import android.content.pm.ParceledListSlice;
import android.content.pm.ProviderInfo;
import android.content.pm.PermissionGroupInfo;
@@ -351,7 +352,7 @@ interface IPackageManager {
*/
void updateExternalMediaStatus(boolean mounted, boolean reportStatus);
- String nextPackageToClean(String lastPackage);
+ PackageCleanItem nextPackageToClean(in PackageCleanItem lastPackage);
void movePackage(String packageName, IPackageMoveObserver observer, int flags);
@@ -369,6 +370,8 @@ interface IPackageManager {
in VerificationParams verificationParams,
in ContainerEncryptionParams encryptionParams);
+ int installExistingPackage(String packageName);
+
void verifyPendingInstall(int id, int verificationCode);
void extendVerificationTimeout(int id, int verificationCodeAtTimeout, long millisecondsToDelay);
diff --git a/core/java/android/content/pm/ManifestDigest.java b/core/java/android/content/pm/ManifestDigest.java
index f5e72e0..75505bc 100644
--- a/core/java/android/content/pm/ManifestDigest.java
+++ b/core/java/android/content/pm/ManifestDigest.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package android.content.pm;
import android.os.Parcel;
diff --git a/core/java/android/content/pm/PackageCleanItem.aidl b/core/java/android/content/pm/PackageCleanItem.aidl
new file mode 100644
index 0000000..9bb203e
--- /dev/null
+++ b/core/java/android/content/pm/PackageCleanItem.aidl
@@ -0,0 +1,18 @@
+/* Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.content.pm;
+
+parcelable PackageCleanItem;
diff --git a/core/java/android/content/pm/PackageCleanItem.java b/core/java/android/content/pm/PackageCleanItem.java
new file mode 100644
index 0000000..eea3b9c
--- /dev/null
+++ b/core/java/android/content/pm/PackageCleanItem.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** @hide */
+public class PackageCleanItem {
+ public final String packageName;
+ public final boolean andCode;
+
+ public PackageCleanItem(String packageName, boolean andCode) {
+ this.packageName = packageName;
+ this.andCode = andCode;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ try {
+ if (obj != null) {
+ PackageCleanItem other = (PackageCleanItem)obj;
+ return packageName.equals(other.packageName) && andCode == other.andCode;
+ }
+ } catch (ClassCastException e) {
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result = 31 * result + packageName.hashCode();
+ result = 31 * result + (andCode ? 1 : 0);
+ return result;
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int parcelableFlags) {
+ dest.writeString(packageName);
+ dest.writeInt(andCode ? 1 : 0);
+ }
+
+ public static final Parcelable.Creator<PackageCleanItem> CREATOR
+ = new Parcelable.Creator<PackageCleanItem>() {
+ public PackageCleanItem createFromParcel(Parcel source) {
+ return new PackageCleanItem(source);
+ }
+
+ public PackageCleanItem[] newArray(int size) {
+ return new PackageCleanItem[size];
+ }
+ };
+
+ private PackageCleanItem(Parcel source) {
+ packageName = source.readString();
+ andCode = source.readInt() != 0;
+ }
+}
diff --git a/core/java/android/content/pm/PackageInfoLite.java b/core/java/android/content/pm/PackageInfoLite.java
index 9625944..a1566da 100644
--- a/core/java/android/content/pm/PackageInfoLite.java
+++ b/core/java/android/content/pm/PackageInfoLite.java
@@ -32,6 +32,11 @@ public class PackageInfoLite implements Parcelable {
public String packageName;
/**
+ * The android:versionCode of the package.
+ */
+ public int versionCode;
+
+ /**
* Specifies the recommended install location. Can be one of
* {@link #PackageHelper.RECOMMEND_INSTALL_INTERNAL} to install on internal storage
* {@link #PackageHelper.RECOMMEND_INSTALL_EXTERNAL} to install on external media
@@ -58,6 +63,7 @@ public class PackageInfoLite implements Parcelable {
public void writeToParcel(Parcel dest, int parcelableFlags) {
dest.writeString(packageName);
+ dest.writeInt(versionCode);
dest.writeInt(recommendedInstallLocation);
dest.writeInt(installLocation);
@@ -82,6 +88,7 @@ public class PackageInfoLite implements Parcelable {
private PackageInfoLite(Parcel source) {
packageName = source.readString();
+ versionCode = source.readInt();
recommendedInstallLocation = source.readInt();
installLocation = source.readInt();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index b3e98e7..0d99d3f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -310,6 +310,23 @@ public abstract class PackageManager {
public static final int INSTALL_FROM_ADB = 0x00000020;
/**
+ * Flag parameter for {@link #installPackage} to indicate that this install
+ * should immediately be visible to all users.
+ *
+ * @hide
+ */
+ public static final int INSTALL_ALL_USERS = 0x00000040;
+
+ /**
+ * Flag parameter for {@link #installPackage} to indicate that it is okay
+ * to install an update to an app where the newly installed app has a lower
+ * version code than the currently installed app.
+ *
+ * @hide
+ */
+ public static final int INSTALL_ALLOW_DOWNGRADE = 0x00000080;
+
+ /**
* Flag parameter for
* {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate
* that you don't want to kill the app containing the component. Be careful when you set this
@@ -529,6 +546,14 @@ public abstract class PackageManager {
public static final int INSTALL_FAILED_UID_CHANGED = -24;
/**
+ * Installation return code: this is passed to the {@link IPackageInstallObserver} by
+ * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
+ * the new package has an older version code than the currently installed package.
+ * @hide
+ */
+ public static final int INSTALL_FAILED_VERSION_DOWNGRADE = -25;
+
+ /**
* 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
@@ -625,7 +650,15 @@ public abstract class PackageManager {
*
* @hide
*/
- public static final int DONT_DELETE_DATA = 0x00000001;
+ public static final int DELETE_KEEP_DATA = 0x00000001;
+
+ /**
+ * Flag parameter for {@link #deletePackage} to indicate that you want the
+ * package deleted for all users.
+ *
+ * @hide
+ */
+ public static final int DELETE_ALL_USERS = 0x00000002;
/**
* Return code for when package deletion succeeds. This is passed to the
@@ -2175,8 +2208,8 @@ public abstract class PackageManager {
if ((flags & GET_SIGNATURES) != 0) {
packageParser.collectCertificates(pkg, 0);
}
- return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0, null, false,
- COMPONENT_ENABLED_STATE_DEFAULT);
+ PackageUserState state = new PackageUserState();
+ return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0, null, state);
}
/**
@@ -2267,6 +2300,14 @@ public abstract class PackageManager {
ContainerEncryptionParams encryptionParams);
/**
+ * If there is already an application with the given package name installed
+ * on the system for other users, also install it for the calling user.
+ * @hide
+ */
+ public abstract int installExistingPackage(String packageName)
+ throws NameNotFoundException;
+
+ /**
* Allows a package listening to the
* {@link Intent#ACTION_PACKAGE_NEEDS_VERIFICATION package verification
* broadcast} to respond to the package manager. The response must include
@@ -2337,7 +2378,8 @@ public abstract class PackageManager {
* @param observer An observer callback to get notified when the package deletion is
* complete. {@link android.content.pm.IPackageDeleteObserver#packageDeleted(boolean)} will be
* called when that happens. observer may be null to indicate that no callback is desired.
- * @param flags - possible values: {@link #DONT_DELETE_DATA}
+ * @param flags - possible values: {@link #DELETE_KEEP_DATA},
+ * {@link #DELETE_ALL_USERS}.
*
* @hide
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ac75040..237f5c5 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -203,11 +203,14 @@ public class PackageParser {
*/
public static class PackageLite {
public final String packageName;
+ public final int versionCode;
public final int installLocation;
public final VerifierInfo[] verifiers;
- public PackageLite(String packageName, int installLocation, List<VerifierInfo> verifiers) {
+ public PackageLite(String packageName, int versionCode,
+ int installLocation, List<VerifierInfo> verifiers) {
this.packageName = packageName;
+ this.versionCode = versionCode;
this.installLocation = installLocation;
this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
}
@@ -243,14 +246,15 @@ public class PackageParser {
return name.endsWith(".apk");
}
+ /*
public static PackageInfo generatePackageInfo(PackageParser.Package p,
int gids[], int flags, long firstInstallTime, long lastUpdateTime,
HashSet<String> grantedPermissions) {
-
+ PackageUserState state = new PackageUserState();
return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
- grantedPermissions, false, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
- UserHandle.getCallingUserId());
+ grantedPermissions, state, UserHandle.getCallingUserId());
}
+ */
/**
* Generate and return the {@link PackageInfo} for a parsed package.
@@ -260,23 +264,30 @@ public class PackageParser {
*/
public static PackageInfo generatePackageInfo(PackageParser.Package p,
int gids[], int flags, long firstInstallTime, long lastUpdateTime,
- HashSet<String> grantedPermissions, boolean stopped, int enabledState) {
+ HashSet<String> grantedPermissions, PackageUserState state) {
return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
- grantedPermissions, stopped, enabledState, UserHandle.getCallingUserId());
+ grantedPermissions, state, UserHandle.getCallingUserId());
+ }
+
+ private static boolean checkUseInstalled(int flags, PackageUserState state) {
+ return state.installed || ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0);
}
public static PackageInfo generatePackageInfo(PackageParser.Package p,
int gids[], int flags, long firstInstallTime, long lastUpdateTime,
- HashSet<String> grantedPermissions, boolean stopped, int enabledState, int userId) {
+ HashSet<String> grantedPermissions, PackageUserState state, int userId) {
+ if (!checkUseInstalled(flags, state)) {
+ return null;
+ }
PackageInfo pi = new PackageInfo();
pi.packageName = p.packageName;
pi.versionCode = p.mVersionCode;
pi.versionName = p.mVersionName;
pi.sharedUserId = p.mSharedUserId;
pi.sharedUserLabel = p.mSharedUserLabel;
- pi.applicationInfo = generateApplicationInfo(p, flags, stopped, enabledState, userId);
+ pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
pi.installLocation = p.installLocation;
pi.firstInstallTime = firstInstallTime;
pi.lastUpdateTime = lastUpdateTime;
@@ -312,7 +323,7 @@ public class PackageParser {
if (activity.info.enabled
|| (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
pi.activities[j++] = generateActivityInfo(p.activities.get(i), flags,
- stopped, enabledState, userId);
+ state, userId);
}
}
}
@@ -334,7 +345,7 @@ public class PackageParser {
if (activity.info.enabled
|| (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
pi.receivers[j++] = generateActivityInfo(p.receivers.get(i), flags,
- stopped, enabledState, userId);
+ state, userId);
}
}
}
@@ -355,8 +366,8 @@ public class PackageParser {
final Service service = p.services.get(i);
if (service.info.enabled
|| (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.services[j++] = generateServiceInfo(p.services.get(i), flags, stopped,
- enabledState, userId);
+ pi.services[j++] = generateServiceInfo(p.services.get(i), flags,
+ state, userId);
}
}
}
@@ -377,8 +388,8 @@ public class PackageParser {
final Provider provider = p.providers.get(i);
if (provider.info.enabled
|| (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags, stopped,
- enabledState, userId);
+ pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags,
+ state, userId);
}
}
}
@@ -840,11 +851,19 @@ public class PackageParser {
return null;
}
int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
+ int versionCode = 0;
+ int numFound = 0;
for (int i = 0; i < attrs.getAttributeCount(); i++) {
String attr = attrs.getAttributeName(i);
if (attr.equals("installLocation")) {
installLocation = attrs.getAttributeIntValue(i,
PARSE_DEFAULT_INSTALL_LOCATION);
+ numFound++;
+ } else if (attr.equals("versionCode")) {
+ versionCode = attrs.getAttributeIntValue(i, 0);
+ numFound++;
+ }
+ if (numFound >= 2) {
break;
}
}
@@ -867,7 +886,7 @@ public class PackageParser {
}
}
- return new PackageLite(pkgName.intern(), installLocation, verifiers);
+ return new PackageLite(pkgName.intern(), versionCode, installLocation, verifiers);
}
/**
@@ -3458,13 +3477,25 @@ public class PackageParser {
}
}
- private static boolean copyNeeded(int flags, Package p, int enabledState, Bundle metaData) {
- if (enabledState != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
- boolean enabled = enabledState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+ private static boolean copyNeeded(int flags, Package p,
+ PackageUserState state, Bundle metaData, int userId) {
+ if (userId != 0) {
+ // We always need to copy for other users, since we need
+ // to fix up the uid.
+ return true;
+ }
+ if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
+ boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
if (p.applicationInfo.enabled != enabled) {
return true;
}
}
+ if (!state.installed) {
+ return true;
+ }
+ if (state.stopped) {
+ return true;
+ }
if ((flags & PackageManager.GET_META_DATA) != 0
&& (metaData != null || p.mAppMetaData != null)) {
return true;
@@ -3476,32 +3507,34 @@ public class PackageParser {
return false;
}
- public static ApplicationInfo generateApplicationInfo(Package p, int flags, boolean stopped,
- int enabledState) {
- return generateApplicationInfo(p, flags, stopped, enabledState, UserHandle.getCallingUserId());
+ public static ApplicationInfo generateApplicationInfo(Package p, int flags,
+ PackageUserState state) {
+ return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
}
public static ApplicationInfo generateApplicationInfo(Package p, int flags,
- boolean stopped, int enabledState, int userId) {
+ PackageUserState state, int userId) {
if (p == null) return null;
- if (!copyNeeded(flags, p, enabledState, null) && userId == 0) {
+ if (!checkUseInstalled(flags, state)) {
+ return null;
+ }
+ if (!copyNeeded(flags, p, state, null, userId)) {
// CompatibilityMode is global state. It's safe to modify the instance
// of the package.
if (!sCompatibilityModeEnabled) {
p.applicationInfo.disableCompatibilityMode();
}
- if (stopped) {
- p.applicationInfo.flags |= ApplicationInfo.FLAG_STOPPED;
- } else {
- p.applicationInfo.flags &= ~ApplicationInfo.FLAG_STOPPED;
- }
- if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+ // Make sure we report as installed. Also safe to do, since the
+ // default state should be installed (we will always copy if we
+ // need to report it is not installed).
+ p.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
+ if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
p.applicationInfo.enabled = true;
- } else if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
- || enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
+ } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+ || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
p.applicationInfo.enabled = false;
}
- p.applicationInfo.enabledSetting = enabledState;
+ p.applicationInfo.enabledSetting = state.enabled;
return p.applicationInfo;
}
@@ -3520,18 +3553,23 @@ public class PackageParser {
if (!sCompatibilityModeEnabled) {
ai.disableCompatibilityMode();
}
- if (stopped) {
+ if (state.stopped) {
ai.flags |= ApplicationInfo.FLAG_STOPPED;
} else {
ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
}
- if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+ if (state.installed) {
+ ai.flags |= ApplicationInfo.FLAG_INSTALLED;
+ } else {
+ ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
+ }
+ if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
ai.enabled = true;
- } else if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
- || enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
+ } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+ || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
ai.enabled = false;
}
- ai.enabledSetting = enabledState;
+ ai.enabledSetting = state.enabled;
return ai;
}
@@ -3578,16 +3616,19 @@ public class PackageParser {
}
}
- public static final ActivityInfo generateActivityInfo(Activity a, int flags, boolean stopped,
- int enabledState, int userId) {
+ public static final ActivityInfo generateActivityInfo(Activity a, int flags,
+ PackageUserState state, int userId) {
if (a == null) return null;
- if (!copyNeeded(flags, a.owner, enabledState, a.metaData) && userId == 0) {
+ if (!checkUseInstalled(flags, state)) {
+ return null;
+ }
+ if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
return a.info;
}
// Make shallow copies so we can store the metadata safely
ActivityInfo ai = new ActivityInfo(a.info);
ai.metaData = a.metaData;
- ai.applicationInfo = generateApplicationInfo(a.owner, flags, stopped, enabledState, userId);
+ ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
return ai;
}
@@ -3612,17 +3653,19 @@ public class PackageParser {
}
}
- public static final ServiceInfo generateServiceInfo(Service s, int flags, boolean stopped,
- int enabledState, int userId) {
+ public static final ServiceInfo generateServiceInfo(Service s, int flags,
+ PackageUserState state, int userId) {
if (s == null) return null;
- if (!copyNeeded(flags, s.owner, enabledState, s.metaData)
- && userId == UserHandle.getUserId(s.info.applicationInfo.uid)) {
+ if (!checkUseInstalled(flags, state)) {
+ return null;
+ }
+ if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
return s.info;
}
// Make shallow copies so we can store the metadata safely
ServiceInfo si = new ServiceInfo(s.info);
si.metaData = s.metaData;
- si.applicationInfo = generateApplicationInfo(s.owner, flags, stopped, enabledState, userId);
+ si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
return si;
}
@@ -3655,13 +3698,15 @@ public class PackageParser {
}
}
- public static final ProviderInfo generateProviderInfo(Provider p, int flags, boolean stopped,
- int enabledState, int userId) {
+ public static final ProviderInfo generateProviderInfo(Provider p, int flags,
+ PackageUserState state, int userId) {
if (p == null) return null;
- if (!copyNeeded(flags, p.owner, enabledState, p.metaData)
+ if (!checkUseInstalled(flags, state)) {
+ return null;
+ }
+ if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
&& ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
- || p.info.uriPermissionPatterns == null)
- && userId == 0) {
+ || p.info.uriPermissionPatterns == null)) {
return p.info;
}
// Make shallow copies so we can store the metadata safely
@@ -3670,7 +3715,7 @@ public class PackageParser {
if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
pi.uriPermissionPatterns = null;
}
- pi.applicationInfo = generateApplicationInfo(p.owner, flags, stopped, enabledState, userId);
+ pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
return pi;
}
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
new file mode 100644
index 0000000..1a71bfb
--- /dev/null
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+
+import java.util.HashSet;
+
+/**
+ * Per-user state information about a package.
+ */
+public class PackageUserState {
+ public boolean stopped;
+ public boolean notLaunched;
+ public boolean installed;
+ public int enabled;
+
+ public HashSet<String> disabledComponents;
+ public HashSet<String> enabledComponents;
+
+ public PackageUserState() {
+ installed = true;
+ enabled = COMPONENT_ENABLED_STATE_DEFAULT;
+ }
+
+ public PackageUserState(PackageUserState o) {
+ installed = o.installed;
+ stopped = o.stopped;
+ notLaunched = o.notLaunched;
+ enabled = o.enabled;
+ disabledComponents = o.disabledComponents != null
+ ? new HashSet<String>(o.disabledComponents) : null;
+ enabledComponents = o.enabledComponents != null
+ ? new HashSet<String>(o.enabledComponents) : null;
+ }
+} \ No newline at end of file
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 0843d85..d33bd80 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -28,6 +28,9 @@ public final class UserHandle implements Parcelable {
/** @hide A user id to indicate all users on the device */
public static final int USER_ALL = -1;
+ /** @hide A user handle to indicate all users on the device */
+ public static final UserHandle ALL = new UserHandle(USER_ALL);
+
/** @hide A user id to indicate the currently active user */
public static final int USER_CURRENT = -2;
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index 246b0c9..c5e7d9d 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -49,6 +49,7 @@ public class PackageHelper {
public static final int RECOMMEND_FAILED_ALREADY_EXISTS = -4;
public static final int RECOMMEND_MEDIA_UNAVAILABLE = -5;
public static final int RECOMMEND_FAILED_INVALID_URI = -6;
+ public static final int RECOMMEND_FAILED_VERSION_DOWNGRADE = -7;
private static final boolean localLOGV = true;
private static final String TAG = "PackageHelper";
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 6e1b9d6..a1fd14e 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -864,7 +864,7 @@ public class PackageManagerTests extends AndroidTestCase {
public void deleteFromRawResource(int iFlags, int dFlags) {
InstallParams ip = sampleInstallFromRawResource(iFlags, false);
- boolean retainData = ((dFlags & PackageManager.DONT_DELETE_DATA) != 0);
+ boolean retainData = ((dFlags & PackageManager.DELETE_KEEP_DATA) != 0);
GenericReceiver receiver = new DeleteReceiver(ip.pkg.packageName);
DeleteObserver observer = new DeleteObserver();
try {
@@ -914,12 +914,12 @@ public class PackageManagerTests extends AndroidTestCase {
@LargeTest
public void testDeleteNormalInternalRetainData() {
- deleteFromRawResource(0, PackageManager.DONT_DELETE_DATA);
+ deleteFromRawResource(0, PackageManager.DELETE_KEEP_DATA);
}
@LargeTest
public void testDeleteFwdLockedInternalRetainData() {
- deleteFromRawResource(PackageManager.INSTALL_FORWARD_LOCK, PackageManager.DONT_DELETE_DATA);
+ deleteFromRawResource(PackageManager.INSTALL_FORWARD_LOCK, PackageManager.DELETE_KEEP_DATA);
}
@LargeTest
@@ -929,7 +929,7 @@ public class PackageManagerTests extends AndroidTestCase {
return;
}
- deleteFromRawResource(PackageManager.INSTALL_EXTERNAL, PackageManager.DONT_DELETE_DATA);
+ deleteFromRawResource(PackageManager.INSTALL_EXTERNAL, PackageManager.DELETE_KEEP_DATA);
}
/* sdcard mount/unmount tests ******/
@@ -1656,7 +1656,7 @@ public class PackageManagerTests extends AndroidTestCase {
false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
// Delete the package now retaining data.
GenericReceiver receiver = new DeleteReceiver(ip.pkg.packageName);
- invokeDeletePackage(ip.pkg.packageName, PackageManager.DONT_DELETE_DATA, receiver);
+ invokeDeletePackage(ip.pkg.packageName, PackageManager.DELETE_KEEP_DATA, receiver);
assertTrue(invokeMovePackageFail(ip.pkg.packageName, moveFlags, result));
} catch (Exception e) {
failStr(e);
@@ -2532,7 +2532,7 @@ public class PackageManagerTests extends AndroidTestCase {
GenericReceiver receiver = new DeleteReceiver(ip.pkg.packageName);
try {
- invokeDeletePackage(ip.pkg.packageName, PackageManager.DONT_DELETE_DATA, receiver);
+ invokeDeletePackage(ip.pkg.packageName, PackageManager.DELETE_KEEP_DATA, receiver);
} catch (Exception e) {
failStr(e);
}
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index a28b8a4..b36bd55 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -26,6 +26,7 @@ import android.content.pm.MacAuthenticatedInputStream;
import android.content.pm.ContainerEncryptionParams;
import android.content.pm.IPackageManager;
import android.content.pm.LimitedLengthInputStream;
+import android.content.pm.PackageCleanItem;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfoLite;
import android.content.pm.PackageManager;
@@ -181,6 +182,7 @@ public class DefaultContainerService extends IntentService {
}
ret.packageName = pkg.packageName;
+ ret.versionCode = pkg.versionCode;
ret.installLocation = pkg.installLocation;
ret.verifiers = pkg.verifiers;
@@ -268,12 +270,14 @@ public class DefaultContainerService extends IntentService {
if (PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE.equals(intent.getAction())) {
IPackageManager pm = IPackageManager.Stub.asInterface(
ServiceManager.getService("package"));
- String pkg = null;
+ PackageCleanItem pkg = null;
try {
while ((pkg=pm.nextPackageToClean(pkg)) != null) {
- eraseFiles(Environment.getExternalStorageAppDataDirectory(pkg));
- eraseFiles(Environment.getExternalStorageAppMediaDirectory(pkg));
- eraseFiles(Environment.getExternalStorageAppObbDirectory(pkg));
+ eraseFiles(Environment.getExternalStorageAppDataDirectory(pkg.packageName));
+ eraseFiles(Environment.getExternalStorageAppMediaDirectory(pkg.packageName));
+ if (pkg.andCode) {
+ eraseFiles(Environment.getExternalStorageAppObbDirectory(pkg.packageName));
+ }
}
} catch (RemoteException e) {
}
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index e222936..e6bcaa1 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -210,7 +210,7 @@ public class ActiveServices {
ComponentName startServiceLocked(IApplicationThread caller,
Intent service, String resolvedType,
- int callingPid, int callingUid) {
+ int callingPid, int callingUid, int userId) {
if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
+ " type=" + resolvedType + " args=" + service.getExtras());
@@ -226,7 +226,7 @@ public class ActiveServices {
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType,
- callingPid, callingUid, UserHandle.getUserId(callingUid), true);
+ callingPid, callingUid, userId, true);
if (res == null) {
return null;
}
@@ -264,7 +264,7 @@ public class ActiveServices {
}
int stopServiceLocked(IApplicationThread caller, Intent service,
- String resolvedType) {
+ String resolvedType, int userId) {
if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
+ " type=" + resolvedType);
@@ -278,9 +278,7 @@ public class ActiveServices {
// If this service is active, make sure it is stopped.
ServiceLookupResult r = retrieveServiceLocked(service, resolvedType,
- Binder.getCallingPid(), Binder.getCallingUid(),
- callerApp == null ? UserHandle.getCallingUserId() : callerApp.userId,
- false);
+ Binder.getCallingPid(), Binder.getCallingUid(), userId, false);
if (r != null) {
if (r.record != null) {
final long origId = Binder.clearCallingIdentity();
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 8fc12d3..2b4f8b1 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -10554,7 +10554,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
public ComponentName startService(IApplicationThread caller, Intent service,
- String resolvedType) {
+ String resolvedType, int userId) {
enforceNotIsolatedCaller("startService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
@@ -10566,9 +10566,10 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
+ checkValidCaller(callingUid, userId);
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(caller, service,
- resolvedType, callingPid, callingUid);
+ resolvedType, callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
@@ -10581,22 +10582,24 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.v(TAG, "startServiceInPackage: " + service + " type=" + resolvedType);
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(null, service,
- resolvedType, -1, uid);
+ resolvedType, -1, uid, UserHandle.getUserId(uid));
Binder.restoreCallingIdentity(origId);
return res;
}
}
public int stopService(IApplicationThread caller, Intent service,
- String resolvedType) {
+ String resolvedType, int userId) {
enforceNotIsolatedCaller("stopService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
+ checkValidCaller(Binder.getCallingUid(), userId);
+
synchronized(this) {
- return mServices.stopServiceLocked(caller, service, resolvedType);
+ return mServices.stopServiceLocked(caller, service, resolvedType, userId);
}
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 4252b90..b0aca21 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -64,11 +64,12 @@ import android.content.pm.IPackageManager;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.InstrumentationInfo;
+import android.content.pm.PackageCleanItem;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfoLite;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
-import android.content.pm.UserInfo;
+import android.content.pm.PackageUserState;
import android.content.pm.PackageParser.ActivityIntentInfo;
import android.content.pm.PackageStats;
import android.content.pm.ParceledListSlice;
@@ -103,7 +104,6 @@ import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
-import android.os.UserManager;
import android.provider.Settings.Secure;
import android.security.SystemKeyStore;
import android.util.DisplayMetrics;
@@ -168,6 +168,7 @@ public class PackageManagerService extends IPackageManager.Stub {
static final boolean DEBUG_UPGRADE = false;
private static final boolean DEBUG_INSTALL = false;
private static final boolean DEBUG_REMOVE = false;
+ private static final boolean DEBUG_BROADCASTS = false;
private static final boolean DEBUG_SHOW_INFO = false;
private static final boolean DEBUG_PACKAGE_INFO = false;
private static final boolean DEBUG_INTENT_MATCHING = false;
@@ -662,15 +663,21 @@ public class PackageManagerService extends IPackageManager.Stub {
break;
}
case START_CLEANING_PACKAGE: {
- String packageName = (String)msg.obj;
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
+ PackageCleanItem item = new PackageCleanItem((String)msg.obj,
+ msg.arg2 != 0);
synchronized (mPackages) {
- if (!mSettings.mPackagesToBeCleaned.contains(packageName)) {
- mSettings.mPackagesToBeCleaned.add(packageName);
+ if (msg.arg1 == UserHandle.USER_ALL) {
+ int[] users = sUserManager.getUserIds();
+ for (int user : users) {
+ mSettings.addPackageToCleanLPw(user, item);
+ }
+ } else {
+ mSettings.addPackageToCleanLPw(msg.arg1, item);
}
}
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- startCleaningPackages();
+ startCleaningPackages(-1);
} break;
case POST_INSTALL: {
if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
@@ -692,15 +699,14 @@ public class PackageManagerService extends IPackageManager.Stub {
}
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
res.pkg.applicationInfo.packageName,
- extras, null, null, UserHandle.USER_ALL);
+ extras, null, null, res.users);
if (update) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
res.pkg.applicationInfo.packageName,
- extras, null, null, UserHandle.USER_ALL);
+ extras, null, null, res.users);
sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
null, null,
- res.pkg.applicationInfo.packageName, null,
- UserHandle.USER_ALL);
+ res.pkg.applicationInfo.packageName, null, res.users);
}
if (res.removedInfo.args != null) {
// Remove the replaced package's older resources safely now
@@ -1562,19 +1568,17 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageInfo generatePackageInfo(PackageParser.Package p, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
PackageInfo pi;
- if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
- // The package has been uninstalled but has retained data and resources.
- pi = PackageParser.generatePackageInfo(p, null, flags, 0, 0, null, false, 0, userId);
- } else {
- final PackageSetting ps = (PackageSetting) p.mExtras;
- if (ps == null) {
- return null;
- }
- final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
- pi = PackageParser.generatePackageInfo(p, gp.gids, flags,
- ps.firstInstallTime, ps.lastUpdateTime, gp.grantedPermissions,
- ps.getStopped(userId), ps.getEnabled(userId), userId);
- pi.applicationInfo.enabledSetting = ps.getEnabled(userId);
+ final PackageSetting ps = (PackageSetting) p.mExtras;
+ if (ps == null) {
+ return null;
+ }
+ final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
+ final PackageUserState state = ps.readUserState(userId);
+ pi = PackageParser.generatePackageInfo(p, gp.gids, flags,
+ ps.firstInstallTime, ps.lastUpdateTime, gp.grantedPermissions,
+ state, userId);
+ if (pi != null) {
+ pi.applicationInfo.enabledSetting = state.enabled;
pi.applicationInfo.enabled =
pi.applicationInfo.enabledSetting == COMPONENT_ENABLED_STATE_DEFAULT
|| pi.applicationInfo.enabledSetting == COMPONENT_ENABLED_STATE_ENABLED;
@@ -1741,14 +1745,15 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps != null) {
if (ps.pkg == null) {
- PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName, flags, userId);
+ PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName,
+ flags, userId);
if (pInfo != null) {
return pInfo.applicationInfo;
}
return null;
}
- return PackageParser.generateApplicationInfo(ps.pkg, flags, ps.getStopped(userId),
- ps.getEnabled(userId), userId);
+ return PackageParser.generateApplicationInfo(ps.pkg, flags,
+ ps.readUserState(userId), userId);
}
return null;
}
@@ -1758,20 +1763,23 @@ public class PackageManagerService extends IPackageManager.Stub {
if (!sUserManager.exists(userId)) return null;
PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps != null) {
- PackageParser.Package pkg = new PackageParser.Package(packageName);
- if (ps.pkg == null) {
- ps.pkg = new PackageParser.Package(packageName);
- ps.pkg.applicationInfo.packageName = packageName;
- ps.pkg.applicationInfo.flags = ps.pkgFlags;
- ps.pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
- ps.pkg.applicationInfo.sourceDir = ps.codePathString;
- ps.pkg.applicationInfo.dataDir =
+ PackageParser.Package pkg = ps.pkg;
+ if (pkg == null) {
+ if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) == 0) {
+ return null;
+ }
+ pkg = new PackageParser.Package(packageName);
+ pkg.applicationInfo.packageName = packageName;
+ pkg.applicationInfo.flags = ps.pkgFlags;
+ pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
+ pkg.applicationInfo.sourceDir = ps.codePathString;
+ pkg.applicationInfo.dataDir =
getDataPathForPackage(ps.pkg.packageName, 0).getPath();
- ps.pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
+ pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
}
- // ps.pkg.mSetEnabled = ps.getEnabled(userId);
- // ps.pkg.mSetStopped = ps.getStopped(userId);
- return generatePackageInfo(ps.pkg, flags, userId);
+ // pkg.mSetEnabled = ps.getEnabled(userId);
+ // pkg.mSetStopped = ps.getStopped(userId);
+ return generatePackageInfo(pkg, flags, userId);
}
return null;
}
@@ -1789,13 +1797,12 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps == null) return null;
// Note: isEnabledLP() does not apply here - always return info
- return PackageParser.generateApplicationInfo(p, flags, ps.getStopped(userId),
- ps.getEnabled(userId));
+ return PackageParser.generateApplicationInfo(p, flags, ps.readUserState(userId));
}
if ("android".equals(packageName)||"system".equals(packageName)) {
return mAndroidApplication;
}
- if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
+ if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
return generateApplicationInfoFromSettingsLPw(packageName, flags, userId);
}
}
@@ -1862,8 +1869,8 @@ public class PackageManagerService extends IPackageManager.Stub {
if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
if (ps == null) return null;
- return PackageParser.generateActivityInfo(a, flags, ps.getStopped(userId),
- ps.getEnabled(userId), userId);
+ return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
+ userId);
}
if (mResolveComponentName.equals(component)) {
return mResolveActivity;
@@ -1882,8 +1889,8 @@ public class PackageManagerService extends IPackageManager.Stub {
if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
if (ps == null) return null;
- return PackageParser.generateActivityInfo(a, flags, ps.getStopped(userId),
- ps.getEnabled(userId), userId);
+ return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
+ userId);
}
}
return null;
@@ -1899,8 +1906,8 @@ public class PackageManagerService extends IPackageManager.Stub {
if (s != null && mSettings.isEnabledLPr(s.info, flags, userId)) {
PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
if (ps == null) return null;
- return PackageParser.generateServiceInfo(s, flags, ps.getStopped(userId),
- ps.getEnabled(userId), userId);
+ return PackageParser.generateServiceInfo(s, flags, ps.readUserState(userId),
+ userId);
}
}
return null;
@@ -1916,8 +1923,8 @@ public class PackageManagerService extends IPackageManager.Stub {
if (p != null && mSettings.isEnabledLPr(p.info, flags, userId)) {
PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
if (ps == null) return null;
- return PackageParser.generateProviderInfo(p, flags, ps.getStopped(userId),
- ps.getEnabled(userId), userId);
+ return PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId),
+ userId);
}
}
return null;
@@ -2870,8 +2877,8 @@ public class PackageManagerService extends IPackageManager.Stub {
} else {
final PackageParser.Package p = mPackages.get(packageName);
if (p != null && ps != null) {
- ai = PackageParser.generateApplicationInfo(p, flags, ps.getStopped(userId),
- ps.getEnabled(userId), userId);
+ ai = PackageParser.generateApplicationInfo(p, flags,
+ ps.readUserState(userId), userId);
}
}
@@ -2901,10 +2908,13 @@ public class PackageManagerService extends IPackageManager.Stub {
&& (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
&& (!mSafeMode || isSystemApp(p))) {
PackageSetting ps = mSettings.mPackages.get(p.packageName);
- finalList.add(PackageParser.generateApplicationInfo(p, flags,
- ps != null ? ps.getStopped(userId) : false,
- ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
- userId));
+ if (ps != null) {
+ ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
+ ps.readUserState(userId), userId);
+ if (ai != null) {
+ finalList.add(ai);
+ }
+ }
}
}
}
@@ -2921,14 +2931,12 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageSetting ps = provider != null
? mSettings.mPackages.get(provider.owner.packageName)
: null;
- return provider != null
+ return ps != null
&& mSettings.isEnabledLPr(provider.info, flags, userId)
&& (!mSafeMode || (provider.info.applicationInfo.flags
&ApplicationInfo.FLAG_SYSTEM) != 0)
? PackageParser.generateProviderInfo(provider, flags,
- ps != null ? ps.getStopped(userId) : false,
- ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
- userId)
+ ps.readUserState(userId), userId)
: null;
}
}
@@ -2948,14 +2956,15 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageParser.Provider p = entry.getValue();
PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
- if (p.syncable
+ if (ps != null && p.syncable
&& (!mSafeMode || (p.info.applicationInfo.flags
&ApplicationInfo.FLAG_SYSTEM) != 0)) {
- outNames.add(entry.getKey());
- outInfo.add(PackageParser.generateProviderInfo(p, 0,
- ps != null ? ps.getStopped(userId) : false,
- ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
- userId));
+ ProviderInfo info = PackageParser.generateProviderInfo(p, 0,
+ ps.readUserState(userId), userId);
+ if (info != null) {
+ outNames.add(entry.getKey());
+ outInfo.add(info);
+ }
}
}
}
@@ -2973,7 +2982,7 @@ public class PackageManagerService extends IPackageManager.Stub {
while (i.hasNext()) {
final PackageParser.Provider p = i.next();
PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
- if (p.info.authority != null
+ if (ps != null && p.info.authority != null
&& (processName == null
|| (p.info.processName.equals(processName)
&& UserHandle.isSameApp(p.info.applicationInfo.uid, uid)))
@@ -2983,10 +2992,9 @@ public class PackageManagerService extends IPackageManager.Stub {
if (finalList == null) {
finalList = new ArrayList<ProviderInfo>(3);
}
- finalList.add(PackageParser.generateProviderInfo(p, flags,
- ps != null ? ps.getStopped(userId) : false,
- ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
- userId));
+ ProviderInfo info = PackageParser.generateProviderInfo(p, flags,
+ ps.readUserState(userId), userId);
+ finalList.add(info);
}
}
}
@@ -3047,7 +3055,7 @@ public class PackageManagerService extends IPackageManager.Stub {
continue;
}
PackageParser.Package pkg = scanPackageLI(file,
- flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);
+ flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
// Don't mess around with apps in system partition.
if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
@@ -3115,7 +3123,7 @@ public class PackageManagerService extends IPackageManager.Stub {
* Returns null in case of errors and the error code is stored in mLastScanError
*/
private PackageParser.Package scanPackageLI(File scanFile,
- int parseFlags, int scanMode, long currentTime) {
+ int parseFlags, int scanMode, long currentTime, UserHandle user) {
mLastScanError = PackageManager.INSTALL_SUCCEEDED;
String scanPath = scanFile.getPath();
parseFlags |= mDefParseFlags;
@@ -3215,7 +3223,7 @@ public class PackageManagerService extends IPackageManager.Stub {
*/
if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
!= PackageManager.SIGNATURE_MATCH) {
- deletePackageLI(pkg.packageName, true, 0, null, false);
+ deletePackageLI(pkg.packageName, null, true, 0, null, false);
ps = null;
} else {
/*
@@ -3268,7 +3276,7 @@ public class PackageManagerService extends IPackageManager.Stub {
setApplicationInfoPaths(pkg, codePath, resPath);
// Note that we invoke the following method only if we are about to unpack an application
PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
- | SCAN_UPDATE_SIGNATURE, currentTime);
+ | SCAN_UPDATE_SIGNATURE, currentTime, user);
/*
* If the system app should be overridden by a previously installed
@@ -3472,7 +3480,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
- int parseFlags, int scanMode, long currentTime) {
+ int parseFlags, int scanMode, long currentTime, UserHandle user) {
File scanFile = new File(pkg.mScanPath);
if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
pkg.applicationInfo.publicSourceDir == null) {
@@ -3664,7 +3672,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// the PkgSetting exists already and doesn't have to be created.
pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
destResourceFile, pkg.applicationInfo.nativeLibraryDir,
- pkg.applicationInfo.flags, true, false);
+ pkg.applicationInfo.flags, user, false);
if (pkgSetting == null) {
Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
@@ -4024,7 +4032,9 @@ public class PackageManagerService extends IPackageManager.Stub {
// Add the new setting to mPackages
mPackages.put(pkg.applicationInfo.packageName, pkg);
// Make sure we don't accidentally delete its data.
- mSettings.mPackagesToBeCleaned.remove(pkgName);
+ for (int i=0; i<mSettings.mPackagesToBeCleaned.size(); i++) {
+ mSettings.mPackagesToBeCleaned.valueAt(i).remove(pkgName);
+ }
// Take care of first install / last update times.
if (currentTime != 0) {
@@ -4840,7 +4850,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// System apps are never considered stopped for purposes of
// filtering, because there may be no way for the user to
// actually re-launch them.
- return ps.getStopped(userId) && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0;
+ return (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
+ && ps.getStopped(userId);
}
}
return false;
@@ -4863,12 +4874,17 @@ public class PackageManagerService extends IPackageManager.Stub {
&ApplicationInfo.FLAG_SYSTEM) == 0) {
return null;
}
- final ResolveInfo res = new ResolveInfo();
PackageSetting ps = (PackageSetting) activity.owner.mExtras;
- res.activityInfo = PackageParser.generateActivityInfo(activity, mFlags,
- ps != null ? ps.getStopped(userId) : false,
- ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
- userId);
+ if (ps == null) {
+ return null;
+ }
+ ActivityInfo ai = PackageParser.generateActivityInfo(activity, mFlags,
+ ps.readUserState(userId), userId);
+ if (ai == null) {
+ return null;
+ }
+ final ResolveInfo res = new ResolveInfo();
+ res.activityInfo = ai;
if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
res.filter = info;
}
@@ -5031,8 +5047,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// System apps are never considered stopped for purposes of
// filtering, because there may be no way for the user to
// actually re-launch them.
- return ps.getStopped(userId)
- && (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0;
+ return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
+ && ps.getStopped(userId);
}
}
return false;
@@ -5056,12 +5072,14 @@ public class PackageManagerService extends IPackageManager.Stub {
&ApplicationInfo.FLAG_SYSTEM) == 0) {
return null;
}
- final ResolveInfo res = new ResolveInfo();
PackageSetting ps = (PackageSetting) service.owner.mExtras;
- res.serviceInfo = PackageParser.generateServiceInfo(service, mFlags,
- ps != null ? ps.getStopped(userId) : false,
- ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
- userId);
+ if (ps == null) {
+ return null;
+ }
+ ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags,
+ ps.readUserState(userId), userId);
+ final ResolveInfo res = new ResolveInfo();
+ res.serviceInfo = si;
if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
res.filter = filter;
}
@@ -5152,13 +5170,14 @@ public class PackageManagerService extends IPackageManager.Stub {
};
static final void sendPackageBroadcast(String action, String pkg,
- Bundle extras, String targetPkg, IIntentReceiver finishedReceiver, int userId) {
+ Bundle extras, String targetPkg, IIntentReceiver finishedReceiver,
+ int[] userIds) {
IActivityManager am = ActivityManagerNative.getDefault();
if (am != null) {
try {
- int[] userIds = userId == UserHandle.USER_ALL
- ? sUserManager.getUserIds()
- : new int[] {userId};
+ if (userIds == null) {
+ userIds = sUserManager.getUserIds();
+ }
for (int id : userIds) {
final Intent intent = new Intent(action,
pkg != null ? Uri.fromParts("package", pkg, null) : null);
@@ -5170,11 +5189,18 @@ public class PackageManagerService extends IPackageManager.Stub {
}
// Modify the UID when posting to other users
int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
- if (uid > 0 && id > 0) {
+ if (uid > 0 && UserHandle.getUserId(uid) != id) {
uid = UserHandle.getUid(id, UserHandle.getAppId(uid));
intent.putExtra(Intent.EXTRA_UID, uid);
}
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ if (DEBUG_BROADCASTS) {
+ RuntimeException here = new RuntimeException("here");
+ here.fillInStackTrace();
+ Slog.d(TAG, "Sending to user " + id + ": "
+ + intent.toShortString(false, true, false, false)
+ + " " + intent.getExtras(), here);
+ }
am.broadcastIntent(null, intent, null, finishedReceiver,
0, null, null, null, finishedReceiver != null, false, id);
}
@@ -5192,8 +5218,9 @@ public class PackageManagerService extends IPackageManager.Stub {
return mMediaMounted || Environment.isExternalStorageEmulated();
}
- public String nextPackageToClean(String lastPackage) {
+ public PackageCleanItem nextPackageToClean(PackageCleanItem lastPackage) {
// writer
+ final int userId = UserHandle.getCallingUserId();
synchronized (mPackages) {
if (!isExternalMediaAvailable()) {
// If the external storage is no longer mounted at this point,
@@ -5201,34 +5228,65 @@ public class PackageManagerService extends IPackageManager.Stub {
// packages files and can not delete any more. Bail.
return null;
}
- if (lastPackage != null) {
- mSettings.mPackagesToBeCleaned.remove(lastPackage);
+ ArrayList<PackageCleanItem> pkgs = mSettings.mPackagesToBeCleaned.get(userId);
+ if (pkgs != null) {
+ if (lastPackage != null) {
+ pkgs.remove(lastPackage);
+ }
+ if (pkgs.size() > 0) {
+ return pkgs.get(0);
+ }
}
- return mSettings.mPackagesToBeCleaned.size() > 0
- ? mSettings.mPackagesToBeCleaned.get(0) : null;
}
+ // Move on to the next user to clean.
+ long ident = Binder.clearCallingIdentity();
+ try {
+ startCleaningPackages(userId);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ return null;
}
- void schedulePackageCleaning(String packageName) {
- mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName));
+ void schedulePackageCleaning(String packageName, int userId, boolean andCode) {
+ if (false) {
+ RuntimeException here = new RuntimeException("here");
+ here.fillInStackTrace();
+ Slog.d(TAG, "Schedule cleaning " + packageName + " user=" + userId
+ + " andCode=" + andCode, here);
+ }
+ mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE,
+ userId, andCode ? 1 : 0, packageName));
}
- void startCleaningPackages() {
+ void startCleaningPackages(int lastUser) {
// reader
+ int nextUser = -1;
synchronized (mPackages) {
if (!isExternalMediaAvailable()) {
return;
}
- if (mSettings.mPackagesToBeCleaned.size() <= 0) {
+ final int N = mSettings.mPackagesToBeCleaned.size();
+ if (N <= 0) {
return;
}
+ for (int i=0; i<N; i++) {
+ int user = mSettings.mPackagesToBeCleaned.keyAt(i);
+ if (user > lastUser) {
+ nextUser = user;
+ break;
+ }
+ }
+ if (nextUser < 0) {
+ nextUser = mSettings.mPackagesToBeCleaned.keyAt(0);
+ }
}
Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
IActivityManager am = ActivityManagerNative.getDefault();
if (am != null) {
try {
- am.startService(null, intent, null);
+ am.startService(null, intent, null, nextUser);
} catch (RemoteException e) {
}
}
@@ -5291,7 +5349,7 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageParser.PARSE_CHATTY |
PackageParser.PARSE_MUST_BE_APK,
SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
- System.currentTimeMillis());
+ System.currentTimeMillis(), null);
if (p != null) {
/*
* TODO this seems dangerous as the package may have
@@ -5320,13 +5378,13 @@ public class PackageManagerService extends IPackageManager.Stub {
extras.putInt(Intent.EXTRA_UID, removedUid);
extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
- extras, null, null, UserHandle.USER_ALL);
+ extras, null, null, null);
}
if (addedPackage != null) {
Bundle extras = new Bundle(1);
extras.putInt(Intent.EXTRA_UID, addedUid);
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
- extras, null, null, UserHandle.USER_ALL);
+ extras, null, null, null);
}
}
@@ -5365,6 +5423,12 @@ public class PackageManagerService extends IPackageManager.Stub {
null);
final int uid = Binder.getCallingUid();
+ UserHandle user;
+ if ((flags&PackageManager.INSTALL_ALL_USERS) != 0) {
+ user = UserHandle.ALL;
+ } else {
+ user = Process.myUserHandle();
+ }
final int filteredFlags;
@@ -5379,10 +5443,51 @@ public class PackageManagerService extends IPackageManager.Stub {
final Message msg = mHandler.obtainMessage(INIT_COPY);
msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
- verificationParams, encryptionParams);
+ verificationParams, encryptionParams, user);
mHandler.sendMessage(msg);
}
+ /**
+ * @hide
+ */
+ @Override
+ public int installExistingPackage(String packageName) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
+ null);
+ PackageSetting pkgSetting;
+ final int uid = Binder.getCallingUid();
+ final int userId = UserHandle.getUserId(uid);
+
+ long callingId = Binder.clearCallingIdentity();
+ try {
+ boolean sendAdded = false;
+ Bundle extras = new Bundle(1);
+
+ // writer
+ synchronized (mPackages) {
+ pkgSetting = mSettings.mPackages.get(packageName);
+ if (pkgSetting == null) {
+ return PackageManager.INSTALL_FAILED_INVALID_URI;
+ }
+ if (!pkgSetting.getInstalled(userId)) {
+ pkgSetting.setInstalled(true, userId);
+ mSettings.writePackageRestrictionsLPr(userId);
+ extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userId, pkgSetting.appId));
+ sendAdded = true;
+ }
+ }
+
+ if (sendAdded) {
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
+ packageName, extras, null, null, new int[] {userId});
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+
+ return PackageManager.INSTALL_SUCCEEDED;
+ }
+
@Override
public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
@@ -5840,17 +5945,19 @@ public class PackageManagerService extends IPackageManager.Stub {
private int mRet;
private File mTempPackage;
final ContainerEncryptionParams encryptionParams;
+ final UserHandle user;
InstallParams(Uri packageURI,
IPackageInstallObserver observer, int flags,
String installerPackageName, VerificationParams verificationParams,
- ContainerEncryptionParams encryptionParams) {
+ ContainerEncryptionParams encryptionParams, UserHandle user) {
this.mPackageURI = packageURI;
this.flags = flags;
this.observer = observer;
this.installerPackageName = installerPackageName;
this.verificationParams = verificationParams;
this.encryptionParams = encryptionParams;
+ this.user = user;
}
public ManifestDigest getManifestDigest() {
@@ -5860,6 +5967,10 @@ public class PackageManagerService extends IPackageManager.Stub {
return verificationParams.getManifestDigest();
}
+ public UserHandle getUser() {
+ return user;
+ }
+
private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
String packageName = pkgLite.packageName;
int installLocation = pkgLite.installLocation;
@@ -5869,6 +5980,16 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageParser.Package pkg = mPackages.get(packageName);
if (pkg != null) {
if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
+ // Check for downgrading.
+ if ((flags & PackageManager.INSTALL_ALLOW_DOWNGRADE) == 0) {
+ if (pkgLite.versionCode < pkg.mVersionCode) {
+ Slog.w(TAG, "Can't install update of " + packageName
+ + " update version " + pkgLite.versionCode
+ + " is older than installed version "
+ + pkg.mVersionCode);
+ return PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE;
+ }
+ }
// Check for updated system application.
if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
if (onSd) {
@@ -5995,6 +6116,8 @@ public class PackageManagerService extends IPackageManager.Stub {
ret = PackageManager.INSTALL_FAILED_INVALID_URI;
} else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
+ } else if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
+ ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
} else {
// Override with defaults if needed.
loc = installLocationPolicy(pkgLite, flags);
@@ -6338,14 +6461,17 @@ public class PackageManagerService extends IPackageManager.Stub {
final Uri packageURI;
final String installerPackageName;
final ManifestDigest manifestDigest;
+ final UserHandle user;
InstallArgs(Uri packageURI, IPackageInstallObserver observer, int flags,
- String installerPackageName, ManifestDigest manifestDigest) {
+ String installerPackageName, ManifestDigest manifestDigest,
+ UserHandle user) {
this.packageURI = packageURI;
this.flags = flags;
this.observer = observer;
this.installerPackageName = installerPackageName;
this.manifestDigest = manifestDigest;
+ this.user = user;
}
abstract void createCopyFile();
@@ -6396,11 +6522,12 @@ public class PackageManagerService extends IPackageManager.Stub {
FileInstallArgs(InstallParams params) {
super(params.getPackageUri(), params.observer, params.flags,
- params.installerPackageName, params.getManifestDigest());
+ params.installerPackageName, params.getManifestDigest(),
+ params.getUser());
}
FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
- super(null, null, 0, null, null);
+ super(null, null, 0, null, null, null);
File codeFile = new File(fullCodePath);
installDir = codeFile.getParentFile();
codeFileName = fullCodePath;
@@ -6409,7 +6536,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
- super(packageURI, null, 0, null, null);
+ super(packageURI, null, 0, null, null, null);
installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
String apkName = getNextCodePath(null, pkgName, ".apk");
codeFileName = new File(installDir, apkName + ".apk").getPath();
@@ -6683,13 +6810,15 @@ public class PackageManagerService extends IPackageManager.Stub {
AsecInstallArgs(InstallParams params) {
super(params.getPackageUri(), params.observer, params.flags,
- params.installerPackageName, params.getManifestDigest());
+ params.installerPackageName, params.getManifestDigest(),
+ params.getUser());
}
AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
boolean isExternal, boolean isForwardLocked) {
super(null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
- | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null);
+ | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
+ null, null, null);
// Extract cid from fullCodePath
int eidx = fullCodePath.lastIndexOf("/");
String subStr1 = fullCodePath.substring(0, eidx);
@@ -6700,14 +6829,16 @@ public class PackageManagerService extends IPackageManager.Stub {
AsecInstallArgs(String cid, boolean isForwardLocked) {
super(null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0)
- | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null);
+ | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
+ null, null, null);
this.cid = cid;
setCachePath(PackageHelper.getSdDir(cid));
}
AsecInstallArgs(Uri packageURI, String cid, boolean isExternal, boolean isForwardLocked) {
super(packageURI, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
- | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null);
+ | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
+ null, null, null);
this.cid = cid;
}
@@ -7031,6 +7162,7 @@ public class PackageManagerService extends IPackageManager.Stub {
class PackageInstalledInfo {
String name;
int uid;
+ int[] users;
PackageParser.Package pkg;
int returnCode;
PackageRemovedInfo removedInfo;
@@ -7040,14 +7172,12 @@ public class PackageManagerService extends IPackageManager.Stub {
* Install a non-existing package.
*/
private void installNewPackageLI(PackageParser.Package pkg,
- int parseFlags,
- int scanMode,
+ int parseFlags, int scanMode, UserHandle user,
String installerPackageName, PackageInstalledInfo res) {
// Remember this for later, in case we need to rollback this install
String pkgName = pkg.packageName;
boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists();
- res.name = pkgName;
synchronized(mPackages) {
if (mSettings.mRenamedPackages.containsKey(pkgName)) {
// A package with the same name is already installed, though
@@ -7070,7 +7200,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
mLastScanError = PackageManager.INSTALL_SUCCEEDED;
PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
- System.currentTimeMillis());
+ System.currentTimeMillis(), user);
if (newPackage == null) {
Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -7087,17 +7217,15 @@ public class PackageManagerService extends IPackageManager.Stub {
// delete the package data and cache directories that it created in
// scanPackageLocked, unless those directories existed before we even tried to
// install.
- deletePackageLI(
- pkgName, false,
- dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
+ deletePackageLI(pkgName, UserHandle.ALL, false,
+ dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0,
res.removedInfo, true);
}
}
}
private void replacePackageLI(PackageParser.Package pkg,
- int parseFlags,
- int scanMode,
+ int parseFlags, int scanMode, UserHandle user,
String installerPackageName, PackageInstalledInfo res) {
PackageParser.Package oldPackage;
@@ -7114,15 +7242,16 @@ public class PackageManagerService extends IPackageManager.Stub {
}
boolean sysPkg = (isSystemApp(oldPackage));
if (sysPkg) {
- replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
+ replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
+ user, installerPackageName, res);
} else {
- replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
+ replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
+ user, installerPackageName, res);
}
}
private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
- PackageParser.Package pkg,
- int parseFlags, int scanMode,
+ PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
String installerPackageName, PackageInstalledInfo res) {
PackageParser.Package newPackage = null;
String pkgName = deletedPackage.packageName;
@@ -7137,7 +7266,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
// First delete the existing package while retaining the data directory
- if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
+ if (!deletePackageLI(pkgName, null, true, PackageManager.DELETE_KEEP_DATA,
res.removedInfo, true)) {
// If the existing package wasn't successfully deleted
res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
@@ -7146,7 +7275,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Successfully deleted the old package. Now proceed with re-installation
mLastScanError = PackageManager.INSTALL_SUCCEEDED;
newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME,
- System.currentTimeMillis());
+ System.currentTimeMillis(), user);
if (newPackage == null) {
Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -7167,8 +7296,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// install.
if(updatedSettings) {
deletePackageLI(
- pkgName, true,
- PackageManager.DONT_DELETE_DATA,
+ pkgName, null, true,
+ PackageManager.DELETE_KEEP_DATA,
res.removedInfo, true);
}
// Since we failed to install the new package we need to restore the old
@@ -7183,7 +7312,7 @@ public class PackageManagerService extends IPackageManager.Stub {
int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE
| SCAN_UPDATE_TIME;
if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode,
- origUpdateTime) == null) {
+ origUpdateTime, user) == null) {
Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
return;
}
@@ -7201,8 +7330,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
- PackageParser.Package pkg,
- int parseFlags, int scanMode,
+ PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
String installerPackageName, PackageInstalledInfo res) {
PackageParser.Package newPackage = null;
boolean updatedSettings = false;
@@ -7251,7 +7379,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Successfully disabled the old package. Now proceed with re-installation
mLastScanError = PackageManager.INSTALL_SUCCEEDED;
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
- newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0);
+ newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0, user);
if (newPackage == null) {
Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -7274,7 +7402,7 @@ public class PackageManagerService extends IPackageManager.Stub {
removePackageLI(newPackage, true);
}
// Add back the old system package
- scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0);
+ scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0, user);
// Restore the old system information in Settings
synchronized(mPackages) {
if (updatedSettings) {
@@ -7333,6 +7461,10 @@ public class PackageManagerService extends IPackageManager.Stub {
UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0
? UPDATE_PERMISSIONS_ALL : 0));
res.name = pkgName;
+ PackageSetting ps = mSettings.mPackages.get(pkgName);
+ if (ps != null) {
+ res.users = ps.getInstalledUsers(sUserManager.getUserIds());
+ }
res.uid = newPackage.applicationInfo.uid;
res.pkg = newPackage;
mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE);
@@ -7448,12 +7580,18 @@ public class PackageManagerService extends IPackageManager.Stub {
setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
if (replace) {
- replacePackageLI(pkg, parseFlags, scanMode,
+ replacePackageLI(pkg, parseFlags, scanMode, args.user,
installerPackageName, res);
} else {
- installNewPackageLI(pkg, parseFlags, scanMode,
+ installNewPackageLI(pkg, parseFlags, scanMode, args.user,
installerPackageName,res);
}
+ synchronized (mPackages) {
+ PackageSetting ps = mSettings.mPackages.get(pkgName);
+ if (ps != null) {
+ res.users = ps.getInstalledUsers(sUserManager.getUserIds());
+ }
+ }
}
private static boolean isForwardLocked(PackageParser.Package pkg) {
@@ -7544,10 +7682,11 @@ public class PackageManagerService extends IPackageManager.Stub {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DELETE_PACKAGES, null);
// Queue up an async operation since the package deletion may take a little while.
+ final int uid = Binder.getCallingUid();
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
- final int returnCode = deletePackageX(packageName, true, true, flags);
+ final int returnCode = deletePackageX(packageName, uid, flags);
if (observer != null) {
try {
observer.packageDeleted(packageName, returnCode);
@@ -7573,8 +7712,7 @@ public class PackageManagerService extends IPackageManager.Stub {
* persisting settings for later use
* sending a broadcast if necessary
*/
- private int deletePackageX(String packageName, boolean sendBroadCast,
- boolean deleteCodeAndResources, int flags) {
+ private int deletePackageX(String packageName, int uid, int flags) {
final PackageRemovedInfo info = new PackageRemovedInfo();
final boolean res;
@@ -7589,27 +7727,30 @@ public class PackageManagerService extends IPackageManager.Stub {
}
synchronized (mInstallLock) {
- res = deletePackageLI(packageName, deleteCodeAndResources,
- flags | REMOVE_CHATTY, info, true);
+ res = deletePackageLI(packageName,
+ (flags & PackageManager.DELETE_ALL_USERS) != 0
+ ? UserHandle.ALL : new UserHandle(UserHandle.getUserId(uid)),
+ true, flags | REMOVE_CHATTY, info, true);
}
- if (res && sendBroadCast) {
+ if (res) {
boolean systemUpdate = info.isRemovedPackageSystemUpdate;
- info.sendBroadcast(deleteCodeAndResources, systemUpdate);
+ info.sendBroadcast(true, systemUpdate);
// If the removed package was a system update, the old system packaged
// was re-enabled; we need to broadcast this information
if (systemUpdate) {
Bundle extras = new Bundle(1);
- extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
+ extras.putInt(Intent.EXTRA_UID, info.removedAppId >= 0
+ ? info.removedAppId : info.uid);
extras.putBoolean(Intent.EXTRA_REPLACING, true);
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
- extras, null, null, UserHandle.USER_ALL);
+ extras, null, null, null);
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
- extras, null, null, UserHandle.USER_ALL);
+ extras, null, null, null);
sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
- null, packageName, null, UserHandle.USER_ALL);
+ null, packageName, null, null);
}
}
// Force a gc here.
@@ -7618,7 +7759,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// other processes clean up before deleting resources.
if (info.args != null) {
synchronized (mInstallLock) {
- info.args.doPostDeleteLI(deleteCodeAndResources);
+ info.args.doPostDeleteLI(true);
}
}
@@ -7628,29 +7769,30 @@ public class PackageManagerService extends IPackageManager.Stub {
static class PackageRemovedInfo {
String removedPackage;
int uid = -1;
- int removedUid = -1;
+ int removedAppId = -1;
+ int[] removedUsers = null;
boolean isRemovedPackageSystemUpdate = false;
// Clean up resources deleted packages.
InstallArgs args = null;
void sendBroadcast(boolean fullRemove, boolean replacing) {
Bundle extras = new Bundle(1);
- extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
+ extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
if (replacing) {
extras.putBoolean(Intent.EXTRA_REPLACING, true);
}
if (removedPackage != null) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
- extras, null, null, UserHandle.USER_ALL);
+ extras, null, null, removedUsers);
if (fullRemove && !replacing) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, removedPackage,
- extras, null, null, UserHandle.USER_ALL);
+ extras, null, null, removedUsers);
}
}
- if (removedUid >= 0) {
+ if (removedAppId >= 0) {
sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null, null,
- UserHandle.getUserId(removedUid));
+ removedUsers);
}
}
}
@@ -7664,17 +7806,19 @@ public class PackageManagerService extends IPackageManager.Stub {
private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
int flags, boolean writeSettings) {
String packageName = p.packageName;
- if (outInfo != null) {
- outInfo.removedPackage = packageName;
- }
removePackageLI(p, (flags&REMOVE_CHATTY) != 0);
// Retrieve object to delete permissions for shared user later on
final PackageSetting deletedPs;
// reader
synchronized (mPackages) {
deletedPs = mSettings.mPackages.get(packageName);
+ if (outInfo != null) {
+ outInfo.removedPackage = packageName;
+ outInfo.removedUsers = deletedPs != null
+ ? deletedPs.getInstalledUsers(sUserManager.getUserIds()) : null;
+ }
}
- if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
+ if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
int retCode = mInstaller.remove(packageName, 0);
if (retCode < 0) {
Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
@@ -7684,14 +7828,14 @@ public class PackageManagerService extends IPackageManager.Stub {
// TODO: Kill the processes first
sUserManager.removePackageForAllUsers(packageName);
}
- schedulePackageCleaning(packageName);
+ schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);
}
// writer
synchronized (mPackages) {
if (deletedPs != null) {
- if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
+ if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
if (outInfo != null) {
- outInfo.removedUid = mSettings.removePackageLPw(packageName);
+ outInfo.removedAppId = mSettings.removePackageLPw(packageName);
}
if (deletedPs != null) {
updatePermissionsLPw(deletedPs.name, null, 0);
@@ -7740,10 +7884,10 @@ public class PackageManagerService extends IPackageManager.Stub {
outInfo.isRemovedPackageSystemUpdate = true;
if (ps.versionCode < p.mVersionCode) {
// Delete data for downgrades
- flags &= ~PackageManager.DONT_DELETE_DATA;
+ flags &= ~PackageManager.DELETE_KEEP_DATA;
} else {
// Preserve data by setting flag
- flags |= PackageManager.DONT_DELETE_DATA;
+ flags |= PackageManager.DELETE_KEEP_DATA;
}
boolean ret = deleteInstalledPackageLI(p, true, flags, outInfo,
writeSettings);
@@ -7760,7 +7904,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Install the system package
PackageParser.Package newPkg = scanPackageLI(ps.codePath,
PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
- SCAN_MONITOR | SCAN_NO_PATHS, 0);
+ SCAN_MONITOR | SCAN_NO_PATHS, 0, null);
if (newPkg == null) {
Slog.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
@@ -7807,7 +7951,7 @@ public class PackageManagerService extends IPackageManager.Stub {
/*
* This method handles package deletion in general
*/
- private boolean deletePackageLI(String packageName,
+ private boolean deletePackageLI(String packageName, UserHandle user,
boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
boolean writeSettings) {
if (packageName == null) {
@@ -7816,6 +7960,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
PackageParser.Package p;
boolean dataOnly = false;
+ int removeUser = -1;
+ int appId = -1;
synchronized (mPackages) {
p = mPackages.get(packageName);
if (p == null) {
@@ -7823,15 +7969,53 @@ public class PackageManagerService extends IPackageManager.Stub {
dataOnly = true;
PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps == null) {
- Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
+ Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
return false;
}
p = ps.pkg;
}
+ if (p == null) {
+ Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
+ return false;
+ }
+ final PackageSetting ps = (PackageSetting)p.mExtras;
+ if (!isSystemApp(p) && ps != null && user != null
+ && user.getIdentifier() != UserHandle.USER_ALL) {
+ // The caller is asking that the package only be deleted for a single
+ // user. To do this, we just mark its uninstalled state and delete
+ // its data.
+ ps.setUserState(user.getIdentifier(),
+ COMPONENT_ENABLED_STATE_DEFAULT,
+ false, //installed
+ true, //stopped
+ true, //notLaunched
+ null, null);
+ if (ps.isAnyInstalled(sUserManager.getUserIds())) {
+ // Other user still have this package installed, so all
+ // we need to do is clear this user's data and save that
+ // it is uninstalled.
+ removeUser = user.getIdentifier();
+ appId = ps.appId;
+ mSettings.writePackageRestrictionsLPr(removeUser);
+ } else {
+ // We need to set it back to 'installed' so the uninstall
+ // broadcasts will be sent correctly.
+ ps.setInstalled(true, user.getIdentifier());
+ }
+ }
}
- if (p == null) {
- Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
- return false;
+
+ if (removeUser >= 0) {
+ // From above, we determined that we are deleting this only
+ // for a single user. Continue the work here.
+ if (outInfo != null) {
+ outInfo.removedPackage = packageName;
+ outInfo.removedAppId = appId;
+ outInfo.removedUsers = new int[] {removeUser};
+ }
+ mInstaller.clearUserData(packageName, removeUser);
+ schedulePackageCleaning(packageName, removeUser, false);
+ return true;
}
if (dataOnly) {
@@ -7876,7 +8060,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- private void clearExternalStorageDataSync(String packageName, boolean allData) {
+ private void clearExternalStorageDataSync(String packageName, int userId, boolean allData) {
final boolean mounted;
if (Environment.isExternalStorageEmulated()) {
mounted = true;
@@ -7892,44 +8076,52 @@ public class PackageManagerService extends IPackageManager.Stub {
}
final Intent containerIntent = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
- ClearStorageConnection conn = new ClearStorageConnection();
- if (mContext.bindService(containerIntent, conn, Context.BIND_AUTO_CREATE)) {
- try {
- long timeout = SystemClock.uptimeMillis() + 5000;
- synchronized (conn) {
- long now = SystemClock.uptimeMillis();
- while (conn.mContainerService == null && now < timeout) {
- try {
- conn.wait(timeout - now);
- } catch (InterruptedException e) {
+ int[] users;
+ if (userId == UserHandle.USER_ALL) {
+ users = sUserManager.getUserIds();
+ } else {
+ users = new int[] { userId };
+ }
+ for (int curUser : users) {
+ ClearStorageConnection conn = new ClearStorageConnection();
+ if (mContext.bindService(containerIntent, conn, Context.BIND_AUTO_CREATE, curUser)) {
+ try {
+ long timeout = SystemClock.uptimeMillis() + 5000;
+ synchronized (conn) {
+ long now = SystemClock.uptimeMillis();
+ while (conn.mContainerService == null && now < timeout) {
+ try {
+ conn.wait(timeout - now);
+ } catch (InterruptedException e) {
+ }
}
}
- }
- if (conn.mContainerService == null) {
- return;
- }
- final File externalCacheDir = Environment
- .getExternalStorageAppCacheDirectory(packageName);
- try {
- conn.mContainerService.clearDirectory(externalCacheDir.toString());
- } catch (RemoteException e) {
- }
- if (allData) {
- final File externalDataDir = Environment
- .getExternalStorageAppDataDirectory(packageName);
- try {
- conn.mContainerService.clearDirectory(externalDataDir.toString());
- } catch (RemoteException e) {
+ if (conn.mContainerService == null) {
+ return;
}
- final File externalMediaDir = Environment
- .getExternalStorageAppMediaDirectory(packageName);
+ final File externalCacheDir = Environment
+ .getExternalStorageAppCacheDirectory(packageName);
try {
- conn.mContainerService.clearDirectory(externalMediaDir.toString());
+ conn.mContainerService.clearDirectory(externalCacheDir.toString());
} catch (RemoteException e) {
}
+ if (allData) {
+ final File externalDataDir = Environment
+ .getExternalStorageAppDataDirectory(packageName);
+ try {
+ conn.mContainerService.clearDirectory(externalDataDir.toString());
+ } catch (RemoteException e) {
+ }
+ final File externalMediaDir = Environment
+ .getExternalStorageAppMediaDirectory(packageName);
+ try {
+ conn.mContainerService.clearDirectory(externalMediaDir.toString());
+ } catch (RemoteException e) {
+ }
+ }
+ } finally {
+ mContext.unbindService(conn);
}
- } finally {
- mContext.unbindService(conn);
}
}
}
@@ -7948,7 +8140,7 @@ public class PackageManagerService extends IPackageManager.Stub {
synchronized (mInstallLock) {
succeeded = clearApplicationUserDataLI(packageName, userId);
}
- clearExternalStorageDataSync(packageName, true);
+ clearExternalStorageDataSync(packageName, userId, true);
if (succeeded) {
// invoke DeviceStorageMonitor's update method to clear any notifications
DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
@@ -8022,7 +8214,7 @@ public class PackageManagerService extends IPackageManager.Stub {
synchronized (mInstallLock) {
succeded = deleteApplicationCacheFilesLI(packageName, userId);
}
- clearExternalStorageDataSync(packageName, false);
+ clearExternalStorageDataSync(packageName, userId, false);
if(observer != null) {
try {
observer.onRemoveCompleted(packageName, succeded);
@@ -8480,7 +8672,7 @@ public class PackageManagerService extends IPackageManager.Stub {
extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
extras.putInt(Intent.EXTRA_UID, packageUid);
sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null,
- UserHandle.getUserId(packageUid));
+ new int[] {UserHandle.getUserId(packageUid)});
}
public void setPackageStoppedState(String packageName, boolean stopped, int userId) {
@@ -9085,7 +9277,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (DEBUG_SD_INSTALL)
Log.i(TAG, "Loading packages");
loadMediaPackages(processCids, uidArr, removeCids);
- startCleaningPackages();
+ startCleaningPackages(-1);
} else {
if (DEBUG_SD_INSTALL)
Log.i(TAG, "Unloading packages");
@@ -9106,7 +9298,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
: Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
- sendPackageBroadcast(action, null, extras, null, finishedReceiver, UserHandle.USER_ALL);
+ sendPackageBroadcast(action, null, extras, null, finishedReceiver, null);
}
}
@@ -9151,7 +9343,7 @@ public class PackageManagerService extends IPackageManager.Stub {
doGc = true;
synchronized (mInstallLock) {
final PackageParser.Package pkg = scanPackageLI(new File(codePath), parseFlags,
- 0, 0);
+ 0, 0, null);
// Scan the package
if (pkg != null) {
/*
@@ -9260,8 +9452,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// Delete package internally
PackageRemovedInfo outInfo = new PackageRemovedInfo();
synchronized (mInstallLock) {
- boolean res = deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
- outInfo, false);
+ boolean res = deletePackageLI(pkgName, null, false,
+ PackageManager.DELETE_KEEP_DATA, outInfo, false);
if (res) {
pkgList.add(pkgName);
} else {
diff --git a/services/java/com/android/server/pm/PackageSettingBase.java b/services/java/com/android/server/pm/PackageSettingBase.java
index 56f2166..6d31f0e 100644
--- a/services/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/java/com/android/server/pm/PackageSettingBase.java
@@ -20,11 +20,13 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import android.content.pm.PackageUserState;
+import android.content.pm.UserInfo;
import android.util.SparseArray;
-import android.util.SparseIntArray;
import java.io.File;
import java.util.HashSet;
+import java.util.List;
/**
* Settings base class for pending and resolved classes.
@@ -62,19 +64,11 @@ class PackageSettingBase extends GrantedPermissions {
boolean permissionsFixed;
boolean haveGids;
+ private static final PackageUserState DEFAULT_USER_STATE = new PackageUserState();
+
// Whether this package is currently stopped, thus can not be
// started until explicitly launched by the user.
- private SparseArray<Boolean> stopped = new SparseArray<Boolean>();
-
- // Set to true if we have never launched this app.
- private SparseArray<Boolean> notLaunched = new SparseArray<Boolean>();
-
- /* Explicitly disabled components */
- private SparseArray<HashSet<String>> disabledComponents = new SparseArray<HashSet<String>>();
- /* Explicitly enabled components */
- private SparseArray<HashSet<String>> enabledComponents = new SparseArray<HashSet<String>>();
- /* Enabled state */
- private SparseIntArray enabled = new SparseIntArray();
+ private final SparseArray<PackageUserState> userState = new SparseArray<PackageUserState>();
int installStatus = PKG_INSTALL_COMPLETE;
@@ -115,12 +109,11 @@ class PackageSettingBase extends GrantedPermissions {
permissionsFixed = base.permissionsFixed;
haveGids = base.haveGids;
- notLaunched = base.notLaunched;
-
- disabledComponents = (SparseArray<HashSet<String>>) base.disabledComponents.clone();
- enabledComponents = (SparseArray<HashSet<String>>) base.enabledComponents.clone();
- enabled = (SparseIntArray) base.enabled.clone();
- stopped = (SparseArray<Boolean>) base.stopped.clone();
+ userState.clear();
+ for (int i=0; i<base.userState.size(); i++) {
+ userState.put(base.userState.keyAt(i),
+ new PackageUserState(base.userState.valueAt(i)));
+ }
installStatus = base.installStatus;
origPackage = base.origPackage;
@@ -171,103 +164,174 @@ class PackageSettingBase extends GrantedPermissions {
signatures = base.signatures;
permissionsFixed = base.permissionsFixed;
haveGids = base.haveGids;
- stopped = base.stopped;
- notLaunched = base.notLaunched;
- disabledComponents = base.disabledComponents;
- enabledComponents = base.enabledComponents;
- enabled = base.enabled;
+ userState.clear();
+ for (int i=0; i<base.userState.size(); i++) {
+ userState.put(base.userState.keyAt(i), base.userState.valueAt(i));
+ }
installStatus = base.installStatus;
}
+ private PackageUserState modifyUserState(int userId) {
+ PackageUserState state = userState.get(userId);
+ if (state == null) {
+ state = new PackageUserState();
+ userState.put(userId, state);
+ }
+ return state;
+ }
+
+ public PackageUserState readUserState(int userId) {
+ PackageUserState state = userState.get(userId);
+ return state != null ? state : DEFAULT_USER_STATE;
+ }
+
void setEnabled(int state, int userId) {
- enabled.put(userId, state);
+ modifyUserState(userId).enabled = state;
}
int getEnabled(int userId) {
- return enabled.get(userId, COMPONENT_ENABLED_STATE_DEFAULT);
+ return readUserState(userId).enabled;
+ }
+
+ void setInstalled(boolean inst, int userId) {
+ modifyUserState(userId).installed = inst;
+ }
+
+ boolean getInstalled(int userId) {
+ return readUserState(userId).installed;
+ }
+
+ boolean isAnyInstalled(int[] users) {
+ for (int user: users) {
+ if (readUserState(user).installed) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ int[] getInstalledUsers(int[] users) {
+ int num = 0;
+ for (int user : users) {
+ if (getInstalled(user)) {
+ num++;
+ }
+ }
+ int[] res = new int[num];
+ num = 0;
+ for (int user : users) {
+ if (getInstalled(user)) {
+ res[num] = user;
+ num++;
+ }
+ }
+ return res;
}
boolean getStopped(int userId) {
- return stopped.get(userId, false);
+ return readUserState(userId).stopped;
}
void setStopped(boolean stop, int userId) {
- stopped.put(userId, stop);
+ modifyUserState(userId).stopped = stop;
}
boolean getNotLaunched(int userId) {
- return notLaunched.get(userId, false);
+ return readUserState(userId).notLaunched;
}
void setNotLaunched(boolean stop, int userId) {
- notLaunched.put(userId, stop);
+ modifyUserState(userId).notLaunched = stop;
+ }
+
+ void setUserState(int userId, int enabled, boolean installed, boolean stopped,
+ boolean notLaunched, HashSet<String> enabledComponents,
+ HashSet<String> disabledComponents) {
+ PackageUserState state = modifyUserState(userId);
+ state.enabled = enabled;
+ state.installed = installed;
+ state.stopped = stopped;
+ state.notLaunched = notLaunched;
+ state.enabledComponents = enabledComponents;
+ state.disabledComponents = disabledComponents;
}
HashSet<String> getEnabledComponents(int userId) {
- return getComponentHashSet(enabledComponents, userId);
+ return readUserState(userId).enabledComponents;
}
HashSet<String> getDisabledComponents(int userId) {
- return getComponentHashSet(disabledComponents, userId);
+ return readUserState(userId).disabledComponents;
}
void setEnabledComponents(HashSet<String> components, int userId) {
- enabledComponents.put(userId, components);
+ modifyUserState(userId).enabledComponents = components;
}
void setDisabledComponents(HashSet<String> components, int userId) {
- disabledComponents.put(userId, components);
+ modifyUserState(userId).disabledComponents = components;
+ }
+
+ void setEnabledComponentsCopy(HashSet<String> components, int userId) {
+ modifyUserState(userId).enabledComponents = components != null
+ ? new HashSet<String>(components) : null;
}
- private HashSet<String> getComponentHashSet(SparseArray<HashSet<String>> setArray, int userId) {
- HashSet<String> set = setArray.get(userId);
- if (set == null) {
- set = new HashSet<String>(1);
- setArray.put(userId, set);
+ void setDisabledComponentsCopy(HashSet<String> components, int userId) {
+ modifyUserState(userId).disabledComponents = components != null
+ ? new HashSet<String>(components) : null;
+ }
+
+ PackageUserState modifyUserStateComponents(int userId, boolean disabled, boolean enabled) {
+ PackageUserState state = modifyUserState(userId);
+ if (disabled && state.disabledComponents == null) {
+ state.disabledComponents = new HashSet<String>(1);
+ }
+ if (enabled && state.enabledComponents == null) {
+ state.enabledComponents = new HashSet<String>(1);
}
- return set;
+ return state;
}
void addDisabledComponent(String componentClassName, int userId) {
- HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
- disabled.add(componentClassName);
+ modifyUserStateComponents(userId, true, false).disabledComponents.add(componentClassName);
}
void addEnabledComponent(String componentClassName, int userId) {
- HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
- enabled.add(componentClassName);
+ modifyUserStateComponents(userId, false, true).enabledComponents.add(componentClassName);
}
boolean enableComponentLPw(String componentClassName, int userId) {
- HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
- HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
- boolean changed = disabled.remove(componentClassName);
- changed |= enabled.add(componentClassName);
+ PackageUserState state = modifyUserStateComponents(userId, false, true);
+ boolean changed = state.disabledComponents != null
+ ? state.disabledComponents.remove(componentClassName) : false;
+ changed |= state.enabledComponents.add(componentClassName);
return changed;
}
boolean disableComponentLPw(String componentClassName, int userId) {
- HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
- HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
- boolean changed = enabled.remove(componentClassName);
- changed |= disabled.add(componentClassName);
+ PackageUserState state = modifyUserStateComponents(userId, true, false);
+ boolean changed = state.enabledComponents != null
+ ? state.enabledComponents.remove(componentClassName) : false;
+ changed |= state.disabledComponents.add(componentClassName);
return changed;
}
boolean restoreComponentLPw(String componentClassName, int userId) {
- HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
- HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
- boolean changed = enabled.remove(componentClassName);
- changed |= disabled.remove(componentClassName);
+ PackageUserState state = modifyUserStateComponents(userId, true, true);
+ boolean changed = state.disabledComponents != null
+ ? state.disabledComponents.remove(componentClassName) : false;
+ changed |= state.enabledComponents != null
+ ? state.enabledComponents.remove(componentClassName) : false;
return changed;
}
int getCurrentEnabledStateLPr(String componentName, int userId) {
- HashSet<String> disabled = getComponentHashSet(disabledComponents, userId);
- HashSet<String> enabled = getComponentHashSet(enabledComponents, userId);
- if (enabled.contains(componentName)) {
+ PackageUserState state = readUserState(userId);
+ if (state.enabledComponents != null && state.enabledComponents.contains(componentName)) {
return COMPONENT_ENABLED_STATE_ENABLED;
- } else if (disabled.contains(componentName)) {
+ } else if (state.disabledComponents != null
+ && state.disabledComponents.contains(componentName)) {
return COMPONENT_ENABLED_STATE_DISABLED;
} else {
return COMPONENT_ENABLED_STATE_DEFAULT;
@@ -275,11 +339,6 @@ class PackageSettingBase extends GrantedPermissions {
}
void removeUser(int userId) {
- enabled.delete(userId);
- stopped.delete(userId);
- enabledComponents.delete(userId);
- disabledComponents.delete(userId);
- notLaunched.delete(userId);
+ userState.delete(userId);
}
-
}
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index cfc0f5c..a341304 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -38,11 +38,13 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
+import android.content.pm.PackageCleanItem;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PermissionInfo;
import android.content.pm.Signature;
import android.content.pm.UserInfo;
+import android.content.pm.PackageUserState;
import android.content.pm.VerifierDeviceIdentity;
import android.os.Binder;
import android.os.Environment;
@@ -92,9 +94,12 @@ final class Settings {
private static final String TAG_PACKAGE = "pkg";
private static final String ATTR_NAME = "name";
+ private static final String ATTR_USER = "user";
+ private static final String ATTR_CODE = "code";
private static final String ATTR_NOT_LAUNCHED = "nl";
private static final String ATTR_ENABLED = "enabled";
private static final String ATTR_STOPPED = "stopped";
+ private static final String ATTR_INSTALLED = "inst";
private final File mSettingsFilename;
private final File mBackupSettingsFilename;
@@ -156,7 +161,8 @@ final class Settings {
// Packages that have been uninstalled and still need their external
// storage data deleted.
- final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>();
+ final SparseArray<ArrayList<PackageCleanItem>> mPackagesToBeCleaned
+ = new SparseArray<ArrayList<PackageCleanItem>>();
// Packages that have been renamed since they were first installed.
// Keys are the new names of the packages, values are the original
@@ -200,10 +206,11 @@ final class Settings {
PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
- String nativeLibraryPathString, int pkgFlags, boolean create, boolean add) {
+ String nativeLibraryPathString, int pkgFlags, UserHandle user, boolean add) {
final String name = pkg.packageName;
PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,
- resourcePath, nativeLibraryPathString, pkg.mVersionCode, pkgFlags, create, add);
+ resourcePath, nativeLibraryPathString, pkg.mVersionCode, pkgFlags,
+ user, add);
return p;
}
@@ -364,7 +371,8 @@ final class Settings {
private PackageSetting getPackageLPw(String name, PackageSetting origPackage,
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
- String nativeLibraryPathString, int vc, int pkgFlags, boolean create, boolean add) {
+ String nativeLibraryPathString, int vc, int pkgFlags,
+ UserHandle installUser, boolean add) {
PackageSetting p = mPackages.get(name);
if (p != null) {
if (!p.codePath.equals(codePath)) {
@@ -407,11 +415,6 @@ final class Settings {
}
}
if (p == null) {
- // Create a new PackageSettings entry. this can end up here because
- // of code path mismatch or user id mismatch of an updated system partition
- if (!create) {
- return null;
- }
if (origPackage != null) {
// We are consuming the data from an existing package.
p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
@@ -445,8 +448,20 @@ final class Settings {
List<UserInfo> users = getAllUsers();
if (users != null) {
for (UserInfo user : users) {
- p.setStopped(true, user.id);
- p.setNotLaunched(true, user.id);
+ // By default we consider this app to be installed
+ // for the user if no user has been specified (which
+ // means to leave it at its original value, and the
+ // original default value is true), or we are being
+ // asked to install for all users, or this is the
+ // user we are installing for.
+ final boolean installed = installUser == null
+ || installUser.getIdentifier() == UserHandle.USER_ALL
+ || installUser.getIdentifier() == user.id;
+ p.setUserState(user.id, COMPONENT_ENABLED_STATE_DEFAULT,
+ installed,
+ true, // stopped,
+ true, // notLaunched
+ null, null);
writePackageRestrictionsLPr(user.id);
}
}
@@ -472,12 +487,10 @@ final class Settings {
if (users != null) {
for (UserInfo user : users) {
int userId = user.id;
- p.setDisabledComponents(
- new HashSet<String>(dis.getDisabledComponents(userId)),
- userId);
- p.setEnabledComponents(
- new HashSet<String>(dis.getEnabledComponents(userId)),
- userId);
+ p.setDisabledComponentsCopy(
+ dis.getDisabledComponents(userId), userId);
+ p.setEnabledComponentsCopy(
+ dis.getEnabledComponents(userId), userId);
}
}
// Add new setting to list of user ids
@@ -498,6 +511,25 @@ final class Settings {
// user preferences
addPackageSettingLPw(p, name, sharedUser);
}
+ } else {
+ if (installUser != null) {
+ // The caller has explicitly specified the user they want this
+ // package installed for, and the package already exists.
+ // Make sure it conforms to the new request.
+ List<UserInfo> users = getAllUsers();
+ if (users != null) {
+ for (UserInfo user : users) {
+ if (installUser.getIdentifier() == UserHandle.USER_ALL
+ || installUser.getIdentifier() == user.id) {
+ boolean installed = p.getInstalled(user.id);
+ if (!installed) {
+ p.setInstalled(true, user.id);
+ writePackageRestrictionsLPr(user.id);
+ }
+ }
+ }
+ }
+ }
}
return p;
}
@@ -778,10 +810,14 @@ final class Settings {
+ "assuming all started");
// At first boot, make sure no packages are stopped.
// We usually want to have third party apps initialize
- // in the stopped state, but not at first boot.
+ // in the stopped state, but not at first boot. Also
+ // consider all applications to be installed.
for (PackageSetting pkg : mPackages.values()) {
- pkg.setStopped(false, userId);
- pkg.setNotLaunched(false, userId);
+ pkg.setUserState(userId, COMPONENT_ENABLED_STATE_DEFAULT,
+ true, // installed
+ false, // stopped
+ false, // notLaunched
+ null, null);
}
return;
}
@@ -823,17 +859,21 @@ final class Settings {
XmlUtils.skipCurrentTag(parser);
continue;
}
- String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
- int enabled = enabledStr == null ? COMPONENT_ENABLED_STATE_DEFAULT
- : Integer.parseInt(enabledStr);
- ps.setEnabled(enabled, userId);
- String stoppedStr = parser.getAttributeValue(null, ATTR_STOPPED);
- boolean stopped = stoppedStr == null ? false : Boolean.parseBoolean(stoppedStr);
- ps.setStopped(stopped, userId);
- String notLaunchedStr = parser.getAttributeValue(null, ATTR_NOT_LAUNCHED);
- boolean notLaunched = stoppedStr == null ? false
- : Boolean.parseBoolean(notLaunchedStr);
- ps.setNotLaunched(notLaunched, userId);
+ final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
+ final int enabled = enabledStr == null
+ ? COMPONENT_ENABLED_STATE_DEFAULT : Integer.parseInt(enabledStr);
+ final String installedStr = parser.getAttributeValue(null, ATTR_INSTALLED);
+ final boolean installed = installedStr == null
+ ? true : Boolean.parseBoolean(installedStr);
+ final String stoppedStr = parser.getAttributeValue(null, ATTR_STOPPED);
+ final boolean stopped = stoppedStr == null
+ ? false : Boolean.parseBoolean(stoppedStr);
+ final String notLaunchedStr = parser.getAttributeValue(null, ATTR_NOT_LAUNCHED);
+ final boolean notLaunched = stoppedStr == null
+ ? false : Boolean.parseBoolean(notLaunchedStr);
+
+ HashSet<String> enabledComponents = null;
+ HashSet<String> disabledComponents = null;
int packageDepth = parser.getDepth();
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
@@ -845,13 +885,14 @@ final class Settings {
}
tagName = parser.getName();
if (tagName.equals(TAG_ENABLED_COMPONENTS)) {
- HashSet<String> components = readComponentsLPr(parser);
- ps.setEnabledComponents(components, userId);
+ enabledComponents = readComponentsLPr(parser);
} else if (tagName.equals(TAG_DISABLED_COMPONENTS)) {
- HashSet<String> components = readComponentsLPr(parser);
- ps.setDisabledComponents(components, userId);
+ disabledComponents = readComponentsLPr(parser);
}
}
+
+ ps.setUserState(userId, enabled, installed, stopped, notLaunched,
+ enabledComponents, disabledComponents);
} else {
Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
+ parser.getName());
@@ -876,7 +917,7 @@ final class Settings {
private HashSet<String> readComponentsLPr(XmlPullParser parser)
throws IOException, XmlPullParserException {
- HashSet<String> components = new HashSet<String>();
+ HashSet<String> components = null;
int type;
int outerDepth = parser.getDepth();
String tagName;
@@ -891,6 +932,9 @@ final class Settings {
if (tagName.equals(TAG_ITEM)) {
String componentName = parser.getAttributeValue(null, ATTR_NAME);
if (componentName != null) {
+ if (components == null) {
+ components = new HashSet<String>();
+ }
components.add(componentName);
}
}
@@ -936,41 +980,44 @@ final class Settings {
serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
for (final PackageSetting pkg : mPackages.values()) {
- if (pkg.getStopped(userId)
- || pkg.getNotLaunched(userId)
- || pkg.getEnabled(userId) != COMPONENT_ENABLED_STATE_DEFAULT
- || pkg.getEnabledComponents(userId).size() > 0
- || pkg.getDisabledComponents(userId).size() > 0) {
+ PackageUserState ustate = pkg.readUserState(userId);
+ if (ustate.stopped || ustate.notLaunched || !ustate.installed
+ || ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT
+ || (ustate.enabledComponents != null
+ && ustate.enabledComponents.size() > 0)
+ || (ustate.disabledComponents != null
+ && ustate.disabledComponents.size() > 0)) {
serializer.startTag(null, TAG_PACKAGE);
serializer.attribute(null, ATTR_NAME, pkg.name);
- boolean stopped = pkg.getStopped(userId);
- boolean notLaunched = pkg.getNotLaunched(userId);
- int enabled = pkg.getEnabled(userId);
- if (DEBUG_MU) Log.i(TAG, " pkg=" + pkg.name + ", state=" + enabled);
- HashSet<String> enabledComponents = pkg.getEnabledComponents(userId);
- HashSet<String> disabledComponents = pkg.getDisabledComponents(userId);
-
- if (stopped) {
+ if (DEBUG_MU) Log.i(TAG, " pkg=" + pkg.name + ", state=" + ustate.enabled);
+
+ if (!ustate.installed) {
+ serializer.attribute(null, ATTR_INSTALLED, "false");
+ }
+ if (ustate.stopped) {
serializer.attribute(null, ATTR_STOPPED, "true");
}
- if (notLaunched) {
+ if (ustate.notLaunched) {
serializer.attribute(null, ATTR_NOT_LAUNCHED, "true");
}
- if (enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
- serializer.attribute(null, ATTR_ENABLED, Integer.toString(enabled));
+ if (ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
+ serializer.attribute(null, ATTR_ENABLED,
+ Integer.toString(ustate.enabled));
}
- if (enabledComponents.size() > 0) {
+ if (ustate.enabledComponents != null
+ && ustate.enabledComponents.size() > 0) {
serializer.startTag(null, TAG_ENABLED_COMPONENTS);
- for (final String name : enabledComponents) {
+ for (final String name : ustate.enabledComponents) {
serializer.startTag(null, TAG_ITEM);
serializer.attribute(null, ATTR_NAME, name);
serializer.endTag(null, TAG_ITEM);
}
serializer.endTag(null, TAG_ENABLED_COMPONENTS);
}
- if (disabledComponents.size() > 0) {
+ if (ustate.disabledComponents != null
+ && ustate.disabledComponents.size() > 0) {
serializer.startTag(null, TAG_DISABLED_COMPONENTS);
- for (final String name : disabledComponents) {
+ for (final String name : ustate.disabledComponents) {
serializer.startTag(null, TAG_ITEM);
serializer.attribute(null, ATTR_NAME, name);
serializer.endTag(null, TAG_ITEM);
@@ -1210,9 +1257,17 @@ final class Settings {
if (mPackagesToBeCleaned.size() > 0) {
for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
- serializer.startTag(null, "cleaning-package");
- serializer.attribute(null, ATTR_NAME, mPackagesToBeCleaned.get(i));
- serializer.endTag(null, "cleaning-package");
+ final int userId = mPackagesToBeCleaned.keyAt(i);
+ final String userStr = Integer.toString(userId);
+ final ArrayList<PackageCleanItem> pkgs = mPackagesToBeCleaned.valueAt(i);
+ for (int j=0; j<pkgs.size(); j++) {
+ serializer.startTag(null, "cleaning-package");
+ PackageCleanItem item = pkgs.get(i);
+ serializer.attribute(null, ATTR_NAME, item.packageName);
+ serializer.attribute(null, ATTR_CODE, item.andCode ? "true" : "false");
+ serializer.attribute(null, ATTR_USER, userStr);
+ serializer.endTag(null, "cleaning-package");
+ }
}
}
@@ -1468,6 +1523,17 @@ final class Settings {
return ret;
}
+ void addPackageToCleanLPw(int userId, PackageCleanItem pkg) {
+ ArrayList<PackageCleanItem> pkgs = mPackagesToBeCleaned.get(userId);
+ if (pkgs == null) {
+ pkgs = new ArrayList<PackageCleanItem>();
+ mPackagesToBeCleaned.put(userId, pkgs);
+ }
+ if (!pkgs.contains(pkg)) {
+ pkgs.add(pkg);
+ }
+ }
+
boolean readLPw(List<UserInfo> users) {
FileInputStream str = null;
if (mBackupSettingsFilename.exists()) {
@@ -1545,8 +1611,21 @@ final class Settings {
readDisabledSysPackageLPw(parser);
} else if (tagName.equals("cleaning-package")) {
String name = parser.getAttributeValue(null, ATTR_NAME);
+ String userStr = parser.getAttributeValue(null, ATTR_USER);
+ String codeStr = parser.getAttributeValue(null, ATTR_CODE);
if (name != null) {
- mPackagesToBeCleaned.add(name);
+ int user = 0;
+ boolean andCode = true;
+ try {
+ if (userStr != null) {
+ user = Integer.parseInt(userStr);
+ }
+ } catch (NumberFormatException e) {
+ }
+ if (codeStr != null) {
+ andCode = Boolean.parseBoolean(codeStr);
+ }
+ addPackageToCleanLPw(user, new PackageCleanItem(name, andCode));
}
} else if (tagName.equals("renamed-package")) {
String nname = parser.getAttributeValue(null, "new");
@@ -1623,7 +1702,8 @@ final class Settings {
if (idObj != null && idObj instanceof SharedUserSetting) {
PackageSetting p = getPackageLPw(pp.name, null, pp.realName,
(SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
- pp.nativeLibraryPathString, pp.versionCode, pp.pkgFlags, true, true);
+ pp.nativeLibraryPathString, pp.versionCode, pp.pkgFlags,
+ UserHandle.ALL, true);
if (p == null) {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Unable to create application package for " + pp.name);
@@ -2292,6 +2372,10 @@ final class Settings {
return ps;
}
+ private String compToString(HashSet<String> cmp) {
+ return cmp != null ? Arrays.toString(cmp.toArray()) : "[]";
+ }
+
boolean isEnabledLPr(ComponentInfo componentInfo, int flags, int userId) {
if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
return true;
@@ -2302,24 +2386,26 @@ final class Settings {
Log.v(PackageManagerService.TAG, "isEnabledLock - packageName = "
+ componentInfo.packageName + " componentName = " + componentInfo.name);
Log.v(PackageManagerService.TAG, "enabledComponents: "
- + Arrays.toString(packageSettings.getEnabledComponents(userId).toArray()));
+ + compToString(packageSettings.getEnabledComponents(userId)));
Log.v(PackageManagerService.TAG, "disabledComponents: "
- + Arrays.toString(packageSettings.getDisabledComponents(userId).toArray()));
+ + compToString(packageSettings.getDisabledComponents(userId)));
}
if (packageSettings == null) {
return false;
}
- final int enabled = packageSettings.getEnabled(userId);
- if (enabled == COMPONENT_ENABLED_STATE_DISABLED
- || enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
+ PackageUserState ustate = packageSettings.readUserState(userId);
+ if (ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED
+ || ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
|| (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled
- && enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
+ && ustate.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
return false;
}
- if (packageSettings.getEnabledComponents(userId).contains(componentInfo.name)) {
+ if (ustate.enabledComponents != null
+ && ustate.enabledComponents.contains(componentInfo.name)) {
return true;
}
- if (packageSettings.getDisabledComponents(userId).contains(componentInfo.name)) {
+ if (ustate.disabledComponents != null
+ && ustate.disabledComponents.contains(componentInfo.name)) {
return false;
}
return componentInfo.enabled;
@@ -2378,7 +2464,7 @@ final class Settings {
if (pkgSetting.installerPackageName != null) {
PackageManagerService.sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH,
pkgSetting.name, null,
- pkgSetting.installerPackageName, null, userId);
+ pkgSetting.installerPackageName, null, new int[] {userId});
}
pkgSetting.setNotLaunched(false, userId);
}
@@ -2427,7 +2513,6 @@ final class Settings {
ApplicationInfo.FLAG_RESTORE_ANY_VERSION, "RESTORE_ANY_VERSION",
ApplicationInfo.FLAG_EXTERNAL_STORAGE, "EXTERNAL_STORAGE",
ApplicationInfo.FLAG_LARGE_HEAP, "LARGE_HEAP",
- ApplicationInfo.FLAG_STOPPED, "STOPPED",
ApplicationInfo.FLAG_FORWARD_LOCK, "FORWARD_LOCK",
ApplicationInfo.FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
};
@@ -2537,22 +2622,28 @@ final class Settings {
pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
pw.print(" haveGids="); pw.println(ps.haveGids);
pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
- pw.print(" installStatus="); pw.print(ps.installStatus);
+ pw.print(" installStatus="); pw.println(ps.installStatus);
for (UserInfo user : users) {
- pw.print(" User "); pw.print(user.id); pw.print(": ");
+ pw.print(" User "); pw.print(user.id); pw.print(": ");
+ pw.print(" installed=");
+ pw.print(ps.getInstalled(user.id));
pw.print(" stopped=");
pw.print(ps.getStopped(user.id));
+ pw.print(" notLaunched=");
+ pw.print(ps.getNotLaunched(user.id));
pw.print(" enabled=");
pw.println(ps.getEnabled(user.id));
- if (ps.getDisabledComponents(user.id).size() > 0) {
- pw.println(" disabledComponents:");
- for (String s : ps.getDisabledComponents(user.id)) {
+ HashSet<String> cmp = ps.getDisabledComponents(user.id);
+ if (cmp != null && cmp.size() > 0) {
+ pw.println(" disabledComponents:");
+ for (String s : cmp) {
pw.print(" "); pw.println(s);
}
}
- if (ps.getEnabledComponents(user.id).size() > 0) {
- pw.println(" enabledComponents:");
- for (String s : ps.getEnabledComponents(user.id)) {
+ cmp = ps.getEnabledComponents(user.id);
+ if (cmp != null && cmp.size() > 0) {
+ pw.println(" enabledComponents:");
+ for (String s : cmp) {
pw.print(" "); pw.println(s);
}
}
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index 6a76c5d..8899ea2 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -262,7 +262,9 @@ public class UserManagerService extends IUserManager.Stub {
* @return the array of user ids.
*/
int[] getUserIds() {
- return mUserIds;
+ synchronized (mUsers) {
+ return mUserIds;
+ }
}
private void readUserList() {
@@ -611,12 +613,11 @@ public class UserManagerService extends IUserManager.Stub {
* Caches the list of user ids in an array, adjusting the array size when necessary.
*/
private void updateUserIdsLocked() {
- if (mUserIds == null || mUserIds.length != mUsers.size()) {
- mUserIds = new int[mUsers.size()];
- }
+ int[] newUsers = new int[mUsers.size()];
for (int i = 0; i < mUsers.size(); i++) {
- mUserIds[i] = mUsers.keyAt(i);
+ newUsers[i] = mUsers.keyAt(i);
}
+ mUserIds = newUsers;
}
/**
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 12ad4fe..6047cda 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -360,6 +360,18 @@ public class MockContext extends Context {
throw new UnsupportedOperationException();
}
+ /** @hide */
+ @Override
+ public ComponentName startServiceAsUser(Intent service, UserHandle user) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** @hide */
+ @Override
+ public boolean stopServiceAsUser(Intent service, UserHandle user) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
throw new UnsupportedOperationException();
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index ac40fc6b..562f286 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -41,6 +41,7 @@ import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
@@ -531,6 +532,15 @@ public class MockPackageManager extends PackageManager {
throw new UnsupportedOperationException();
}
+ /**
+ * @hide
+ */
+ @Override
+ public int installExistingPackage(String packageName)
+ throws NameNotFoundException {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public void verifyPendingInstall(int id, int verificationCode) {
throw new UnsupportedOperationException();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 3d45bff..76033d4 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -1281,6 +1281,18 @@ public final class BridgeContext extends Context {
}
@Override
+ public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) {
+ // pass
+ return null;
+ }
+
+ @Override
+ public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) {
+ // pass
+ return false;
+ }
+
+ @Override
public void unbindService(ServiceConnection arg0) {
// pass