20251028在荣品RD-RK3588-MID开发板的Android13系统下解决关机的时候最近打开的应用不关的问题
20251028在荣品RD-RK3588-MID开发板的Android13系统下解决关机的时候最近打开的应用不关的问题
2025/10/28 18:12
缘起:公司的APK应用开发工程师的需求/品味/审美比较独特,报告了超多问题。!
要求关机/poweroff的时候,最近打开的应用也要清除。
直接调用“全部清除”不就得了。
源码由DeepSeek给出来!
测试设备:Android手机【版本10+】、荣品RD-RK3588-MID开发板
测试步骤:按 虚拟按键,左下角的 3条横线,看看 打开了几个应用。
长按 POWER按键 重启。
重启完成 之后,继续 按 虚拟按键的 ,可以看见 以前的应用还在![破涕为笑]
好的,你这边测试是软重启是吧,
你可以试一下断电硬重启
测试设备:Android手机【版本10+】、荣品RD-RK3588-MID开发板
测试步骤:按 虚拟按键,左下角的 3条横线,看看 打开了几个应用。
长按 POWER按键 【上一次重启,这一次 关机 也有】。
重启完成 之后,继续 按 虚拟按键的 ,可以看见 以前的应用还在![破涕为笑]?
POWEROFF也有这个问题 有点说不过去了。[疑问]
是否是 RK/Android的问题?
如果 是 Android的问题?请问 如何在poweroff走关机的流程之前,调用【全部清除,干掉所有的APP】[破涕为笑]?
ZT10/28 10:17:12
有个小问题 开机重启 Home 会看到上次的记录
ZT 10/28 10:17:22
关机,再开机
这个 问题 非 致命性 BUG/不影响功能,记录在案,押后处理。
先要要确认 是否是 RK/Android的问题?
如果 是 Android的问题?【解决思路之一】 如何在poweroff走关机的流程之前,调用【全部清除,干掉所有的APP】[破涕为笑]?@余顺
第一步:
RK3588 Android13关机清除APP方案
在RK3588的Android13关机的时候,请问如何 修改SDK代码,以调用 “全部清除” 拿掉所有历史打开的APP,
方案一:修改ActivityManagerService(推荐)
1. 修改文件:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
2. 添加清除方法:
java
// 在ActivityManagerService类中添加方法
private void clearAllRecentTasksOnShutdown() {
try {
// 获取ActivityTaskManager服务
IActivityTaskManager atm = ActivityTaskManager.getService();
if (atm != null) {
// 移除所有最近任务
atm.removeAllVisibleRecentTasks();
// 或者使用以下方法清除所有任务
// List<ActivityManager.RecentTaskInfo> recentTasks =
// getRecentTasks(Integer.MAX_VALUE, 0, userId);
// for (ActivityManager.RecentTaskInfo task : recentTasks) {
// removeTask(task.persistentId);
// }
Slog.i(TAG, "Cleared all recent tasks on shutdown");
}
} catch (RemoteException e) {
Slog.e(TAG, "Failed to clear recent tasks on shutdown", e);
}
}
3. 在关机流程中调用:
在shutdown()方法中添加调用:
java
@Override
public void shutdown(int timeout) {
// 先清除所有最近任务
clearAllRecentTasksOnShutdown();
// 原有关机代码
// ... existing shutdown code ...
}
编译的时候出错:
请复核一下方法一的代码:
warning: Supported source version 'RELEASE_9' from annotation processor 'android.processor.compat.changeid.ChangeIdProcessor' less than -source '11'
out/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/javac/shard32/srcjars/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java:6896: error: cannot find symbol
IActivityTaskManager atm = ActivityTaskManager.getService();
^
symbol: class IActivityTaskManager
location: class ActivityManagerService
out/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/javac/shard32/srcjars/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java:6896: error: cannot find symbol
IActivityTaskManager atm = ActivityTaskManager.getService();
^
symbol: variable ActivityTaskManager
location: class ActivityManagerService
2 errors
1 warning
16:43:32 ninja failed with: exit status 1
#### failed to build some targets (02:12 (mm:ss)) ####
Build android failed!
rootroot@rootroot-X99-Turbo:~/rk-android13-20250818RD-RK3588-MID$


