首页 > 其他分享 >Android Framework AMS(09)service组件分析-3(bindService和unbindService关键流程分析)

Android Framework AMS(09)service组件分析-3(bindService和unbindService关键流程分析)

时间:2024-10-17 23:20:59浏览次数:3  
标签:服务 bindService service unbindService app 绑定 false null

该系列文章总纲链接:专题总纲目录 Android Framework 总纲


本章关键点总结 & 说明:

说明:上上一章节主要解读应用层service组件启动的2种方式startService和bindService,以及从APP层到AMS调用之间的打通。上一章节我们关注了service组件启动方式的一种:startService启动方式。本章节主要关注service组件启动方式的另一种:bindService启动方式,分析关键API为service组件的bindService和unbindService方法。

我们从AMS.bindService和AMS.unbindService分别来分析,分析的主要流程为:

  • AMS.bindService->service组件onCreate、onBind
  • AMS.unbindService->service组件onUnBind、onDestroy

接下来开始详细解读。

1 AMS.bindService流程解读(onCreate、onBind)

AMS.bindService代码实现如下:

//ActivityManagerService
    public int bindService(IApplicationThread caller, IBinder token,
                Intent service, String resolvedType,
                IServiceConnection connection, int flags, int userId) {
            // 检查调用者是否是隔离的进程,如果不是,则抛出安全异常
            enforceNotIsolatedCaller("bindService");
            //...
            synchronized(this) {
                return mServices.bindServiceLocked(caller, token, service, resolvedType,
                        connection, flags, userId);
            }
        }

这里调用了ActivityService的bindServiceLocked方法,代码实现如下:

