使用bindService主要分两种情形:

1. Service的调用者client与Service在同一个App中;
2. Service的调用者client是App1中的一个Activity,而Service是App2中的Service,client与service分属两个App,这种情形下主要用于实现跨进程的通信。

bindService 的生命周期:

Service被绑定bindService()的时候调用onCreate()和onBind()方法,onStartCommand()方法不被被调用

这里写图片描述

 完整的客户端生命周期:onCreate() → onBind() → unbindService → onUnbind() → onDestroy()

bindService 源码分析

在这里插入图片描述

 相关类介绍

  • Instrumentation

用于实现应用程序测试代码的基类。当在打开仪器的情况下运行时,这个类将在任何应用程序代码之前为您实例化,允许您监视系统与应用程序的所有交互。可以通过AndroidManifest.xml的<Instrumentation>标签描述该类的实现。

  • ActivityManager

该类提供与Activity、Service和Process相关的信息以及交互方法, 可以被看作是ActivityManagerService的辅助类。

  • ActivityManagerService

Android中最核心的服务,主要负责系统中四大组件的启动、切换、调度及应用程序的管理和调度等工作。

  • ActivityThread

管理应用程序进程中主线程的执行,根据Activity管理者的请求调度和执行activities、broadcasts及其相关的操作。

  • frameworks/base/core/java/android/content/Context.java

抽象函数,具体的实现是在 子类中

    public abstract boolean bindService(@RequiresPermission Intent service,
            @NonNull ServiceConnection conn, @BindServiceFlags int flags);
  • frameworks/base/core/java/android/content/ContextWrapper.java
    public ContextWrapper(Context base) {
        mBase = base;
    }

    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        return mBase.bindService(service, conn, flags);
    }
  • frameworks/base/core/java/android/app/ContextImpl.java

可以看到 ContextWrapper类的bindService方法直接调用到 mBase.bindService方法,mBase其实就是ContextImpl实例,所以我们跟进去ContextImpl的bindService方法:

    @Override
    public boolean bindService(Intent service, ServiceConnection conn, int flags) {
        warnIfCallingFromSystemProcess();

// executor 为空
        return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,
                getUser());
    }

    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
            String instanceName, Handler handler, Executor executor, UserHandle user) {
        // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
        IServiceConnection sd;

// 前面对一些异常处理

        if (mPackageInfo != null) {
            if (executor != null) {

                sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
            } else {
// 1. 将 ServiceConnection对象转换成ServiceDispatcher.InnerConnection对象
                sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
            }
        } else {
            throw new RuntimeException("Not supported in system context");
        }

        validateServiceIntent(service);
        try {
            IBinder token = getActivityToken();
            if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
                    && mPackageInfo.getApplicationInfo().targetSdkVersion
                    < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                flags |= BIND_WAIVE_PRIORITY;
            }
// service 准备离开这个进程
            service.prepareToLeaveProcess(this);

// 2. binder 调用,最终调用到ActivityManagerService的bindIsolatedService方法
            int res = ActivityManager.getService().bindIsolatedService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, instanceName, 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();
        }
    }

获取 service 过程:

先看第一点:

1. 将 ServiceConnection对象转换成ServiceDispatcher.InnerConnection对象

-------------------------------------------------start-------------------------------------------------

mPackageInfo.getServiceDispatcher方法,将 ServiceConnection对象转换成ServiceDispatcher.InnerConnection对象

  • frameworks/base/core/java/android/app/LoadedApk.java
    public final IServiceConnection getServiceDispatcher(ServiceConnection c,
            Context context, Executor executor, int flags) {
        return getServiceDispatcherCommon(c, context, null, executor, flags);
    }

    private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,
            Context context, Handler handler, Executor executor, int flags) {
        synchronized (mServices) {
            LoadedApk.ServiceDispatcher sd = null;

// 存储了一个应用当前活动的 ServiceConnection和 ServiceDispatcher之间的映射关系
            ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
            if (map != null) {
                if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
                sd = map.get(c);
            }
            if (sd == null) {
                if (executor != null) {
                    sd = new ServiceDispatcher(c, context, executor, flags);
                } else {

// 这里创建一个 ServiceDispatcher
                    sd = new ServiceDispatcher(c, context, handler, flags);
                }
                if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
                if (map == null) {
                    map = new ArrayMap<>();
                    mServices.put(context, map);
                }
// 保存到 map 中
                map.put(c, sd);
            } else {
                sd.validate(context, handler, executor);
            }

// 通过 ServiceDispatcher 获取 IServiceConnection
            return sd.getIServiceConnection();
        }
    }

