android startService流程梳理笔记

1、ContextWrapper.startService

  startService是Context的方法,Activity、Service都继承自ContextWrapper,而ContextWrapper又继承自Context,BroadcastReceiver的onReceive方法中有个参数是Context类型的,所以我们在Activity、Service、BroadcastReceiver中都可以调用startService方法,当在Activity等中调用startService时,首先会调用到ContextWrapper的startService方法:

public ComponentName startService(Intent service) {
     return mBase.startService(service);
}

2、ContextImpl.startService

  mBase是ContextImpl的实例,从名字也可以看到ContextImpl也是Context的子类,从ContextWrapper的名字也可以看到,它只是Context的包装类,其函数内部的实现都是通过调用内部ContextImpl类的实例mBase来完成实际请求,这被称为装饰者模式。

  ContextImpl的startService直接调用startServiceAsUser,在startServiceAsUser中调用ActivityManagerNative.getDefault().startService,ActivityManagerNative.getDefault()返回一个IActivityManager对象,典型的Binder通信。所以接下来会通过ActivityManagerProxy的startService经由Binder调用到ActivityManagerService(继承自ActivityManagerNative)的startService方法。

public ComponentName startServiceAsUser(Intent service, UserHandle user) {
     try {
         service.setAllowFds( false );
         ComponentName cn = ActivityManagerNative.getDefault().startService(
             mMainThread.getApplicationThread(), service,
             service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
     ...
         return cn;
     } catch (RemoteException e) {
         return null ;
     }
}

3、ActivityManagerService.startService与ActiveServices

  在ActivityManagerService的startService中,首先检查Caller的合法性(PID、UID),然后调用ActiveServices的startServiceLocked方法(在旧版本中这个方法在ActivityManagerService中),在startServiceLocked中,首先通过retrieveServiceLocked检索我们调用startService时传入的Intent信息,将结果存入ServiceLookupResult.record中(ServiceRecord),紧接着调用ActiveServices的bringUpServiceLocked方法。

  在bringUpServiceLocked中调用ActivityManagerService的startProcessLocked获得一个ProcessRecord对象并将其加入到mPendingServices队列中。startServiceLocked、bringUpServiceLocked都是从ActivityManagerService中调用过来的,所以是一直运行在ActivityaManagerService进程中,再调用ActivityManagerService的方法就是直接调用,而不用通过IPC。

  ActivityManagerService中有两个重载形式的startProcessLocked,首先进入参数多的那一个,通过newProcessRecordLocked获得一个ProcessRecord对象,然后把这个对象作为参数调用另一个形式的startProcessLocked,在这个startProcessLocked中,调用Process.start创建一个新的进程,将返回的Process.ProcessStartResult对象、新进程的PID及获得的ProcessRecord对象放入mPidSelfLocked列表中。

final ProcessRecord startProcessLocked(String processName,
         ApplicationInfo info, boolean knownToBeDead, int intentFlags,
         String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated) {
     ...
     app = newProcessRecordLocked( null , info, processName, isolated);
     ...
     startProcessLocked(app, hostingType, hostingNameStr);
     return (app.pid != 0 ) ? app : null ;
}
 
 
private final void startProcessLocked(ProcessRecord app,
         String hostingType, String hostingNameStr) {
     ...
     Process.ProcessStartResult startResult = Process.start( "android.app.ActivityThread" ,
                     app.processName, uid, uid, gids, debugFlags, mountExternal,
                     app.info.targetSdkVersion, null , null );
     ...
     synchronized (mPidsSelfLocked) {
         this .mPidsSelfLocked.put(startResult.pid, app);
         ...
     }
     ...
}

4、ActivityThread.main

  在Process.start中创建了一个进程,然后调用了ActivityThread的main函数。

public static void main(String[] args) {
     ...
     Looper.prepareMainLooper();
     ActivityThread thread = new ActivityThread();
     thread.attach( false );
     if (sMainThreadHandler == null ) {
         sMainThreadHandler = thread.getHandler();
     }
     ...
     Looper.loop();
     ...
}

5、ActivityManagerService.attachApplication

  在main中新建一个ActivityThread对象,并调用其attach方法,参数表示是否是系统进程。这里已经是在新进程里了。在attach中,又调用了ActivityManagerNative.getDefault().attachApplication(mAppThread)。同样,经由Binder由ActivityManagerProxy到了ActivityManagerService的attachApplication方法,在attachApplication中直接调用attachApplicationLocked。

  在attachApplicationLocked中,通过新进程的PID获得在第3步中放入mPidSelfLocked列表中的ProcessRecord对象,然后调用ActiveyServices的attachApplicationLocked方法,在这个方法中通过进程PID与进程名找到在第3步中放入mPendingServices中的ServiceRecord对象,再以这个找到的ServiceRecord对象与传入的ProcessRecord对象为参数调用realStartServiceLocked,这个函数也在ActiveServices中。

private final boolean attachApplicationLocked(IApplicationThread thread, nt pid) {
     ProcessRecord app;
     if (pid != MY_PID && pid >= 0 ) {
         synchronized (mPidsSelfLocked) {
             app = mPidsSelfLocked.get(pid);
         }
     } else {
         app = null ;
     }
     ...
     mServices.attachApplicationLocked(app, processName);
     ...
}
 
 
boolean attachApplicationLocked(ProcessRecord proc, String processName) throws Exception {
     boolean didSomething = false ;
     // Collect any services that are waiting for this process to come up.
     if (mPendingServices.size() > 0 ) {
         ServiceRecord sr = null ;
         try {
             for ( int i= 0 ; i<mPendingServices.size(); i++) {
                 sr = mPendingServices.get(i);
                 if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                         || !processName.equals(sr.processName))) {
                     continue ;
                 }
 
                 mPendingServices.remove(i);
                 i--;
                 realStartServiceLocked(sr, proc);
                 didSomething = true ;
             }
         } catch (Exception e) {
             Slog.w(TAG, "Exception in new application when starting service "
                     + sr.shortName, e);
             throw e;
         }
     }
     ...
}

