AMS : bind service 分析

810 阅读10分钟

案例

从 Android O 开始,start service 是有限制的,即不允许启动后台 app 的 Service。但是对于 bind service 而言,是没有这个限制的。官方文档的原话如下

These rules don't affect bound services in any way. If your app defines a bound service, other components can bind to that service whether or not your app is in the foreground.

因此,我选择分析的案例如下

  1. 一个宿主 App。宿主进程没有启动,并且它有一个可以被绑定的 Service。
  2. 一个客户端 App。在 MainActivity 中 bind 宿主 App 的 Service。

具体代码,本文就不展示了,因为一个入门的 Android 开发,都会写这个代码。

本文基于 Android 14 代码分析。

客户端发起 bind service

客户端发起 bind service 会调用如下代码

// ContextImpl.java

// 参数 flags 的值一般为 Context.BIND_AUTO_CREATE
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
    warnIfCallingFromSystemProcess();
    return bindServiceCommon(service, conn, Integer.toUnsignedLong(flags), null,
            mMainThread.getHandler(), null, getUser());
}

private boolean bindServiceCommon(Intent service, ServiceConnection conn, long flags,
        String instanceName, Handler handler, Executor executor, UserHandle user) {
    // 1. 获取一个注册给服务端的 service 链接
    // 它是一个 Binder
    IServiceConnection sd;
    if (conn == null) {
        throw new IllegalArgumentException("connection is null");
    }
    if (handler != null && executor != null) {
        throw new IllegalArgumentException("Handler and Executor both supplied");
    }
    if (mPackageInfo != null) {
        if (executor != null) {
            // ...
        } else {
            // LoadedApk 中创建 ServiceDispatcher,并从这个对象中,
            // 获取注册给服务端的 service 链接
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        }
    } else {
        throw new RuntimeException("Not supported in system context");
    }
    
    // Intent 必须明确指明 Service 的 ComponentName 或者 package
    validateServiceIntent(service);
    
    try {
        // 获取 activity token,目前是从 activity 发起 bind service
        // 因此,这里是可以成功获取到 activity token
        IBinder token = getActivityToken();
        if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
                && mPackageInfo.getApplicationInfo().targetSdkVersion
                < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            // ...
        }
        
        service.prepareToLeaveProcess(this);
        
        // 2.向服务端发起 bind service
        int res = ActivityManager.getService().bindServiceInstance(
                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);
        }
        
        // 这里的判断条件是有问题的,只有返回 1 才表示正在拉起 service
        // 其实还可以返回 -1 和 0,这都是有问题的情况
        return res != 0;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

客户端 bind service 的过程如下

  1. 获取一个注册给服务端的 service 链接。ServiceConnection 不是一个 Binder,无法注册给服务,因此这里利用 IServiceConnection.aidl 创建一个 Binder 并注册给服务端,用于接收 Service 连接状态的回调。参考【创建注册给服务端的 service 链接
  2. 向服务端发起 bind service 请求。

创建注册给服务端的 service 链接

来看下注册给服务端的 service 链接,是如何创建的

// LoadedApk.java

public final IServiceConnection getServiceDispatcher(ServiceConnection c,
        Context context, Handler handler, long flags) {
    return getServiceDispatcherCommon(c, context, handler, null, flags);
}

private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,
        Context context, Handler handler, Executor executor, long flags) {
    synchronized (mServices) {
        LoadedApk.ServiceDispatcher sd = null;
        
        // 1. 以 ServiceConnection 为 KEY,从缓存 mServices 获取 ServiceDispatcher
        ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
        if (map != null) {
            // ...
        }
              
        // 2. 缓存中没有获取到,那就创建一个 ServiceDispatcher,并缓存
        if (sd == null) {
            if (executor != null) {
                // ...
            } else {
                // 创建 service 链接
                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.put(c, sd);
        } else {
            // ...
        }
        
        // 3. 从 ServiceDispatcher 获取注册给服务端的 service 链接
        return sd.getIServiceConnection();
    }
}

假设在 MainActivity 中是第一次发起 bind service,那么缓存中是没有记录的,因此只能先创建 ServiceDispatcher,然后缓存它,最后从 ServiceDispatcher 中获取注册给服务端的 service 链接。

现在来看下,从 ServiceDispatcher 获取的 service 链接,到底是什么

static final class ServiceDispatcher {
    private final ServiceDispatcher.InnerConnection mIServiceConnection;

    private final ServiceConnection mConnection;
    
    private static class InnerConnection extends IServiceConnection.Stub {
        // ...
    }
    
    ServiceDispatcher(ServiceConnection conn,
            Context context, Handler activityThread, long flags) {
        // 这是一个 Binder,传递给服务端的 service 链接
        mIServiceConnection = new InnerConnection(this);
        
        // 这是 App 端创建的 ServiceConnection 对象
        mConnection = conn;
        
        // ..
        
        mFlags = flags;
    }   
    
    // 返回 Binder ,代表服务端的 service 链接
    IServiceConnection getIServiceConnection() {
        return mIServiceConnection;
    } 
}

从 ServiceDispatcher 中获取的 service 链接,确实是一个 Binder,并且是根据 IServiceConnection.aidl 创建的 Binder。

用一个流程图,展示服务端如何通知客户端 service 的连接状态的

graph TD
system_server --> mIServiceConnection.aidl
mIServiceConnection.aidl --> InnerConnection
InnerConnection --> ServiceDispatcher
ServiceDispatcher --> ServiceConnection

服务端处理 bind service

// ActivityManagerService.java

public int bindService(IApplicationThread caller, IBinder token, Intent service,
        String resolvedType, IServiceConnection connection, long flags,
        String callingPackage, int userId) throws TransactionTooLargeException {
    return bindServiceInstance(caller, token, service, resolvedType, connection, flags,
            null, callingPackage, userId);
}

public int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,
        String resolvedType, IServiceConnection connection, long flags, String instanceName,
        String callingPackage, int userId) throws TransactionTooLargeException {
    return bindServiceInstance(caller, token, service, resolvedType, connection, flags,
            instanceName, false, INVALID_UID, null, null, callingPackage, userId);
}