看下 ServiceDispatcher 的 构造方法:

在ServiceDispatcher的构造方法中,首先创建了InnerConnection对象,并赋值给它的成员变量mIServiceConnection,接着将ServiceConnection 对象conn赋值给成员变量mConnection ,将ActivityThread类中的Handler H mH赋值给mActivityThread 成员变量。

        private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
            = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();

        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        ServiceDispatcher(ServiceConnection conn,
                Context context, Handler activityThread, int flags) {

// 这里创建了 mIServiceConnection 
            mIServiceConnection = new InnerConnection(this);
            mConnection = conn;
            mContext = context;
            mActivityThread = activityThread;
            mActivityExecutor = null;
            mLocation = new ServiceConnectionLeaked(null);
            mLocation.fillInStackTrace();
            mFlags = flags;
        }

其中 sd.getIServiceConnection(),就是获取了 mIServiceConnection 对象

        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
        IServiceConnection getIServiceConnection() {
            return mIServiceConnection;
        }

InnerConnection为ServiceDispatcher中的静态内部类,继承自 IServiceConnection.Stub,很显然,它是一个binder对象。类似于ApplicationThread,InnerConnection中的方法是运行在客户端进程中的Binder线程池中的,它主要参与Service绑定后ServiceConnection 中onServiceConnected方法的回调过程。可以看到在InnerConnection的构造方法中只是对外部传入的ServiceDispatcher对象通过WeakReference做了一次封装,使得InnerConnection对象持有ServiceDispatcher对象的引用

        private static class InnerConnection extends IServiceConnection.Stub {
            @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
            final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;

            InnerConnection(LoadedApk.ServiceDispatcher sd) {
                mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
            }

            public void connected(ComponentName name, IBinder service, boolean dead)
                    throws RemoteException {
                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
                if (sd != null) {
                    sd.connected(name, service, dead);
                }
            }
        }

-------------------------------------------------end-------------------------------------------------

接下来继续:binder 调用,调用到ActivityManagerService的bindIsolatedService方法,而sd 作为参数继续往下走

  • frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
    final ActiveServices mServices;

    public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String instanceName,
            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");
        }

        // Ensure that instanceName, which is caller provided, does not contain
        // unusual characters.
        if (instanceName != null) {
            for (int i = 0; i < instanceName.length(); ++i) {
                char c = instanceName.charAt(i);
                if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
                            || (c >= '0' && c <= '9') || c == '_' || c == '.')) {
                    throw new IllegalArgumentException("Illegal instanceName");
                }
            }
        }

        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, instanceName, callingPackage, userId);
        }
    }
  • frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

调用ActiveServices的bindServiceLocked。
bindServiceLocked比较长我们只看关键部分。它的主要操作步骤如下。