6、ActiveServices.realStartServiceLocked

  在realStartServiceLocked中,取得传入的ProcessRecord对象的IApplicationThread类型的成员变量thread,调用其scheduleCreateService方法,同ActivityManagerProxy一样,调用的是ApplicationThreadProxy的scheduleCreateService,然后经由Binder到ApplicationThread的scheduleCreateService(ApplicationThread是ActivityThread的私有内部类)。

7、ApplicationThread.scheduleCreateService与ActivityThread.handleCreateService

  在ApplicationThread的scheduleCreateService中调用了外部类ActivityThread的queueOrSendMessage方法,向H中sendMessage(H继承自Handler),接下来肯定到了H的handleMessage,在handleMessage中走CREATE_SERVICE的switch case,调用外部类ActivityThread的handleCreateService方法。

  在handleCreateService通过JAVA的ClassLoader load加载要启动的Service的类,并通过newInstance新建一个Service的实例,new ContextImpl,makeApplication并跟新建的Service实例attach,然后调用我们熟悉的Service的onCreate方法,至此Service启动成功。

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 {
         java.lang.ClassLoader cl = packageInfo.getClassLoader();
         service = (Service) cl.loadClass(data.info.name).newInstance();
     } catch (Exception e) {
         ...
     }
 
     try {
         if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
 
         ContextImpl context = new ContextImpl();
         context.init(packageInfo, null , this );
 
         Application app = packageInfo.makeApplication( false , mInstrumentation);
         context.setOuterContext(service);
         service.attach(context, this , data.info.name, data.token, app,
                     ActivityManagerNative.getDefault());
         // 调用Service的onCreate,即要启动的Service的onCreate
         service.onCreate();
         mServices.put(data.token, service);
         try {
             ActivityManagerNative.getDefault().serviceDoneExecuting(
                     data.token, 0 , 0 , 0 );
         } catch (RemoteException e) {
             // nothing to do.
         }
     } catch (Exception e) {
         ...
     }
}

 

总结:

  1、调用ContextImpl的startService,通过Binder进入ActivityManagerService的进程执行ActivityManagerService的startService方法。

  2、在startService过程中新建一个进程,在新建的进程中创建Looper,调用ActivityThread的attach方法,然后就又进入了ActivityManagerService的进程。

  3、获取要在新进程启动的服务的相关信息,在ActivityManagerService中通过ApplicationThreadProxy又进入Service进程,Service的进程启起来,调用我们熟悉的Service的onCreate方法。

猜你喜欢

转载自blog.csdn.net/tuyerv/article/details/78486629