Android bindService 流程分析

进程间通信

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 IActivityManagerSingleton =
 new Singleton() {
 @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 clist = r.connections.valueAt(conni);
                        for (int i=0; i

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

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

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

你可能感兴趣的:(Android bindService 流程分析)