private int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,
        String resolvedType, IServiceConnection connection, long flags, String instanceName,
        boolean isSdkSandboxService, int sdkSandboxClientAppUid,
        String sdkSandboxClientAppPackage,
        IApplicationThread sdkSandboxClientApplicationThread,
        String callingPackage, int userId)
        throws TransactionTooLargeException {
    // ...

    try {
        if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
            final ComponentName cn = service.getComponent();
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindService:"
                    + (cn != null ? cn.toShortString() : service.getAction()));
        }
        synchronized (this) {
            // 交给 ActiveService 处理
            return mServices.bindServiceLocked(caller, token, service, resolvedType, connection,
                    flags, instanceName, isSdkSandboxService, sdkSandboxClientAppUid,
                    sdkSandboxClientAppPackage, sdkSandboxClientApplicationThread,
                    callingPackage, userId);
        }
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
}

在服务端,Service 的事务,统一交给 ActiveServices 处理的

// ActiveServices.java

int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
        String resolvedType, final IServiceConnection connection, long flags,
        String instanceName, boolean isSdkSandboxService, int sdkSandboxClientAppUid,
        String sdkSandboxClientAppPackage, IApplicationThread sdkSandboxClientApplicationThread,
        String callingPackage, final int userId)
        throws TransactionTooLargeException {
    if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
            + " type=" + resolvedType + " conn=" + connection.asBinder()
            + " flags=0x" + Long.toHexString(flags));
    final int callingPid = Binder.getCallingPid();
    final int callingUid = Binder.getCallingUid();

    // 获取客户端进程
    final ProcessRecord callerApp = mAm.getRecordForAppLOSP(caller);
    if (callerApp == null) {
        throw new SecurityException(
                "Unable to find app for caller " + caller
                + " (pid=" + callingPid
                + ") when binding service " + service);
    }

    ActivityServiceConnectionsHolder<ConnectionRecord> activity = null;
    if (token != null) {
        // 获取 activity 用来管理 service 链接的对象
        // 其实就是获取 ActivityRecord#mServiceConnectionsHolder,用来管理 activity 的所有 service connection
        activity = mAm.mAtmInternal.getServiceConnectionsHolder(token);
        if (activity == null) {
            Slog.w(TAG, "Binding with unknown activity: " + token);
            return 0;
        }
    }

    int clientLabel = 0;
    PendingIntent clientIntent = null;
    // 目前是三方app发起的 bind service,不是系统app
    final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID;

    if (isCallerSystem) {
        // ...
    }

    // ...

    // 检测客户端进程是否处于前台
    final boolean callerFg = callerApp.mState.getSetSchedGroup()
            != ProcessList.SCHED_GROUP_BACKGROUND;
    // 一下几个变量都为 false
    final boolean isBindExternal =
            (flags & Integer.toUnsignedLong(Context.BIND_EXTERNAL_SERVICE)) != 0
            || (flags & Context.BIND_EXTERNAL_SERVICE_LONG) != 0;
    final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0;
    final boolean inSharedIsolatedProcess = (flags & Context.BIND_SHARED_ISOLATED_PROCESS) != 0;

    ProcessRecord attributedApp = null;
    if (sdkSandboxClientAppUid > 0) {
        // ...
    }

    // 1. 从服务端缓存中获取 ServiceRecord,如果没有,就创建并缓存。
    ServiceLookupResult res = retrieveServiceLocked(service, instanceName,
            isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage,
            resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg,
            isBindExternal, allowInstant, null /* fgsDelegateOptions */,
            inSharedIsolatedProcess);
    if (res == null) {
        return 0;
    }
    if (res.record == null) {
        return -1;
    }
    // ServiceRecord 在服务端代表一个 Service
    ServiceRecord s = res.record;


    // 建立绑定关系的数据结构
    final AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp, attributedApp);

    // 这里获取的其实 ProcessRecord#mServices,是客户端进程用来保存 service 信息,例如保存客户端进程发起的所有 service 链接
    final ProcessServiceRecord clientPsr = b.client.mServices;
    
    // ...

    final long origId = Binder.clearCallingIdentity();

    try {
        // ...

        // 2.创建一个服务端的 service 链接,并用数据结构保存
        ConnectionRecord c = new ConnectionRecord(b, activity,
                connection, flags, clientLabel, clientIntent,
                callerApp.uid, callerApp.processName, callingPackage, res.aliasComponent);
        IBinder binder = connection.asBinder();
        // ServiceRecord#connections 建立客户端链接到服务端链接的映射
        s.addConnection(binder, c);
        // AppBindRecord#connections 保存链接
        // AppBindRecord 代表 app 端与 service 的绑定记录
        b.connections.add(c);
        if (activity != null) {
            // ActivityRecord#mServiceConnectionsHolder 保存链接
            activity.addConnection(c);
        }
        // 客户端进程 ProcessRecord#mServices 保存链接
        clientPsr.addConnection(c);
        c.startAssociationIfNeeded();

        // ...

        // 由于客户端可以通过一个链接来 bind 多个 service,因此服务端,需要建立一对多的关系
        // mServiceConnections: IBinder -> ArrayList<ConnectionRecord>
        ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
        if (clist == null) {
            clist = new ArrayList<>();
            mServiceConnections.put(binder, clist);
        }
        clist.add(c);

        boolean needOomAdj = false;
        if (c.hasFlag(Context.BIND_AUTO_CREATE)) {
            s.lastActivity = SystemClock.uptimeMillis();
            needOomAdj = true;
            // 3.尝试拉起 service,但是由于宿主进程还没有创建,因此得先创建进程,那么这里就返回 null
            if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                    permissionsReviewRequired, packageFrozen, true) != null) {
                mAm.updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_BIND_SERVICE);
                return 0;
            }
        }

        setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, s, userId,
                BackgroundStartPrivileges.NONE, true /* isBindService */,
                false /* isStartService */);

        if (s.app != null) {
            // ...
        }
        if (needOomAdj) {
            mAm.updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_BIND_SERVICE);
        }

        // ...

        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
                + ": received=" + b.intent.received
                + " apps=" + b.intent.apps.size()
                + " doRebind=" + b.intent.doRebind);

        if (s.app != null && b.intent.received) {
            // ...
        } else if (!b.intent.requested) {
            // 4。由于进程还在创建中,因此这里不能发起 bind service
            requestServiceBindingLocked(s, b.intent, callerFg, false);
        }

        maybeLogBindCrossProfileService(userId, callingPackage, callerApp.info.uid);

        getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);

    } finally {
        Binder.restoreCallingIdentity(origId);
    }

    notifyBindingServiceEventLocked(callerApp, callingPackage);

    return 1;
}

