Framework篇 - startService 启动过程

本文源代码基于 Android 7.0。

这篇文章来分析一下 startService() 的启动过程,相对于 startActivity() 要简单的多。

 

目录:

  1. 发起端进程
  2. system server 进程
  3. 目标进程
  4. 总结

 

 

1. Context

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

启动服务调用的是 context.startService(),实现在 ContextImpl 类。

    // 启动服务
    @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, mUser);
    }

    private ComponentName startServiceCommon(Intent service, UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            ComponentName cn = ActivityManagerNative.getDefault().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), getOpPackageName(), user.getIdentifier());
            // ...
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

还是会调用 ActivityManagerNative.getDefault().startService(),这个过程就不再分析了,最终会从发起端进程进入到 system server 进程,找到 ActivityManagerService。

 

 

2. system server 进程

 

  • 2.1 ActivityManagerService

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

    // 启动Service
    @Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, 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 = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid, callingPackage, userId);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

mServices 为 ActiveServices 类型。

 

  • 2.2 ActiveServices

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

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, String callingPackage, final int userId)
            throws TransactionTooLargeException {
        // ...    
        return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    }

    ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
        r.callStart = false;
        synchronized (r.stats.getBatteryStats()) {
            r.stats.startRunningLocked();
        }
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
        if (error != null) {
            return new ComponentName("!!", error);
        }
        // ...
        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.versionCode, 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 (app == null && !permissionsReviewRequired) {
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    "service", r.name, 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(),当目标进程已存在,则直接执行 realStartServiceLocked()。
当目标进程不存在,则先执行 startProcessLocked() 创建进程, 经过层层调用 (这个具体过程可以看这篇文章:Framework篇 - 四大组件与进程启动的关系),最后会调用到 ActivityManagerService.attachApplicationLocked,然后再执行 realStartServiceLocked()。

    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        if (app.thread == null) {
            throw new RemoteException();
        }
        //...
        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
        // ...
    }

会调用该目标进程 (Service 所在的进程) 的 ActivityThread.scheduleCreateService()。

 

 

3. 目标进程

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

public final class ActivityThread {
	private class ApplicationThread extends ApplicationThreadNative {
		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.H 对象 CREATE_SERVICE 消息。H 收到消息后,调用 handleCreateService():

private void handleCreateService(CreateServiceData data) {
    LoadedApk packageInfo = getPackageInfoNoCheck(
            data.info.applicationInfo, data.compatInfo);
    Service service = null;
    try {
	// 反射创建 Service
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        service = (Service) cl.loadClass(data.info.name).newInstance();
    } catch (Exception e) {
        if (!mInstrumentation.onException(service, e)) {
            throw new RuntimeException(
                "Unable to instantiate service " + data.info.name
                + ": " + e.toString(), e);
        }
    }

    try {
	// 创建 ContextImpl 对象
        ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
        context.setOuterContext(service);
	// 创建 Application 对象
        Application app = packageInfo.makeApplication(false, mInstrumentation);
        service.attach(context, this, data.info.name, data.token, app,
                ActivityManagerNative.getDefault());
	// 调用服务onCreate()方法
        service.onCreate();
        mServices.put(data.token, service);
        try {
	   // 调用服务创建完成
            ActivityManagerNative.getDefault().serviceDoneExecuting(
                    data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    } catch (Exception e) {
    }
}

 

 

4. 总结

 

 

  • 1. Process A 进程采用 Binder IPC 向 system_server 进程发起 startService 请求;
  • 2. system_server 进程接收到请求后,向 zygote 进程发送创建进程的请求;
  • 3. zygote 进程 fork 出新的子进程 Remote Service 进程;
  • 4. Remote Service 进程,通过 Binder IPC 向 sytem_server 进程发起 attachApplication 请求;
  • 5. system_server 进程在收到请求后,进行一系列准备工作后,再通过 Binder IPC 向 remote Service 进程发送scheduleCreateService 请求;
  • 6. Remote Service 进程的 Binder 线程在收到请求后,通过 handler 向主线程发送 CREATE_SERVICE 消息;
  • 7. 主线程在收到 Message 后,通过发射机制创建目标 Service,并回调 Service.onCreate() 方法。

到此,服务便正式启动完成。当创建的是本地服务或者服务所属进程已创建时,则无需经过上述步骤2、3,直接创建服务即可。

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
.NET Framework 4.5-x86-x64是一种由微软公司开发的应用程序框架。它提供了一种创建和运行各种类型应用程序的环境,包括桌面应用程序、Web应用程序和移动应用程序。 使用.NET Framework 4.5-x86-x64,开发人员可以利用其强大的功能来创建功能丰富、高性能的应用程序。它提供了一系列的类库和工具,可以轻松地处理各种任务,例如图形处理、数据访问和网络通信。它还支持多种编程语言,包括C#、Visual Basic和F#等,使开发人员可以按照自己的喜好选择最适合自己的编程语言。 对于应用程序的部署,.NET Framework 4.5-x86-x64提供了高度灵活性和可移植性。开发人员可以将应用程序打包成自包含的可执行文件,方便用户在不同计算机上安装和运行。此外,.NET Framework 4.5-x86-x64还支持与现有系统和应用程序的集成,使应用程序能够与其他软件进行无缝协作。 作为一个跨平台的框架,.NET Framework 4.5-x86-x64可以在多个操作系统上运行,包括Windows、Linux和macOS等。这为开发人员提供了更大的灵活性和选择性,使他们可以根据不同的需求和目标平台选择最适合的环境。 总之,.NET Framework 4.5-x86-x64是一个功能强大、灵活性高的应用程序框架,它为开发人员提供了丰富的工具和资源,使他们能够轻松地创建出各种类型的应用程序,并在不同平台上进行部署和运行。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值