Android 跨进程通信-(四)Binder机制之Server

目录

前言

一 在Activity中调用startService

1.startServiceLocked()

2.bringUpServiceLocked()

(1)realStartServiceLocked()创建APP进程的Service

(2)在AMS中的startProcessLocked()创建Service进程

二 在Activity中调用bindService()

1.bindServiceLocked()

2.requestServiceBindingLocked()

三 小结Service

四 总结


前言

在 Android 跨进程通信-(二)Binder机制之ServiceManagerAndroid 跨进程通信-(三)Binder机制之Client已经总结了Binder机制中的ServiceManager和Client进程的创建过程,那么Server的进程是如何创建出来的呢?

本次基于上次假设的一个APP去访问一个AIDL服务来进行分析,那么就看一个AIDL服务进程是怎么创建的呢?由于Android10这部分改动比较大,暂时现在Android8的基础上理解下这个过程。

在一个APP中,既可以在APP进程中启动一个Service,随着APP的进程的存在而存在;当然也可以启动一个单独进程的Service,也就是AIDLService。从源码的角度简单的分析下这个过程。

一 在Activity中调用startService

最终会调用到 /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java的startService(),简单逻辑代码如下:

@Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
         //.......
        synchronized(this) {
            //.......
            ComponentName res;
            try {
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            }
          //.......
            return res;
        }
    }

其中的mServices为ActiveServices的实例,ActiveServices为创建Serivice的工具类,负责把Service最终在对应的进程中启动。

下面就看下ActiveServices里面的几个方法是怎么把Service给创建出来的。

1.startServiceLocked()

进入到/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java中,简单的贴下startServiceLocked()里面的主要逻辑:

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
       //.......
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
    }
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;
    }

2.bringUpServiceLocked()

通过在ActiveServices中自身的方法调用,进入到bringUpServiceLocked()中,简单的代码逻辑如下:

 private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        //(1)如果该app已经创建好了该service,则直接返回
        if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }
        //.....
        if (!isolated) {
       //......
        //(2)如果该service不需要单独进程,运行在APP进程
            if (app != null && app.thread != null) {
                try {
                     //......
                    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) {
        //(3)该Service需要单独的进程
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingType, r.name, false, isolated, false)) == null) {
             //......
                return msg;
            }
 //......
        }
    //......
        return null;
    }

 这里会根据该Service是否需要单独的进程来决定调用realStartServiceLocked()还是mAm.startProcessLocked()来创建一个进程来启动该Service。

(1)realStartServiceLocked()创建APP进程的Service

简单的贴一点逻辑代码,如图:

private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        //.....
           app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
        //.....
 }

从代码中很容易的看到,这里已经调用到之前我们在 Android 跨进程通信-(三)Binder机制之Client提到的ActivityThread的维护的那个循环消息队列,此时调用到ActivityThread的scheduleCreateService(),然后将CREATE_SERVICE消息发送到该消息队列中。

进入到frameworks/base/core/java/android/app/ActivityThread.java简单到看下是怎么处理这个消息的,该消息对应的handleCreateService(),简单的代码逻辑如下:

 private void handleCreateService(CreateServiceData data) {
          //.....
        try {
           //.....
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            //执行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();
            }
        }
      //.....
    }

最终调用到 通过AMS调用到ActiveServices中的serviceDoneExecuting将Service在APP进程启动。

(2)在AMS中的startProcessLocked()创建Service进程

在AMS中最终通过方法调用到最下面的startProcessLocked(),最终就是调用Process.start()方法。

 private boolean startProcessLocked(String hostingType, String hostingNameStr, String entryPoint,
            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
            String seInfo, String requiredAbi, String instructionSet, String invokeWith,
            long startTime) {
             //......
        if (mConstants.FLAG_PROCESS_START_ASYNC) {
            if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
                    "Posting procStart msg for " + app.toShortString());
            mProcStartHandler.post(() -> {
                try {
                   //......
                    final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,
                            app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,
                            requiredAbi, instructionSet, invokeWith, app.startTime);
                      //......
    }

    private ProcessStartResult startProcess(String hostingType, String entryPoint,
            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
            String seInfo, String requiredAbi, String instructionSet, String invokeWith,
            long startTime) {
        try {
         //......
            else {
                startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith,
                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});
            }
            return startResult;
         //......
    }

进入到 /frameworks/base/core/java/android/os/Process.java中看下start()源码,简单的贴下逻辑:

 public static final ProcessStartResult start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int runtimeFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String invokeWith,
                                  String[] zygoteArgs) {
        return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
    }