ActiveServices 处理 bind service 过程

  1. 从服务端缓存中获取 ServiceRecord,如果没有,就创建并缓存。参考【获取 service 数据】
  2. 创建一个 service 链接 ServiceConnection,并用相应的数据结构保存。参考【建立 service 链接关系图】
  3. 尝试拉起 Service,但是由于宿主进程还没有创建,因此不能直接拉起 Service,而是需要先创建进程。等进程起来后,在 attach application 的过程中,再拉起 Service。参考【尝试拉起 service】
  4. 由于 Service 还没有被拉起,因此不能执行 bind service 请求。

获取 service 数据

private ServiceLookupResult retrieveServiceLocked(Intent service,
        String instanceName, boolean isSdkSandboxService, int sdkSandboxClientAppUid,
        String sdkSandboxClientAppPackage, String resolvedType,
        String callingPackage, int callingPid, int callingUid, int userId,
        boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
        boolean allowInstant, ForegroundServiceDelegationOptions fgsDelegateOptions,
        boolean inSharedIsolatedProcess) {
    // ...

    ServiceRecord r = null;
    if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "retrieveServiceLocked: " + service
            + " type=" + resolvedType + " callingUid=" + callingUid);

    userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId,
            /* allowAll= */false, getAllowMode(service, callingPackage),
            /* name= */ "service", callingPackage);

    // 从 mServiceMap 中根据 userId 获取 ServiceMap
    // 假设 service 在服务端没有任何数据记录
    ServiceMap smap = getServiceMapLocked(userId);

    // Intent 中可能指定了一个 service 别名,这里就是解析别名,然后把别名和真名保存到 Resolution
    final ComponentAliasResolver.Resolution<ComponentName> resolution =
            mAm.mComponentAliasResolver.resolveService(service, resolvedType,
                    /* match flags */ 0, userId, callingUid);

    final ComponentName comp;
    if (instanceName == null) {
        // 获取 Intent 指定的 ComponentName
        // 有可能 Intent 没有制定 ComponentName 而是指定 package
        // 我们假设 Intent 中指定的是 ComponentName
        comp = service.getComponent();
    } else {
        // ...
    }

    if (comp != null) {
        // null
        r = smap.mServicesByInstanceName.get(comp);
        
        if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by component: " + r);
    }
    
    if (r == null && !isBindExternal && instanceName == null) {
        // 使用 Intent 创建一个包装类 FilterComparison,作为保存数据时的 KEY 值
        Intent.FilterComparison filter = new Intent.FilterComparison(service);
       
        // null
        r = smap.mServicesByIntent.get(filter);
        if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by intent: " + r);
    }
    
    if (r != null) {
        // ...
    }

    // fgsDelegateOptions 此时为 null
    if (r == null && fgsDelegateOptions != null) {
        // ...
    }

    if (r == null) {
        try {
            int flags = ActivityManagerService.STOCK_PM_FLAGS
                    | PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
            if (allowInstant) {
                // ...
            }
            
            // 从 PKMS 查询 service 信息
            ResolveInfo rInfo = mAm.getPackageManagerInternal().resolveService(service,
                    resolvedType, flags, userId, callingUid);
            ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null;
            if (sInfo == null) {
                Slog.w(TAG_SERVICE, "Unable to start service " + service + " U=" + userId +
                      ": not found");
                return null;
            }
            
            // ...

            // 由于 Intent 可能没有制定 ComponentName,因此这里确保得到 ComponentName
            ComponentName className = new ComponentName(sInfo.applicationInfo.packageName,
                                                        sInfo.name);
            ComponentName name = comp != null ? comp : className;
            
            if (!mAm.validateAssociationAllowedLocked(callingPackage, callingUid,
                    name.getPackageName(), sInfo.applicationInfo.uid)) {
                String msg = "association not allowed between packages "
                        + callingPackage + " and " + name.getPackageName();
                Slog.w(TAG, "Service lookup failed: " + msg);
                return new ServiceLookupResult(msg);
            }

            // Store the defining packageName and uid, as they might be changed in
            // the ApplicationInfo for external services (which run with the package name
            // and uid of the caller).
            String definingPackageName = sInfo.applicationInfo.packageName;
            int definingUid = sInfo.applicationInfo.uid;
            if ((sInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0) {
                // ...
            } else if (isBindExternal) {
                // ...
            }
            
            if (inSharedIsolatedProcess) {
                // ...
            }
            
            if (userId > 0) {
                // 不分析单例 service
                if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
                        sInfo.name, sInfo.flags)
                        && mAm.isValidSingletonCall(callingUid, sInfo.applicationInfo.uid)) {
                    // ...
                }
                
                sInfo = new ServiceInfo(sInfo);
                sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
            }
            
            // null
            r = smap.mServicesByInstanceName.get(name);
            
            if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE,
                    "Retrieved via pm by intent: " + r);
            
            // 参数 createIfNeeded 为 true,表示找不到 service 数据就创建
            if (r == null && createIfNeeded) {
                final Intent.FilterComparison filter
                        = new Intent.FilterComparison(service.cloneFilter());
                final ServiceRestarter res = new ServiceRestarter();
                String processName = getProcessNameForService(sInfo, name, callingPackage,
                        instanceName, isSdkSandboxService, inSharedIsolatedProcess);
                
                // 1.创建 service 记录
                r = new ServiceRecord(mAm, className, name, definingPackageName,
                        definingUid, filter, sInfo, callingFromFg, res,
                        processName, sdkSandboxClientAppUid,
                        sdkSandboxClientAppPackage, inSharedIsolatedProcess);
                res.setService(r);
                
                // 2.用数据结构保存
                smap.mServicesByInstanceName.put(name, r);
                smap.mServicesByIntent.put(filter, r);

                for (int i=mPendingServices.size()-1; i>=0; i--) {
                    // ...
                }
                for (int i = mPendingBringups.size() - 1; i >= 0; i--) {
                    // ...
                }
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Retrieve created new service: " + r);
            }
        } catch (RemoteException ex) {
            // pm is in same process, this will never happen.
        }
    }
    
    // 此时已经创建了 service 记录,因此 r 不为 null
    if (r != null) {
        // 向 ServiceRecord 中填充数据
        r.mRecentCallingPackage = callingPackage;
        r.mRecentCallingUid = callingUid;
        try {
            r.mRecentCallerApplicationInfo =
                    mAm.mContext.getPackageManager().getApplicationInfoAsUser(callingPackage,
                            0, UserHandle.getUserId(callingUid));
        } catch (PackageManager.NameNotFoundException e) {
        }
        
        // ... 省略权限检查代码...
        
        r.appInfo.seInfo += generateAdditionalSeInfoFromService(service);
        
        // 3.把数据包装成 ServiceLookupResult 返回
        return new ServiceLookupResult(r, resolution.getAlias());
    }
    return null;
}

