Android 源码分析 (七) StartService 启动

本文详细解析了Android应用中启动Service的过程,从Activity的startService开始,逐步深入到ContextImpl、ActivityThread、AMS(Activity Manager Service)以及进程间的通信。过程中涉及到Context的创建、ServiceRecord的查找与创建、进程的启动以及Service生命周期的onCreate方法调用。
摘要由CSDN通过智能技术生成

startService 启动过程

ContextImpl 到 AMS 的调用过程

当我们在 Activity 中调用 startActivity 函数的时候,点击 startActivity 看源码实现会发现它是在 ContextWrapper 类中实现的。

我们继续看 Context 的 startService 实现,代码如下:

//Context.java
public abstract class Context {
 ...
       @Nullable
    public abstract ComponentName startService(Intent service);
 ...
  
}

可以看到 Context 是一个抽象类,那么它具体实现是哪个类?我们之前介绍了 Activity 的启动,那么在启动的时候,就会创建 Context ,注意看下面代码,如下:

//ActivityThread.java
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
      

        /**
         * 1. 通过封装启动 Activity 信息类 ActivityClientRecord 来获取到 ActivityInfo
         */
        ActivityInfo aInfo = r.activityInfo;
        /**
         * 2. 如果 r.packageInfo == null 就获取 LoadedApk 实例
         */
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        /**
         * 3. 通过封装启动 Activity 信息类 ActivityClientRecord 来获取启动 Activity 组件的 ComponentName
         */
        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }
        /**
         * 4. 创建Activity 中的上下文环境
         */
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            /**
             * 拿到当前上下文加载的 ClassLoader 加载器
             */
            java.lang.ClassLoader cl = appContext.getClassLoader();
            /**
             * 5. 调用 Instrumentation.newActivity 函数 ,内部通过 ClassLoader 类加载器来创建 Activity 的实例
             */
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
           ...
        }

        try {
            /**
             * 6. 得到 Application 对象
             */
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            ....
                /**
                 * 7. 将 appContext 等对象依附在 Activity 的 attach 函数中,进行 Activity  attach 初始化
                 */
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);

               ...

        return activity;
    }

我们看下注释 4 的实现,代码如下:

//ActivityThread.java
    private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
...

        //1.创建 Activity 的 Context 对象
        ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);

...
        return appContext;
    }
//ContextImpl.java
    static ContextImpl createActivityContext(ActivityThread mainThread,
            LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId,
            Configuration overrideConfiguration) {
        ...
				2. 实例化 Context 的实现类 ContextImpl
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName,
                activityToken, null, 0, classLoader);

...
        return context;
    }

通过上面代码我们知道,最后在 createActivityContext 函数中实例化了 ContextImpl 对象,现在我们回到 ActivityThread performLaunchActivity 函数,代码如下

//ActivityThread.java
                
activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);
//Activity.java
    final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback) {
      	//调用父类函数
        attachBaseContext(context);
      
      ....
        
    }
//ContextThemeWrapper
  public class ContextThemeWrapper extends ContextWrapper {
    ...
	@Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(newBase);
    }
    
    ...
      
  }

继续调用父类,代码如下:

public class ContextWrapper extends Context {
    Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }
    

    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
      	//赋值给 Context
        mBase = base;
    }

到最后我们看到 Context 的实现类 ContextImpl 赋值给了 ContextWrapper 的成员变量 mBase,现在我们直接去 ContextImpl 的 startService 看它具体实现,代码如下:

//ContextImpl
class ContextImpl extends Context {
  ...
    @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        /**
         * 调用内部 startServiceCommon 函数
         */
        return startServiceCommon(service, false, mUser);
    }
 ...
   
}

继续调用内部函数,代码如下:

//ContextImpl
    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            /**
             * 调用 AMS 代理的 IActivityManager  的 startService 函数
             */
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
      ...
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

我们已经见过了这种调用方式,其内部就是通过 aidl 来进行应用进程与 AMS(SystemServer) 进程通信,最后回调到 AMS 的 startService 函数

ActivityThread 启动 Service

通过上一小节我们知道最后会回到 AMS 的 startService 函数中,那么我们直接看 AMS 中的具体实现,代码如下:

//AMS.java

   /**
     * 这里是 ContextImpl 通过进程间通信调用的
     * @param caller
     * @param service
     * @param resolvedType
     * @param requireForeground
     * @param callingPackage
     * @param userId
     * @return
     * @throws TransactionTooLargeException
     */
    @Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {

      ...
            try {
                
                 1. 调用 ActiveService 的 startServiceLocked 函数
                 
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }

注释 1 的代码具体实现是通过 ActiveService 类调用 startServiceLocked 函数,代码如下:

//ActiveService.java

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
            ...

        
         1. 查找是否有与参数 Service 对应的 ServiceRecord
         
        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false);

        if (res == null) {
            return null;
        }
        if (res.record == null) {
            return new ComponentName("!", res.permission != null
                    ? res.permission : "private to package");
        }

        
        2. 通过 ServiceLookupResult 得到参数 Service 对应的 ServiceRecord ,并传入到注释 3 处的 startServiceInnerLocked 中
         */
        ServiceRecord r = res.record;

        ...
        
          3. 调用内部 startServiceInnerLocked 函数
         
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
    }