具体实现的代码对应frameworks/base/core/java/android/os/ZygoteProcess.java的相对应的方法。这里不在多余去贴代码,其中的逻辑就是最终通过之前AMS与Zygote进程创建的socket通道,通知Zygote进程创建Service进程。那么当Zygote进程接收到创建进程的通知的时候,该方式同Android 跨进程通信-(三)Binder机制之Client中的3.APP进程的初始化。所以也就是解答了我之前在Android 跨进程通信-(三)Binder机制之Client中的疑问,创建APP进程和创建Server进程的方式都是一样的。


刚才说的是startService()的方式,下面在简单的总结下bindService()。

二 在Activity中调用bindService()

与在Activity调用startService()逻辑一样,最终会调用到 /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java的bindService(),简单逻辑代码如下:

   public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
            int userId) throws TransactionTooLargeException {
        //......
        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
    }

 同样也是借助ActiveServices将对应的Service在相应的进程中创建出来。

1.bindServiceLocked()

简单的贴下bindServiceLocked()里面的主要逻辑:

int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {
        //.....
        if (mAm.mPermissionReviewRequired) {
            if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                    s.packageName, s.userId)) {
                 //.....
                RemoteCallback callback = new RemoteCallback(
                        new RemoteCallback.OnResultListener() {
                    @Override
                    public void onResult(Bundle result) {
                        synchronized(mAm) {
                            final long identity = Binder.clearCallingIdentity();
                            try {
                              //.....
                                if (!mAm.getPackageManagerInternalLocked()
                                        .isPermissionsReviewRequired(
                                                serviceRecord.packageName,
                                                serviceRecord.userId)) {
                                    try {
                                        bringUpServiceLocked(serviceRecord,
                                                serviceIntent.getFlags(),
                                                callerFg, false, false);
                                    } 
                                    //.....
        }
        //.....
        if (s.app != null && b.intent.received) {
         // 这个就是在ServiceConnection的onServiceConnected()得到Server返回的IBinder对象
                try {
                    c.conn.connected(s.name, b.intent.binder, false);
                } catch (Exception e) {
                    Slog.w(TAG, "Failure sending service " + s.shortName
                            + " to connection " + c.conn.asBinder()
                            + " (in " + c.binding.client.processName + ")", e);
                }
              //.....
            if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                    requestServiceBindingLocked(s, b.intent, callerFg, true);
             }
         } else if (!b.intent.requested) {
                requestServiceBindingLocked(s, b.intent, callerFg, false);
        }

        return 1;
    }

同样也是通过bringUpServiceLocked()中,用来将Service在对应的进程中创建出来,只不过bindService()通过还需要有一个与bind过程,具体实现见requestServiceBindingLocked()

2.requestServiceBindingLocked()

因为这次主要是想看看Service进程是怎么创建出来的,所以剩下的过程requestServiceBindingLocked()通知ActivityThread的消息循环机制来处理的BIND_SERVICE完成最后的绑定,这里不在去介绍。

  private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        //......
        if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
            //......
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
            } 
        //......
        }
        return true;
    }

三 小结Service

通过源码简单分析了下Service是怎么创建出来的。

  • 1.在APP进程内的进程的Service:通过ActivityThread中的消息循环机制来将Service创建出来即可;
  • 2.单独进程的Service:通过AMS的startProcessLocked()来调用到Process.start(),通过之前AMS与Zygote进程建立的socke通道,通知Zygote进程创建一个新的进程;
  • 3.ActiveServices为创建Service的工具类,维护着Service的生命周期的相应方法。

四 总结

  • Service进程的创建和Activity的进程创建逻辑一致,因为都是AMS发出通知,Zygote进程的socket通信上收到创建进程的通知之后,创建进程

通过Android 跨进程通信-(二)Binder机制之ServiceManagerAndroid 跨进程通信-(三)Binder机制之Client以及本文总结,现在已经了解了Binder通信中的四个角色的进程是怎么创建出来的,那么在反过来去总结下三者的通信:见Android 跨进程通信-(五)Binder机制之一次拷贝的原理

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值