【 Android 10 四大组件 】系列 -- Service 的 " 启动流程 "

DeepCoder

前言

由于源码分析的代码量比较大,大部分博客网站的内容显示页面都比较窄,显示出来的效果都异常丑陋,所以您也可以直接查看 《 Thinking in Android 》 来阅读这边文章,希望这篇文章能帮你梳理清楚 “Service 的启动流程”


核心源码

关键类 路径
ContextImpl.java frameworks/base/core/java/android/app/ContextImpl.java
ContextWrapper.java frameworks/base/core/java/android/content/ContextWrapper.java
ContextThemeWrapper.java frameworks/base/core/java/android/view/ContextThemeWrapper.java
Activity.java frameworks/base/core/java/android/app/Activity.java
ActivityManager.java frameworks/base/core/java/android/app/ActivityManager.java
ActivityManagerService.java frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
ActiveServices.java frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
ActivityThread.java frameworks/base/core/java/android/app/ActivityThread.java


Service 的启动过程相对 Activity 的启动过程来说简单了很多,我们都知道怎么去创建和启动一个 Service,那么你有没有从源码角度研究过 Service 启动后在系统层是如何运作的


Activity.startService()

首先我们知道:要启动一个 Service 的时候,一般都是在 Activity 中通过 startService() 来启动:

Intent intent = new Intent(MainActivity.this, xxxService.class);
startService(intent);

但是我们在 Activity 源码中并没有实现 startService() 方法,那它在哪里被调用的?找不到我们就去 Activity 的父类中找。

// frameworks/base/core/java/android/app/Activity.java

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback, WindowControllerCallback,
        AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {
        
}

// frameworks/base/core/java/android/view/ContextThemeWrapper.java

public class ContextThemeWrapper extends ContextWrapper {

}

// frameworks/base/core/java/android/content/ContextWrapper.java
public class ContextWrapper extends Context {

}

Activity 继承了 ContextThemeWrapper 类,ContextThemeWrapper 又继承了 ContextWrapper 类,ContextWrapper 又继承了 Context 类。


ContextWrapper.startService()

ContextWrapper 中实现了 startService() 方法:

// frameworks/base/core/java/android/content/ContextWrapper.java

public class ContextWrapper extends Context {

    Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }

    @Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }

}

所以 startService() 方法其实是由 ContextWrapper 实现的,紧接着又调用了 mBase.startService() 方法,mBase 对象是 Context 的子类 ContextImpl,所以调用最终进入 ContextImpl 类的 startService() 方法。


ContextImpl.startService()

// frameworks/base/core/java/android/app/ContextImpl.java

class ContextImpl extends Context {

    @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }

    private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            // 通过 Binder 进程间通信进入 ActivityManagerService 的 startService() 方法
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                    getContentResolver()), requireForeground, getOpPackageName(), user.getIdentifier());
            ... ...

            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

}


ActivityManager.getService()

// frameworks/base/core/java/android/app/ActivityManager.java

public class ActivityManager {

    @UnsupportedAppUsage
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    @UnsupportedAppUsage
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

}


ActivityManagerService.startService()

接下来就执行到 ActivityManagerServicestartService() 方法:

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

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {

    final ActiveServices mServices;

    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
        ... ...

        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res;
            try {
                // 调用 ActiveServices 的 startServiceLocked() 方法
                res = mServices.startServiceLocked(caller, service, resolvedType, callingPid,
                            callingUid, requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }

}


ActiveServices.startServiceLocked()

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

public final class ActiveServices {

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
        return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,
                callingPackage, userId, false);
    }

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage,
            final int userId, boolean allowBackgroundActivityStarts)
            throws TransactionTooLargeException {
        ... ...
        
        // 解析 AndroidManifest.xml 文件中配置 Service 的 intent-filter 相关内容信息
        ServiceLookupResult res = retrieveServiceLocked(service, null, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false, false);
        if (res == null) {
            return null;
        }
        ... ...

        ServiceRecord r = res.record;
        ... ...

        // 调用 startServiceInnerLocked() 方法
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
    }

}

通过 retrieveServiceLocked() 方法来解析 AndroidManifest.xml 文件中配置 Service 的 intent-filter 相关内容信息。

当解析完 Serviceintent-filter 相关内容信息后,解析的结果会保存在 res.record 变量中。而 res 变量是一个 ServiceLookupResult 类型的对象,它的 record 变量则是一个 ServiceRecord 类型对象,用来表示一个 Service


ActiveServices.startServiceInnerLocked()

ActiveServices 的 startServiceLocked() 方法最后调用了 startServiceInnerLocked() 方法:

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

public final class ActiveServices {

    ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
        ... ...

        // 调用 bringUpServiceLocked() 方法
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
        ... ...

    }
}


ActiveServices.bringUpServiceLocked()

调用 bringUpServiceLocked() 方法进一步处理:

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

public final class ActiveServices {

    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        ... ...