int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
                      String resolvedType, final IServiceConnection connection, int flags,
                      String callingPackage, final int userId) throws TransactionTooLargeException {
    //…
    //1、首先会根据token找到其对应的ActivityRecord,ActivityRecord表示的是一个activity记录,此处指的是调用bindService的activity
    ActivityRecord activity = null;
    if (token != null) {
        activity = ActivityRecord.isInStackLocked(token);
        if (activity == null) {
            Slog.w(TAG, “Binding with unknown activity: “ + token);
            return 0;
        }
    }
    //…
    //2、调用retrieveServiceLocked解析传入的intent等参数获得一个ServiceRecord对象
// retrieveServiceLocked查找对应的service

    ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
                    Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
    ServiceRecord s = res.record;

    //...
    //3、把传入的connection封装成一个ConnectionRecord对象,connection就是步骤3获得的InnerConnection,
    // 因为后续AMS需要使用它来告诉activity service已经启动起来了,所以要把它保存起来,这里保存在好几个地方
    //AppBindRecord中存储了当前ServiceRecord, intent以及发起方的进程信息。
    AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
    ConnectionRecord c = new ConnectionRecord(b, activity,
                connection, flags, clientLabel, clientIntent);
    IBinder binder = connection.asBinder();
    ArrayList<ConnectionRecord> clist = s.connections.get(binder);
    if (clist == null) {
        clist = new ArrayList<ConnectionRecord>();
        s.connections.put(binder, clist);
    }
    // clist是ServiceRecord.connections的成员变量
    clist.add(c);
     //b是指AppBindRecord
    b.connections.add(c);
    if (activity != null) {
        if (activity.connections == null) {
            activity.connections = new HashSet<ConnectionRecord>();
        }
        activity.connections.add(c);
    }
    b.client.connections.add(c);

    //...
    //4、最初绑定service时传入的flag是BIND_AUTO_CREATE,所以此处符合条件进而调用bringUpServiceLocked启动要绑定的service
    if ((flags&Context.BIND_AUTO_CREATE) != 0) {
        s.lastActivity = SystemClock.uptimeMillis();
        if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                permissionsReviewRequired) != null) {
            return 0;
        }
    }
    //…
    if (s.app != null) {
            if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                s.app.treatLikeActivity = true;
            }
            //5、更新service所在进程的优先级
            mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities
                    || s.app.treatLikeActivity, b.client);
            mAm.updateOomAdjLocked(s.app);
        }

        if (s.app != null && b.intent.received) {
            try {
                //6、Service已经正在运行,则调用InnerConnection的代理对象
                c.conn.connected(s.name, b.intent.binder);
            } catch (Exception e) {
                ...
            }
            //7、当第一个app连接到该binding, 且之前已被bind过, 则回调onRebind()方法
            if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                requestServiceBindingLocked(s, b.intent, callerFg, true);
            }
        } else if (!b.intent.requested) {
            //8、最终回调onBind()方法
            requestServiceBindingLocked(s, b.intent, callerFg, false);
        }
    return 1;
}

bindServiceLocked做的事情比较多,我们再来梳理一下,首先在注释1处查找请求绑定的Activity是否存在,之后在注释2处通过retrieveServiceLocked查找对应的service。在注释3处创建AppBindRecord和ConnectionRecord,AppBindRecord记录着当前ServiceRecord, intent以及发起方的进程信息,ConnectionRecord则是对connection进行封装。创建完成后会把ConnectionRecord存到ServiceRecord和AppBindRecord中。注释4处通过bringUpServiceLocked来启动service,之后在注释5处更新service所在进程的优先级,在注释6处Service已经正在运行,调用InnerConnection的代理对象。注释7处判断是否回调onRebind方法。注释8处requestServiceBindingLocked最终回调onBind()方法。

4. bringUpServiceLocked启动要绑定的service

-------------------------------------------------start------------------------------------------------

    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen,
            boolean enqueueOomAdj)
            throws TransactionTooLargeException {
        if (r.app != null && r.app.getThread() != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }

-----

        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
        ProcessRecord app;

        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid);
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                        + " app=" + app);
            if (app != null) {
                final IApplicationThread thread = app.getThread();
                final int pid = app.getPid();
                final UidRecord uidRecord = app.getUidRecord();
                if (thread != null) {
                    try {
                        app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode,
                                mAm.mProcessStats);
// 重点代码--
                        realStartServiceLocked(r, app, thread, pid, uidRecord, execInFg,
                                enqueueOomAdj);
                        return null;
                    } catch (TransactionTooLargeException e) {
                        throw e;
                    } catch (RemoteException e) {
                        Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
                    }

                    // If a dead object exception was thrown -- fall through to
                    // restart the application.
                }
            }

service的启动最终是在realStartServiceLocked里

    private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
            IApplicationThread thread, int pid, UidRecord uidRecord, boolean execInFg,
            boolean enqueueOomAdj) throws RemoteException {
        if (thread == null) {
            throw new RemoteException();
        }
        if (DEBUG_MU)
            Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
                    + ", ProcessRecord.uid = " + app.uid);
        r.setProcess(app, thread, pid, uidRecord);
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

        final ProcessServiceRecord psr = app.mServices;
        final boolean newService = psr.startService(r);
        bumpServiceExecutingLocked(r, execInFg, "create", null /* oomAdjReason */);
        mAm.updateLruProcessLocked(app, false, null);
        updateServiceForegroundLocked(psr, /* oomAdj= */ false);
        // Force an immediate oomAdjUpdate, so the client app could be in the correct process state
        // before doing any service related transactions
        mAm.enqueueOomAdjTargetLocked(app);
        mAm.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);

