主页 > 软件开发  > 

recent移除task时,结束其所有进程和service(全Android版本)

recent移除task时,结束其所有进程和service(全Android版本)

Android原生系统在清理后台应用时,其实并不能清理所有进程。例如:

在点击系统自带的播放器以后,播放音乐的时候,在最近任务栏recents列表中,点击全部清除,发现音乐播放器还在播放音乐。

现提供两种解决方案

一、Launcher中forceStopPackage Android9 vendor下面的launcher 里面 RecentsView.java TaskActionController.java removeTask 方法里面 - ActivityManagerWrapper.getInstance().removeTask(task.key.id); + final ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE); + String pkgName = task.key.getPackageName(); + Log.d(TAG, "Stopping pkgName " + pkgName); + am.forceStopPackage(pkgName); Android13 alps_mssi/frameworks/base/data/etc/com.android.launcher3.xml <permission name="android.permission.STOP_APP_SWITCHES"/> + <permission name="android.permission.FORCE_STOP_PACKAGES"/> alps_mssi/vendor/mediatek/proprietary/packages/apps/Launcher3/quickstep/AndroidManifest.xml + <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES"/> alps_mssi/vendor/mediatek/proprietary/packages/apps/Launcher3/quickstep/src/com/android/quickstep/views/RecentsView.java import java.util.Objects; import java.util.function.Consumer; +import android.app.ActivityManager; +import android.app.ActivityOptions; + /** * A list of recent tasks. */ @@ -3127,12 +3130,16 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T if (success) { if (shouldRemoveTask) { if (dismissedTaskView.getTask() != null) { + //andy + String pkgname = dismissedTaskView.getTask().key.getPackageName(); + Log.e("andy---RecentsView","pkgname="+pkgname); + if (ENABLE_QUICKSTEP_LIVE_TILE.get() && dismissedTaskView.isRunningTask()) { finishRecentsAnimation(true /* toRecents */, false /* shouldPip */, - () -> removeTaskInternal(dismissedTaskViewId)); + () -> removeTaskInternal(dismissedTaskViewId,pkgname)); } else { - removeTaskInternal(dismissedTaskViewId); + removeTaskInternal(dismissedTaskViewId,pkgname); } mActivity.getStatsLogManager().logger() .withItemInfo(dismissedTaskView.getItemInfo()) @@ -3401,7 +3408,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T return lastVisibleIndex; } - private void removeTaskInternal(int dismissedTaskViewId) { + private void removeTaskInternal(int dismissedTaskViewId, String pkgname) { int[] taskIds = getTaskIdsForTaskViewId(dismissedTaskViewId); int primaryTaskId = taskIds[0]; int secondaryTaskId = taskIds[1]; @@ -3411,6 +3418,10 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T if (secondaryTaskId != -1) { ActivityManagerWrapper.getInstance().removeTask(secondaryTaskId); } + //andy + ActivityManager am = (ActivityManager) mActivity.getSystemService(Context.ACTIVITY_SERVICE); + Log.e("andy---RecentsView---", "pkgname = " + pkgname); + am.forceStopPackage(pkgname); }, REMOVE_TASK_WAIT_FOR_APP_STOP_MS); } @@ -3436,6 +3447,12 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T int count = getTaskViewCount(); for (int i = 0; i < count; i++) { addDismissedTaskAnimations(requireTaskViewAt(i), duration, anim); + //andy + String pkgname = requireTaskViewAt(i).getTask().key.getPackageName(); + Log.e("andy---RecentsView---createAllTasksDismissAnimation---","pkgname="+pkgname); + ActivityManager am = (ActivityManager) mActivity.getSystemService(Context.ACTIVITY_SERVICE); + am.forceStopPackage(pkgname); + } mPendingAnimation = anim; 二、AMS中判断前台service也杀死

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

