Android Service 启动流程

打印 上一主题 下一主题

主题 1898|帖子 1898|积分 5694

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在早些年学习Android的时候,对Service有过总结,但是主要是如何去使用,注意事项,startService和bindService的区别。
Android Service_public int onstartcommand(intent intent, int flags-CSDN博客
但是今天从源码来总结下framework层的启动流程大抵是什么样的。
一、startService()

平常,在我们的activity里,我们通过startService去启动一个service服务。
1.context.startService

使用例子:
  1. //testActivity
  2.     @Override
  3.     public void onClick(View v) {
  4.         Intent it=new Intent(this, SimpleService.class);
  5.         switch (v.getId()){
  6.             case R.id.startService:
  7.                 startService(it);
  8.                 break;
  9.             case R.id.stopService:
  10.                 stopService(it);
  11.                 break;
  12.         }
复制代码
这儿,现实上是调用的context上下文去调用的这个方法,那我们去看下里面的代码
  1. @Override
  2. public ComponentName startService(Intent service) {
  3.     warnIfCallingFromSystemProcess();
  4.     return startServiceCommon(service, false, mUser);
  5. }
  6. private ComponentName startServiceCommon(Intent service, boolean requireForeground,
  7.         UserHandle user) {
  8.     try {
  9.         validateServiceIntent(service);
  10.         service.prepareToLeaveProcess(this);
  11.         ComponentName cn = ActivityManager.getService().startService(
  12.             mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
  13.                         getContentResolver()), requireForeground,
  14.                         getOpPackageName(), user.getIdentifier());
  15.        ...
  16.         return cn;
  17.     } catch (RemoteException e) {
  18.         throw e.rethrowFromSystemServer();
  19.     }
  20. }
复制代码
2.ActivityManager.getService().startService()

可以看到:焦点代码为ActivityManager.getService().startService()
在 Activity 中使用的 startService 方法是定义在 Context 的抽象类中,它的真正实现类是 ContextImpl,以是先进入 ContextImpl 类。先从startService开始,然后进入本类的startServiceCommon方法,并最终调用ActivityManagerNative.getDefault()对象的 startService 方法。ActivityManager.getService()获取到IActivityManager对象,而且是通过单利模式创建的。
  1. public static IActivityManager getService() {
  2.     return IActivityManagerSingleton.get();
  3. }
  4. private static final Singleton<IActivityManager> IActivityManagerSingleton =
  5.         new Singleton<IActivityManager>() {
  6.             @Override
  7.             protected IActivityManager create() {
  8.                 final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
  9.                 final IActivityManager am = IActivityManager.Stub.asInterface(b);
  10.                 return am;
  11.             }
  12.         };
复制代码
看下ActivityManager.getService()这个如果看过app启动流程就知道,这玩意儿在创建application和activity时也看到过。这儿用到了binder实现进程间通信,最后走到了AMS里面
看下ActivityManagerService中startService()代码

这里面走到了startServiceLocked()方法,此中mServices是ActiveServices。
ActiveServices这里面进行了以下步骤:
1.通过 retrieveServiceLocked 方法来解析 service 这个 Intent,就是解析前面我们在 AndroidManifest.xml 定义的 Service 标签的 intent-filter 相干内容,然后将解析效果放在 res.record 中。
2.调用 startServiceInnerLocked 方法。

在startServiceInnerLocked 方法中会调用 bringUpServiceLocked 方法。

3.bringUpServiceLocked方法中,当 Service 所在的进程存在时,将调用realStartServiceLocked 方法来启动 Service,否则的话调用 startProcessLocked 方法来启动新进程。
情况一:realStartServiceLocked()

这里面会调用 app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState);
这里会走到ApplicationThread去sendMessage,最后去创建service,执行onCreate方法,后面有详细说明。因为它运行的进程已存在,就直接去创建了,如果不存在,接着往下走
情况二:startProcessLocked() 
 4.startProcessLocked()是ActivityManagerSevice中的方法,
  1. //在ActivityManagerService类中
  2. private final void startProcessLocked(ProcessRecord app, String hostingType,
  3.         String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
  4.     boolean isActivityProcess = (entryPoint == null);
  5.     if (entryPoint == null)
  6.         entryPoint = "android.app.ActivityThread";
  7.     checkTime(startTime, "startProcess: asking zygote to start proc");
  8.     //通过 processName,uid 等启动新进程
  9.     Process.start(entryPoint,
  10.                         app.processName, uid, uid, gids, debugFlags, mountExternal,
  11.                         app.info.targetSdkVersion, app.info.seinfo, requiredAbi,
  12.                         instructionSet, app.info.dataDir, entryPointArgs);
  13. }
  14. //在Process类中
  15. public static final ProcessStartResult start(final String processClass,
  16.                               final String niceName,
  17.                               int uid, int gid, int[] gids,
  18.                               int debugFlags, int mountExternal,
  19.                               int targetSdkVersion,
  20.                               String seInfo,
  21.                               String abi,
  22.                               String instructionSet,
  23.                               String appDataDir,
  24.                               String invokeWith,
  25.                               String[] zygoteArgs) {
  26.     return zygoteProcess.start(processClass, niceName, uid, gid, gids,
  27.                 debugFlags, mountExternal, targetSdkVersion, seInfo,
  28.                 abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
  29. }
复制代码
从这儿,启动了一个新的进程,创建一个新的进程过后就会走到熟悉的ActivityThread类的main方法里面去
3.启动新进程去ActivityThread

熟悉的源码
  1. public static void main(String[] args) {
  2.     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
  3.     CloseGuard.setEnabled(false);
  4.     // 初始化应用中需要使用的系统路径
  5.     Environment.initForCurrentUser();
  6.     Looper.prepareMainLooper();
  7.     //创建ActivityThread 对象
  8.     ActivityThread thread = new ActivityThread();
  9.     thread.attach(false);
  10.     Looper.loop();
  11.     throw new RuntimeException("Main thread loop unexpectedly exited");
  12. }
复制代码
大抵流程:


  • 1.绑定应用进程到ActivityManagerService

    • 在 Android 应用程序中,每一个进程对应一个 ActivityThread 实例,然后这里创建了 ActivityThread 对象并调用了其 attach 方法

  • 2.主线程Handler消息处理

    • 启动looper轮询器,以是在activity大概service创建handler对象时,不需要手动调用looper。缘故原由就是在这里
    • 首先Looper.prepareMainLooper();是为主线程创建了Looper,然后thread.getHandler();是生存了主线程的Handler,最后Looper.loop();进入消息循环。

其余的不用看了,主要看thread.attach(false)


  • main()方法通过thread.attach(false)绑定应用进程。ActivityManagerNative通过getDefault()方法返回ActivityManagerService实例,ActivityManagerService通过attachApplication将ApplicationThread对象绑定到ActivityManagerService,而ApplicationThread作为Binder实现ActivityManagerService对应用进程的通信和控制
  • 在ActivityManagerService内部,attachApplication现实是通过调用attachApplicationLocked实现的,这里采用了synchronized关键字保证同步。
  1. //ActivityThread.java
  2. private void attach(boolean system) {
  3.     final IActivityManager mgr = ActivityManagerNative.getDefault();
  4.     try {
  5.         //这里调用了 ActivityManagerProxy.attachApplication 方法。
  6.         mgr.attachApplication(mAppThread);
  7.     } catch (RemoteException ex) {
  8.         // Ignore
  9.     }
  10. }
  11. //ActivityManagerService.java 然后看看attachApplication方法
  12. @Override
  13. public final void attachApplication(IApplicationThread thread) {
  14.     synchronized (this) {
  15.         int callingPid = Binder.getCallingPid();
  16.         final long origId = Binder.clearCallingIdentity();
  17.         attachApplicationLocked(thread, callingPid);
  18.         Binder.restoreCallingIdentity(origId);
  19.     }
  20. }
复制代码
往里面走,里面的代码很多,这儿根据我看过的源码,分为三个方向
1.关于application,他会走到 thread.bindApplication去绑定application,执行后续操作(创建application,执行onCreate生命周期)
2.关于activity,他会走到mStackSupervisor.attachApplicationLocked(app)执行有关activity的操作(走到scheduleLaunchActivity)
上面两个步骤,具体可看我之前的博客 Android App启动流程和源码详解-CSDN博客
3.关于service,他会走到 didSomething |= mServices.attachApplicationLocked(app, processName);执行service的后续操作。
关键代码:
  1. private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {
  2.     if (app.instr != null) {//app的
  3.         thread.bindApplication(processName, appInfo, providers,
  4.                 app.instr.mClass,
  5.                 profilerInfo, app.instr.mArguments,
  6.                 app.instr.mWatcher,
  7.                 app.instr.mUiAutomationConnection, testMode,
  8.                 mBinderTransactionTrackingEnabled, enableTrackAllocation,
  9.                 isRestrictedBackupMode || !normalMode, app.persistent,
  10.                 new Configuration(getGlobalConfiguration()), app.compat,
  11.                 getCommonServicesLocked(app.isolated),
  12.                 mCoreSettingsObserver.getCoreSettingsLocked(),
  13.                 buildSerial);
  14.     } else {
  15.         thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
  16.                 null, null, null, testMode,
  17.                 mBinderTransactionTrackingEnabled, enableTrackAllocation,
  18.                 isRestrictedBackupMode || !normalMode, app.persistent,
  19.                 new Configuration(getGlobalConfiguration()), app.compat,
  20.                 getCommonServicesLocked(app.isolated),
  21.                 mCoreSettingsObserver.getCoreSettingsLocked(),
  22.                 buildSerial);
  23.     }
  24.    
  25.     // See if the top visible activity is waiting to run in this process...
  26.     if (normalMode) {
  27.         try {//activity的
  28.             if (mStackSupervisor.attachApplicationLocked(app)) {
  29.                 didSomething = true;
  30.             }
  31.         } catch (Exception e) {
  32.             Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
  33.             badApp = true;
  34.         }
  35.     }
  36.     // Find any services that should be running in this process...
  37.     if (!badApp) {
  38.         try {//sevice的
  39.             didSomething |= mServices.attachApplicationLocked(app, processName);
  40.             checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
  41.         } catch (Exception e) {
  42.             Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
  43.             badApp = true;
  44.         }
  45.     }
  46.    
  47. }
