Android Service启动流程刨析

作者:Android技术栈 时间:2023-07-31 11:28:58 

强调一下阅读系统源码,起码要对进程间通信要了解,对binder机制非常非常清楚,binder就是指南针,要不然你会晕头转向;强行阅读,就容易睡着。

Service启动先来一张图感受一下

Android Service启动流程刨析

这张图能够说明一个大致的流程,但是服务的启动肯定不是这么简单,但是我们先简单的总结一下,逐渐深入。服务的启动形式有两种,startService()和 binderService(),我们看startService()这一种。startService是ContextWrapper里面的方法。

ContextWrapper.java

@Override
  public ComponentName startService(Intent service) {
      return mBase.startService(service);//mBase这里指的是ContextImpl类
  }

ContextImpl.java

@Override
   public ComponentName startService(Intent service) {
       warnIfCallingFromSystemProcess();
       return startServiceCommon(service, mUser);
   }
private ComponentName startServiceCommon(Intent service, UserHandle user) {
       try {
           //检验Intent
           validateServiceIntent(service);
            ......
           ComponentName cn = ActivityManagerNative.getDefault().startService(
               mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                           getContentResolver()), getOpPackageName(), user.getIdentifier());
            ......
           return cn;
       } catch (RemoteException e) {
           throw new RuntimeException("Failure from system", e);
       }
   }

校验完Intent后,就调用ActivityManagerNative.getDefault(),获取一个IActivityManager对象,将启动Service这件事情交给了IActivityManager。我们看一下ActivityManagerNative的类定义

public abstract class ActivityManagerNative extends Binder implements IActivityManager

这种模式是不是非常熟悉啊? 继承了Binder,实现了一个IActivityManager接口,这个跟我们生成了远程服务通信生成的AIDL的java文件怎么那么像,现在告诉你,这就是为了远程服务通信做准备的,只是一般这种类我们都是自动生成的,ActivityManagerNative 是谷歌的人自己写

一个完整的AID L有两部分,一个是个跟服务端通信的Stub,一个是跟客户端通信的Proxy; ActivityManagerNative就是Stub,阅读源码发现在ActivityManagerNative 文件中还有个ActivityManagerProxy,那么跟客户端通信的Proxy也有了。先看IActivityManager怎么获取的

ActivityManagerNative.java

static public IActivityManager getDefault() {
       return gDefault.get();
   }
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
       protected IActivityManager create() {
         //获取名为"activity"的服务,服务都注册到ServiceManager来统一管理
           IBinder b = ServiceManager.getService("activity");
           if (false) {
               Log.v("ActivityManager", "default service binder = " + b);
           }
           IActivityManager am = asInterface(b);
           if (false) {
               Log.v("ActivityManager", "default service = " + am);
           }
           return am;
       }
   };

就是一个单例设计模式,获取到服务对象IBinder,把这个IBinder转换成IActivityManager返回了。现在由IActivityManager启动服务。

public ComponentName startService(IApplicationThread caller, Intent service,
           String resolvedType, String callingPackage, int userId) throws RemoteException
   {
       Parcel data = Parcel.obtain();
       Parcel reply = Parcel.obtain();
       data.writeInterfaceToken(IActivityManager.descriptor);
       data.writeStrongBinder(caller != null ? caller.asBinder() : null);
       service.writeToParcel(data, 0);
       data.writeString(resolvedType);
       data.writeString(callingPackage);
       data.writeInt(userId);
       mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
       reply.readException();
       ComponentName res = ComponentName.readFromParcel(reply);
       data.recycle();
       reply.recycle();
       return res;
   }

上面说了ActivityManagerProxy作为binder通信的客户端,ActivityManagerNative 作为binder通信的服务端; mRemote.transact()是binder通信的客户端发起方法,经过binder驱动,最后回到binder服务端ActivityManagerNative的onTransact()方法。

@Override
   public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
           throws RemoteException {
           .......
       switch (code) {
            case START_SERVICE_TRANSACTION: {
                       data.enforceInterface(IActivityManager.descriptor);
                       IBinder b = data.readStrongBinder();
                       IApplicationThread app = ApplicationThreadNative.asInterface(b);
                       Intent service = Intent.CREATOR.createFromParcel(data);
                       String resolvedType = data.readString();
                       String callingPackage = data.readString();
                       int userId = data.readInt();
                       ComponentName cn = startService(app, service, resolvedType, callingPackage, userId);
                       reply.writeNoException();
                       ComponentName.writeToParcel(cn, reply);
                       return true;
                   }
       }
       .......
   }

ActivityManagerNative的真正实现是ActivityManagerService,所以binder通信的服务端的ActivityManagerService,ActivityManagerProxy.startService()最终调用ActivityManagerService.startService()。注意这就跨进程了,ActivityManagerService是一个服务端的进程。看ActivityManagerService中的startService方法。

ActivityManagerService.java

public ComponentName startService(IApplicationThread caller, Intent service,
           String resolvedType, String callingPackage, int userId)
           throws TransactionTooLargeException {
       ......
       synchronized(this) {
           .......
           ComponentName res = mServices.startServiceLocked(caller, service,
                   resolvedType, callingPid, callingUid, callingPackage, userId);
           Binder.restoreCallingIdentity(origId);
           return res;
       }
   }