//ActivityService
    //关键流程:step1
    int bindServiceLocked(IApplicationThread caller, IBinder token,
            Intent service, String resolvedType,
            IServiceConnection connection, int flags, int userId) {
        // 获取请求绑定服务的客户端应用记录
        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
        //...

        // 如果token不为空,尝试获取对应的Activity记录
        ActivityRecord activity = null;
        if (token != null) {
            activity = ActivityRecord.isInStackLocked(token);
            //...
        }

        // 获取客户端为服务绑定设置的标签和PendingIntent
        int clientLabel = 0;
        PendingIntent clientIntent = null;

        // 如果调用者是系统进程,尝试获取客户端Intent和标签
        if (callerApp.info.uid == Process.SYSTEM_UID) {
            try {
                clientIntent = service.getParcelableExtra(Intent.EXTRA_CLIENT_INTENT);
            } catch (RuntimeException e) {
            }
            if (clientIntent != null) {
                clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
                if (clientLabel != 0) {
                    // 如果设置了客户端标签,创建一个新的Intent用于服务绑定
                    service = service.cloneFilter();
                }
            }
        }

        // 如果设置了BIND_TREAT_LIKE_ACTIVITY标志,检查调用者是否有MANAGE_ACTIVITY_STACKS权限
        if ((flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
            mAm.enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
                    "BIND_TREAT_LIKE_ACTIVITY");
        }

        // 判断调用者是否在前台运行
        final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;

        // 查找服务记录
        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType,
                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);
        // 如果服务记录为空或未找到服务,返回0或-1
        if (res == null) {
            return 0;
        }
        if (res.record == null) {
            return -1;
        }
        ServiceRecord s = res.record;

        // 清除调用者的身份信息,以便在操作过程中不泄露调用者的信息
        final long origId = Binder.clearCallingIdentity();

        try {
            // 如果服务需要重启,取消重启计划
            if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {}

            // 如果设置了BIND_AUTO_CREATE标志,更新服务最后活跃的时间
            if ((flags & Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                if (!s.hasAutoCreateConnections()) {
                    ProcessStats.ServiceState stracker = s.getTracker();
                    if (stracker != null) {
                        stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(),
                                s.lastActivity);
                    }
                }
            }

            // 启动与服务的关联
            mAm.startAssociationLocked(callerApp.uid, callerApp.processName,
                    s.appInfo.uid, s.name, s.processName);

            // 检索服务的应用绑定记录
            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
            // 创建新的连接记录
            ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent);

            // 获取连接的Binder
            IBinder binder = connection.asBinder();
            // 获取服务的连接列表
            ArrayList<ConnectionRecord> clist = s.connections.get(binder);
            if (clist == null) {
                clist = new ArrayList<ConnectionRecord>();
                s.connections.put(binder, clist);
            }
            // 将连接记录添加到服务的连接列表中
            clist.add(c);
            b.connections.add(c);
            // 如果有Activity记录,将其添加到Activity的连接列表中
            if (activity != null) {
                if (activity.connections == null) {
                    activity.connections = new HashSet<ConnectionRecord>();
                }
                activity.connections.add(c);
            }
            b.client.connections.add(c);
            // 如果设置了BIND_ABOVE_CLIENT标志,标记客户端有高于自身的服务绑定
            if ((c.flags & Context.BIND_ABOVE_CLIENT) != 0) {
                b.client.hasAboveClient = true;
            }
            // 如果服务的应用记录不为空,更新服务的客户端活动
            if (s.app != null) {
                updateServiceClientActivitiesLocked(s.app, c, true);
            }
            // 获取全局服务连接列表
            clist = mServiceConnections.get(binder);
            if (clist == null) {
                clist = new ArrayList<ConnectionRecord>();
                mServiceConnections.put(binder, clist);
            }
            clist.add(c);

            // 如果设置了BIND_AUTO_CREATE标志,启动服务
            if ((flags & Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                //关键方法:拉起服务
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {
                    return 0;
                }
            }

            // 如果服务的应用记录不为空,根据标志更新服务的属性
            if (s.app != null) {
                if ((flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                    s.app.treatLikeActivity = true;
                }
                // 更新服务的最近最少使用状态和内存调整
                mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities
                        || s.app.treatLikeActivity, b.client);
                mAm.updateOomAdjLocked(s.app);
            }

            // 如果服务的应用记录不为空且Intent已接收,连接客户端
            if (s.app != null && b.intent.received) {
                try {
                    c.conn.connected(s.name, b.intent.binder);
                } catch (Exception e) {
                    // 异常处理代码...
                }

                // 如果Intent只有一个绑定且需要重新绑定,请求服务绑定
                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                    requestServiceBindingLocked(s, b.intent, callerFg, true);
                }
            } else if (!b.intent.requested) {
                // 如果Intent未请求,请求服务绑定
                requestServiceBindingLocked(s, b.intent, callerFg, false);
            }

            // 确保服务不在启动的后台服务列表中
            getServiceMap(s.userId).ensureNotStartingBackground(s);

        } finally {
            // 恢复调用者的身份信息
            Binder.restoreCallingIdentity(origId);
        }

        // 返回1表示服务绑定成功
        return 1;
    }
   //关键流程:step2
    private final String bringUpServiceLocked(ServiceRecord r,
            int intentFlags, boolean execInFg, boolean whileRestarting) {

        // 如果服务的应用记录不为空且应用线程不为空,说明服务已经在运行,直接发送服务参数
        if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }

        // 如果服务不在重启中,并且重启延迟时间大于0,则不启动服务
        if (!whileRestarting && r.restartDelay > 0) {
            return null;
        }

        // 如果服务在重启中,从重启服务列表中移除该服务
        if (mRestartingServices.remove(r)) {
            clearRestartingIfNeededLocked(r);
        }

        // 如果服务是延迟启动的,从延迟启动列表中移除该服务,并设置服务不再延迟
        if (r.delayed) {
            getServiceMap(r.userId).mDelayedStartList.remove(r);
            r.delayed = false;
        }

        // 如果用户未启动,关闭服务并返回
        if (mAm.mStartedUsers.get(r.userId) == null) {
            bringDownServiceLocked(r);
            return msg;
        }

        try {
            // 设置包停止状态为非停止状态
            AppGlobals.getPackageManager().setPackageStoppedState(
                    r.packageName, false, r.userId);
        } catch (RemoteException e) {
            //...
        }

        // 判断服务是否运行在隔离进程中
        final boolean isolated = (r.serviceInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        ProcessRecord app;

        // 如果服务不在隔离进程中,尝试获取已有的进程记录
        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            // 如果进程记录不为空且进程线程不为空,尝试添加包并启动服务
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                    //关键方法:实际启动服务
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (RemoteException e) {
                    //...
                }
            }
        } else {
            // 如果服务运行在隔离进程中,尝试获取隔离进程记录
            app = r.isolatedProc;
        }

        // 如果进程记录为空,尝试启动新进程
        if (app == null) {
            if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    "service", r.name, false, isolated, false)) == null) {
                bringDownServiceLocked(r);
                return msg;
            }
            // 如果服务运行在隔离进程中,保存隔离进程记录
            if (isolated) {
                r.isolatedProc = app;
            }
        }

        // 如果服务不在待处理列表中,添加到待处理列表
        if (!mPendingServices.contains(r)) {
            mPendingServices.add(r);
        }

        // 如果服务已经请求停止,取消停止请求
        if (r.delayedStop) {
            r.delayedStop = false;
            if (r.startRequested) {
                stopServiceLocked(r);
            }
        }
        return null;
    }
    //关键流程:step3
    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        // 如果进程记录的应用线程为空,抛出远程异常
        if (app.thread == null) {
            throw new RemoteException();
        }
        // 设置服务的应用记录
        r.app = app;
        // 更新服务的最后活动时间和重启时间
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

        // 将服务添加到应用的服务体系表中
        app.services.add(r);
        // 增加服务执行的计数,并根据是否在前台执行来更新状态
        bumpServiceExecutingLocked(r, execInFg, "create");
        // 更新进程的最近最少使用(LRU)状态
        mAm.updateLruProcessLocked(app, false, null);
        // 更新内存调整
        mAm.updateOomAdjLocked();

        boolean created = false;
        try {
            // 同步电池统计数据的更新
            synchronized (r.stats.getBatteryStats()) {
                r.stats.startLaunchedLocked();
            }
            // 确保包的dex文件已经优化
            mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
            // 强制进程状态至少为服务状态
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            // 关键方法:通过应用线程调度服务的创建
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            r.postNotification();
            // 标记服务已创建
            created = true;
        } catch (DeadObjectException e) {
            //...
        } finally {
            // 如果服务未创建成功,进行清理操作
            if (!created) {
                app.services.remove(r);
                r.app = null;
                // 安排服务重启
                scheduleServiceRestartLocked(r, false);
                return;
            }
        }

        // 请求服务的绑定
        requestServiceBindingsLocked(r, execInFg);
        // 更新服务客户端活动
        updateServiceClientActivitiesLocked(app, null, true);
        // 如果服务请求启动并且需要调用 onStartCommand,添加一个启动项
        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),null, null));
        }

        // 发送服务参数,回调执行 onStartCommand
        sendServiceArgsLocked(r, execInFg, true);

        // 如果服务是延迟启动的,从延迟启动列表中移除
        if (r.delayed) {
            getServiceMap(r.userId).mDelayedStartList.remove(r);
            r.delayed = false;
        }

        // 如果服务已经请求延迟停止,取消延迟停止请求
        if (r.delayedStop) {
            r.delayedStop = false;
            if (r.startRequested) {
                stopServiceLocked(r);
            }
        }
    }