复制代码
上面第三步,mServices.attachApplicationLocked看源码,会走到app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState);方法,哎,你看他又归去了,走到了ApplicationThread里去了,ApplicationThread是Activity的内部类(上面不创建进程也是调用的词方法),我们点进去看下源码:
  1. public final void scheduleCreateService(IBinder token,  ServiceInfo info,
  2.         CompatibilityInfo compatInfo, int processState) {
  3.     updateProcessState(processState, false);
  4.     CreateServiceData s = new CreateServiceData();
  5.     s.token = token;
  6.     s.info = info;
  7.     s.compatInfo = compatInfo;
  8.     sendMessage(H.CREATE_SERVICE, s);
  9. }
复制代码
哎哟喂,殊途同归啊,和application和activity一样,最后都用到了用handler去处理消息。
来嘛,看下handler的handleMessage()方法
  1. ...
  2. case CREATE_SERVICE:
  3.                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
  4.                     handleCreateService((CreateServiceData)msg.obj);
  5.                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
  6.                     break;
  7. ...
复制代码
继续往里走:handleCreateService((CreateServiceData)msg.obj);
1.通过类加载器 ClassLoader 来加载 Service 对象
2.创建一个 ContextImpl 对象,每个 Activity 和 Service 都有一个 Context 对象。
  1. private void handleCreateService(CreateServiceData data) {
  2.     Service service = null;
  3.     try {
  4.         //(1)通过类加载器来加载 Service 对象
  5.         java.lang.ClassLoader cl = packageInfo.getClassLoader();
  6.         service = (Service) cl.loadClass(data.info.name).newInstance();
  7.     } catch (Exception e) {
  8.         //......
  9.     }
  10.     //(2)这里创建 ContextImpl 对象
  11.     ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
  12.     context.setOuterContext(service);
  13.     Application app = packageInfo.makeApplication(false, mInstrumentation);
  14.     service.attach(context, this, data.info.name, data.token, app,ActivityManagerNative.getDefault());
  15.     //(3)这里调用 Service 的 onCreate 方法
  16.     service.onCreate();
  17.     mServices.put(data.token, service);
  18. }