您遇到的编译错误是因为缺少正确的导入。让我提供修正后的代码:
修正后的方案一代码
1. 首先添加必要的导入
在 ActivityManagerService.java 文件的开头添加以下导入:
java
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
2. 修正的清除方法
java
// 在ActivityManagerService类中添加方法
private void clearAllRecentTasksOnShutdown() {
try {
// 使用正确的方式获取ActivityTaskManager服务
IActivityTaskManager atm = ActivityTaskManager.getService();
if (atm != null) {
// 移除所有最近任务
atm.removeAllVisibleRecentTasks();
Slog.i(TAG, "Cleared all recent tasks on shutdown");
}
} catch (RemoteException e) {
Slog.e(TAG, "Failed to clear recent tasks on shutdown", e);
}
}
3. 在shutdown方法中调用
找到 shutdown 方法,在方法开始处添加调用:
java
@Override
public boolean shutdown(int timeout) {
// 在关机时清除所有最近任务
clearAllRecentTasksOnShutdown();
// 原有的shutdown代码保持不变
// ... existing shutdown code ...
return true;
}


效果图:



RK3588 Android13关机清除APP方案
在RK3588的Android13关机的时候,请问如何 修改SDK代码,以调用 “全部清除” 拿掉所有历史打开的APP,
在Android系统中,关机过程会发送关机广播,然后系统会关闭所有活动。但是,默认情况下,系统并不会在关机时清除所有最近任务(即历史打开的APP)。如果你想要在关机时清除所有最近任务,你需要修改系统代码。
在Android中,最近任务(Recent Tasks)是由SystemUI管理的。因此,我们可以在关机过程中通知SystemUI清除最近任务。
以下是一种可能的实现方法:
首先,我们需要在关机流程中找到一个合适的点来触发清除最近任务的操作。在Android中,关机时会发送Intent.ACTION_SHUTDOWN广播,我们可以监听这个广播,但是这里我们需要在系统代码中直接添加调用,因为我们需要系统权限。
另一种方法是在ShutdownThread中添加代码,因为关机流程是由ShutdownThread控制的。
我们也可以考虑在ActivityManagerService中添加清除最近任务的功能,因为ActivityManagerService负责管理Activity和任务。
这里我们选择在ShutdownThread中添加代码,因为它是直接处理关机流程的。
具体步骤:
a. 找到ShutdownThread类。在AOSP中,这个类通常位于frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java。
b. 在ShutdownThread的run()方法中,在关机流程的某个阶段(例如,在广播关机意图之后,但在真正关闭电源之前)添加清除最近任务的代码。
c. 清除最近任务可以通过ActivityManagerService的removeAllTasks()方法来实现。但是请注意,removeAllTasks()方法可能会被限制,因此我们需要检查可用性。
实际上,在Android中,我们可以使用ActivityManager的removeTask或removeAllTasks方法,但是这些方法需要系统权限。在系统代码中,我们可以直接调用。
在ShutdownThread中,我们可以通过IActivityManager来调用清除任务的方法。
d. 但是,请注意,从Android 5.0开始,Google对最近任务的管理做了更改,我们可能需要使用ActivityTaskManager而不是ActivityManager。
由于我们是在RK3588的Android13上修改,所以我们需要使用新的API。
在Android 10及以上,最近任务的管理在ActivityTaskManager中。我们可以通过ActivityTaskManager的removeAllVisibleRecentTasks()方法来清除最近任务。
但是,请注意,ShutdownThread中可能没有直接引用ActivityTaskManager,我们需要添加相应的导入和调用。
具体代码修改:
在ShutdownThread.java文件中,添加导入:
java
import android.app.ActivityTaskManager;
import android.content.Context;
在run()方法中,在广播关机意图之后,添加以下代码:
java
// Clear all recent tasks
try {
ActivityTaskManager atm = (ActivityTaskManager) Context.getSystemService(Context.ACTIVITY_TASK_SERVICE);
if (atm != null) {
atm.removeAllVisibleRecentTasks();
}
} catch (Exception e) {
Log.e(TAG, "Failed to clear recent tasks", e);
}
但是,请注意,ActivityTaskManager的removeAllVisibleRecentTasks()方法是一个系统API,需要系统权限。由于ShutdownThread运行在系统进程中,所以应该有权调用。
然而,实际上,在Android 13中,ActivityTaskManager并没有提供removeAllVisibleRecentTasks()方法。相反,我们可以使用ActivityTaskManager的removeAllRecentTasks()方法,但是这个方法在Android 13中已经被隐藏,并且需要系统权限。
另一种方法是使用IActivityTaskManager接口,通过AIDL调用。但是,我们也可以使用ActivityManager的clearRecentTasks()方法,但是这个方法在Android 5.0之后被标记为隐藏。
考虑到这些,我们可以通过反射来调用,但更稳定的方法是使用系统内部API。
实际上,在Android系统中,SystemUI中的RecentTasks类负责管理最近任务。但是,我们这里是在关机流程中,我们可以直接调用ActivityManagerService的相关方法。
由于我们是在系统服务器中,我们可以直接获取ActivityManagerService的实例并调用其方法。
在ShutdownThread中,我们可以通过ActivityManager.getService()来获取IActivityManager,然后调用其方法。但是,IActivityManager接口中并没有直接清除最近任务的方法。
我们可以通过调用IActivityManager的removeTask方法遍历删除所有任务,但是这样效率低且复杂。
另一种方法是,我们直接调用ActivityTaskManagerService的removeAllRecentTasks()方法。但是,我们需要获取到ActivityTaskManagerService的实例。
在系统代码中,我们可以通过ActivityTaskManager.getService()来获取IActivityTaskManager,然后调用removeAllRecentTasks()。
但是,removeAllRecentTasks()方法在IActivityTaskManager中是有定义的,但是它是一个系统API,并且需要系统权限。
我们可以这样写:
java
IActivityTaskManager atm = ActivityTaskManager.getService();
if (atm != null) {
atm.removeAllRecentTasks();
}
但是,请注意,removeAllRecentTasks()方法可能会抛出RemoteException,我们需要处理。
所以,修改后的代码可能如下:
在ShutdownThread.java的run()方法中,在广播关机意图之后,添加:
java
// Clear all recent tasks
try {
IActivityTaskManager atm = ActivityTaskManager.getService();
if (atm != null) {
atm.removeAllRecentTasks();
}
} catch (RemoteException e) {
Log.e(TAG, "Failed to clear recent tasks", e);
}
同时,需要导入:
java
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
import android.os.RemoteException;
但是,请注意,removeAllRecentTasks()方法在Android 13中可能被限制,需要系统权限。由于ShutdownThread运行在系统进程,所以应该可以调用。
另外,请注意,这个方法会清除所有最近任务,包括默认的launcher任务,所以下次开机时,launcher会重新启动。
最后,由于我们修改了系统代码,需要重新编译系统并刷机。
注意:以上代码是基于AOSP的代码结构,具体在RK3588的SDK中,可能会有一些差异,请根据实际情况调整。
另外,RK3588的SDK可能对关机流程有自定义的修改,所以请确保在修改时不会影响其他关机流程。
由于关机流程是系统关键流程,请谨慎修改,并充分测试。
在RK3588的Android 13上实现关机时清除所有历史打开的APP,你需要修改系统服务代码。以下是几种实现方案:
方案一:修改ActivityManagerService(推荐)
1. 修改文件:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
2. 添加清除方法:
java
// 在ActivityManagerService类中添加方法
private void clearAllRecentTasksOnShutdown() {
try {
// 获取ActivityTaskManager服务
IActivityTaskManager atm = ActivityTaskManager.getService();
if (atm != null) {
// 移除所有最近任务
atm.removeAllVisibleRecentTasks();
// 或者使用以下方法清除所有任务
// List<ActivityManager.RecentTaskInfo> recentTasks =
// getRecentTasks(Integer.MAX_VALUE, 0, userId);
// for (ActivityManager.RecentTaskInfo task : recentTasks) {
// removeTask(task.persistentId);
// }
Slog.i(TAG, "Cleared all recent tasks on shutdown");
}
} catch (RemoteException e) {
Slog.e(TAG, "Failed to clear recent tasks on shutdown", e);
}
}
3. 在关机流程中调用:
在shutdown()方法中添加调用:
java
@Override
public void shutdown(int timeout) {
// 先清除所有最近任务
clearAllRecentTasksOnShutdown();
// 原有关机代码
// ... existing shutdown code ...
}
方案二:修改ShutdownThread
1. 修改文件:
frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java
2. 在beginShutdown()方法中添加:
java
private static void beginShutdown() {
// 在关机开始时清除最近任务
clearAllRecentTasks();
// 原有代码
// ... existing code ...
}
private static void clearAllRecentTasks() {
try {
IActivityTaskManager atm = ActivityTaskManager.getService();
if (atm != null) {
// 清除所有可见的最近任务
atm.removeAllVisibleRecentTasks();
// 强制停止所有后台进程
ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
if (am != null) {
am.forceStopPackage(mContext.getPackageName());
}
}
} catch (Exception e) {
Log.e(TAG, "Failed to clear recent tasks during shutdown", e);
}
}
方案三:修改RecentTasks.java
1. 修改文件:
frameworks/base/services/core/java/com/android/server/wm/RecentTasks.java
2. 添加关机清理方法:
java
public void cleanupOnShutdown() {
synchronized (mService) {
// 清除所有任务
for (int i = mTasks.size() - 1; i >= 0; i--) {
Task task = mTasks.get(i);
removeTask(task);
}
// 清除持久化数据
mTaskPersister.unloadAllData();
// 保存空的任务列表
mTaskPersister.persistTasks(null);
}
}
方案四:通过广播接收器(如果权限允许)
1. 创建关机广播接收器:
java
public class ShutdownClearReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
clearAllRecentTasks(context);
}
}
private void clearAllRecentTasks(Context context) {
try {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
// 通过ActivityManager清除任务
if (am != null) {
// 这个方法可能需要系统权限
Method method = am.getClass().getMethod("removeAllVisibleRecentTasks");
method.invoke(am);
}
} catch (Exception e) {
Log.e("ShutdownClear", "Failed to clear recent tasks", e);
}
}
}
完整实现建议:
我建议采用方案一,因为它最直接且权限足够。具体实现步骤:
在ActivityManagerService.java的shutdown()方法开始处添加:
java
@Override
public boolean shutdown(int timeout) {
// 清除所有最近任务
clearAllRecentTasksOnShutdown();
// 原有关机逻辑
return super.shutdown(timeout);
}
实现clearAllRecentTasksOnShutdown()方法:
java
private void clearAllRecentTasksOnShutdown() {
synchronized (this) {
try {
// 获取所有用户
int[] userIds = mUserController.getUserIds();
for (int userId : userIds) {
// 清除该用户的所有最近任务
removeAllTasksForUser(userId);
}
Slog.i(TAG, "Cleared all recent tasks for all users on shutdown");
} catch (Exception e) {
Slog.e(TAG, "Error clearing recent tasks on shutdown", e);
}
}
}
private void removeAllTasksForUser(int userId) {
// 实现具体的任务清除逻辑
// 这里需要根据你的Android版本调整具体实现
}
编译和测试:
修改完成后,重新编译系统:
bash
source build/envsetup.sh
lunch rk3588-userdebug # 根据你的实际配置
make -j8
刷机测试关机功能
注意:这些修改需要系统级权限,请确保在系统签名或eng/userdebug版本上测试。生产版本可能需要额外的权限处理。
请复核一下方法一的代码:
warning: Supported source version 'RELEASE_9' from annotation processor 'android.processor.compat.changeid.ChangeIdProcessor' less than -source '11'
out/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/javac/shard32/srcjars/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java:6896: error: cannot find symbol
IActivityTaskManager atm = ActivityTaskManager.getService();
^
symbol: class IActivityTaskManager
location: class ActivityManagerService
out/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/javac/shard32/srcjars/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java:6896: error: cannot find symbol
IActivityTaskManager atm = ActivityTaskManager.getService();
^
symbol: variable ActivityTaskManager
location: class ActivityManagerService
2 errors
1 warning
16:43:32 ninja failed with: exit status 1
#### failed to build some targets (02:12 (mm:ss)) ####
Build android failed!
rootroot@rootroot-X99-Turbo:~/rk-android13-20250818RD-RK3588-MID$
我们遇到了编译错误,因为无法找到IActivityTaskManager和ActivityTaskManager。在Android 13中,ActivityTaskManager相关的类可能已经被移动或更改。我们需要使用正确的方法来获取ActivityTaskManager服务。
在Android 10及以上,ActivityTaskManager是一个系统服务,我们可以通过ActivityTaskManager.getService()来获取其接口,但是需要导入相应的包。
但是,在ActivityManagerService中,可能已经有一个mActivityTaskManager的实例,我们可以使用它。如果没有,我们可以通过ActivityTaskManager.getService()来获取,但需要注意导入正确的类。
我们来看一下正确的导入和用法:
首先,我们需要在ActivityManagerService.java文件的开头添加导入:
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
但是,如果代码中已经存在这些导入,那么可能是其他问题。如果不存在,添加它们。
然而,在Android 13的代码中,ActivityManagerService可能已经使用mActivityTaskManager来调用相关方法。我们可以查看是否有mActivityTaskManager这个成员变量。
如果存在mActivityTaskManager,我们可以直接使用它。
我们可以修改方法一,使用mActivityTaskManager来清除最近任务。
另外,我们也可以使用ActivityManagerService内部的方法来清除最近任务,比如通过mRecentTasks来清除。
让我们考虑一个更安全的方法:使用ActivityManagerService内部的mRecentTasks。
在ActivityManagerService中,有一个成员变量mRecentTasks,它是RecentTasks类的实例。我们可以通过它来清除最近任务。
我们可以这样实现:
在ActivityManagerService中添加一个方法:
private void clearAllRecentTasksOnShutdown() {
synchronized (this) {
// 清除所有最近任务
mRecentTasks.cleanupOnShutdown();
}
}
然后,我们需要在RecentTasks类中实现cleanupOnShutdown方法(方案三中我们提到了RecentTasks.java的修改)。
但是,如果我们不想修改RecentTasks类,我们也可以直接调用RecentTasks的现有方法。
我们可以查看RecentTasks类中是否有清除所有任务的方法。如果没有,我们可以通过循环移除所有任务。
在RecentTasks中,有一个mTasks列表,我们可以通过移除所有任务来实现。
但是,请注意,我们可能需要考虑多用户的情况。
因此,我们可以这样实现:
private void clearAllRecentTasksOnShutdown() {
synchronized (this) {
// 获取所有最近任务并移除
List<Task> tasks = mRecentTasks.getTasks();
for (int i = tasks.size() - 1; i >= 0; i--) {
Task task = tasks.get(i);
// 移除任务
mRecentTasks.removeTask(task);
}
}
}
但是,请注意,getTasks()可能返回一个不可修改的列表,或者我们移除任务时可能会影响循环。因此,我们可以使用一个临时列表。
另外,我们也可以使用ActivityManagerService中已有的方法,例如removeAllVisibleRecentTasks。
实际上,ActivityManagerService中有一个removeAllVisibleRecentTasks方法,我们可以直接调用它。
我们可以这样:
private void clearAllRecentTasksOnShutdown() {
try {
removeAllVisibleRecentTasks();
} catch (RemoteException e) {
Slog.e(TAG, "Failed to clear recent tasks on shutdown", e);
}
}
但是,removeAllVisibleRecentTasks方法可能会受到权限检查,我们需要确保在系统进程中运行,并且具有足够的权限。
由于我们是在系统关机时调用,而且是在ActivityManagerService内部,所以权限应该足够。
因此,我们可以直接调用removeAllVisibleRecentTasks。
那么,我们修改方法一:
在ActivityManagerService的shutdown方法中,在调用super.shutdown之前,调用clearAllRecentTasksOnShutdown。
然后,clearAllRecentTasksOnShutdown方法实现为:
private void clearAllRecentTasksOnShutdown() {
try {
removeAllVisibleRecentTasks();
} catch (RemoteException e) {
// 忽略异常,或者打印日志
Slog.e(TAG, "Failed to clear recent tasks on shutdown", e);
}
}
但是,removeAllVisibleRecentTasks方法可能会要求调用者具有权限,并且可能会检查调用者的身份。我们可以在ActivityManagerService内部找到一个类似的方法,看看它是如何实现的。
我们也可以看到,removeAllVisibleRecentTasks方法在ActivityManagerService中已经存在,它是一个Binder方法,通常被系统UI调用。
我们可以直接调用它,因为我们现在就在ActivityManagerService中。
所以,我们不需要通过IActivityTaskManager,而是直接调用自己的方法。
因此,我们修改方案一:
在ActivityManagerService.java中:
在shutdown方法中调用clearAllRecentTasksOnShutdown。
实现clearAllRecentTasksOnShutdown,直接调用removeAllVisibleRecentTasks。
但是,注意removeAllVisibleRecentTasks方法需要传入一个调用者的userId,我们可以从Binder.getCallingUserId()获取,但在关机时,我们可能没有调用者。我们可以使用当前用户。
我们看一下removeAllVisibleRecentTasks方法的定义:
@Override
public void removeAllVisibleRecentTasks() throws RemoteException {
...
}
它没有参数,所以我们可以直接调用。
但是,我们看一下ActivityManagerService中的removeAllVisibleRecentTasks实现:
@Override
public void removeAllVisibleRecentTasks() {
...
}
它内部会处理多用户吗?我们看一下代码。
在Android 13的ActivityManagerService中,removeAllVisibleRecentTasks方法会清除当前用户的所有可见最近任务。它通过mRecentTasks来移除任务。
因此,我们可以直接调用它。
所以,我们修改代码:
在ActivityManagerService的shutdown方法中:
@Override
public boolean shutdown(int timeout) {
clearAllRecentTasksOnShutdown();
return super.shutdown(timeout);
}
private void clearAllRecentTasksOnShutdown() {
try {
removeAllVisibleRecentTasks();
} catch (Exception e) {
Slog.e(TAG, "Failed to clear recent tasks on shutdown", e);
}
}
但是,注意:removeAllVisibleRecentTasks方法可能会抛出RemoteException,但是我们在ActivityManagerService内部调用,实际上不会抛出RemoteException,因为它是本地调用。
所以,我们可以不捕获RemoteException,而是捕获Exception。
另外,我们也可以考虑清除所有用户的任务,而不仅仅是当前用户。但是,removeAllVisibleRecentTasks可能只清除当前用户的任务。如果我们想要清除所有用户的任务,我们需要循环所有用户。
但是,在关机时,我们可能只需要清除当前用户的任务,因为关机是针对整个设备的。
如果我们想要清除所有用户的任务,我们可以这样做:
private void clearAllRecentTasksOnShutdown() {
try {
// 获取所有用户
int[] userIds = mUserController.getUserIds();
for (int userId : userIds) {
// 切换到每个用户,然后清除任务
removeAllVisibleRecentTasksForUser(userId);
}
} catch (Exception e) {
Slog.e(TAG, "Failed to clear recent tasks on shutdown", e);
}
}
但是,ActivityManagerService中可能没有removeAllVisibleRecentTasksForUser方法,我们可以通过mRecentTasks来清除指定用户的任务。
我们可以查看RecentTasks类中是否有清除指定用户任务的方法。
如果没有,我们可以通过循环mRecentTasks中的任务,并移除指定用户的任务。
但是,为了简单起见,我们假设关机时只需要清除当前用户的任务。因为通常设备在关机时,当前用户就是主要用户。
如果我们坚持要清除所有用户的任务,我们可以这样:
private void clearAllRecentTasksOnShutdown() {
synchronized (this) {
// 获取所有用户
int[] userIds = mUserController.getUserIds();
for (int userId : userIds) {
// 清除该用户的所有任务
mRecentTasks.removeTasksForUser(userId);
}
}
}
但是,我们需要查看RecentTasks类中是否有removeTasksForUser方法。在Android 13中,RecentTasks类有一个removeTasksForUser方法,但是它是包权限的,我们可以调用。
所以,我们可以这样写。
但是,我们也可以看到,在ActivityManagerService中,有一个方法removeTasksByPackageName,它内部调用了mRecentTasks.removeTasksForUser(userId, packageName)。所以我们也可以仿照它。
但是,我们想要移除所有任务,所以我们可以直接调用mRecentTasks.removeTasksForUser(userId)来移除该用户的所有任务。
我们看一下RecentTasks的removeTasksForUser方法:
void removeTasksForUser(int userId) {
// 移除该用户的所有任务
for (int i = mTasks.size() - 1; i >= 0; i--) {
Task task = mTasks.get(i);
if (task.mUserId == userId) {
removeTask(task);
}
}
}
但是,我们可能没有权限直接调用removeTasksForUser,因为它是RecentTasks的方法,并且是包权限。但是ActivityManagerService和RecentTasks在同一个包中,所以可以调用。
因此,我们可以使用mRecentTasks.removeTasksForUser(userId)来清除每个用户的任务。
所以,我们修改clearAllRecentTasksOnShutdown:
private void clearAllRecentTasksOnShutdown() {
synchronized (this) {
int[] userIds = mUserController.getUserIds();
for (int userId : userIds) {
mRecentTasks.removeTasksForUser(userId);
}
}
}
但是,我们需要注意,mRecentTasks可能为null,或者mUserController可能为null。我们可以在初始化之后调用。
由于关机时这些服务都已经初始化,所以应该没问题。
综上所述,我建议使用清除所有用户的任务的方法。
因此,我们修改ActivityManagerService的shutdown方法,在其中调用clearAllRecentTasksOnShutdown,然后实现clearAllRecentTasksOnShutdown为清除所有用户的任务。
如果编译时发现mRecentTasks没有removeTasksForUser方法,我们可以查看RecentTasks类中可用的方法,或者通过循环mRecentTasks中的任务来逐个移除。
如果RecentTasks中没有removeTasksForUser,我们可以这样:
private void clearAllRecentTasksOnShutdown() {
synchronized (this) {
// 获取所有任务
List<Task> tasks = mRecentTasks.getTasks();
for (int i = tasks.size() - 1; i >= 0; i--) {
Task task = tasks.get(i);
mRecentTasks.removeTask(task);
}
}
}
但是,这样可能会在循环移除时修改列表,所以使用从后往前遍历。
我们选择一种实现。
由于我们不确定RecentTasks的具体实现,我们可以采用最直接的方式:循环移除所有任务。
所以,我们修改代码:
private void clearAllRecentTasksOnShutdown() {
synchronized (this) {
// 获取所有任务
List<Task> tasks = mRecentTasks.getTasks();
for (int i = tasks.size() - 1; i >= 0; i--) {
Task task = tasks.get(i);
mRecentTasks.removeTask(task);
}
}
}
但是,我们需要注意,getTasks()返回的任务列表可能是快照,我们移除任务时,mRecentTasks内部的列表会变化,但是我们的循环是从后往前,所以不会影响。
另外,我们也可以使用迭代器,但是这里我们使用索引从后往前是安全的。
因此,我们采用这个实现。
现在,我们重新编译。
但是,我们可能会遇到Task类找不到的问题。我们需要导入Task类。
在ActivityManagerService的导入中添加:
import com.android.server.wm.Task;
但是,如果Task类不在同一个包中,我们需要导入正确的包。
在ActivityManagerService中,Task的完整路径可能是:com.android.server.wm.Task
我们查看一下导入是否已经存在,如果不存在,添加它。
如果编译通过,那么我们就实现了关机清除所有最近任务的功能。
如果仍然有错误,我们可能需要调整代码。
总结步骤:
在ActivityManagerService.java的shutdown方法中,在调用super.shutdown之前,调用clearAllRecentTasksOnShutdown。
实现clearAllRecentTasksOnShutdown方法,使用同步块,循环mRecentTasks.getTasks(),逐个移除任务。
确保导入了Task类。
如果mRecentTasks没有getTasks方法,我们可以直接使用mRecentTasks的成员变量mTasks,但是不推荐,因为这样破坏了封装。
我们查看RecentTasks类,它有一个getTasks方法,返回List<Task>。
所以,我们使用getTasks方法。
现在,我们修改代码,并重新编译。
您遇到的编译错误是因为缺少正确的导入。让我提供修正后的代码:
修正后的方案一代码
1. 首先添加必要的导入
在 ActivityManagerService.java 文件的开头添加以下导入:
java
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
2. 修正的清除方法
java
// 在ActivityManagerService类中添加方法
private void clearAllRecentTasksOnShutdown() {
try {
// 使用正确的方式获取ActivityTaskManager服务
IActivityTaskManager atm = ActivityTaskManager.getService();
if (atm != null) {
// 移除所有最近任务
atm.removeAllVisibleRecentTasks();
Slog.i(TAG, "Cleared all recent tasks on shutdown");
}
} catch (RemoteException e) {
Slog.e(TAG, "Failed to clear recent tasks on shutdown", e);
}
}
3. 在shutdown方法中调用
找到 shutdown 方法,在方法开始处添加调用:
java
@Override
public boolean shutdown(int timeout) {
// 在关机时清除所有最近任务
clearAllRecentTasksOnShutdown();
// 原有的shutdown代码保持不变
// ... existing shutdown code ...
return true;
}
备选方案:使用现有方法
如果上面的方法仍有问题,可以使用ActivityManagerService内部的现有方法:
方案一A:使用removeAllRecentTasks方法
java
private void clearAllRecentTasksOnShutdown() {
try {
// 直接调用ActivityManagerService内部的方法
removeAllRecentTasks();
Slog.i(TAG, "Cleared all recent tasks on shutdown");
} catch (Exception e) {
Slog.e(TAG, "Failed to clear recent tasks on shutdown", e);
}
}
方案一B:通过RecentTasks清理
java
private void clearAllRecentTasksOnShutdown() {
synchronized (this) {
try {
// 通过mRecentTasks清理
if (mRecentTasks != null) {
// 获取所有任务并清除
List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(
Integer.MAX_VALUE, 0, UserHandle.USER_ALL);
for (ActivityManager.RecentTaskInfo task : tasks) {
removeTask(task.persistentId);
}
Slog.i(TAG, "Cleared all recent tasks on shutdown");
}
} catch (Exception e) {
Slog.e(TAG, "Failed to clear recent tasks on shutdown", e);
}
}
}
方案二:修改ShutdownThread(推荐备选)
如果ActivityManagerService修改仍有问题,建议使用ShutdownThread方案:
修改文件:
frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java
在beginShutdown方法中添加:
java
private static void beginShutdown() {
// 在关机开始时清除最近任务
clearAllRecentTasks();
// 原有代码保持不变
// ... existing code ...
}
private static void clearAllRecentTasks() {
try {
// 通过ActivityManager清除任务
ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
if (am != null) {
// 使用反射调用系统方法
Method method = am.getClass().getMethod("removeAllVisibleRecentTasks");
if (method != null) {
method.invoke(am);
Log.i(TAG, "Cleared all recent tasks on shutdown");
}
}
} catch (Exception e) {
Log.e(TAG, "Failed to clear recent tasks during shutdown", e);
}
}
编译前检查
在编译前,请确保:
检查导入:确认所有使用的类都已正确导入
检查方法存在:在源码中搜索确保使用的方法确实存在
权限检查:确保代码有足够的系统权限
推荐的完整实现
我建议先尝试方案一A,因为它最简洁:
java
// 在ActivityManagerService.java的shutdown方法开始处添加:
@Override
public boolean shutdown(int timeout) {
// 清除所有最近任务
try {
removeAllRecentTasks();
Slog.i(TAG, "Cleared all recent tasks on shutdown");
} catch (Exception e) {
Slog.e(TAG, "Failed to clear recent tasks on shutdown", e);
}
// 原有shutdown逻辑
return super.shutdown(timeout);
}
如果仍有编译问题,请提供具体的错误信息,我可以进一步帮您调整。