在注释 1 处的 retrieveServiceLocked 函数会查找是否有与参数 service 对应的 ServiceRecord, 如果没有找到,就会调用 PMS 去获取参数 service 对应的 Service 信息,并封装到 ServiceRecord 中,最后将 ServiceRecord 封装为 ServiceLookupResult 返回。其中 ServiceRecord 用于描述一个 Service, 和此前讲过的 ActivityRecord 类似,在注释 2 中将得到的 ServiceRecord 赋值给注释 3 ,最后调用内部 startServiceInnerLocked 函数,代码如下:

//ActiveServices.java


    ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
			 ...
        /**
         * 继续调用内部函数
         */
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
       ...

        return r.name;
    }

我们继续看 bringUpServiceLocked 函数

//ActiveServices.java

    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        ....
        
         1. 获取 Service 想要在哪个进程中运行
         
        final String procName = r.processName;
        String hostingType = "service";
        ProcessRecord app;

        if (!isolated) {
            
             2. 将 procname 和 Service 的 uid 传入到 AMS 的getProcessRecordLocked 函数,查询是否已经存在了当前启动的 Service
             
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
      

            
             3. 如果运行 Service 的应用程序进程已经存在
             
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                    /**
                     * 3.1 启动 Service
                     */
                    realStartServiceLocked(r, app, execInFg);
                    return null;
...
            }
        } else {
...


        
          4. 如果用来运行的 Service 的应用程序进程不存在
         
        if (app == null && !permissionsReviewRequired) {
            
             5. 创建应用程序进程
            
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingType, 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;
            }
....

        return null;
    }

主要逻辑就是通过在 AMS 查询需要启动的 Service 所在的进程是否已经存在,如果存在则启动 Service, 如果不存在就调用 注释 5 内部函数,创建一个应用程序进程。

我们接着看启动 Service 函数,代码如下:

//ActiveService.java

    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        ...
            /**
             * 1. 调用 app.thread 函数,其实就是调用 IApplicationThread 的 scheduleCreateService 函数
             */
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
         ...
    }

这里的函数如果调用了 scheduleCreateService 说明已经离开了 AMS 进程,那么 app.thread 到底是什么了?app.thread 就是 IApplicationThread 它是一个 aidl 文件,具体实现在 ActivityThread 的非静态内部类

//ActivityThread.java
public final class ActivityThread {
...
private class ApplicationThread extends IApplicationThread.Stub {
 ...
   
        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);
        }   
 ...
  
  
}

这里调用内部重载函数这里只需记住 H.CREATE_SERVIC 标记,具体实现代码如下:

  //ActivityThread.java 
	private void sendMessage(int what, Object obj) {
        
         1. 继续调用内部重载函数 what = H.CREATE_SERVIC
         

        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);
        }
        
          2. 通过 H 的 Handler 将 what = H.CREATE_SERVIC 消息 what 发送出去
         
        mH.sendMessage(msg);
    }

 H 类的 sendMessage 将标志为 H.CREATE_SERVIC 发送出去。这里的 H 类就是继承的 Handler 

//ActivityThread.java
public final class ActivityThread {
//初始化 H 类
final H mH = new H();
  
    /**
     * H 继承自 handler 是应用程序进程中主线程的消息管理类
     */
    private class H extends Handler {
      ...
        
      public static final int CREATE_SERVICE  = 114;
      
     .... 
  		public void handleMessage(Message msg) {
       ...
                
      case CREATE_SERVICE:
       //调用 handleCreateService
       handleCreateService((CreateServiceData)msg.obj);
       Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
       break;
       ...
     }
    }
  
}

H 的 handleMessage 接收到发送过来的消息,调用 handleCreateService 函数,我们来看下具体实现:

//ActivityService.java


    private void handleCreateService(CreateServiceData data) {

        
         1. 拿到要启动 Service 的应用程序的 LoadApk
         
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            
              2. 拿到类加载器
             
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            
             3. 创建 Servcie 实例
             
            service = (Service) cl.loadClass(data.info.name).newInstance();
        } catch (Exception e) {
            ...
        }

        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
            /**
             * 4. 创建 Context 实例
             */
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);
            
             5. 拿到缓存中的 Application
             
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            
             6. 执行 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) {
            ...
        }
    }

至此 主要通过 ClassLoader 加载 Service 类,与 service 绑定 Application 和 Context 一个是应用级别,一个是服务级别,最后执行 Service 生命周期 onCreate 函数,这样服务就启动了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值