复制代码
哎,这不就来了吗,最后执行了service的onCreate()生命周期。
二、bindService()

1.ContextImpl类中bindService()

具体使用:
  1. TestActivity.java
  2. private void test(){
  3.     Intent intent = new Intent(this, XXXService.class);
  4.     // bindService 的具体实现在 ContextImpl
  5.     // BIND_AUTO_CREATE 参数具体使用的代码 ActivityServices
  6.     bindService(intent, conn, BIND_AUTO_CREATE);
  7. }
  8. private ServiceConnection conn = new ServiceConnection() {  
  9.     @Override  
  10.     public void onServiceConnected(ComponentName name, IBinder service) {  
  11.        // 绑定成功
  12.     }  
  13.     @Override  
  14.     public void onServiceDisconnected(ComponentName name) {
  15.       // 绑定结束
  16.     }
  17. }
复制代码
bindService源码:
  1. @Override
  2. public boolean bindService(Intent service, ServiceConnection conn,
  3.         int flags) {
  4.     // mMainThread.getHandler(),传入的 handle 是主线程的 Handle
  5.     return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
  6.             Process.myUserHandle());
  7. }
  8. private boolean bindServiceCommon(Intent service, ServiceConnection conn,
  9.         int flags, Handler handler, UserHandle user) {
  10.     IServiceConnection sd;
  11.     if (mPackageInfo != null) {
  12.         // 1,将传入的 ServiceConnection 转化为 IServiceConnection 返回
  13.         // mPackgeInfo 是 LoadedApk
  14.         sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
  15.     }
  16.     validateServiceIntent(service);
  17.     try {
  18.         IBinder token = getActivityToken();
  19.         ...
  20.         // 2,Binder 调用 AMS 的 bindService 方法,下面具体分析
  21.         int res = ActivityManagerNative.getDefault().bindService(
  22.             mMainThread.getApplicationThread(), getActivityToken(), service,
  23.             service.resolveTypeIfNeeded(getContentResolver()),
  24.             sd, flags, getOpPackageName(), user.getIdentifier());
  25.         return res != 0;
  26.     }
  27.     //...
  28. }