假设服务端还没有为 Service 建立数据,那么只能先创建记录 ServiceRecord,然后缓存。

使用的数据结构的类关系图,如下

classDiagram

ServiceMap *-- ActiveServices
ServiceRecord *-- ServiceMap

class ServiceRecord {
~Intent.FilterComparison intent
~ServiceInfo serviceInfo
}

class ActiveServices {
~SparseArray< userId, ServiceMap> mServiceMap
}

class ServiceMap {
~ArrayMap< ComponentName, ServiceRecord> mServicesByInstanceName
~ArrayMap< Intent.FilterComparison, ServiceRecord> mServicesByIntent
}

建立 service 链接关系图

Service 链接的关系图如下

classDiagram

IntentBindRecord *-- ServiceRecord
AppBindRecord *-- IntentBindRecord
ProcessServiceRecord *-- ProcessRecord
ProcessRecord *-- IntentBindRecord
ActivityServiceConnectionsHolder *-- ActivityRecord
ConnectionRecord *-- ProcessServiceRecord
ConnectionRecord *-- AppBindRecord
ConnectionRecord *-- ServiceRecord
ConnectionRecord *-- ActivityServiceConnectionsHolder
ConnectionRecord *-- ActiveService

class ActivityRecord {
~ActivityServiceConnectionsHolder mServiceConnectionsHolder
}

