[实践] Android源码 - 阻止APP被长按HOME键方式结束掉
@(Android研究)[阻止APP被系统结束]
[TOC]
前言
本文只讲做法,不讲理论。
实践
系统:Android5.1.1
当前实践修改了Android5.1.1的源码。
理论部分可以看我的文章:Android5.1.1源码 - 分析在最近的APP列表中清理APP的过程
假设APP包名为"com.a.b.c",让包名为"com.a.b.c"的APP进程不被系统结束掉。
找到ActivityManagerService.cleanUpRemovedTaskLocked方法所在的文件"frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java",下面对是ActivityManagerService.cleanUpRemovedTaskLocked方法修改后的代码:
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;
}
if (!killProcess) {
return;
}
// Determine if the process(es) for this task should be killed.
final String pkg = component.getPackageName();
// 新添加的代码。
if("com.a.b.c".equals(pkg)) {
return;
}
ArrayList<ProcessRecord> procsToKill = 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) {
// 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;
}
}
// 除了不被删除的任务,剩下的任务都可以被结束。
// Add process to kill list.
procsToKill.add(proc);
}
}
// Find any running services associated with this app and stop if needed.
mServices.cleanUpRemovedTaskLocked(tr, component, new Intent(tr.getBaseIntent()));
// 结束进程
// 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.kill("remove task", true);
} else {
pr.waitingToKill = "remove task";
}
}
}
下面是ActivityManagerService.cleanUpRemovedTaskLocked方法的源码:
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;
}
if (!killProcess) {
return;
}
// Determine if the process(es) for this task should be killed.
final String pkg = component.getPackageName();
ArrayList<ProcessRecord> procsToKill = 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) {
// 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;
}
}
// 除了不被删除的任务,剩下的任务都可以被结束。
// Add process to kill list.
procsToKill.add(proc);
}
}
// Find any running services associated with this app and stop if needed.
mServices.cleanUpRemovedTaskLocked(tr, component, new Intent(tr.getBaseIntent()));
// 结束进程
// 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.kill("remove task", true);
} else {
pr.waitingToKill = "remove task";
}
}
}
实践二
系统:Android4.4.4_r2
当前实践修改了Android4.4.4_r2的源码。
找到ActivityManagerService.cleanUpRemovedTaskLocked方法所在的文件"frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java",下面是ActivityManagerService.cleanUpRemovedTaskLocked方法的源码:
private void cleanUpRemovedTaskLocked(TaskRecord tr, int flags) {
tr.disposeThumbnail();
mRecentTasks.remove(tr);
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;
}
......
if (killProcesses) {
......
}
}
通过观察上面的源码可以发现当killProcesses为true时将会执行清理代码,当killProcesses为false时则不会执行清理代码,而killProcesses是否为true与ActivityManager.REMOVE_TASK_KILL_PROCESS标志相关。
下面是对ActivityManagerService.cleanUpRemovedTaskLocked方法修改后的代码:
private void cleanUpRemovedTaskLocked(TaskRecord tr, int flags) {
flags = flags&ActivityManager.REMOVE_TASK_KILL_PROCESS;
tr.disposeThumbnail();
mRecentTasks.remove(tr);
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;
}
......
if (killProcesses) {
......
}
}