这一条调用关系线下来,从调用关系上依次为:

  

  1.   bindServiceLocked 
  2. bringUpServiceLocked
  3. realStartServiceLocked  

  

最后的realStartServiceLocked才是实际启动服务的方法,主要作用是确保服务在正确的进程中被创建和启动。它涉及到与应用程序线程的通信,服务状态的更新,以及服务生命周期的管理。代码中的scheduleCreateService方法用于请求应用程序线程创建服务,requestServiceBindingsLocked方法用于请求服务的绑定。到这里我们主要关注2个关键方法:

  • scheduleCreateService(调用service的onCreate)
  • requestServiceBindingsLocked(调用到service的onBind)

1.1 scheduleCreateService相关流程解读(bindService到onCreate)

这里实际上是以bindService到service组件调用onCreate的流程分析为目的。代码实现如下:


//ActivityThread
    //ApplicationThread
        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);
        }
    //消息处理
    private class H extends Handler {
        //...
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case CREATE_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
                    handleCreateService((CreateServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                //...
            }
        }
        //...
    }
    //...
    private void handleCreateService(CreateServiceData data) {
        // 取消调度GC Idler,以确保在服务创建期间不会进行垃圾回收,影响服务启动性能
        unscheduleGcIdler();

        // 获取服务所在应用的LoadedApk对象,它包含了应用的加载信息
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);

        Service service = null;
        try {
            // 获取ClassLoader对象,用于加载服务类
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            // 加载服务类并创建实例
            service = (Service) cl.loadClass(data.info.name).newInstance();
        } catch (Exception e) {
            //...
        }

        try {
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);

            // 创建应用程序实例
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            // 服务attach到上下文环境
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManagerNative.getDefault());
            // 调用服务的onCreate()生命周期方法
            service.onCreate();
            // 将服务实例存储在映射中,以便后续访问
            mServices.put(data.token, service);
            // 通知AMS服务已执行完成
            try {
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                //...
            }
        } catch (Exception e) {
            //...
        }
    }

这段代码的主要作用是创建服务实例并初始化服务的上下文环境。它涉及到类加载、服务实例化、上下文环境的设置以及服务生命周期的管理(主要是onCreate)。代码中的CreateServiceData对象包含了创建服务所需的所有信息,如服务信息、兼容性信息等。ContextImpl对象表示服务的上下文环境,它提供了服务所需的各种资源和信息。Service对象是服务的实际实例,它实现了服务的具体功能。

1.2 requestServiceBindingsLocked相关流程分析(bindService到onBind)

这里实际上是以bindService到service组件调用onBind的流程分析为目的。代码实现如下:

//ActivityService
    //关键流程:step1
    private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg) {
        // 遍历服务记录中的所有绑定记录
        for (int i = r.bindings.size() - 1; i >= 0; i--) {
            // 获取服务的一个绑定记录
            IntentBindRecord ibr = r.bindings.valueAt(i);
            // 请求服务与客户端的绑定
            // 如果绑定失败,则中断循环,不再请求后续的绑定
            if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
                break;
            }
        }
    }
    //关键流程:step2
    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) {
        if (r.app == null || r.app.thread == null) {
            return false;
        }
        // 如果服务尚未请求绑定,或者这是一次重新绑定,并且有待绑定的客户端
        if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
                // 增加服务执行的计数,并根据是否在前台执行来更新状态
                bumpServiceExecutingLocked(r, execInFg, "bind");
                // 强制服务所在进程的状态至少为服务状态
                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
                // 关键方法:通过服务的应用线程,调度服务的绑定操作
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
                // 如果这不是重新绑定,则标记该服务的绑定已被请求
                if (!rebind) {
                    i.requested = true;
                }
                // 标记服务已被绑定,且设置不需要重新绑定的标志
                i.hasBound = true;
                i.doRebind = false;
            } catch (RemoteException e) {
                return false;
            }
        }
        return true;
    }

