Service的启动过程

Service的启动过程(基于9.0系统)

Service是Android系统中四大组件之一,在实际开发中有着非常重要的作用,这里就对Service的启动过程进行一些总结。

在Activity中可以通过startService开启一个服务,而Activity中的startService方法实际调用的是Activity父类ContextWrapper的方法,ContextWrapper的相关源码如下:

ContextWrapper类:

//Context类型,具体实现类是ContextImpl
Context mBase;
  
@Override
public ComponentName startService(Intent service) {
     return mBase.startService(service);
}

ContextWrapper也没有直接开启服务,而是调用了mBase的startService方法,mBase的具体实现是ContextImpl《Context的创建过程》,下面看下ContextImpl类中执行开启服务的代码:

ContextImpl类:

@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);
            
			//关键代码1(ActivityManager.getService()是AMS)
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
                            
            if (cn != null) {
                if (cn.getPackageName().equals("!")) {
                    throw new SecurityException(
                            "Not allowed to start service " + service
                            + " without permission " + cn.getClassName());
                } else if (cn.getPackageName().equals("!!")) {
                    throw new SecurityException(
                            "Unable to start service " + service
                            + ": " + cn.getClassName());
                } else if (cn.getPackageName().equals("?")) {
                    throw new IllegalStateException(
                            "Not allowed to start service " + service + ": " + cn.getClassName());
                }
            }
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
}

由上面的代码可知,ContextImpl的startService又调用了startServiceCommon方法,在关键代码1处可知,调用了ActivityManager.getService()的startService方法,这里先看下ActivityManager.getService()是什么,ActivityManager的相关源码如下:

ActivityManager:

/**
 * @hide
 */
public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
}

private static final Singleton<IActivityManager> IActivityManagerSingleton =
        new Singleton<IActivityManager>() {
            @Override
            protected IActivityManager create() {

				//关键代码2
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
};

由ActivityManager的getService方法和关键代码2处可以知到,ActivityManager的getService方法获取的是IActivityManager类型的Binder对象,是AMS的代理,最终代码调用就到了AMS的startService方法了,这是一个进程间通信的过程,AMS开启服务的源码如下:

ActivityManagerService:

@Override
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage, int userId)
        throws TransactionTooLargeException {
    enforceNotIsolatedCaller("startService");
    // Refuse possible leaked file descriptors
    if (service != null && service.hasFileDescriptors() == true) {
        throw new IllegalArgumentException("File descriptors passed in Intent");
    }

    if (callingPackage == null) {
        throw new IllegalArgumentException("callingPackage cannot be null");
    }

    if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
            "*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground);
    synchronized(this) {
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        ComponentName res;
        try {
			//关键代码3
            res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid,
                    requireForeground, callingPackage, userId);
                    
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return res;
    }
}

在关键代码3处,调用了ActiveServices的startServiceLocked方法,相关代码如下:

ActiveServices:

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

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

	    .............

    return r.name;
}

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
         if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                    
                    //关键代码
                    realStartServiceLocked(r, app, execInFg);
                    
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }

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

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

			//关键代码 4(app.thread是ApplicationThread)
           app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                app.repProcState);
}

在startServiceLocked方法中依次调用了自身的startServiceInnerLocked方法、bringUpServiceLocked方法、realStartServiceLocked方法,在关键代码 4处的app.thread指代的是ApplicationThread,它的类型是IApplicationThread,也是一个Binder,该调用是一次IPC调用,scheduleCreateService执行在客户端的Bindre线程池中,看下scheduleCreateService的源码:

ApplicationThread:

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;
	
				//关键代码5 发送一个创建Service的handler消息
	            sendMessage(H.CREATE_SERVICE, s);
}

由关键代码5可知,向H类(handler)发送消息,将线程从线程池切换到了UI线程,H类处理创建服务的代码如下:

H类:

  case CREATE_SERVICE://处理创建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;

H类中接收到CREATE_SERVICE消息后 ,又调用了ActivityThread的方法处理服务创建,handleCreateService源码如下:

ActivityThread:

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;
    try {
    
		//关键代码6  通过反射创建service
        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);

		//关键代码7 创建Context
        ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
        context.setOuterContext(service);

		//关键代码8 创建Application(如果存在就直接返回,不存在才去创建)
        Application app = packageInfo.makeApplication(false, mInstrumentation);
        
		//关键代码9 进行一些service初始化操作
        service.attach(context, this, data.info.name, data.token, app,
                ActivityManager.getService());

		//关键代码10 调用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);
        }
    }
}

在关键代码6处通过反射创建了service实例,在关键代码7处创建了Context实例,在关键代码8处创建Application(如果存在就直接返回,不存在才去创建),在关键代码9处对service进行初始化操作,在关键代码10处调用了service的onCreate方法,到此service创建并启动完成。为了整个调用流程看起来更直观一些,下面给出了相关类的调用流程图:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值