class ServiceRecord {
~ArrayMap< Intent.FilterComparison, IntentBindRecord> bindings
~ArrayMap< IBinder, ArrayList< ConnectionRecord>> connections
}

class IntentBindRecord {
~ArrayMap< ProcessRecord, AppBindRecord> apps
}

class AppBindRecord {
~ServiceRecord service
~IntentBindRecord intent
~ProcessRecord client
~ArraySet< ConnectionRecord> connections
}

class ProcessRecord {
~ProcessServiceRecord mServices
}

class ProcessServiceRecord{
-ArraySet< ConnectionRecord> mConnections
}

class ConnectionRecord{
~AppBindRecord binding
~ActivityServiceConnectionsHolder< ConnectionRecord> activity
~IServiceConnection conn
}

class ActivityServiceConnectionsHolder {
-ArraySet< ConnectionRecord> mConnections
}

class ActiveService {
~ArrayMap< IBinder, ArrayList< ConnectionRecord>> mServiceConnections
}

尝试拉起 service

private String bringUpServiceInnerLocked(ServiceRecord r, int intentFlags, boolean execInFg,
        boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen,
        boolean enqueueOomAdj)
        throws TransactionTooLargeException {
    if (r.app != null && r.app.getThread() != null) {
        // ...
    }

    if (!whileRestarting && mRestartingServices.contains(r)) {
        // ...
    }

    if (DEBUG_SERVICE) {
        Slog.v(TAG_SERVICE, "Bringing up " + r + " " + r.intent + " fg=" + r.fgRequired);
    }

    if (mRestartingServices.remove(r)) {
        // ...
    }

    if (r.delayed) {
        // ...
    }

    if (!mAm.mUserController.hasStartedUserState(r.userId)) {
        // ...
    }

    // Report usage if binding is from a different package except for explicitly exempted
    // bindings
    if (!r.appInfo.packageName.equals(r.mRecentCallingPackage)
            && !r.isNotAppComponentUsage) {
        mAm.mUsageStatsService.reportEvent(
                r.packageName, r.userId, UsageEvents.Event.APP_COMPONENT_USED);
    }

    // Service is now being launched, its package can't be stopped.
    try {
        mAm.mPackageManagerInt.setPackageStoppedState(
                r.packageName, false, r.userId);
    } catch (IllegalArgumentException e) {
        Slog.w(TAG, "Failed trying to unstop package "
                + r.packageName + ": " + e);
    }

    // isolated 为 false
    final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
    final String procName = r.processName;
    HostingRecord hostingRecord = new HostingRecord(
            HostingRecord.HOSTING_TYPE_SERVICE, r.instanceName,
            r.definingPackageName, r.definingUid, r.serviceInfo.processName,
            getHostingRecordTriggerType(r));
    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) {
            // ...
        }
    } else {
        // ...
    }

    if (app == null && !permissionsReviewRequired && !packageFrozen) {
        if (r.isSdkSandbox) {
            // ...
        } else {
            // 1.创建 service 宿主进程
            app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated);
        }
        
        // ...
    }

    if (r.fgRequired) {
        // ...
    }

    // 2.mPendingServices 保存还没有被绑定的 service
    if (!mPendingServices.contains(r)) {
        mPendingServices.add(r);
    }

    if (r.delayedStop) {
        // ...
    }

    return null;
}

由于宿主进程还没有创建,因此无法拉起 service,只能先创建进程,然后用 ActiveService#mPendingServices 保存要绑定的 service。

创建宿主进程

进程创建后,会执行 App 的入口函数 ActivityThread#main(),然后会执行 ActivityThread#attach()

// ActivityThread.java