复制代码
getServiceDispatcher方法
  1. public final IServiceConnection getServiceDispatcher(ServiceConnection c,
  2.         Context context, Handler handler, int flags) {
  3.     synchronized (mServices) {
  4.         LoadedApk.ServiceDispatcher sd = null;
  5.         // private final ArrayMap<Context,
  6.         // ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
  7.         // 根据当前的 Context 获取 ArrayMap<ServiceConnection,  LoadedApk.ServiceDispatcher>
  8.         ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
  9.         if (map != null) {
  10.             // 如果存在,尝试根据当前的 ServiceConnection 获取 ServiceDispatcher
  11.             sd = map.get(c);
  12.         }
  13.         if (sd == null) {
  14.             // 如果与 ServiceConnection 对应的 ServiceDispatcher 不存在,创建一个保存了当前
  15.                         // ServiceConnection 的 ServiceDispatcher 对象,
  16.             // 并将之前传入的主线的 Handle 保存,同时创建一个 InnerConnection 对象保存
  17.             sd = new ServiceDispatcher(c, context, handler, flags);
  18.             if (map == null) {
  19.                 map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
  20.                 mServices.put(context, map);
  21.             }
  22.             // 将该 ServiceConnection 与 ServiceDispatcher 关系保存
  23.             map.put(c, sd);
  24.         } else {
  25.             // 如果最开始就获取到 ServiceDispatcher,比如多次 bindService,
  26.             // 就会调用 ServiceDispatcher 的 validate 判断此次 bindService 是否合法
  27.             // validate 的判断逻辑比较简单:
  28.                         // 1.判断当前的 context 是否和之前 bindService 的一样
  29.                         // 2.判断当前 handler 是否是主线程的 handle
  30.             // 以上两个条件都满足的情况下正常执行,反之抛出相应的异常
  31.             sd.validate(context, handler);
  32.         }
  33.         return sd.getIServiceConnection();
  34.     }
  35. }
