diff options
| -rwxr-xr-x | services/core/java/com/android/server/am/ActivityManagerService.java | 388 |
1 files changed, 180 insertions, 208 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index d0f5eeda2ee5..fe424fc63e74 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -61,7 +61,6 @@ import com.android.internal.app.IAppOpsService; import com.android.internal.app.IVoiceInteractor; import com.android.internal.app.ProcessMap; import com.android.internal.app.ProcessStats; -import com.android.internal.content.PackageMonitor; import com.android.internal.os.BackgroundThread; import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.ProcessCpuTracker; @@ -1826,99 +1825,6 @@ public final class ActivityManagerService extends ActivityManagerNative } }; - /** - * Monitor for package changes and update our internal state. - */ - private final PackageMonitor mPackageMonitor = new PackageMonitor() { - @Override - public void onPackageRemoved(String packageName, int uid) { - // Remove all tasks with activities in the specified package from the list of recent tasks - final int eventUserId = getChangingUserId(); - synchronized (ActivityManagerService.this) { - for (int i = mRecentTasks.size() - 1; i >= 0; i--) { - TaskRecord tr = mRecentTasks.get(i); - if (tr.userId != eventUserId) continue; - - ComponentName cn = tr.intent.getComponent(); - if (cn != null && cn.getPackageName().equals(packageName)) { - // If the package name matches, remove the task - removeTaskByIdLocked(tr.taskId, true); - } - } - } - } - - @Override - public boolean onPackageChanged(String packageName, int uid, String[] components) { - onPackageModified(packageName); - return true; - } - - @Override - public void onPackageModified(String packageName) { - final int eventUserId = getChangingUserId(); - final IPackageManager pm = AppGlobals.getPackageManager(); - final ArrayList<Pair<Intent, Integer>> recentTaskIntents = - new ArrayList<Pair<Intent, Integer>>(); - final HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>(); - final ArrayList<Integer> tasksToRemove = new ArrayList<Integer>(); - // Copy the list of recent tasks so that we don't hold onto the lock on - // ActivityManagerService for long periods while checking if components exist. - synchronized (ActivityManagerService.this) { - for (int i = mRecentTasks.size() - 1; i >= 0; i--) { - TaskRecord tr = mRecentTasks.get(i); - if (tr.userId != eventUserId) continue; - - recentTaskIntents.add(new Pair<Intent, Integer>(tr.intent, tr.taskId)); - } - } - // Check the recent tasks and filter out all tasks with components that no longer exist. - for (int i = recentTaskIntents.size() - 1; i >= 0; i--) { - Pair<Intent, Integer> p = recentTaskIntents.get(i); - ComponentName cn = p.first.getComponent(); - if (cn != null && cn.getPackageName().equals(packageName)) { - if (componentsKnownToExist.contains(cn)) { - // If we know that the component still exists in the package, then skip - continue; - } - try { - ActivityInfo info = pm.getActivityInfo(cn, 0, eventUserId); - if (info != null) { - componentsKnownToExist.add(cn); - } else { - tasksToRemove.add(p.second); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to query activity info for component: " + cn, e); - } - } - } - // Prune all the tasks with removed components from the list of recent tasks - synchronized (ActivityManagerService.this) { - for (int i = tasksToRemove.size() - 1; i >= 0; i--) { - removeTaskByIdLocked(tasksToRemove.get(i), false); - } - } - } - - @Override - public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) { - // Force stop the specified packages - int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); - if (packages != null) { - for (String pkg : packages) { - synchronized (ActivityManagerService.this) { - if (forceStopPackageLocked(pkg, -1, false, false, false, false, false, - userId, "finished booting")) { - return true; - } - } - } - } - return false; - } - }; - public void setSystemProcess() { try { ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true); @@ -6166,8 +6072,26 @@ public final class ActivityManagerService extends ActivityManagerNative } } - // Register receivers to handle package update events - mPackageMonitor.register(mContext, Looper.getMainLooper(), UserHandle.ALL, false); + IntentFilter pkgFilter = new IntentFilter(); + pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); + pkgFilter.addDataScheme("package"); + mContext.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES); + if (pkgs != null) { + for (String pkg : pkgs) { + synchronized (ActivityManagerService.this) { + if (forceStopPackageLocked(pkg, -1, false, false, false, false, false, + 0, "finished booting")) { + setResultCode(Activity.RESULT_OK); + return; + } + } + } + } + } + }, pkgFilter); // Let system services know. mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED); @@ -8401,6 +8325,47 @@ public final class ActivityManagerService extends ActivityManagerNative } } + private void removeTasksByPackageNameLocked(String packageName, int userId) { + // Remove all tasks with activities in the specified package from the list of recent tasks + for (int i = mRecentTasks.size() - 1; i >= 0; i--) { + TaskRecord tr = mRecentTasks.get(i); + if (tr.userId != userId) continue; + + ComponentName cn = tr.intent.getComponent(); + if (cn != null && cn.getPackageName().equals(packageName)) { + // If the package name matches, remove the task. + removeTaskByIdLocked(tr.taskId, true); + } + } + } + + private void removeTasksByRemovedPackageComponentsLocked(String packageName, int userId) { + final IPackageManager pm = AppGlobals.getPackageManager(); + final HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>(); + + for (int i = mRecentTasks.size() - 1; i >= 0; i--) { + TaskRecord tr = mRecentTasks.get(i); + if (tr.userId != userId) continue; + + ComponentName cn = tr.intent.getComponent(); + if (cn != null && cn.getPackageName().equals(packageName)) { + // Skip if component still exists in the package. + if (componentsKnownToExist.contains(cn)) continue; + + try { + ActivityInfo info = pm.getActivityInfo(cn, 0, userId); + if (info != null) { + componentsKnownToExist.add(cn); + } else { + removeTaskByIdLocked(tr.taskId, false); + } + } catch (RemoteException e) { + Log.e(TAG, "Activity info query failed. component=" + cn, e); + } + } + } + } + /** * Removes the task with the specified task id. * @@ -15660,128 +15625,135 @@ public final class ActivityManagerService extends ActivityManagerNative } } - // Handle special intents: if this broadcast is from the package - // manager about a package being removed, we need to remove all of - // its activities from the history stack. - final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals( - intent.getAction()); - if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction()) - || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction()) - || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction()) - || Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction()) - || uidRemoved) { - if (checkComponentPermission( - android.Manifest.permission.BROADCAST_PACKAGE_REMOVED, - callingPid, callingUid, -1, true) - == PackageManager.PERMISSION_GRANTED) { - if (uidRemoved) { - final Bundle intentExtras = intent.getExtras(); - final int uid = intentExtras != null - ? intentExtras.getInt(Intent.EXTRA_UID) : -1; - if (uid >= 0) { - BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics(); - synchronized (bs) { - bs.removeUidStatsLocked(uid); - } - mAppOpsService.uidRemoved(uid); + final String action = intent.getAction(); + if (action != null) { + switch (action) { + case Intent.ACTION_UID_REMOVED: + case Intent.ACTION_PACKAGE_REMOVED: + case Intent.ACTION_PACKAGE_CHANGED: + case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE: + case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE: + // Handle special intents: if this broadcast is from the package + // manager about a package being removed, we need to remove all of + // its activities from the history stack. + if (checkComponentPermission( + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED, + callingPid, callingUid, -1, true) + != PackageManager.PERMISSION_GRANTED) { + String msg = "Permission Denial: " + intent.getAction() + + " broadcast from " + callerPackage + " (pid=" + callingPid + + ", uid=" + callingUid + ")" + + " requires " + + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED; + Slog.w(TAG, msg); + throw new SecurityException(msg); } - } else { - // If resources are unavailable just force stop all - // those packages and flush the attribute cache as well. - if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) { - String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); - if (list != null && (list.length > 0)) { - for (String pkg : list) { - forceStopPackageLocked(pkg, -1, false, true, true, false, false, userId, - "storage unmount"); + switch (action) { + case Intent.ACTION_UID_REMOVED: + final Bundle intentExtras = intent.getExtras(); + final int uid = intentExtras != null + ? intentExtras.getInt(Intent.EXTRA_UID) : -1; + if (uid >= 0) { + BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics(); + synchronized (bs) { + bs.removeUidStatsLocked(uid); + } + mAppOpsService.uidRemoved(uid); } - cleanupRecentTasksLocked(UserHandle.USER_ALL); - sendPackageBroadcastLocked( - IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list, userId); - } - } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals( - intent.getAction())) { - cleanupRecentTasksLocked(UserHandle.USER_ALL); - } else { - Uri data = intent.getData(); - String ssp; - if (data != null && (ssp=data.getSchemeSpecificPart()) != null) { - boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals( - intent.getAction()); - boolean fullUninstall = removed && - !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); - if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) { - forceStopPackageLocked(ssp, UserHandle.getAppId( - intent.getIntExtra(Intent.EXTRA_UID, -1)), false, true, true, - false, fullUninstall, userId, - removed ? "pkg removed" : "pkg changed"); + break; + case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE: + // If resources are unavailable just force stop all those packages + // and flush the attribute cache as well. + String list[] = + intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); + if (list != null && list.length > 0) { + for (int i = 0; i < list.length; i++) { + forceStopPackageLocked(list[i], -1, false, true, true, + false, false, userId, "storage unmount"); + } + cleanupRecentTasksLocked(UserHandle.USER_ALL); + sendPackageBroadcastLocked( + IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list, + userId); } - if (removed) { - sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED, - new String[] {ssp}, userId); - if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { - mAppOpsService.packageRemoved( - intent.getIntExtra(Intent.EXTRA_UID, -1), ssp); - - // Remove all permissions granted from/to this package - removeUriPermissionsForPackageLocked(ssp, userId, true); + break; + case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE: + cleanupRecentTasksLocked(UserHandle.USER_ALL); + break; + case Intent.ACTION_PACKAGE_REMOVED: + case Intent.ACTION_PACKAGE_CHANGED: + Uri data = intent.getData(); + String ssp; + if (data != null && (ssp=data.getSchemeSpecificPart()) != null) { + boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action); + boolean fullUninstall = removed && + !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); + if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) { + forceStopPackageLocked(ssp, UserHandle.getAppId( + intent.getIntExtra(Intent.EXTRA_UID, -1)), + false, true, true, false, fullUninstall, userId, + removed ? "pkg removed" : "pkg changed"); + } + if (removed) { + sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED, + new String[] {ssp}, userId); + if (fullUninstall) { + mAppOpsService.packageRemoved( + intent.getIntExtra(Intent.EXTRA_UID, -1), ssp); + + // Remove all permissions granted from/to this package + removeUriPermissionsForPackageLocked(ssp, userId, true); + + removeTasksByPackageNameLocked(ssp, userId); + } + } else { + removeTasksByRemovedPackageComponentsLocked(ssp, userId); } } + break; + } + break; + case Intent.ACTION_PACKAGE_ADDED: + // Special case for adding a package: by default turn on compatibility mode. + Uri data = intent.getData(); + String ssp; + if (data != null && (ssp = data.getSchemeSpecificPart()) != null) { + final boolean replacing = + intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); + mCompatModePackages.handlePackageAddedLocked(ssp, replacing); + + if (replacing) { + removeTasksByRemovedPackageComponentsLocked(ssp, userId); } } - } - } else { - String msg = "Permission Denial: " + intent.getAction() - + " broadcast from " + callerPackage + " (pid=" + callingPid - + ", uid=" + callingUid + ")" - + " requires " - + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED; - Slog.w(TAG, msg); - throw new SecurityException(msg); - } - - // Special case for adding a package: by default turn on compatibility - // mode. - } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) { - Uri data = intent.getData(); - String ssp; - if (data != null && (ssp=data.getSchemeSpecificPart()) != null) { - mCompatModePackages.handlePackageAddedLocked(ssp, - intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)); - } - } - - /* - * If this is the time zone changed action, queue up a message that will reset the timezone - * of all currently running processes. This message will get queued up before the broadcast - * happens. - */ - if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) { - mHandler.sendEmptyMessage(UPDATE_TIME_ZONE); - } - - /* - * If the user set the time, let all running processes know. - */ - if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) { - final int is24Hour = intent.getBooleanExtra( - Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1 : 0; - mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0)); - BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); - synchronized (stats) { - stats.noteCurrentTimeChangedLocked(); + break; + case Intent.ACTION_TIMEZONE_CHANGED: + // If this is the time zone changed action, queue up a message that will reset + // the timezone of all currently running processes. This message will get + // queued up before the broadcast happens. + mHandler.sendEmptyMessage(UPDATE_TIME_ZONE); + break; + case Intent.ACTION_TIME_CHANGED: + // If the user set the time, let all running processes know. + final int is24Hour = + intent.getBooleanExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1 + : 0; + mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0)); + BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); + synchronized (stats) { + stats.noteCurrentTimeChangedLocked(); + } + break; + case Intent.ACTION_CLEAR_DNS_CACHE: + mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG); + break; + case Proxy.PROXY_CHANGE_ACTION: + ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO); + mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy)); + break; } } - if (Intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) { - mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG); - } - - if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) { - ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO); - mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy)); - } - // Add to the sticky list if requested. if (sticky) { if (checkPermission(android.Manifest.permission.BROADCAST_STICKY, |