Android6 在最近的任务界面,把正在播放的音乐关掉,播放的音乐没有停止 @Override public boolean removeTask(int taskId) { synchronized (this) { enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS, "removeTask()"); long ident = Binder.clearCallingIdentity(); try { return removeTaskByIdLocked(taskId, true); } finally { Binder.restoreCallingIdentity(ident); } } } private boolean removeTaskByIdLocked(int taskId, boolean killProcess) { TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(taskId, false); /// M: BMW. [ALPS01455940], remove task which not in recent task /// but we really want to remove. Add recent task will auto remove /// duplicate task record (the same task affinity) @{ if (MultiWindowProxy.isSupported() && tr == null) { ArrayList<ActivityStack> stackList = mStackSupervisor.getStacks(); for (int i = 0; i < stackList.size(); i++) { ActivityStack stack = stackList.get(i); TaskRecord task = stack.topTask(); if (MultiWindowProxy.getInstance().isFloatingStack(stack.mStackId) && task != null && task.taskId == taskId) { tr = task; } } } /// @} if (tr != null) { tr.removeTaskActivitiesLocked(); cleanUpRemovedTaskLocked(tr, killProcess); if (tr.isPersistable) { notifyTaskPersisterLocked(null, true); } return true; } Slog.w(TAG, "Request to remove task ignored for non-existent task " + taskId); return false; } private void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess) { mRecentTasks.remove(tr); tr.removedFromRecents(); ComponentName component = tr.getBaseIntent().getComponent(); if (component == null) { Slog.w(TAG, "No component for base intent of task: " + tr); return; } // Find any running services associated with this app and stop if needed. mServices.cleanUpRemovedTaskLocked(tr, component, new Intent(tr.getBaseIntent())); if (!killProcess) { return; } // Determine if the process(es) for this task should be killed. final String pkg = component.getPackageName(); ArrayList<ProcessRecord> procsToKill = new ArrayList<>(); 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) { // Don't kill process for a different user. continue; } if (proc == mHomeProcess) { // Don't kill the home process along with tasks from the same package. continue; } if (!proc.pkgList.containsKey(pkg)) { // Don't kill process that is not associated with this task. continue; } for (int k = 0; k < proc.activities.size(); k++) { TaskRecord otherTask = proc.activities.get(k).task; if (tr.taskId != otherTask.taskId && otherTask.inRecents) { // Don't kill process(es) that has an activity in a different task that is // also in recents. return; } } if (proc.foregroundServices) { // Don't kill process(es) with foreground service. return; } // Add process to kill list. procsToKill.add(proc); } } // Kill the running processes. for (int i = 0; i < procsToKill.size(); i++) { ProcessRecord pr = procsToKill.get(i); if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE && pr.curReceiver == null) { pr.kill("remove task", true); } else { // We delay killing processes that are not in the background or running a receiver. pr.waitingToKill = "remove task"; } } } 可以看到,如果是foreground的service,就不会kill掉进程 让service 不调用 public final void startForeground(int id, Notification notification); 问题解决 但如果不调用这个,service就是后台的,系统内存紧张时就会被杀掉, 后续看看有没有别的解决办法~ 改framework?实在不行就这么干 Android7 private void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess, boolean removeFromRecents) { if (removeFromRecents) { mRecentTasks.remove(tr); tr.removedFromRecents(); } ComponentName component = tr.getBaseIntent().getComponent(); if (component == null) { Slog.w(TAG, "No component for base intent of task: " + tr); return; } // Find any running services associated with this app and stop if needed. mServices.cleanUpRemovedTaskLocked(tr, component, new Intent(tr.getBaseIntent())); if (!killProcess) { return; } // Determine if the process(es) for this task should be killed. final String pkg = component.getPackageName(); ArrayList<ProcessRecord> procsToKill = new ArrayList<>(); 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) { // Don't kill process for a different user. continue; } if (proc == mHomeProcess) { // Don't kill the home process along with tasks from the same package. continue; } if (!proc.pkgList.containsKey(pkg)) { // Don't kill process that is not associated with this task. continue; } for (int k = 0; k < proc.activities.size(); k++) { TaskRecord otherTask = proc.activities.get(k).task; if (tr.taskId != otherTask.taskId && otherTask.inRecents) { // Don't kill process(es) that has an activity in a different task that is // also in recents. return; } } - if (proc.foregroundServices) { - // Don't kill process(es) with foreground service. - return; - } // Add process to kill list. procsToKill.add(proc); } } // Kill the running processes. for (int i = 0; i < procsToKill.size(); i++) { ProcessRecord pr = procsToKill.get(i); - if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND - && pr.curReceiver == null) { pr.kill("remove task", true); - } else { - // We delay killing processes that are not in the background or running a receiver. - pr.waitingToKill = "remove task"; - } } } Android11 packages/apps/Launcher3/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java void removeTask(Task task, boolean killProcess, boolean removeFromRecents, String reason) { if (task.mInRemoveTask) { // Prevent recursion. return; } task.mInRemoveTask = true; try { task.performClearTask(reason); cleanUpRemovedTaskLocked(task, killProcess, removeFromRecents); mService.getLockTaskController().clearLockedTask(task); mService.getTaskChangeNotificationController().notifyTaskStackChanged(); if (task.isPersistable) { mService.notifyTaskPersisterLocked(null, true); } } finally { task.mInRemoveTask = false; } } void cleanUpRemovedTaskLocked(Task task, boolean killProcess, boolean removeFromRecents) { if (removeFromRecents) { mRecentTasks.remove(task); } ComponentName component = task.getBaseIntent().getComponent(); if (component == null) { Slog.w(TAG, "No component for base intent of task: " + task); return; } // Find any running services associated with this app and stop if needed. final Message msg = PooledLambda.obtainMessage(ActivityManagerInternal::cleanUpServices, mService.mAmInternal, task.mUserId, component, new Intent(task.getBaseIntent())); mService.mH.sendMessage(msg); if (!killProcess) { return; } // Determine if the process(es) for this task should be killed. final String pkg = component.getPackageName(); ArrayList<Object> procsToKill = new ArrayList<>(); ArrayMap<String, SparseArray<WindowProcessController>> pmap = mService.mProcessNames.getMap(); for (int i = 0; i < pmap.size(); i++) { SparseArray<WindowProcessController> uids = pmap.valueAt(i); for (int j = 0; j < uids.size(); j++) { WindowProcessController proc = uids.valueAt(j); if (proc.mUserId != task.mUserId) { // Don't kill process for a different user. continue; } if (proc == mService.mHomeProcess) { // Don't kill the home process along with tasks from the same package. continue; } if (!proc.mPkgList.contains(pkg)) { // Don't kill process that is not associated with this task. continue; } if (!proc.shouldKillProcessForRemovedTask(task)) { // Don't kill process(es) that has an activity in a different task that is also // in recents, or has an activity not stopped. return; } // core modify start /*if (proc.hasForegroundServices()) { // Don't kill process(es) with foreground service. return; }*/ // core modify end // Add process to kill list. procsToKill.add(proc); } } // Kill the running processes. Post on handle since we don't want to hold the service lock // while calling into AM. final Message m = PooledLambda.obtainMessage( ActivityManagerInternal::killProcessesForRemovedTask, mService.mAmInternal, procsToKill); mService.mH.sendMessage(m); } public void killProcessesForRemovedTask(ArrayList<Object> procsToKill) { synchronized (ActivityManagerService.this) { for (int i = 0; i < procsToKill.size(); i++) { final WindowProcessController wpc = (WindowProcessController) procsToKill.get(i); final ProcessRecord pr = (ProcessRecord) wpc.mOwner; // core modify start /*if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND && pr.curReceivers.isEmpty()) {*/ pr.kill("remove task", ApplicationExitInfo.REASON_USER_REQUESTED, ApplicationExitInfo.SUBREASON_UNKNOWN, true); /* } else { // We delay killing processes that are not in the background or running a // receiver. pr.waitingToKill = "remove task"; }*/ // core modify end } } }

标签:

recent移除task时,结束其所有进程和service(全Android版本)由讯客互联软件开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“recent移除task时,结束其所有进程和service(全Android版本)