复制代码
主要看ActivityManagerService.bindService()
2.ActivityManagerService.bindService()

  1. public int bindService(IApplicationThread caller, IBinder token, Intent service,
  2.         String resolvedType, IServiceConnection connection,
  3.         int flags, String callingPackage, int userId) throws TransactionTooLargeException {
  4.     //...
  5.     synchronized(this) {
  6.         // 调用 ActiveServices 的 bindServiceLocked 方法
  7.         return mServices.bindServiceLocked(caller, token, service,
  8.                 resolvedType, connection, flags, callingPackage, userId);
  9.     }
  10. }
复制代码
看到这里面调用了ActiveServices 的 bindServiceLocked,往里走:这里面代码长,但是主要调用是这样的:ActiveServices.bindServiceLocked() -> bringUpServiceLocked() -> realStartServiceLocked()
看realStartServiceLocked方法,刚才在我们startService的时候也调用了这个方法,但是因为它是bind的,以是有些许不同
  1. private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
  2.         boolean execInFg) throws RemoteException {
  3.     //...
  4.     try {
  5.         // 第一步,调用 ApplicationThread 的 scheduleCreateService 方法,
  6.                 // 之后会实例化 Service 并调用 Service 的 onCreate 方法,这里的过程跟上面 startService 中一样。
  7.         // 不会调用 onStartCommand
  8.         app.thread.scheduleCreateService(r, r.serviceInfo,
  9.                                 mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
  10.                 app.repProcState);
  11.     }
  12.     //...
  13.     // 第二步,调用 requestServiceBindingLocked
  14.     requestServiceBindingLocked(r, execInFg);
  15.     updateServiceClientActivitiesLocked(app, null, true);
  16.     // 第三步
  17.     // If the service is in the started state, and there are no
  18.     // pending arguments, then fake up one so its onStartCommand() will
  19.     // be called.
  20.     if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
  21.         r.pendingStarts.add(new ServiceRecord.StartItem(r, false,
  22.                         r.makeNextStartId(), null, null));
  23.     }
  24.     // StartItem 的 taskRemoved 如果是 false 的话,
  25.         // 调用下面方法会调用 Service 的 onStartCommand
  26.     sendServiceArgsLocked(r, execInFg, true);
  27. }
  28. private final boolean requestServiceBindingLocked(ServiceRecord r,
  29.         IntentBindRecord i, boolean execInFg, boolean rebind)
  30.         throws TransactionTooLargeException {
  31.     if ((!i.requested || rebind) && i.apps.size() > 0) {
  32.         try {
  33.             // 调用 ApplicationThread 的 scheduleBindService 方法
  34.             r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
  35.                     r.app.repProcState);
  36.         }
  37.     }
  38.     return true;
  39. }
复制代码
3.ApplicationThread.scheduleBindService()方法

来来来,看下ApplicationThread.scheduleBindService()方法


  • 调用 ApplicationThread 的 scheduleBindService,scheduleBindService 通过 mH 发送一个 H.BIND_SERVICE 消息,mH 收到该消息调用 handleBindService(BindServiceData data)。
 
  1. private void handleBindService(BindServiceData data) {
  2.         Service s = mServices.get(data.token);
  3.         if (DEBUG_SERVICE)
  4.             Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
  5.         if (s != null) {
  6.             try {
  7.                 data.intent.setExtrasClassLoader(s.getClassLoader());
  8.                 data.intent.prepareToEnterProcess();
  9.                 try {
  10.                     if (!data.rebind) {
  11.                    // 调用 Service 的 onBind,返回给客户端调用的 Binder
  12.                         IBinder binder = s.onBind(data.intent);
  13.                 // 调用 AMS 的 publishService,进而通知客户端连接成功
  14.                         ActivityManager.getService().publishService(
  15.                                 data.token, data.intent, binder);
  16.                     } else {
  17.                         s.onRebind(data.intent);
  18.                         ActivityManager.getService().serviceDoneExecuting(
  19.                                 data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
  20.                     }
  21.                     ensureJitEnabled();
  22.                 } catch (RemoteException ex) {
  23.                     throw ex.rethrowFromSystemServer();
  24.                 }
  25.             } catch (Exception e) {
  26.                 if (!mInstrumentation.onException(s, e)) {
  27.                     throw new RuntimeException(
  28.                             "Unable to bind to service " + s
  29.                                     + " with " + data.intent + ": " + e.toString(), e);
  30.                 }
  31.             }
  32.         }
  33.     }
复制代码
 


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

杀鸡焉用牛刀

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表