summaryrefslogtreecommitdiff
path: root/services/java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java')
-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
6 files changed, 719 insertions, 375 deletions
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index e222936b6519..e6bcaa1d92df 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 8fc12d32453c..2b4f8b136316 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 4252b900e261..b0aca21e1eec 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 56f2166ef0bd..6d31f0e81db1 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 cfc0f5c56eba..a341304162ad 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 6a76c5df1790..8899ea2fb874 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;
}
/**