// 记录是否呗创建
        boolean created = false;
        try {
            if (LOG_SERVICE_START_STOP) {
                String nameTerm;
                int lastPeriod = r.shortInstanceName.lastIndexOf('.');
                nameTerm = lastPeriod >= 0 ? r.shortInstanceName.substring(lastPeriod)
                        : r.shortInstanceName;
                EventLogTags.writeAmCreateService(
                        r.userId, System.identityHashCode(r), nameTerm, r.app.uid, pid);
            }

            final int uid = r.appInfo.uid;
            final String packageName = r.name.getPackageName();
            final String serviceName = r.name.getClassName();
            FrameworkStatsLog.write(FrameworkStatsLog.SERVICE_LAUNCH_REPORTED, uid, packageName,
                    serviceName);
            mAm.mBatteryStatsService.noteServiceStartLaunch(uid, packageName, serviceName);
            mAm.notifyPackageUse(r.serviceInfo.packageName,
                                 PackageManager.NOTIFY_PACKAGE_USE_SERVICE);

// 1.发起SystemServer进程到客户端进程的单向IPC操作,创建Service对象并调用其onCreate方法
            thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                    app.mState.getReportedProcState());
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app, "Died when creating service");
            throw e;
        } finally {
            if (!created) {
                // Keep the executeNesting count accurate.
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying, false);

                // Cleanup.
                if (newService) {
                    psr.stopService(r);
                    r.setProcess(null, null, 0, null);
                }

                // Retry.
                if (!inDestroying) {
                    scheduleServiceRestartLocked(r, false);
                }
            }
        }

        if (r.allowlistManager) {
            psr.mAllowlistManager = true;
        }

// 2.若当前Service的启动方式为bindService,则执行Service的绑定操作
        requestServiceBindingsLocked(r, execInFg);

        updateServiceClientActivitiesLocked(psr, null, true);

        if (newService && created) {
            psr.addBoundClientUidsOfNewService(r);
        }

// 3. 若当前Service的启动方式为startService,则新创建一个ServiceRecord.StartItem对象并添加到ServiceRecord对象 r的pendingStarts集合中
        // 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, 0));
        }

// 4.若当前Service的启动方式为startService,则回调当前Service对象的 onStartCommand方法
        sendServiceArgsLocked(r, execInFg, true);

        if (r.delayed) {
            if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);
            getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
            r.delayed = false;
        }

        if (r.delayedStop) {
            // Oh and hey we've already been asked to stop!
            r.delayedStop = false;
            if (r.startRequested) {
                if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
                        "Applying delayed stop (from start): " + r);
                stopServiceLocked(r, enqueueOomAdj);
            }
        }
    }

1 处,发起SystemServer进程到客户端进程的单向IPC操作,创建Service对象并调用其onCreate方法

由于当前Service的启动方式为bindService,所以3处if条件不满足,导致ServiceRecord r的pendingStarts集合为empty,之后4处调用到sendServiceArgsLocked方法,在 sendServiceArgsLocked方法内部获取到pendingStarts.size()为0直接return掉了,至此当前Service对象的 onStartCommand方法并不会被回调。这也就解释了我们通过bindService的方式启动Service,onStartCommand方法并不会被回调的原因。

