当前位置: 首页 > news >正文

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


                  }
              }
          }

相关文章:

  • 日常开发中,使用JSON.stringify来实现深拷贝的坑
  • PHP支付宝--转账到支付宝账户
  • 计算机专业知识【探秘 C/S 工作模式:原理、应用与网络协议案例】
  • NBT群落物种级丰度鉴定新方法sylph
  • 【C语言】有序数组的平方
  • 《DeepSeek 一站式工作生活 AI 助手》
  • 外包干了3年,技术退步太明显了。。。。。
  • Rust 语言入门(一):打印与格式化输出
  • Transformer 模型介绍(四)——编码器 Encoder 和解码器 Decoder
  • DeepSeek应用-一秒对书本要点分析并创建思维脑图
  • Java并发编程——AQS原理解析
  • MobaXterm中文版安装使用教程-附安装包
  • 使用 Spring Boot 和 Canal 实现 MySQL 数据库同步
  • 1997-2019年各省进出口总额数据
  • Android 中使用 FFmpeg 进行音视频处理
  • Spring Boot三:Springboot自动装配原理
  • Java中Map循环安全的删除数据的4中方法
  • Qt5开发入门指南:从零开始掌握跨平台开发
  • ZYNQ TCP Server PS端千兆网口速率低问题,要修改BSP中LWIP配置参数
  • 英语---基础词汇库