ActivityManagerService没有直接干这个活,而是把这个任务交给了mService, mService 是一个 ActiveServices 对象。在早期的安卓版本中并没有这个类,后来重构时抽出这个类专门用来管理Service.

ActiveServices.java

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

tartServiceInnerLocked调用了 bringUpServiceLocked(),bringUpServiceLocked()内部调用了realStartServiceLocked(),我们看realStartServiceLocked()方法。

private final void realStartServiceLocked(ServiceRecord r,
           ProcessRecord app, boolean execInFg) throws RemoteException {
      .......
       try {
           .......
           app.thread.scheduleCreateService(r, r.serviceInfo,
                   mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                   app.repProcState);
           r.postNotification();
           created = true;
       } catch (DeadObjectException e) {
           ....
       } finally {
          ....
       }
       requestServiceBindingsLocked(r, execInFg);
       updateServiceClientActivitiesLocked(app, null, true);
       // If the service is in the started state, and there are no
       // pending arguments, then fake up one so its onStartCommand() will
       // be called.
       if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
           r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                   null, null));
       }
      // 进入onStartCommand()
       sendServiceArgsLocked(r, execInFg, true);
      ....
   }

这里的关键是

app.thread.scheduleCreateService(r, r.serviceInfo,
                   mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),

app 是要运行 Service 的进程对应的 ProcessRecord 对象,代表一个应用进程; 要区分一下,一般我们都是单方向通信,客户端将处理请求发送给服务端,服务端处理后返回,如果要服务端向客户端发送一个&ldquo;请求&rdquo;呢?这里的thread 是一个 ApplicationThreadProxy 对象,它是应用进程的 ApplicatonThread 对象在 AMS 端的代理,AMS 靠它来和应用进程进行通信。所以AMS和应用进程可以双向通信了。

Android Service启动流程刨析

ApplicationThreadProxy.java

public final void scheduleCreateService(IBinder token, ServiceInfo info,
       CompatibilityInfo compatInfo, int processState) throws RemoteException {
   Parcel data = Parcel.obtain();
   data.writeInterfaceToken(IApplicationThread.descriptor);
   data.writeStrongBinder(token);
   info.writeToParcel(data, 0);
   compatInfo.writeToParcel(data, 0);
   data.writeInt(processState);
   try {
       mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
   } catch (TransactionTooLargeException e) {
       throw e;
   }
   data.recycle();
}

执行mRemote.transact后,就会回调ApplicationThreadNative的onTransact,这是Binder的套路。

ApplicationThreadNative.java

public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
       throws RemoteException {
   switch (code) {
   case SCHEDULE_CREATE_SERVICE_TRANSACTION: {
       data.enforceInterface(IApplicationThread.descriptor);
       IBinder token = data.readStrongBinder();
       ServiceInfo info = ServiceInfo.CREATOR.createFromParcel(data);
       CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
       int processState = data.readInt();
       scheduleCreateService(token, info, compatInfo, processState);
       return true;
   }
   ...
}

内部调用scheduleCreateService,看上面的图,可以知道,scheduleCreateService是属于ApplicatonThread的。

ApplicatonThread.java

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类处理的,H类就是系统Hander,专门处理系统请求的; 比如一些Activity的生命周期等全在这里面。这个 H对象是在应用进程的主线程中创建的,所以最终的结果是把创建 Service 的消息传到了主线程,因此Service是运行在主线程中的。

H.java

private class H extends Handler {
         .........
           public void handleMessage(Message msg) {
           if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
           switch (msg.what) {
            case CREATE_SERVICE:
                   Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
                   handleCreateService((CreateServiceData)msg.obj);
                   Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
           }
       }

ActivityThread.java

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) {
           .......
       }
       try {
           if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
            //创建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) {
               // nothing to do.
           }
       } catch (Exception e) {
          .......
       }
   }

到此Service的onCreate就回调了,那么onStartCommand()何时回调呢?在realStartServiceLocked中调用了sendServiceArgsLocked(r, execInFg, true),sendServiceArgsLocked与上面类似,最终也是发送了一个(SERVICE_ARGS)消息。

ApplicationThread.java

public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
           int flags ,Intent args) {
           ServiceArgsData s = new ServiceArgsData();
           s.token = token;
           s.taskRemoved = taskRemoved;
           s.startId = startId;
           s.flags = flags;
           s.args = args;
           sendMessage(H.SERVICE_ARGS, s);
       }

ActivityThread.java

