Android Service的启动流程源码分析(8.0)

一,写在前面

       在Android中服务有两种状态,一种是启动服务,一种是绑定服务,它们有着不同的生命周期。启动服务的生命周期:onCreate,onStart,onDestroy;绑定服务的生命周期:onCreate,onBind,onUnBind,onDestroy。至于服务具体如何使用,本篇将不做介绍。主要介绍从源码角度,解析启动服务过程。需要注意的是,阅读本篇文章之前建议先了解Activity的启动流程,可参考博客 Android Activity的启动流程源码解析 。

二,进入主题

       通常需要在Activity组件中启动一个服务,用于在后台执行一些计算的操作。这时,会调用startService(Intent service)方法,其实这个方法的具体实现在Activity的父类ContextWrapper类中,类ContextWrapper是Context的子类。好了,查看源码开始分析吧~
       查看ContextWrapper$startService源码:
    @Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }
       第3行,字段mBase是Context类型,但Context是一个抽象类,事实上mBase变量是一个ContextImpl对象。给mBase变量设置值是在Activity$attach方法被调用时完成,具体分析见文章 Android Activity的启动流程源码解析 ,这里不再重复阐述。

       查看ContextImpl$startService方法源码:
    @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }

//继续查看

    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
       //...code

	ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
	
	//...code
    }
       第13行,ActivityManager.getService()返回的是一个IActivityManager的一个代理对象,利用AIDL技术完成进程间通信,需要找到那个extends IActivityManager.Stub的实现类,它就是ActivityManagerService。IActivityManager的代理对象调用startService方法,会向系统服务ActivityManagerService发送一个请求,基于Binder机制,会调用ActivityManagerService$startService方法。详细的代码流程分析见文章 Android Activity的启动流程源码解析 ,这里不再重复阐述。

       查看ActivityManagerService$startService方法源码:
@Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
	
	//...code

        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res;
            try {
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }
       第14行,变量mServices是ActiveServices类型的对象。于是,启动服务的工作交给了ActiveServices来处理。
       
       查看ActiveServices源码如下:
    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
	    
	    //...code

	    ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false);

	    //...code

	    ServiceRecord r = res.record;

	    //...code

	    r.lastActivity = SystemClock.uptimeMillis();
            r.startRequested = true;
            r.delayedStop = false;
            r.fgRequired = fgRequired;
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                service, neededGrants, callingUid));
	    
	    //...code

	    ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
	    return cmp;	    	    
    }

    //继续查看

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

	    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 {
	    
	    //...

	    app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);

            //...

	    sendServiceArgsLocked(r, execInFg, true);
	    
    }
       第13行,ServiceRecord封装了要启动的服务一些信息,r作为方法的参数进行传递。
       第62行,app.thread是一个IApplicationThread的代理对象,最终会调用ApplicationThread$scheduleCreateService方法启动服务,具体分析可以参考文章 Android Activity的启动流程源码解析 。内部会调用Service$onCreate方法启动服务,后面会有所分析。
       第68行,内部会调用onStartCommand方法,这里不做过多介绍,代码流程与onCreate类似。

三,启动服务的操作,交给ActivityThread来处理

       继续app.thread.scheduleCreateService进行分析,值得一提的是,ApplicationThread是ActivityThread的内部类。
       查看ApplicationThread$scheduleCreateService源码:
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);
}

       查看ActivityThread$sendMessage源码如下:
private void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
}

//继续查看

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
}
       第19行,Handler发送了一个消息,于是启动服务的操作在消息的处理中了。
       查看ActivityThread$handleMessage方法源码:
public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
		
	    //...code

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

	    //...code
	}			    	   	    
}
       第9行,调用handleCreateService方法启动服务。可以发现,启动服务的过程与启动Activity的过程有相同地方,刚开始将启动组件的操作交给系统服务ActivityManagerService来出来,然后,将启动组件的操作交给ApplicationThread来处理。值得一提是,这两步都涉及到进程间的通信,且是基于Binder机制,可以看到Binder机制在framework层的利用无处不在。最后,处理组件的操作都是通过发送一次消息来完成,启动服务与启动Activity具体做的操作比较相同,这也是为何文章开头建议先了解Activity的启动流程。

       继续查看ActivityThread$handleCreateService方法源码:
private void handleCreateService(CreateServiceData data) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        Application app = null;
        try {
            app = packageInfo.makeApplication(false, mInstrumentation);
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = instantiate(cl, data.info.name, data.intent, app,
                    Application::instantiateService);
        } 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);

            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            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);
            }
        }
    }
       仔细分析代码可以发现,启动服务最终调用了Activity$handleCreateService方法,与启动Activity最终调用了ActivityThread$performLaunchActivity方法做的事情有些类似,详情参考文章 Android Activity的启动流程源码解析 。
       handleCreateService启动服务大致有操作:
       第11行,创建Application对象,若应用程序已经存在该对象,则不再创建。
       第13行,通过类加载器ClassLoader创建Service的实例。
       第26行,创建Service的上下文环境,也就是创建ContextImpl对象,会作为Service$attach方法的参数传入。
       第29行,调用Service$attach方法,做初始化一些变量的操作。
       第31行,调用Service$onCreate方法启动服务。
       第32行,将Service的实例对象存入Map集合中,执行Service生命周期的其他方法时,可以在该集合中取出Service实例。
       上述操作,与启动Activity的流程大体类似,每一步操作不再作细致分析,详细分析可以参考文章 Android Activity的启动流程源码解析 。

四,最后

       可以发现,启动服务与启动Activity的流程有很多类似之处,了解Activity的启动流程,对于本篇的理解很有意义~       ^_^
       

   


       





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值