这里我们主要关注requestServiceBindingLocked方法,他的主要作用是检查服务是否能够被绑定(即服务及其应用线程是否存在),如果是,则通过服务的应用线程调度服务的绑定操作。代码中的IntentBindRecord对象包含了服务绑定的详细信息,如绑定的Intent、客户端信息等。整理下,关键步骤如下:

  1. 检查服务及其应用线程是否存在。
  2. 如果服务尚未请求绑定或这是一次重新绑定,且有待绑定的客户端,则继续处理。
  3. 增加服务执行的计数,并根据是否在前台执行来更新状态。
  4. 强制服务所在进程的状态至少为服务状态。
  5. 关键方法:通过服务的应用线程调度服务的绑定操作。
  6. 如果这不是重新绑定,则标记该服务的绑定已被请求,并标记服务已被绑定。

接下来我们主要解读步骤5,scheduleBindService主要是发送消息,代码实现如下:

//ActivityThread
    //ApplicationThread
        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;
            sendMessage(H.BIND_SERVICE, s);
        }
    //消息处理
    private class H extends Handler {
        //...
        public void handleMessage(Message msg) {
            switch (msg.what) {
                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) {
        Service s = mServices.get(data.token);
        // 如果服务实例不为空,继续处理绑定请求
        if (s != null) {
            try {
                // 设置Intent的类加载器为服务的类加载器,以便能正确解析其中的Serializable和Parcelable对象
                data.intent.setExtrasClassLoader(s.getClassLoader());
                // 准备Intent以进入当前进程
                data.intent.prepareToEnterProcess();
                // 尝试处理服务绑定
                try {
                    // 如果这不是重新绑定,调用服务的onBind方法并发布服务的IBinder给客户端
                    if (!data.rebind) {
                        // 关键方法:执行service组件的onBind操作
                        IBinder binder = s.onBind(data.intent);
                        // 发布服务,使客户端能够与服务进行通信
                        ActivityManagerNative.getDefault().publishService(
                                data.token, data.intent, binder);
                    } else {
                        // 如果是重新绑定,调用服务的onRebind方法
                        s.onRebind(data.intent);
                        // 通知AMS服务重新绑定操作已完成
                        ActivityManagerNative.getDefault().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                    ensureJitEnabled();
                } catch (RemoteException ex) {
                    //...
                }
            } catch (Exception e) {
                //...
            }
        }
    }

这段代码的主要作用是处理服务的绑定请求,包括调用服务的onBind或onRebind方法,并发布服务的IBinder给客户端。代码中的BindServiceData对象包含了服务绑定请求所需的所有信息,如服务的token、Intent、是否为重新绑定等。

2 AMS.unbindService流程解读(onUnBind、onDestroy)

AMS.unbindService代码实现如下:

//ActivityManagerService
    public boolean unbindService(IServiceConnection connection) {
        synchronized (this) {
            return mServices.unbindServiceLocked(connection);
        }
    }

这里调用了ActivityService的unbindServiceLocked方法,代码实现如下:

//ActivityService
    //关键流程:step1
    boolean unbindServiceLocked(IServiceConnection connection) {
        IBinder binder = connection.asBinder();
        // 从全局服务连接映射中获取与该Binder相关联的连接记录列表
        ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
        // 如果连接记录列表为空,说明没有找到相应的服务连接,返回false
        if (clist == null) {
            return false;
        }

        final long origId = Binder.clearCallingIdentity();
        try {
            // 遍历连接记录列表,解绑所有相关服务
            while (clist.size() > 0) {
                // 获取列表中的第一个连接记录
                ConnectionRecord r = clist.get(0);
                // 关键方法:解除服务连接
                removeConnectionLocked(r, null, null);
                // 如果列表中的第一个连接记录仍然是r,说明没有被移除,手动移除它
                if (clist.size() > 0 && clist.get(0) == r) {
                    clist.remove(0);
                }

                // 如果服务绑定记录的服务应用不为空,更新相关设置
                if (r.binding.service.app != null) {
                    // 如果设置了BIND_TREAT_LIKE_ACTIVITY标志,更新服务应用的属性
                    if ((r.flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                        r.binding.service.app.treatLikeActivity = true;
                        // 更新服务应用的最近最少使用状态
                        mAm.updateLruProcessLocked(r.binding.service.app,
                                r.binding.service.app.hasClientActivities
                                || r.binding.service.app.treatLikeActivity, null);
                    }
                    // 更新服务应用的内存调整
                    mAm.updateOomAdjLocked(r.binding.service.app);
                }
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return true;
    }
    //关键流程:step2
    void removeConnectionLocked(
        ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
        IBinder binder = c.conn.asBinder();
        // 获取服务绑定记录
        AppBindRecord b = c.binding;
        // 获取服务记录
        ServiceRecord s = b.service;
        // 获取服务的连接列表
        ArrayList<ConnectionRecord> clist = s.connections.get(binder);
        // 如果连接列表不为空,移除对应的连接记录
        if (clist != null) {
            clist.remove(c);
            // 如果连接列表为空,从服务的连接映射中移除该Binder的条目
            if (clist.size() == 0) {
                s.connections.remove(binder);
            }
        }
        // 从服务绑定记录的连接列表中移除连接记录
        b.connections.remove(c);
        // 如果连接记录有关联的活动记录,且不是跳过的活动记录,则移除该连接记录
        if (c.activity != null && c.activity != skipAct) {
            if (c.activity.connections != null) {
                c.activity.connections.remove(c);
            }
        }
        // 如果连接记录绑定的服务应用不是跳过的应用记录,则移除该连接记录
        if (b.client != skipApp) {
            b.client.connections.remove(c);
            // 如果设置了BIND_ABOVE_CLIENT标志,更新服务应用是否有高于自身的服务绑定
            if ((c.flags & Context.BIND_ABOVE_CLIENT) != 0) {
                b.client.updateHasAboveClientLocked();
            }
            // 如果服务应用不为空,更新服务应用的客户端活动
            if (s.app != null) {
                updateServiceClientActivitiesLocked(s.app, c, true);
            }
        }
        // 从全局服务连接映射中移除连接记录
        clist = mServiceConnections.get(binder);
        if (clist != null) {
            clist.remove(c);
            // 如果连接列表为空,从全局服务连接映射中移除该Binder的条目
            if (clist.size() == 0) {
                mServiceConnections.remove(binder);
            }
        }

        // 停止服务应用和客户端应用之间的关联
        mAm.stopAssociationLocked(b.client.uid, b.client.processName, s.appInfo.uid, s.name);

        // 如果服务绑定记录的连接列表为空,则从服务Intent的绑定应用列表中移除该应用
        if (b.connections.size() == 0) {
            b.intent.apps.remove(b.client);
        }

        // 如果服务没有死亡,执行进一步的清理操作
        if (!c.serviceDead) {
            // 如果服务应用不为空,且没有其他绑定的应用,执行服务的unbind操作
            if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
                    && b.intent.hasBound) {
                try {
                    // 增加服务执行的计数,并根据是否在前台执行来更新状态
                    bumpServiceExecutingLocked(s, false, "unbind");
                    // 如果服务应用的进程状态小于等于接收者状态,更新服务应用的最近最少使用状态
                    if (b.client != s.app && (c.flags & Context.BIND_WAIVE_PRIORITY) == 0
                            && s.app.setProcState <= ActivityManager.PROCESS_STATE_RECEIVER) {
                        mAm.updateLruProcessLocked(s.app, false, null);
                    }
                    // 更新服务应用的内存调整
                    mAm.updateOomAdjLocked(s.app);
                    // 标记服务Intent没有绑定的应用
                    b.intent.hasBound = false;
                    b.intent.doRebind = false;
                    // 关键方法:通知服务应用执行unbind操作
                    s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
                } catch (Exception e) {
                    //...
                    serviceProcessGoneLocked(s);
                }
            }

            // 如果设置了BIND_AUTO_CREATE标志,且没有其他自动创建的绑定,则关闭服务
            if ((c.flags & Context.BIND_AUTO_CREATE) != 0) {
                boolean hasAutoCreate = s.hasAutoCreateConnections();
                // 如果没有其他自动创建的绑定,则更新服务的状态跟踪器
                if (!hasAutoCreate) {
                    if (s.tracker != null) {
                        s.tracker.setBound(false, mAm.mProcessStats.getMemFactorLocked(),
                                SystemClock.uptimeMillis());
                    }
                }
                // 如果需要,执行服务的关闭逻辑
                bringDownServiceIfNeededLocked(s, true, hasAutoCreate);
            }
        }
    }

这里我们关注removeConnectionLocked方法,它的主要作用是移除服务连接,包括从服务的连接映射中移除连接记录、更新服务应用的客户端活动、执行服务的unbind操作以及关闭服务。代码中的ConnectionRecord对象包含了服务连接的详细信息,AppBindRecord对象包含了服务绑定的详细信息。到这里我们主要关注2个关键方法:

  • scheduleUnbindService(调用service的onUnbind)
  • bringDownServiceIfNeededLocked(调用到service的onDestroy)

2.1 scheduleUnbindService相关流程解读(unbindservice到onUnbind)

这里实际上是以unbindService到service组件调用onUnbind的流程分析为目的。这里主要是通过scheduleUnbindService方法发送消息,处理解绑操作。该方法代码实现如下:

//ActivityThread
    //ApplicationThread
        public final void scheduleUnbindService(IBinder token, Intent intent) {
            BindServiceData s = new BindServiceData();
            s.token = token;
            s.intent = intent;

            sendMessage(H.UNBIND_SERVICE, s);
        }
    //消息处理
    private class H extends Handler {
        //...
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case UNBIND_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
                    handleUnbindService((BindServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                //...
            }
        }
        //...
    }
    //...
    private void handleUnbindService(BindServiceData data) {
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                // 设置Intent的类加载器为服务的类加载器,以便能正确解析其中的Serializable和Parcelable对象
                data.intent.setExtrasClassLoader(s.getClassLoader());
                // 准备Intent以进入当前进程
                data.intent.prepareToEnterProcess();
                // 调用服务的onUnbind方法,询问服务是否需要重新绑定
                boolean doRebind = s.onUnbind(data.intent);
                // 如果服务需要重新绑定,通知ActivityManager服务解绑已完成,并标记为需要重新绑定
                if (doRebind) {
                    ActivityManagerNative.getDefault().unbindFinished(
                            data.token, data.intent, doRebind);
                } else {
                    // 如果服务不需要重新绑定,通知ActivityManager服务解绑操作已完成
                    ActivityManagerNative.getDefault().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                }
            } catch (Exception e) {
                //...
            }
        }
    }

handleUnbindService方法的主要作用是处理服务的解绑请求,包括调用服务的onUnbind方法,并根据服务的响应通知ActivityManager服务解绑已完成代码中的BindServiceData对象包含了服务解绑请求所需的所有信息,如服务的token、Intent等。

2.2 bringDownServiceIfNeededLocked相关流程解读(unbindservice到onDestroy)

这里实际上是以unbindService到service组件调用onDestroy的流程分析为目的。这里主要是通过bringDownServiceIfNeededLocked方法进行destroy相关操作。

注意:针对仅通过 bindService() 绑定的服务,在执行 unbindService() 操作时,onDestroy() 方法不一定会被调用。针对bind方式启动的service组件。onDestroy() 方法是否会被调用一般取决于以下条件:

  • 所有绑定都已解除:如果服务只通过 bindService() 绑定,并且所有绑定都已解除(即没有任何 ServiceConnection 再与该服务绑定),那么服务将被销毁,onDestroy() 方法会被调用。
  • 服务未延迟停止:如果服务没有设置延迟停止的标志(例如,没有在 onUnbind() 方法中返回 true),那么在所有绑定都解除后,服务将直接停止,onDestroy() 方法会被调用。
  • 如果服务在 onUnbind() 方法中返回 true,表示服务希望在解绑后重新绑定,那么服务不会立即销毁,onDestroy() 方法也不会被调用。在这种情况下,如果服务在未来被重新绑定,onBind() 方法将再次被调用。

总结来说,对于仅通过 bindService() 绑定的服务,如果所有绑定都已解除,并且没有其他机制(如 onUnbind() 返回 true)阻止服务销毁,那么 onDestroy() 方法会被调用。这是服务生命周期的一部分,确保服务在不再需要时能够正确地清理资源。

有了这个了解后,我们继续分析bringDownServiceIfNeededLocked方法,代码实现如下:

//ActivityService
    //关键流程:step1
    private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn, boolean hasConn) {
        // 检查服务是否仍然需要如果服务仍然需要,例如服务正在运行或者有待处理的启动请求,则不停止服务并直接返回
        if (isServiceNeeded(r, knowConn, hasConn)) {
            return;
        }

        // 如果服务在待处理列表中,说明服务的启动请求还在处理中,因此不停止服务
        if (mPendingServices.contains(r)) {
            return;
        }

        // 如果服务不再需要且不在待处理列表中,则停止服务
        bringDownServiceLocked(r);
    }
    //关键流程:step2
    private final void bringDownServiceLocked(ServiceRecord r) {
        // 通知所有绑定到该服务的客户端,服务已经死亡
        for (int conni = r.connections.size() - 1; conni >= 0; conni--) {
            ArrayList<ConnectionRecord> c = r.connections.valueAt(conni);
            for (int i = 0; i < c.size(); i++) {
                ConnectionRecord cr = c.get(i);
                // 标记服务为死亡状态
                cr.serviceDead = true;
                try {
                    // 通知客户端服务已经死亡
                    cr.conn.connected(r.name, null);
                } catch (Exception e) {
                    //...
                }
            }
        }

        // 如果服务已经被应用bind,通知应用服务已经被unbind
        // 本次分析不涉及bind和unbind操作,因此忽略即可
        if (r.app != null && r.app.thread != null) {
            for (int i = r.bindings.size() - 1; i >= 0; i--) {
                IntentBindRecord ibr = r.bindings.valueAt(i);
                if (ibr.hasBound) {
                    try {
                        // 增加服务执行的计数,并根据是否在前台执行来更新状态
                        bumpServiceExecutingLocked(r, false, "bring down unbind");
                        // 更新内存调整
                        mAm.updateOomAdjLocked(r.app);
                        // 标记服务为未绑定状态
                        ibr.hasBound = false;
                        // 通知应用服务已经被解绑
                        r.app.thread.scheduleUnbindService(r, ibr.intent.getIntent());
                    } catch (Exception e) {
                        // 异常处理代码...
                        serviceProcessGoneLocked(r);
                    }
                }
            }
        }

        // 记录服务销毁的时间
        r.destroyTime = SystemClock.uptimeMillis();
        // 获取服务映射对象
        final ServiceMap smap = getServiceMap(r.userId);
        // 从服务映射中移除服务
        smap.mServicesByName.remove(r.name);
        smap.mServicesByIntent.remove(r.intent);
        // 重置服务的总重启次数
        r.totalRestartCount = 0;
        // 取消服务的重启计划
        unscheduleServiceRestartLocked(r, 0, true);

        // 从待处理服务列表中移除服务
        for (int i = mPendingServices.size() - 1; i >= 0; i--) {
            if (mPendingServices.get(i) == r) {
                mPendingServices.remove(i);
            }
        }

        // 取消服务的通知
        r.cancelNotification();
        // 标记服务不在前台
        r.isForeground = false;
        // 重置前台服务的ID
        r.foregroundId = 0;
        // 重置前台通知
        r.foregroundNoti = null;

        // 清除已交付的启动请求
        r.clearDeliveredStartsLocked();
        // 清除待处理的启动请求
        r.pendingStarts.clear();

        // 如果服务所属的应用还存在
        if (r.app != null) {
            // 同步电池统计数据的更新
            synchronized (r.stats.getBatteryStats()) {
                r.stats.stopLaunchedLocked();
            }
            // 从应用的服务列表中移除服务
            r.app.services.remove(r);
            // 如果应用线程还存在,更新服务的前台状态
            if (r.app.thread != null) {
                updateServiceForegroundLocked(r.app, false);
                try {
                    // 增加服务执行的计数,并根据是否在前台执行来更新状态
                    bumpServiceExecutingLocked(r, false, "destroy");
                    // 添加服务到正在销毁的服务列表中
                    mDestroyingServices.add(r);
                    // 标记服务为正在销毁状态
                    r.destroying = true;
                    // 更新内存调整
                    mAm.updateOomAdjLocked(r.app);
                    // 关键方法:通知应用销毁服务
                    r.app.thread.scheduleStopService(r);
                } catch (Exception e) {
                    // 异常处理代码...
                }
            }
        }

        // 清除服务的绑定
        if (r.bindings.size() > 0) {
            r.bindings.clear();
        }

        // 如果服务有重启器,设置服务为null
        if (r.restarter instanceof ServiceRestarter) {
            ((ServiceRestarter) r.restarter).setService(null);
        }

        int memFactor = mAm.mProcessStats.getMemFactorLocked();
        long now = SystemClock.uptimeMillis();
        // 如果服务有状态跟踪器,设置服务为未启动和未绑定状态
        if (r.tracker != null) {
            r.tracker.setStarted(false, memFactor, now);
            r.tracker.setBound(false, memFactor, now);
            // 如果服务的执行嵌套计数为0,清除当前所有者
            if (r.executeNesting == 0) {
                r.tracker.clearCurrentOwner(r, false);
                r.tracker = null;
            }
        }

        // 确保服务不在启动的后台服务列表中
        smap.ensureNotStartingBackground(r);
    }

这里最后的bringDownServiceLocked才是实际关闭服务的方法,它的作用是关闭服务并执行相关的清理工作。它涉及到服务绑定的清理(如果bind则执行unbind操作,主要针对bindservice操作,本次分析不涉及)、服务执行计数的更新、服务状态的更新、服务通知的取消以及服务销毁逻辑的调用。接下来我们关注unbindService的通知应用销毁服务的关键方法scheduleStopService,代码实现如下:

//ActivityThread
    //ApplicationThread
        public final void scheduleStopService(IBinder token) {
            sendMessage(H.STOP_SERVICE, token);
        }
    //消息处理
    private class H extends Handler {
        //...
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case STOP_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
                    handleStopService((IBinder)msg.obj);
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                //...
            }
        }
        //...
    }
    //...
    private void handleStopService(IBinder token) {
        Service s = mServices.remove(token);
        if (s != null) {
            try {
                // 关键方法:调用服务的onDestroy生命周期方法
                s.onDestroy();
                // 获取服务的上下文环境
                Context context = s.getBaseContext();
                // 如果上下文环境是ContextImpl的实例,安排最终的清理工作
                if (context instanceof ContextImpl) {
                    final String who = s.getClassName();
                    // 安排清理服务关联的资源和数据
                    ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
                }

                // 等待队列中的工作完成,确保所有异步任务完成
                QueuedWork.waitToFinish();

                // 通知ActivityManager服务已经执行完成停止操作
                try {
                    ActivityManagerNative.getDefault().serviceDoneExecuting(
                            token, SERVICE_DONE_EXECUTING_STOP, 0, 0);
                } catch (RemoteException e) {
                    //...
                }
            } catch (Exception e) {
                //...
            }
        }
    }