thread.scheduleCreateService

  • frameworks/base/core/java/android/app/ActivityThread.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);
        }

        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {

                case CREATE_SERVICE:
                    if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                                ("serviceCreate: " + String.valueOf(msg.obj)));
                    }
                    handleCreateService((CreateServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;

    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 {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);

            Application app = packageInfo.makeApplication(false, mInstrumentation);

            final java.lang.ClassLoader cl;
            if (data.info.splitName != null) {
                cl = packageInfo.getSplitClassLoader(data.info.splitName);
            } else {
                cl = packageInfo.getClassLoader();
            }
// 通过反射获取到 service 对象
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);

// 获取 context
            ContextImpl context = ContextImpl.getImpl(service
                    .createServiceBaseContext(this, packageInfo));
            if (data.info.splitName != null) {
                context = (ContextImpl) context.createContextForSplit(data.info.splitName);
            }
            if (data.info.attributionTags != null && data.info.attributionTags.length > 0) {
                final String attributionTag = data.info.attributionTags[0];
                context = (ContextImpl) context.createAttributionContext(attributionTag);
            }
            // Service resources must be initialized with the same loaders as the application
            // context.
            context.getResources().addLoaders(
                    app.getResources().getLoaders().toArray(new ResourcesLoader[0]));

            context.setOuterContext(service);
// 与 context 绑定
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
// 回调 onCreate 方法
            service.onCreate();
            mServicesData.put(data.token, data);
            mServices.put(data.token, service);
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }

在binder线程通过Hander(mH)给主线程发送消息,让主线程来处理,mH接收到CREATE_SERVICE的消息,调用handleCreateService()来处理

函数中通过获取ClassLoader反射创建了Service对象(与Activity的创建方式一致),并绑定context,执行onCreate()的生命周期方法

继续往下走,走到 Service的绑定操作 requestServiceBindingsLocked

    private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
            throws TransactionTooLargeException {
        for (int i=r.bindings.size()-1; i>=0; i--) {
            IntentBindRecord ibr = r.bindings.valueAt(i);
            if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
                break;
            }
        }
    }

当我们通过bindService的方式启动Service时,会对ServiceRecord r.bindings集合进行put操作,这样子就导致r.bindings.size()不为0,会调用到for循环中的 requestServiceBindingLocked方法,而当我们通过startService的方式启动Service时,r.bindings.size()为0,for循环条件不满足直接退出。这也就解释了我们通过StartService的方式启动Service时,Service的onBind方法不会回调的原因。

    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        if (r.app == null || r.app.getThread() == 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 {
//发送bind开始的消息
                bumpServiceExecutingLocked(r, execInFg, "bind",
                        OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);

// 调用 ActivityThread 的私有类,去绑定服务
                r.app.getThread().scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.mState.getReportedProcState());
                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, false);
                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, false);
                return false;
            }
        }
        return true;
    }
  • frameworks/base/core/java/android/app/ActivityThread.java
    private class ApplicationThread extends IApplicationThread.Stub {

        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);
        }

                case BIND_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
                    handleBindService((BindServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;


    private void handleBindService(BindServiceData data) {
        CreateServiceData createData = mServicesData.get(data.token);
        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(isProtectedComponent(createData.info),
                        s.getAttributionSource());
                try {
// 如果不是重新绑定的话
                    if (!data.rebind) {
// 回调 service 的onBind 方法
                        IBinder binder = s.onBind(data.intent);
// 把 获取的binder(即onBind的返回值)传递给AMS
                        ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    } else {
                        s.onRebind(data.intent);
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                } 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);
                }
            }
        }
    }

进去AMS的publishService方法:

  • frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
    public void publishService(IBinder token, Intent intent, IBinder service) {
        // 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);
        }
    }
  • frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        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;
                    ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
                    for (int conni = connections.size() - 1; conni >= 0; conni--) {
// 从ServiceRecord.connections中取出ConnectionRecord
                        ArrayList<ConnectionRecord> clist = 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 {
// 回调 connected 方法,上面代码有讲过
                                c.conn.connected(r.name, service, false);
                            } catch (Exception e) {
                                Slog.w(TAG, "Failure sending service " + r.shortInstanceName
                                      + " to connection " + c.conn.asBinder()
                                      + " (in " + c.binding.client.processName + ")", e);
                            }
                        }
                    }
                }

                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false, false);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }
  • frameworks/base/core/java/android/app/LoadedApk.java
        private static class InnerConnection extends IServiceConnection.Stub {
            @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
            final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;

            InnerConnection(LoadedApk.ServiceDispatcher sd) {
                mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
            }

            public void connected(ComponentName name, IBinder service, boolean dead)
                    throws RemoteException {
                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
                if (sd != null) {
                    sd.connected(name, service, dead);
                }
            }
        }
        private final Handler mActivityThread;

       public void connected(ComponentName name, IBinder service, boolean dead) {
            if (mActivityExecutor != null) {
                mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
            } else if (mActivityThread != null) {
// 走到主线程操作
                mActivityThread.post(new RunConnection(name, service, 0, dead));
            } else {
                doConnected(name, service, dead);
            }
        }