private void attach(boolean system, long startSeq) {
    // ...

    if (!system) {
        // ...
        
        final IActivityManager mgr = ActivityManager.getService();
        try {
            // attach application
            mgr.attachApplication(mAppThread, startSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
        // ...
    } else {
        // ...
    }

    // ...
}

App 进程在创建的时候,会向服务端注册一个代表 App 的 Binder,这就是 attach application。

服务端 attach application

现在来看下服务端 attach application 过程中关于处理 service 的代码

    private void attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {

        // ...
        
        try {
            // ...

            if (!mConstants.mEnableWaitForFinishAttachApplication) {
                finishAttachApplicationInner(startSeq, callingUid, pid);
            } else {
                // ...
            }
        } catch (Exception e) {
            // ...
        }
    }
    
    
    private void finishAttachApplicationInner(long startSeq, int uid, int pid) {
        // ...

        synchronized (this) {

            // ...

            // Find any services that should be running in this process...
            if (!badApp) {
                try {
                    // 启动那些等待宿主进程的 service
                    didSomething |= mServices.attachApplicationLocked(app, processName);
                    checkTime(startTime, "finishAttachApplicationInner: "
                            + "after mServices.attachApplicationLocked");
                } catch (Exception e) {
                    // ...
                }
            }

            // ...
        }
    }    

服务端在处理 attach application 过程中,对于 service 的处理,最终是由 ActiveServices#attachApplicationLocked() 完成,如下

// ActiveService.java

    boolean attachApplicationLocked(ProcessRecord proc, String processName)
            throws RemoteException {
        // ...

        // Collect any services that are waiting for this process to come up.
        if (mPendingServices.size() > 0) {
            ServiceRecord sr = null;
            try {
                // mPendingServices 保存了等待进程起来的 service
                for (int i=0; i<mPendingServices.size(); i++) {
                    sr = mPendingServices.get(i);
                    
                    // ...
                    try {
                        // ...
                        
                        // 创建并绑定service
                        realStartServiceLocked(sr, proc, thread, pid, uidRecord, sr.createdFromFg,
                                true);
                    }
                    
                    // ...
                }
            } catch (RemoteException e) {
                //...
            }
        }
        
        // ...
    }

ActiveServices#realStartServiceLocked() 才是真正的拉起 Service 的地方,并且会根据情况去相应执行 start service 和 bind service

// ActiveService.java

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

    // 通知 app 创建 service 前,ServiceRecord 才与进程 ProcessRecord 关联
    r.setProcess(app, thread, pid, uidRecord);
    r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

    final ProcessServiceRecord psr = app.mServices;
    // ProcessServiceRecord#mServices 保存已经启动的 service
    final boolean newService = psr.startService(r);

    // 发送一个超时消息,等待 service 创建完成
    bumpServiceExecutingLocked(r, execInFg, "create",
            OOM_ADJ_REASON_NONE /* use "none" to avoid extra oom adj */);

    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, 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;

            // 创建 service 的 event log: am_create_service
            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.通知 app 端创建 service
        thread.scheduleCreateService(r, r.serviceInfo,
                null /* compatInfo (unused but need to keep method signature) */,
                app.mState.getReportedProcState());
        r.postNotification(false);
        created = true;
    } catch (DeadObjectException e) {
        // ...
    } finally {
        if (!created) {
            // ...
        }
    }

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

    // 2.通知 app 端执行 bind service
    requestServiceBindingsLocked(r, execInFg);

    updateServiceClientActivitiesLocked(psr, null, true);

    if (newService && created) {
        // ProcessServiceRecord#mBoundClientUids 保存 bind service 的客户端 uid
        psr.addBoundClientUidsOfNewService(r);
    }

    // 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) {
        // ...
    }

    // 发送参数给 service 执行任务,这就是 start service 的实现
    sendServiceArgsLocked(r, execInFg, true);

    if (r.delayed) {
        // ...
    }

    if (r.delayedStop) {
        // ...
    }
}

服务端实现 bind service 其实只有两步,一是通知 app 端去创建 Service,app 端会创建 Service 对象,并调用 Service#onCreate(),然后服务端执行 bind service 请求。

服务端处理 bind service 请求的的原理,也就是通知 app 端去执行 bind service,代码如下

// ActiveServices.java

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
        boolean execInFg, boolean rebind) throws TransactionTooLargeException {
    if (r.app == null || r.app.getThread() == null) {
        // ...
    }
    
    if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested
            + " rebind=" + rebind);
    
    if ((!i.requested || rebind) && i.apps.size() > 0) {
        try {
            // create service 时已经发送了超时消息,这里不会再发送了
            bumpServiceExecutingLocked(r, execInFg, "bind", OOM_ADJ_REASON_BIND_SERVICE);
            
            if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                Trace.instant(Trace.TRACE_TAG_ACTIVITY_MANAGER, "requestServiceBinding="
                        + i.intent.getIntent() + ". bindSeq=" + mBindServiceSeqCounter);
            }

            // 通知 app 端 bind service
            r.app.getThread().scheduleBindService(r, i.intent.getIntent(), rebind,
                    r.app.mState.getReportedProcState(), mBindServiceSeqCounter++);
            
            if (!rebind) {
                i.requested = true;
            }
            i.hasBound = true;
            i.doRebind = false;
        } catch (TransactionTooLargeException e) {
            // ...
        } catch (RemoteException e) {
            // ...
        }
    }
    return true;
}

宿主进程创建 Service

服务端已经向 app 端发起了两个请求,一个是 create service,一个是 bind service。

首先看下 app 端是如何处理 create service