这段代码的主要作用是处理服务的停止请求,包括调用服务的onDestroy方法、清理服务关联的资源和数据,以及通知AMS服务已经停止。代码中的mServices是一个保存服务实例的映射,它使用服务的token作为键。代码中的ContextImpl是Android中上下文环境的实现类,它提供了额外的功能,如安排最终的清理工作。至此。我们就分析清楚了2个关键流程:

  • AMS.bindService->service组件onCreate、onBind
  • AMS.unbindService->service组件onUnBind、onDestroy

结合上一章中分析的2个关键流程:

  • AMS.startService->service组件onCreate、onStartCommand
  • AMS.stopService->service组件onDestroy

目前已经对service组件的生命周期和AMS中service组件相关流程有一定的了解。

标签:服务,bindService,service,unbindService,app,绑定,false,null
From: https://blog.csdn.net/vviccc/article/details/142988306

相关文章

  • Service 的实现
    服务(Service)将在集群中运行的应用通过同一个面向外界的端点公开出去,即使工作负载分散于多个后端也完全可行。Kubernetes中Service是将运行在一个或一组Pod上的网络应用程序公开为网络服务的方法。Kubernetes中Service的一个关键目标是无需修改现有应用以使用某种不熟悉......
  • sudo: unable to resolve host xxxx: Name or service not known
    前言在 Linux 环境中,我使用 sudo 执行命令,发生报错:sudo:unabletoresolvehostxxxx:Nameorservicenotknown解决这个错误通常发生在更改主机名后,使用 sudo 命令时出现问题。sudo 命令会尝试解析主机名,但如果无法解析,就会出现"sudo:unabletoresolvehost"的错......
  • 在K8S中,Metric Service有什么作用?
    在Kubernetes(K8S)中,MetricService起到了至关重要的作用。以下是关于MetricService的详细解释:1.定义与功能定义:MetricService是一种用于提供集群内Pod和节点资源使用情况(如CPU、内存等)的标准接口。核心组件:metrics-server是一个关键组件,它作为MetricsAPI服务实现,负责收集并......
  • 如何通过 Service Mesh 构建高效、安全的微服务系统
    1.引言1.1.什么是ServiceMesh?ServiceMesh是一种基础架构层,负责处理微服务之间的通信,它通过在每个服务旁边部署代理(通常称为Sidecar)来捕获和管理服务间的网络流量。这种方式解耦了微服务的业务逻辑和基础设施层的管理工作。ServiceMesh提供了诸如流量管理、服务发......
  • .NET 中的 Web服务(Web Services)和WCF(Windows Communication Foundation)
    一、引言在当今数字化时代,不同的软件系统和应用程序之间需要进行高效、可靠的通信与数据交换。.NET框架中的Web服务和WCF(WindowsCommunicationFoundation)为此提供了强大的技术支持。它们在构建分布式应用程序、实现跨平台通信以及整合不同系统等方面发挥着至关重要的作......
  • 【Azure Cloud Service】使用Key Vault Secret添加.CER证书到Cloud Service Extended
    问题描述因为KeyVault的证书上传功能中,只支持pfx格式的证书,而中间证书,根证书不能转换为pfx格式,只能是公钥证书格式cet或者crt,能通过文本工具直接查看base64编码内容。如一个证书链文件中可以看见中间证书,根证书: 当把包含完成证书链的证书PFX上传到KeyVaultcertificate......
  • Understanding Astrology APIs: Powering the Future of Astrological Services
    UnderstandingAstrologyAPIs Astrologyhasevolvedbeyonditstraditionalroots,seamlesslyblendingwithmoderntechnologytoprovideaccurateandpersonalizedastrologicalservices.Oneofthekeyinnovationsbehindthisshiftistheuseof Astrolog......
  • 【Azure Cloud Service】使用RESTAPI更新Cloud Service(Extended Support) 中所配置的
    问题描述当根据CloudService(ExtendedSupport)文档更新证书(https://docs.azure.cn/zh-cn/cloud-services-extended-support/certificates-and-key-vault)时,如果遇见旧的证书(如中间证书,根证书)信息保存在KeyVaultSecret中,而更新的时候,只能从KeyVault证书中匹配到服务......
  • 【Azure Cloud Service】使用RESTAPI更新Cloud Service(Extended Support) 中所配置的
    问题描述当根据CloudService(ExtendedSupport)文档更新证书(https://docs.azure.cn/zh-cn/cloud-services-extended-support/certificates-and-key-vault)时,如果遇见旧的证书(如中间证书,根证书)信息保存在KeyVaultSecret中,而更新的时候,只能从KeyVault证书中匹配到服务......
  • webservice接口调用报:由于 ContractFilter 在 EndpointDispatcher 不匹配,因此 Action
    1、问题:<s:Envelopexmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><s:Fault><faultcodexmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:ActionNotSupported</faultcode><faul......