美文网首页Android
Android bindService 流程分析

Android bindService 流程分析

作者: 栖风渡 | 来源:发表于2020-04-10 18:27 被阅读0次

    进程间通信

    Binder是什么

    IPC间的通信机制。

    Binder.jpg

    什么时候需要进程间通信

    大图片加载 // 防止出现内存不够

    文件下载

    系统服务进程

    为什么要多进程

    Android进程内存使用有限制,因此需要使用开启新的进程来做一些占内存的其他工作,来保证主进程的正常运行。

    进程间通信为什么使用Binder

    Binder在性能和安全性之前达到了平衡

    Binder 共享内存 Socket
    性能 拷贝一次 无需拷贝 拷贝两次
    特点 基于S/C架构,易用性高 控制复杂易用性差 基于S/C架构,作为一款通用接口,传输效率低,开销大,速度低
    安全性 为每个APP分配UID,同时支持实名和匿名,通过Pid来进行访问控制 以来上层协议,访问控制不安全 以来上层协议,方位接入点开放,不安全

    Binder源码分析

    客户端为什么可以获得Binder

    Bindler绑定流程

    首先调用Context.bindService,代码走到ContextImpl中,调用ContextImpl.bindService,接着走到ComtextImpl.bindServiceCommon

     handler, UserHandle user) {
     // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
     ...........
     try {
     ...............
     // 最主要还是这一句
     int res = ActivityManager.getService().bindService(
     mMainThread.getApplicationThread(), getActivityToken(), service,
     service.resolveTypeIfNeeded(getContentResolver()),
     sd, flags, getOpPackageName(), user.getIdentifier());
     if (res < 0) {
     throw new SecurityException(
     "Not allowed to bind to service " + service);
     }
     return res != 0;
     } catch (RemoteException e) {
     throw e.rethrowFromSystemServer();
     }
     }
    

    // 这里实际上是调用IActivityManger.Proxy.bindService, 但是最终还是通过binder调用到ActivityManagerService.bindService, 因为ActivityManaagerService是IActivityManager.Stub的实现类

    接着分析 ** ActiityManager.getService().bindService **

    ActivityManager.getService().bindService(
     mMainThread.getApplicationThread(), getActivityToken(), service,
     service.resolveTypeIfNeeded(getContentResolver()),
    

    IActivityManager === ***.AIDL
    ActivityManager.getService() -------> IActivityManager.Stub.Proxy ---->ActivityManagerProxy

    IActivityManager.Stub -----------> ActivityManagerNative -------->(ActivityManagerService)

     public static IActivityManager getService() {
     return IActivityManagerSingleton.get();
     }
    ​
     private static final Singleton<IActivityManager> IActivityManagerSingleton =
     new Singleton<IActivityManager>() {
     @Override
     protected IActivityManager create() {
     final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
     // 获取对象ActivityManager.Stub.Proxy 对象
     final IActivityManager am = IActivityManager.Stub.asInterface(b);
     return am;
     }
     };
    

    //ActivityManagerNative 实际上就是IActivityManager.Stub的实现类, 因此看ActivityManagerNative的AasInterface方法。

    /**
    * Cast a Binder object into an activity manager interface, generating
    * a proxy if needed.
    *
    * @deprecated use IActivityManager.Stub.asInterface instead.
    */
    static public IActivityManager asInterface(IBinder obj) {
    return IActivityManager.Stub.asInterface(obj);
    }
    }
    

    // 但是实际的Proxy对象是谁呢 ? 答案就是:ActivityManagerProxy,通过IActiviytManager客户端的bindService方法,调用到IActivityManager的服务端ActivityManagerService的bindServcie方法。

    public int bindService(IApplicationThread caller, IBinder token, Intent service,
     String resolvedType, IServiceConnection connection, int flags, String callingPackage,
     int userId) throws TransactionTooLargeException {
     enforceNotIsolatedCaller("bindService");
    ​
     // Refuse possible leaked file descriptors
     if (service != null && service.hasFileDescriptors() == true) {
     throw new IllegalArgumentException("File descriptors passed in Intent");
     }
    ​
     if (callingPackage == null) {
     throw new IllegalArgumentException("callingPackage cannot be null");
     }
    ​
     synchronized(this) {
     return mServices.bindServiceLocked(caller, token, service,
     resolvedType, connection, flags, callingPackage, userId);
     }
     }
    

    这里的mServices实际上就是# ActivityServices #类

     int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
     String resolvedType, final IServiceConnection connection, int flags,
     String callingPackage, final int userId) throws TransactionTooLargeException {
     .........
     //这里最重要的还是两个方法:1\. bringUpServiceLocked
     if ((flags&Context.BIND_AUTO_CREATE) != 0) {
     s.lastActivity = SystemClock.uptimeMillis();
     if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
     permissionsReviewRequired) != null) {
     return 0;
     }
     }
    
     /// 然后说就是第二个  requestServiceBindingLocked
     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);
     }
    ​
     getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);
    ​
     } finally {
     Binder.restoreCallingIdentity(origId);
     }
    ​
     return 1;
     }
    

    A进程访问B进程

    1. B进程没有启动
    1. B进程启动,但是Service没有启动
    1. B进程启动,Service已经启动,但是没有被绑定,回调onBind
    1. B进程启动,Service已经起来,被绑定过,回调onRebind

    分析bringUpServiceLocked方法

    如果目标app已经启动,调用realStartServiceLocked 方法,在realStartServiceLocked中调用

    • app.thread.scheduleCreateService(r,r.serviceInfo,mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState);*

    ----------->ActivityServices.bringUpServiceLocked --------> ActivityServices.realStartServiceLocked ------> app.thread.scheduleCreateService( )[app.Thread = ActivityThread.ApplicationThread];------> ApplicationThread.scheduleCreateService()----->ApplicationThread.handleCreateService()

     boolean whileRestarting, boolean permissionsReviewRequired)
     throws TransactionTooLargeException {
     //Slog.i(TAG, "Bring up service:");
    
     /////////////////////
     if (!isolated) {
     app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
     if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
     + " app=" + app);
     ////////////////////如果app已经起来,直接调用realStartServiceLocked方法。
     if (app != null && app.thread != null) {
     try {
     app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
     // 这里主要调用了realStartService 这个方法
     realStartServiceLocked(r, app, execInFg);
     return null;
     } catch (TransactionTooLargeException e) {
     throw e;
     } catch (RemoteException e) {
     Slog.w(TAG, "Exception when starting service " + r.shortName, e);
     }
    ​
     // If a dead object exception was thrown -- fall through to
     // restart the application.
     }
     } else {
    
     .................. 
     如果APP没有启动
     if (app == null && !permissionsReviewRequired) {
     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;
     }
     if (isolated) {
     r.isolatedProc = app;
     }
     }
    ​
     ............
     return null;
     }
    

    A 流程 , 如果应用进程已经启动,但是目标Service没有启动查看方法 realStartServiceLocked

     ProcessRecord app, boolean execInFg) throws RemoteException {
     if (app.thread == null) {
     throw new RemoteException();
     }
    
     try {
     if (LOG_SERVICE_START_STOP) {
     String nameTerm;
     int lastPeriod = r.shortName.lastIndexOf('.');
     nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
     EventLogTags.writeAmCreateService(
     r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
     }
     synchronized (r.stats.getBatteryStats()) {
     r.stats.startLaunchedLocked();
     }
     mAm.notifyPackageUse(r.serviceInfo.packageName,
     PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
     app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
     // 调用ProcessRecord.ApplicationThread.shceduleCreateService. 
     app.thread.scheduleCreateService(r, r.serviceInfo,
     mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
     app.repProcState);
     r.postNotification();
     created = true;
     } catch (DeadObjectException e) {
     Slog.w(TAG, "Application dead when creating service " + r);
     mAm.appDiedLocked(app);
     throw e;
     } finally {
     }}
    

    ProcessRecord.ApplicationThread.shceduleCreateService

            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);
            }
    // 2  处理启动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 = packageInfo.getAppFactory()
                        .instantiateService(cl, data.info.name, data.intent);
            } catch (Exception e) {
                if (!mInstrumentation.onException(service, e)) {
                    throw new RuntimeException(
                        "Unable to instantiate service " + data.info.name
                        + ": " + e.toString(), e);
                }
            }
    
            try {
                if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
    
                ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
                context.setOuterContext(service);
                //  MakeApplication
                Application app = packageInfo.makeApplication(false, mInstrumentation);
                // 将Service和Context进行链接
                service.attach(context, this, data.info.name, data.token, app,
                        ActivityManager.getService());
                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) {
                if (!mInstrumentation.onException(service, e)) {
                    throw new RuntimeException(
                        "Unable to create service " + data.info.name
                        + ": " + e.toString(), e);
                }
            }
        }
    
    

    B 流程,APPProcess没有启动,Service也没有启动

    调用ActivityManagerService.startProcessLocked();

        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) {
                        .....
                            //  调用startProcess方法
                        final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,
                                app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,
                                requiredAbi, instructionSet, invokeWith, app.startTime);
                        synchronized (ActivityManagerService.this) {
                            handleProcessStartedLocked(app, startResult, startSeq);
                        }
                    } catch (RuntimeException e) {
                ......
    
            } else {
                try {
                    final ProcessStartResult startResult = startProcess(hostingType, entryPoint, app,
                            uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet,
                            invokeWith, startTime);
                    handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
                            startSeq, false);
                } catch (RuntimeException e) {
                    Slog.e(TAG, "Failure starting process " + app.processName, e);
                    app.pendingStart = false;
                    forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
                            false, false, true, false, false,
                            UserHandle.getUserId(app.userId), "start failure");
                }
                return app.pid > 0;
            }
        }
    

    //startProcess 方法

              ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
              String seInfo, String requiredAbi, String instructionSet, String invokeWith,
              long startTime) {
          try {
              Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                      app.processName);
              checkTime(startTime, "startProcess: asking zygote to start proc");
              final ProcessStartResult startResult;
              if (hostingType.equals("webview_service")) {
                  startResult = startWebView(entryPoint,
                          app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                          app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                          app.info.dataDir, null,
                          new String[] {PROC_START_SEQ_IDENT + app.startSeq});
              } else {
                  // 使用Process。start方法
                  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});
              }
              checkTime(startTime, "startProcess: returned from zygote!");
              return startResult;
          } finally {
              Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
          }
      }
    

    至此, app开始进入绑定流程。

    启动进入请求绑定app

                boolean execInFg, boolean rebind) throws TransactionTooLargeException {
            if (r.app == null || r.app.thread == null) {
                // If service is not currently running, can't yet bind.
                return false;
            }
            if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested
                    + " rebind=" + rebind);
            if ((!i.requested || rebind) && i.apps.size() > 0) {
                try {
                    bumpServiceExecutingLocked(r, execInFg, "bind");
                    r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
                    // 这里调用ApplicationThread的shceduleBindService
                    r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                            r.app.repProcState);
                    if (!rebind) {
                        i.requested = true;
                    }
                    i.hasBound = true;
                    i.doRebind = false;
                } catch (TransactionTooLargeException e) {
                    // Keep the executeNesting count accurate.
                    if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r, e);
                    final boolean inDestroying = mDestroyingServices.contains(r);
                    serviceDoneExecutingLocked(r, inDestroying, inDestroying);
                    throw e;
                } catch (RemoteException e) {
                    if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r);
                    // Keep the executeNesting count accurate.
                    final boolean inDestroying = mDestroyingServices.contains(r);
                    serviceDoneExecutingLocked(r, inDestroying, inDestroying);
                    return false;
                }
            }
            return true;
        }
    

    ApplicationThread

    scheduleBindService
    
     public final void scheduleBindService(IBinder token, Intent intent,
                    boolean rebind, int processState) {
                updateProcessState(processState, false);
                BindServiceData s = new BindServiceData();
                s.token = token;
                s.intent = intent;
                s.rebind = rebind;
    
                if (DEBUG_SERVICE)
                    Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
                            + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
                sendMessage(H.BIND_SERVICE, s);
            }
    
    ----------------------------------------
        handleBindService
            private void handleBindService(BindServiceData data) {
            Service s = mServices.get(data.token);
            if (DEBUG_SERVICE)
                Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
            if (s != null) {
                try {
                    data.intent.setExtrasClassLoader(s.getClassLoader());
                    data.intent.prepareToEnterProcess();
                    try {
                        if (!data.rebind) {
                            // 调用Service.onBinde, 获取binder 并进行返回
                            IBinder binder = s.onBind(data.intent);
                            ActivityManager.getService().publishService(
                                    data.token, data.intent, binder);
                        } else {
                            s.onRebind(data.intent);
                            ActivityManager.getService().serviceDoneExecuting(
                                    data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                        }
                        ensureJitEnabled();
                    } catch (RemoteException ex) {
                        throw ex.rethrowFromSystemServer();
                    }
                } catch (Exception e) {
                    if (!mInstrumentation.onException(s, e)) {
                        throw new RuntimeException(
                                "Unable to bind to service " + s
                                + " with " + data.intent + ": " + e.toString(), e);
                    }
                }
            }
        }
    

    ActivityManagerService.publishService

            // Refuse possible leaked file descriptors
            if (intent != null && intent.hasFileDescriptors() == true) {
                throw new IllegalArgumentException("File descriptors passed in Intent");
            }
    
            synchronized(this) {
                if (!(token instanceof ServiceRecord)) {
                    throw new IllegalArgumentException("Invalid service token");
                }
                mServices.publishServiceLocked((ServiceRecord)token, intent, service);
            }
        }
    
    

    以上代码走到ActivityServices.publishService

            final long origId = Binder.clearCallingIdentity();
            try {
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r
                        + " " + intent + ": " + service);
                if (r != null) {
                    Intent.FilterComparison filter
                            = new Intent.FilterComparison(intent);
                    IntentBindRecord b = r.bindings.get(filter);
                    if (b != null && !b.received) {
                        b.binder = service;
                        b.requested = true;
                        b.received = true;
                        for (int conni=r.connections.size()-1; conni>=0; conni--) {
                            ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
                            for (int i=0; i<clist.size(); i++) {
                                ConnectionRecord c = clist.get(i);
                                if (!filter.equals(c.binding.intent.intent)) {
                                    if (DEBUG_SERVICE) Slog.v(
                                            TAG_SERVICE, "Not publishing to: " + c);
                                    if (DEBUG_SERVICE) Slog.v(
                                            TAG_SERVICE, "Bound intent: " + c.binding.intent.intent);
                                    if (DEBUG_SERVICE) Slog.v(
                                            TAG_SERVICE, "Published intent: " + intent);
                                    continue;
                                }
                                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
                                try {
                                    c.conn.connected(r.name, service, false);
                                } catch (Exception e) {
                                    Slog.w(TAG, "Failure sending service " + r.name +
                                          " to connection " + c.conn.asBinder() +
                                          " (in " + c.binding.client.processName + ")", e);
                                }
                            }
                        }
                    }
    
                    serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
                }
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    

    调用c.conn.connected(r.name, service, false);

    conn = IServiceConnection.proxy -----------Stub = ServiceConnection
    

    这里就走到的ServiceConnection的onServiceConnect方法。

    相关文章

      网友评论

        本文标题:Android bindService 流程分析

        本文链接:https://www.haomeiwen.com/subject/snrdmhtx.html