diff options
Diffstat (limited to 'services/java')
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; } /** |