Android5.1.1源码 - App服务进程被杀后自动重启的原因

原创
2015/11/23 11:58
阅读数 802

Android5.1.1源码 - App服务进程被杀后自动重启的原因

@(Android研究)[App服务重启]


[TOC]


前言

当通过长按HOME键的方式清理一个App时,不仅这个App进程会被杀掉,与这个App相关的服务进程也会被杀掉,但是服务进程被杀后会被系统重启,在下文中分析了重启的原因。

分析

长按HOME键清理App最终会执行到ActivityManagerService.cleanUpRemovedTaskLocked方法中,ActivityManagerService类在文件"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;
    }

    ......

    // 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";
        }
    }
}

mServices是ActiveServices类的对象,mServices.cleanUpRemovedTaskLocked(...)语句杀掉了与app相关的服务进程,在执行完ActiveServices.cleanUpRemovedTaskLocked方法后,就会调用pr.kill方法杀掉app进程和app所属进程组中所有的进程。关于杀掉app所属进程组所有进程的分析可以看这篇文章:Android5.1.1源码 - App进程被杀后与App相关的所有服务进程均被杀的原因。本文主要分析ActiveServices.cleanUpRemovedTaskLocked方法做了什么。

ActiveServices类的源码在文件"frameworks/base/services/core/java/com/android/server/am/ActiveServices.java"中,下面是ActiveServices.cleanUpRemovedTaskLocked方法的源码:

void 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);
                }
            }
        }
    }
}

这个方法先获得了所有的服务,然后将包名与"component.getPackageName()"相等的服务保存到了services中。

遍历services,sr.startRequested为true表明这个服务已经启动,当sr.serviceInfo.flags设置了ServiceInfo.FLAG_STOP_WITH_TASK标识时,会调用stopServiceLocked方法停止服务,如果调用了stopServiceLocked方法那么这个服务就不会再重启了

什么情况下会设置ServiceInfo.FLAG_STOP_WITH_TASK标识哪?当App的AndroidManifest.xml中服务标签被设置了android:stopWithTask="true",那么sr.serviceInfo.flags会被设置ServiceInfo.FLAG_STOP_WITH_TASK标识,下面是一个例子:

<service android:stopWithTask="true" android:name=".MyService" android:process=":myservice" />

回到ActiveServices.cleanUpRemovedTaskLocked方法中,当sr.serviceInfo.flags没有设置ServiceInfo.FLAG_STOP_WITH_TASK标识时,会执行下面的代码:

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);
}

sr.pendingStarts.add(...)语句添加了要重启的服务信息,然后调用sendServiceArgsLocked方法重启服务。

展开阅读全文
加载中

作者的其它热门文章

打赏
1
0 收藏
分享
打赏
0 评论
0 收藏
1
分享
返回顶部
顶部