MicroKibaco / CrazyDailyQuestion

每日一问: 水滴石穿,聚沙成塔,坚持数月, 必有收获~
35 stars 1 forks source link

2019-09-10: 说一说Service的启动流程 #33

Open gys0000 opened 5 years ago

TrampcR commented 5 years ago

Service 的工作过程分为启动过程和绑定过程,它们分别对应的是 startService() 和 bindService()。

一、启动过程——startService

ContextWrapper.startService()
-> Context.startService()
-> ContextImpl.startService() -> startServiceCommon() 
-> ActivityManager.getService().startService()
-> ActivityManagerService.startService()
-> ActiveServices.startServiceLocked() -> startServiceInnerLocked() -> bringUpServiceLocked() -> realStartServiceLocked()
-> ActivityThread.ApplicationThread.scheduleCreateService() -> sendMessage() -> handleCreateService()
-> Service.onCreate()

二、绑定过程——bindService

ContextWrapper.bindService()
-> Context.bindService()
-> ContextImpl.bindService() -> bindServiceCommon()
-> LoadedApk.getServiceDispatcher() -> ActivityManager.getService().bindService()
-> ActivityManagerService.bindService()
-> ActiveServices.bindServiceLocked() -> bringUpServiceLocked() -> realStartServiceLocked()
    -> ActivityThread.ApplicationThread.scheduleCreateService() -> sendMessage() -> handleCreateService()
        -> Service.onCreate()
    -> ActiveServices.requestServiceBindingsLocked() -> requestServiceBindingLocked()
        -> ActivityThread.ApplicationThread.scheduleBindService() -> sendMessage() -> handleBindService()
            -> Service.onBind()
            -> ActivityManagerService.publishService()
                -> ActiveServices.publishServiceLocked()
                -> LoadedApk.ServiceDispatcher.InnerConnection.connected()
                -> LoadedApk.ServiceDispatcher.connected() -> doConnected()
                -> ServiceConnection.onServiceConnected()
pioneerz commented 5 years ago

启动Service的方式有两种:1.startService 2.bindService

1.startService

// TODO 1.ContextImpl
@Override
    public ComponentName startService(Intent service) {
        return startServiceCommon(service, false, mUser);
    }
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            // TODO 判断intent是否有效
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            ComponentName cn = ActivityManager.getService().startService(
            mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
// TODO 2.ActivityManagerService
@Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
        res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
        }
    }
// TODO 3.ActiveService
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    }
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
        ServiceState stracker = r.getTracker();
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
    }
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        realStartServiceLocked(r, app, execInFg);
    }
private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        // TODO **_回调ApplicationThread的scheduleCreateService方法->service的onCreate方法_**
        app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
        sendServiceArgsLocked(r, execInFg, true);
    }
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
            boolean oomAdjusted) throws TransactionTooLargeException {
        // TODO **回调ApplicationThread的scheduleServiceArgs方法->service的onStartCommand方法**
        r.app.thread.scheduleServiceArgs(r, slice);
    }

2.bindService

// TODO 1.ContextImpl
 @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
                Process.myUserHandle());
    }
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
        if (mPackageInfo != null) {
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        } else {
            throw new RuntimeException("Not supported in system context");
        }
        validateServiceIntent(service);
         service.prepareToLeaveProcess(this);
            int res = ActivityManager.getService().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());
    }
// TODO 2.ActivityManagerService
public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
            int userId) throws TransactionTooLargeException {
        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
    }
// TODO 3.ActiveService
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {
        // TODO 这里的流程上面已经分析过,onCreate->onStartCommand。
        bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                        permissionsReviewRequired) ;
        //conn就是客户端创建的IServiceConnection对象
        c.conn.connected(s.name, b.intent.binder);
        requestServiceBindingLocked(s, b.intent, callerFg, false);
}
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        // TODO **回调ApplicationThread的scheduleBindService->onBind()**
        r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
    }
// TODO 4.ActivityManagerService(调用onBind之后,会再次调用ams的publishService)
public void publishService(IBinder token, Intent intent, IBinder service) {
         mServices.publishServiceLocked((ServiceRecord)token, intent, service);
    }
// TODO 5.ActiveService
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        final long origId = Binder.clearCallingIdentity();
        try {
            if (r != null) {
                Intent.FilterComparison filter
                        = new Intent.FilterComparison(intent);
                IntentBindRecord b = r.bindings.get(filter);
                if (b != null && !b.received) {
                    b.binder = service;
                    b.requested = true;
                    b.received = true;
                    for (int conni=r.connections.size()-1; conni>=0; conni--) {
                        ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
                        for (int i=0; i<clist.size(); i++) {
                            ConnectionRecord c = clist.get(i);
                            try {
                                c.conn.connected(r.name, service, false);
                            } catch (Exception e) {
                            }
                        }
                    }
                }
                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
最终会回调ServiceConnection的onServiceConnected方法,拿到服务对象或者服务的binder对象,进而可以操作相关的方法。