private void handleServiceArgs(ServiceArgsData data) {
       Service s = mServices.get(data.token);
       if (s != null) {
           try {
               if (data.args != null) {
                   data.args.setExtrasClassLoader(s.getClassLoader());
                   data.args.prepareToEnterProcess();
               }
               int res;
               if (!data.taskRemoved) {
               //onStartCommand回调
                   res = s.onStartCommand(data.args, data.flags, data.startId);
               } else {
                   s.onTaskRemoved(data.args);
                   res = Service.START_TASK_REMOVED_COMPLETE;
               }
               QueuedWork.waitToFinish();
               try {
                   ActivityManagerNative.getDefault().serviceDoneExecuting(
                           data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
               } catch (RemoteException e) {
                   // nothing to do.
               }
               ensureJitEnabled();
           } catch (Exception e) {
              ......
           }
       }
   }

Service的onCreate的回调和onStartCommand的回调套路是完全一样的,朋友们可以自己体会,onCreate的回调先执行scheduleCreateService()方法,最终回调Service.onCreate(); onStartCommand的回调先执行scheduleServiceArgs()方法,最终回调Service.onStartCommand()

总结一下:

IActivityManager接口中定义了AMS向应用程序(本例中即Service)提供的多种API,Activity通过ActivityManagerProxy就可以使用这些API,向AMS发出请求

所以是通过ActivityManagerProxy,调用ActivityManagerProxy的startService方法; 在内部调用transact,然后会调用ActivityManagerNative中的onTransact()方法,在该方法中,将会r完成AMS与Activity的连接并调用AMS的startService()方法,那么AMS是如何Service所在的应用程序呢?比如scheduleCreateService

原来ApplicationThreadProxy 是应用进程的 ApplicatonThread 对象在 AMS 端的代理,AMS 靠它来和应用进程进行通信。这就是Activity与AMS之间的双向Binder连接;Activity用IActivityManager提供的APIActivityManagerService提出执行某个动作的请求(本例中是启动RemoteService),ActivityManagerService通过IApplicationThread提供的API来控制Activity所在的应用程序

上面的分析省去了很多的内容,如果从进程角度看服务启动过程。

  • Process A进程: 是指调用startService命令所在的进程,也就是启动服务的发起端进程

  • system_server进程: 系统进程,是java framework框架的核心载体,里面运行了大量的系统服务,比如这里提供ApplicationThreadProxy,ActivityManagerService,这个两个服务都运行在system_server进程的不同线程中

  • Zygote进程: 是由init进程孵化而来的,用于创建Java层进程的母体,所有的Java层进程都是由Zygote进程孵化而来

  • Remote Service进程: 远程服务所在进程,是由Zygote进程孵化而来的用于运行Remote服务的进程。主线程主要负责Activity/Service等组件的生命周期以及UI相关操作都运行在这个线程; 另外,每个App进程中至少会有两个binder线程 ApplicationThread和ActivityManagerProxy

Android Service启动流程刨析

启动流程:

  • Process A进程采用Binder IPC向system_server进程发起startService请求;

  • system_server进程接收到请求后,向zygote进程发送创建进程的请求;

  • zygote进程fork出新的子进程Remote Service进程;

  • Remote Service进程,通过Binder IPC向sytem_server进程发起attachApplication请求;

  • system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向remote Service进程发送scheduleCreateService请求;

  • Remote Service进程的binder线程在收到请求后,通过handler向主线程发送CREATE_SERVICE消息;

  • 主线程在收到Message后,通过发射机制创建目标Service,并回调Service.onCreate()方法。 到此,服务便正式启动完成。当创建的是本地服务或者服务所属进程已创建时,则无需经过上述步骤2、3,直接创建服务即可

来源:https://blog.csdn.net/m0_70748845/article/details/126201326

标签:Android,Service,启动
0
投稿

猜你喜欢

  • Android图片处理工具类BitmapUtils

    2022-12-28 05:23:39
  • SpringBoot 2.x 整合Lombok的方法示例

    2022-03-15 17:43:35
  • SpringBoot Redis配置Fastjson进行序列化和反序列化实现

    2023-10-09 04:45:57
  • IDEA java出现无效的源发行版14解决方案

    2021-06-25 08:50:33
  • Java BigDecimal使用方法详解

    2022-03-28 03:45:23
  • java的NIO管道用法代码分享

    2022-05-01 23:52:53
  • mybatis批量添加,批量更新之前如何判断是否已经存在

    2022-01-03 20:33:38
  • Java基础知识之ByteArrayInputStream流的使用

    2023-10-27 14:37:53
  • mybatis 通过拦截器打印完整的sql语句以及执行结果操作

    2023-07-06 04:26:42
  • InputStream数据结构示例解析

    2022-06-12 20:11:53
  • 详解LeakCanary分析内存泄露如何实现

    2022-12-03 22:04:40
  • Android 高仿微信支付数字键盘功能

    2021-08-10 09:36:19
  • 一篇文章带你入门Java变量

    2021-09-21 07:46:02
  • 在Linux上运行C#的方法

    2023-03-06 00:28:39
  • C#多线程之Thread中Thread.Join()函数用法分析

    2022-01-20 14:47:58
  • VC++时钟函数

    2021-06-17 10:07:51
  • Android开发改变字体颜色方法

    2022-11-10 05:51:01
  • java中Hashmap的get方法使用

    2023-10-29 13:10:05
  • SpringBoot Actuator潜在的OOM问题的解决

    2021-08-26 06:36:43
  • C#读取csv格式文件的方法

    2023-08-28 22:38:46
  • asp之家 软件编程 m.aspxhome.com