Android系列:Service的启动解析

461 阅读2分钟

1.service的启动流程

这里先讲解采用startService的方式启动

1.1 Service -> AMS

service的启动入口类是ConetxtImpl

  @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }
    
 private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
        //获取AM的binder对象,与AMS进行IPC
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

1.2 AMS -> Service

AMS中的startService

  @Override
    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 {
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }

启动工作在ActiveServices

    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        
        //ServiceRecord 已经存在 也就是说该Service已经启动过了
        if (r.app != null && r.app.thread != null) {
           // 调用onStartCommand 也就是说再次启动service只会走onStartCommand
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }

  
        final String procName = r.processName;
        ProcessRecord app;

            //获取ProcessRecord 判断当前进程是否存在
          app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            
          if (app != null && app.thread != null) {
                try {
                //启动service
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } 
            }

        // Not running -- get it started, and enqueue this service record
        // to be executed when the app comes up.
        if (app == null && !permissionsReviewRequired) {
            //进程不存在,创建进程
            mAm.startProcessLocked();
        }

        if (!mPendingServices.contains(r)) {
            mPendingServices.add(r);
        }

        return null;
    }

注意:==如果该service已经被启动了,如果再次启动只会走onStartCommand就return,也就是说onStartCommand可能被多次调用,但是onCreate只会被调用一次。==

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

        final boolean newService = app.services.add(r);
        bumpServiceExecutingLocked(r, execInFg, "create");
        mAm.updateLruProcessLocked(app, false, null);
        updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
        mAm.updateOomAdjLocked();

        boolean created = false;
        try {
           //ipc 调用ApplicationThread
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            r.postNotification();
            created = true;
        }  finally {
            if (!created) {

                // Cleanup.
                if (newService) {
                    app.services.remove(r);
                    r.app = null;
                }

                // Retry.
                if (!inDestroying) {
                    scheduleServiceRestartLocked(r, false);
                }
            }
        }

        //
        sendServiceArgsLocked(r, execInFg, true);

    }

从上面的流程我们可以看出,Service和Activity的启动流程是大同小异的。

1.3 ActivityThread

private void handleCreateService(CreateServiceData data) {
        //1
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
        //2
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = (Service) cl.loadClass(data.info.name).newInstance();
        } catch (Exception e) {
        }

        try {
            //3
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            //4
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //5
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            service.onCreate();
            
            mServices.put(data.token, service);
            //5
            ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
    }

小结:

  • 1.获取安装包的信息
    1. 通过类加载器加载Service实例
  • 3.创建ContextImpl
  • 4.获取Application
  • 5.attach一些信息到Service
  • 6.向AMS汇报,service已经启动 的