// ActivityThread.java

    private class ApplicationThread extends IApplicationThread.Stub {
        public final void scheduleCreateService(IBinder token,
                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
            updateProcessState(processState, false);
            
            // 数据包装成 CreateServiceData
            CreateServiceData s = new CreateServiceData();
            s.token = token;
            s.info = info;
            
            // 通过主线程 Handler 执行 create service
            sendMessage(H.CREATE_SERVICE, s);
        }    
    }
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();

    final LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo);
    Service service = null;
    try {
        if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);

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

        final java.lang.ClassLoader cl;
        if (data.info.splitName != null) {
            cl = packageInfo.getSplitClassLoader(data.info.splitName);
        } else {
            cl = packageInfo.getClassLoader();
        }

        // 1.通过反射创建 Service 对象
        service = packageInfo.getAppFactory()
                .instantiateService(cl, data.info.name, data.intent);
        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);

        // 2.service attach
        // Service 对象保存相关的数据,例如 Context,服务端 service token
        service.attach(context, this, data.info.name, data.token, app,
                ActivityManager.getService());
        if (!service.isUiContext()) { // WindowProviderService is a UI Context.
            VirtualDeviceManager vdm = context.getSystemService(VirtualDeviceManager.class);
            if (mLastReportedDeviceId == Context.DEVICE_ID_DEFAULT
                    || vdm.isValidVirtualDeviceId(mLastReportedDeviceId)) {
                service.updateDeviceId(mLastReportedDeviceId);
            }
        }

        // 3.调用 Service#onCreate() 方法
        service.onCreate();

        // 4.保存 service 数据
        // ArrayMap<IBinder, CreateServiceData> mServicesData : 服务端 service -> 服务端 service 数据
        mServicesData.put(data.token, data);
        // ArrayMap<IBinder, Service> mServices : 服务端 service -> app 端 service
        mServices.put(data.token, service);

        try {
            // 5.通知服务端 service create 完成
            // 最后两个参数,对于 bind service 没用,对 start service 才有用
            ActivityManager.getService().serviceDoneExecuting(
                    data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    } catch (Exception e) {
        // ...
    }
}

app 端是在主线程中处理 create service 请求的,过程如下

  1. 通过反射创建 Service 对象。
  2. 执行 service attach,其实就是在 Service 对象中保存 Service 相关信息。
  3. 调用 Service#onCreate()
  4. ArrayMap<IBinder, CreateServiceData> mServicesData 以 service token 为 KEY,保存了服务端传入的 Service 数据,ArrayMap<IBinder, Service> mServices 以 service token 为 KEY,保存了 app 端创建的 Service 对象。
  5. 通知服务端 create service 执行完毕。注意,第二个参数 type 的值为 SERVICE_DONE_EXECUTING_ANON,

服务端收到 app 端 create service 执行完成的消息后,没有作出实质性的动作,简单看下代码即可

// ActivityManagerService.java

public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
    synchronized(this) {
        if (!(token instanceof ServiceRecord)) {
            Slog.e(TAG, "serviceDoneExecuting: Invalid service token=" + token);
            throw new IllegalArgumentException("Invalid service token");
        }
        // 交个 ActiveServices 处理
        mServices.serviceDoneExecutingLocked((ServiceRecord) token, type, startId, res, false);
    }
}
// ActiveServices.java

void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res,
        boolean enqueueOomAdj) {
    boolean inDestroying = mDestroyingServices.contains(r);
    if (r != null) {
        if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {
            // ...
        } else if (type == ActivityThread.SERVICE_DONE_EXECUTING_STOP) {
            // ...
        }
        
        final long origId = Binder.clearCallingIdentity();
        serviceDoneExecutingLocked(r, inDestroying, inDestroying, enqueueOomAdj,
                OOM_ADJ_REASON_EXECUTING_SERVICE);
        Binder.restoreCallingIdentity(origId);
    } else {
        Slog.w(TAG, "Done executing unknown service from pid "
                + Binder.getCallingPid());
    }
}


private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
        boolean finishing, boolean enqueueOomAdj, @OomAdjReason int oomAdjReason) {
    if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "<<< DONE EXECUTING " + r
            + ": nesting=" + r.executeNesting
            + ", inDestroying=" + inDestroying + ", app=" + r.app);
    else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
            "<<< DONE EXECUTING " + r.shortInstanceName);
    
    // 服务端通知 app 端 create service 和 bind service 前,都对 executeNesting 加 1
    // 因此,当前 executeNesting 的值为2
    r.executeNesting--;
    if (r.executeNesting <= 0) {
        // ...
    }
}

宿主进程 bind service

刚才已经分析了 app 端处理 create service 请求,其实就是创建 Service 对象,并调用 Service#onCreate(),现在看下 app 端如何处理 bind service 请求

// ActivityThread.java

    private class ApplicationThread extends IApplicationThread.Stub {
        
        public final void scheduleBindService(IBinder token, Intent intent,
                boolean rebind, int processState, long bindSeq) {
            updateProcessState(processState, false);
            
            // bind service 数据包装为 BindServiceData
            BindServiceData s = new BindServiceData();
            s.token = token;
            s.intent = intent;
            s.rebind = rebind;
            s.bindSeq = bindSeq;

            if (DEBUG_SERVICE)
                Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
                        + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
            
            // 主线程 Handler 中执行 bind service
            // 最终调用 handleBindService()
            sendMessage(H.BIND_SERVICE, s);
        }    
    }
    
    private void handleBindService(BindServiceData data) {
        CreateServiceData createData = mServicesData.get(data.token);
        
        // 1.在 create service 时,mServices 保存过创建的 Service 对象
        // 因此获取到是已经执行 onCreate() 的 Service
        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) {
                        // 2.执行 Service#onBind() 
                        // 注意,参数 intent,不再客户端 bindService() 传入的 Intent 参数
                        // 因此宿主进程的 Service 在执行 onBind() 时,是获取不到客户端在 Intent 中参数
                        IBinder binder = s.onBind(data.intent);
                        
                        // 3. 把 Service#onBind() 返回的 Binder 对象,发布给服务端
                        ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    } else {
                        // ...
                    }
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            } catch (Exception e) {
                // ...
            }
        }
    }    