        ProcessRecord app;

        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);    // 获取 app 对象
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                    // 运行 service 的进程已经启动,调用 realStartServiceLocked() 方法
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
                }

                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
        } else {
            ... ...

        }

        // Not running -- get it started, and enqueue this service record
        // to be executed when the app comes up.
        if (app == null && !permissionsReviewRequired) {
            if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingRecord, false, isolated, false)) == null) {
                String msg = "Unable to launch app "
                        + r.appInfo.packageName + "/"
                        + r.appInfo.uid + " for service "
                        + r.intent.getIntent() + ": process is bad";
                Slog.w(TAG, msg);
                bringDownServiceLocked(r);
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }
        ... ...

        return null;
    }

}

bringUpServiceLocked() 方法首先通过 getProcessRecordLocked() 方法去获取 app 对象,它是一个 ProcessRecord 类型的对象,如果它不为空,说明 Service 要运行的进程已经存在。

Service 运行的进程有两种:

(1)一种是默认的,即运行在 Activity 启动 Service 的那个进程里,也就是说在哪个进程里调用了 startService() 方法,启动的 service 就运行在哪个进程里。

(2)一种是给 Service 一个单独的进程运行,比如在 AndroidManifest 文件里配置了如下内容:

//

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.android.documentsui">

    <application
        android:name=".DocumentsApplication"
        android:label="@string/app_label"
        android:icon="@drawable/app_icon"
        android:supportsRtl="true"
        android:allowBackup="true"
        android:backupAgent=".prefs.BackupAgent"
        android:fullBackupOnly="false">

        <!-- Run FileOperationService in a separate process so that we can use FileLock class to
            wait until jumbo clip is done writing to disk before reading it. See ClipStorage for
            details. -->
        <service
            android:name=".services.FileOperationService"
            android:exported="false"
            android:process=":com.android.documentsui.services">
        </service>

    </application>
</manifest>

在这段配置里有 android:process="xxx" 声明,这个声明用来实现 service 单独运行在 "xxx" 进程里。这样做的好处是,即使应用程序无法工作,由于 service 单独运行在一个进程里,所以会继续工作

回到前面的方法,如果变量 app 为空,就代表 service 要运行的进程还没有启动,于是调用 startProcessLocked() 方法去启动一个新的进程。

如果 app 不为空,采用默认的方式启动 Service,最终调用到 realStartServiceLocked() 方法:


ActiveServices.realStartServiceLocked()

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

public final class ActiveServices {

    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        ... ...

        try {
            ... ...

            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo), app.getReportedProcState());
            ... ...

        }
        ... ...

    }

}

在这个方法中,app 对象的 thread 变量是一个 ApplicationThread Binder 对象,调用它的 scheduleCreateService() 方法之后,会进入客户端的 ActivityThread 中。


ActivityThread.scheduleCreateService()

// frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread extends ClientTransactionHandler {

    // ApplicationThread 是一个 Binder
    private class ApplicationThread extends IApplicationThread.Stub {

        public final void scheduleCreateService(IBinder token,
                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
            updateProcessState(processState, false);
            CreateServiceData s = new CreateServiceData();
            s.token = token;
            s.info = info;
            s.compatInfo = compatInfo;

            sendMessage(H.CREATE_SERVICE, s);
        }

    }
    
}

ApplicationThreadscheduleCreateService() 方法通过调用 sendMessage() 方法来发送一个 msg 消息,当 Handler 接收到了 msg 消息之后,它会调用 handleCreateService() 方法来做进一步处理。


H.handleMessage()

// frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread extends ClientTransactionHandler {

    class H extends Handler {

        public void handleMessage(Message msg) {
            switch (msg.what) {

                case CREATE_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
                    handleCreateService((CreateServiceData)msg.obj);    // 调用 handleCreateService() 方法
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;

            }
        }

    }
}


ActivityThread.handleCreateService()

// frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread extends ClientTransactionHandler {

    private void handleCreateService(CreateServiceData data) {
        ... ...

        LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = packageInfo.getAppFactory().instantiateService(cl, data.info.name, data.intent);
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to instantiate service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }

        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);

            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);

            Application app = packageInfo.makeApplication(false, mInstrumentation);
            service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService());
            service.onCreate();    // 进入 Service.onCreate() 方法
            mServices.put(data.token, service);
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }

}

ActivityThread 类的 handleCreateService() 方法中,首先通过 ClassLoader 类把 Service 加载进来,而参数 data.info.name 表示这个 Service 的名字,instantiateService() 方法是创建一个 Service 实例。接着,创建一个 Context 对象,作为上下文环境之用。

handleCreateService() 方法最后调用了 service 的 onCreate() 方法,当这个方法被调用之后,就会进入应用程序里 Service 的 onCreate() 方法

至此,Service 的启动就分析完毕,这个过程与启动 Activity 相比简单了很多。

阅读 1.2k

《Android 10 系统开发源码钻研录》
One blog for recorded and shared, Android system development. Framework, Mechanism, optimization,...

One blog for recorded and shared, Android system development.

569 声望
3.2k 粉丝
0 条评论
你知道吗?

One blog for recorded and shared, Android system development.

569 声望
3.2k 粉丝
宣传栏