此处的mActivityThread就是主线程的Handler,通过该Handler post消息。

        private final class RunConnection implements Runnable {
            RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
                mName = name;
                mService = service;
                mCommand = command;
                mDead = dead;
            }

            public void run() {
                if (mCommand == 0) {
                    doConnected(mName, mService, mDead);
                } else if (mCommand == 1) {
                    doDeath(mName, mService);
                }
            }

            final ComponentName mName;
            final IBinder mService;
            final int mCommand;
            final boolean mDead;
        }

        public void doConnected(ComponentName name, IBinder service, boolean dead) {
            ServiceDispatcher.ConnectionInfo old;
            ServiceDispatcher.ConnectionInfo info;

            synchronized (this) {
                if (mForgotten) {
                    // We unbound before receiving the connection; ignore
                    // any connection received.
                    return;
                }
                old = mActiveConnections.get(name);
                if (old != null && old.binder == service) {
                    // Huh, already have this one.  Oh well!
                    return;
                }

                if (service != null) {
                    // A new service is being connected... set it all up.
                    info = new ConnectionInfo();
                    info.binder = service;
                    info.deathMonitor = new DeathMonitor(name, service);
                    try {
//建立死亡通知
                        service.linkToDeath(info.deathMonitor, 0);
                        mActiveConnections.put(name, info);
                    } catch (RemoteException e) {
                        // This service was dead before we got it...  just
                        // don't do anything with it.
                        mActiveConnections.remove(name);
                        return;
                    }

                } else {
                    // The named service is being disconnected... clean up.
                    mActiveConnections.remove(name);
                }

                if (old != null) {
                    old.binder.unlinkToDeath(old.deathMonitor, 0);
                }
            }

            // If there was an old service, it is now disconnected.
            if (old != null) {
                mConnection.onServiceDisconnected(name);
            }
            if (dead) {
                mConnection.onBindingDied(name);
            } else {
                // If there is a new viable service, it is now connected.
                if (service != null) {
// 回调onServiceConnected,至此我们就在绑定端的onServiceConnected回调函数中拿到service返回的binder了
                    mConnection.onServiceConnected(name, service);
                } else {
                    // The binding machinery worked, but the remote returned null from onBind().
                    mConnection.onNullBinding(name);
                }
            }
        }

可以看到在doConnected方法的最后调用到了ServiceConnection的onServiceConnected方法。

-------------------------------------------------end-------------------------------------------------

至此bindService的过程就结束了,总结来整个过程大概分为以下几步:
1、首先调用bindService通知AMS绑定service,AMS会先启动service回调其onCreate函数。
2、AMS启动service完成之后继续调用service的onBind函数,获取service返回的binder。
3、AMS把上一步获得的Binder对象通过绑定时传入的ServiceConnection的onServiceConnected函数传给调用端,这样调用端就可以通过binder来调用service提供的相关方法。

  1. Client进程: 通过getServiceDispatcher获取Client进程的匿名Binder服务端,即LoadedApk.ServiceDispatcher.InnerConnection,该对象继承于IServiceConnection.Stub; 再通过bindService调用到system_server进程;
  2. system_server进程: 依次通过scheduleCreateService和scheduleBindService方法, 远程调用到target进程;
  3. target进程: 依次执行onCreate()和onBind()方法; 将onBind()方法的返回值IBinder(作为target进程的binder服务端)通过publishService传递到system_server进程;
  4. system_server进程: 利用IServiceConnection代理对象向Client进程发起connected()调用, 并把target进程的onBind返回Binder对象的代理端传递到Client进程;
  5. Client进程: 回调到onServiceConnection()方法, 该方法的第二个参数便是target进程的binder代理端. 到此便成功地拿到了target进程的代理, 可以畅通无阻地进行交互.

 参考:

1. Service启动流程分析

2. bindService源码解析

3. bindService流程源码分析

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