同样地,app 端受到 bind service 请求后,也是在主线程中执行的,这就保证了 app 端一定会先执行 create service,再执行 bind service。

看下 bind service 过程

  1. 首先从 mServices 中获取 Service 对象。 处理 create service 时,mServices 就保存了 Service 对象,因此这里是可以取出来的。
  2. 执行 Service#onBind()。
  3. 把 Service#onBind() 返回的 Binder 对象发布给服务端。

OK,那么接下来看下服务端如何处理 app 端发布的 Binder

// ActivityManagerService.java

public void publishService(IBinder token, Intent intent, IBinder service) {
    // ...

    synchronized(this) {
        // ...
        
        mServices.publishServiceLocked((ServiceRecord)token, intent, service);
    }
}
// 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) {
                // 1.IntentBindRecord#binder 保存了宿主 Service#onBind() 返回的 Binder
                b.binder = service;
                b.requested = true;
                b.received = true;
                // 遍历 ServiceRecord 中保存的所有链接
                ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
                for (int conni = connections.size() - 1; conni >= 0; conni--) {
                    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)) {
                            // ...
                            continue;
                        }
                        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
                        // If what the client try to start/connect was an alias, then we need to
                        // pass the alias component name instead to the client.
                        final ComponentName clientSideComponentName =
                                c.aliasComponent != null ? c.aliasComponent : r.name;
                        try {
                            // 2.通过客户端注册的 service 链接,通知 service 已经绑定成功
                            // 并把 Service#onBind() 返回的 Binder 返回给客户端
                            c.conn.connected(clientSideComponentName, service, false);
                        } catch (Exception e) {
                            Slog.w(TAG, "Failure sending service " + r.shortInstanceName
                                  + " to connection " + c.conn.asBinder()
                                  + " (in " + c.binding.client.processName + ")", e);
                        }
                    }
                }
            }

            // 3.处理 service 生命周期执行完毕
            // 此时 Service#onBind() 已经执行完毕,没有其他生命周期需要执行,因此会移除超时消息
            serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false, false,
                    OOM_ADJ_REASON_EXECUTING_SERVICE);
        }
    } finally {
        Binder.restoreCallingIdentity(origId);
    }
}

服务端处理 app 端发布的 Binder

  1. 利用 IntentBindRecord#binder 保存 app 端发布的 Binder。
  2. 遍历所有的 service 链接,然后通过链接通知 app 端 service 已经成功连接,并传给客户端 Service#onBinde() 返回的 Binder,客户端就可以通过这个 Binder 来与宿主端 Service 通信。这个链接的类型是 IServiceConnection,就是 app 注册的 Binder。至于 app 端如何处理,请参考前面章节的【创建注册给服务端的 Service 链接
  3. 处理 bind service 执行完成,主要是清除 service 超时消息和 update oom adj。

下面简单看下第3步,有个印象即可

// ActiveServices.java

private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
        boolean finishing, boolean enqueueOomAdj, @OomAdjReason int oomAdjReason) {
    if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "<<< DONE EXECUTING " + r
            + ": nesting=" + r.executeNesting
            + ", inDestroying=" + inDestroying + ", app=" + r.app);
    else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
            "<<< DONE EXECUTING " + r.shortInstanceName);
    
    r.executeNesting--;
    if (r.executeNesting <= 0) {
        if (r.app != null) {
            final ProcessServiceRecord psr = r.app.mServices;
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
                    "Nesting at 0 of " + r.shortInstanceName);
            psr.setExecServicesFg(false);
            psr.stopExecutingService(r);
            if (psr.numberOfExecutingServices() == 0) {
                if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
                        "No more executingServices of " + r.shortInstanceName);
                mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
            } else if (r.executeFg) {
                // ...
            }
            
            if (inDestroying) {
                // ...
            }
            
            if (enqueueOomAdj) {
                // ...
            } else {
                mAm.updateOomAdjLocked(r.app, oomAdjReason);
            }
        }
        
        // Service 所有生命周期都执行完毕,那么 Service 的宿主进程不需要在前台执行了
        r.executeFg = false;
        
        if (r.tracker != null) {
            synchronized (mAm.mProcessStats.mLock) {
                final int memFactor = mAm.mProcessStats.getMemFactorLocked();
                final long now = SystemClock.uptimeMillis();
                r.tracker.setExecuting(false, memFactor, now);
                r.tracker.setForeground(false, memFactor, now);
                if (finishing) {
                    // ...
                }
            }
        }
        if (finishing) {
            // ...
        }
    }
}

时序图

第一幅时序图是客户端发起 bind service,以及服务端处理 bind service,最终的结果是服务端创建宿主进程

1.jpg

第二幅时序图是宿主进程创建后,向服务端发起 attach app,服务端通知宿主create Service,并且 bind service,宿主进程会创建 Service,然后调用它的 onCreate() 和 onBind(),最后发布 Bind 给服务端,而服务端会通知客户端 Service 成功连接

2.jpg

TODO

其实 Bind Service 还有一些内容是值得细讲的,例如对进程优先级的影响,又例如 Service 超时机制。如果后面有时间,再细讲。