SystemUI中,Home键调出小刷子杀最近任务,整个流程从其RecentsPanelView.java开始:
View Codepublic void handleSwipe(View view) { ... // Currently, either direction means the same thing, so ignore direction and remove // the task. final ActivityManager am = (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE); if (am != null) { am.removeTask(ad.persistentTaskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);① // Accessibility feedback setContentDescription( getContext().getString(R.string.accessibility_recents_item_dismissed, ad.getLabel())); sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); setContentDescription(null); } }
View Codeprivate void cleanUpRemovedTaskLocked(TaskRecord tr, int flags) { mRecentTasks.remove(tr); tr.removedFromRecents(mTaskPersister); final boolean killProcesses = (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0; Intent baseIntent = new Intent( tr.intent != null ? tr.intent : tr.affinityIntent); ComponentName component = baseIntent.getComponent(); if (component == null) { Slog.w(TAG, "Now component for base intent of task: " + tr); return; } // Find any running services associated with this app. mServices.cleanUpRemovedTaskLocked(tr, component, baseIntent);④ if (killProcesses) { // Find any running processes associated with this app. final String pkg = component.getPackageName(); ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(); ArrayMap<String, SparseArray<ProcessRecord>> pmap = mProcessNames.getMap(); for (int i=0; i<pmap.size(); i++) { SparseArray<ProcessRecord> uids = pmap.valueAt(i); for (int j=0; j<uids.size(); j++) { ProcessRecord proc = uids.valueAt(j); if (proc.userId != tr.userId) { continue; } if (!proc.pkgList.containsKey(pkg)) { continue; } procs.add(proc); } } // Kill the running processes. for (int i=0; i<procs.size(); i++) { ProcessRecord pr = procs.get(i); if (pr == mHomeProcess) { // Don't kill the home process along with tasks from the same package. continue; } if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) { pr.kill("remove task", true); } else { pr.waitingToKill = "remove task"; } } } } /** * Removes the task with the specified task id. * * @param taskId Identifier of the task to be removed. * @param flags Additional operational flags. May be 0 or * {@link ActivityManager#REMOVE_TASK_KILL_PROCESS}. * @return Returns true if the given task was found and removed. */ private boolean removeTaskByIdLocked(int taskId, int flags) { TaskRecord tr = recentTaskForIdLocked(taskId); if (tr != null) { tr.removeTaskActivitiesLocked(); cleanUpRemovedTaskLocked(tr, flags);③ if (tr.isPersistable) { notifyTaskPersisterLocked(null, true); } return true; } return false; } @Override public boolean removeTask(int taskId, int flags) { synchronized (this) { enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS, "removeTask()"); long ident = Binder.clearCallingIdentity(); try { return removeTaskByIdLocked(taskId, flags);② } finally { Binder.restoreCallingIdentity(ident); } } }
View Codevoid cleanUpRemovedTaskLocked(TaskRecord tr, ComponentName component, Intent baseIntent) { ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>(); ArrayMap<ComponentName, ServiceRecord> alls = getServices(tr.userId); for (int i=0; i<alls.size(); i++) { ServiceRecord sr = alls.valueAt(i); if (sr.packageName.equals(component.getPackageName())) { services.add(sr); } } // Take care of any running services associated with the app. for (int i=0; i<services.size(); i++) { ServiceRecord sr = services.get(i); if (sr.startRequested) { if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) { Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task"); stopServiceLocked(sr); } else { sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true, sr.makeNextStartId(), baseIntent, null)); if (sr.app != null && sr.app.thread != null) { // We always run in the foreground, since this is called as // part of the "remove task" UI operation. sendServiceArgsLocked(sr, true, false); } } } } }
View Code/** * Completely remove all activities associated with an existing * task starting at a specified index. */ final void performClearTaskAtIndexLocked(int activityNdx) { int numActivities = mActivities.size(); for ( ; activityNdx < numActivities; ++activityNdx) { final ActivityRecord r = mActivities.get(activityNdx); if (r.finishing) { continue; } if (stack == null) { // Task was restored from persistent storage. r.takeFromHistory(); mActivities.remove(activityNdx); --activityNdx; --numActivities; } else if (stack.finishActivityLocked(r, Activity.RESULT_CANCELED, null, "clear", false)) { --activityNdx; --numActivities; } } } /** * Completely remove all activities associated with an existing task. */ final void performClearTaskLocked() { mReuseTask = true; performClearTaskAtIndexLocked(0); mReuseTask = false; }
View Code/** * Background thread group - All threads in * this group are scheduled with a reduced share of the CPU. * Value is same as constant SP_BACKGROUND of enum SchedPolicy. * FIXME rename to THREAD_GROUP_BACKGROUND. * @hide */ public static final int THREAD_GROUP_BG_NONINTERACTIVE = 0;