• Android 深入理解 Service 的启动和绑定


    Service 的启动原理

    1.Service 的启动有哪几种方式
    2.Service 启动过程中主要流程有哪些
    3.Service 启动过程中涉及哪些参与者,通信过程是怎样的
    
    • 1
    • 2
    • 3

    startService()

        @Override
        public ComponentName startService(Intent service) {
            return mBase.startService(service);
        }
    
    • 1
    • 2
    • 3
    • 4

    ContextImpl 的 startService()

    	// 调用了 startService 下面的 startServiceCommon() 函数
        @Override
        public ComponentName startService(Intent service) {
            warnIfCallingFromSystemProcess();
            return startServiceCommon(service, false, mUser);
        }
    
        private ComponentName startServiceCommon(Intent service, boolean requireForeground,
                UserHandle user) {
            try {
                validateServiceIntent(service);
                service.prepareToLeaveProcess(this);
                // 拿到了 AMS 的 binder 对象,然后调用 AMS 的 startService() 函数 同时把  applicationThread binder 对象作为参数给 AMS 传入。
                ComponentName cn = ActivityManager.getService().startService(
                    mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                                getContentResolver()), requireForeground,
                                getOpPackageName(), user.getIdentifier());
                // 。。。
                return cn;
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    startServiceCommon() 函数,拿到了 AMS 的 binder 对象,然后调用其 startService() 函数,并把 ApplicationThread 作为参数给 AMS 传过去。

    • 接下来看一下 AMS 的 startService() 函数。
        @Override
        public ComponentName startService(IApplicationThread caller, Intent service,
                String resolvedType, boolean requireForeground, String callingPackage, int userId)
                throws TransactionTooLargeException {
            enforceNotIsolatedCaller("startService");
            synchronized(this) {
                ComponentName res;
                try {
                    res = mServices.startServiceLocked(caller, service,
                            resolvedType, callingPid, callingUid,
                            requireForeground, callingPackage, userId);
                } finally {
                    Binder.restoreCallingIdentity(origId);
                }
                return res;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    AMS 的 startService 中调用了ActiveServices 的 mServices.startServiceLocked() 方法

    • mServices.startServiceLocked()
        ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,...)throws TransactionTooLargeException {
    		// 根据传入的 Intent 查找到 ServiceRecord 对象。
            ServiceLookupResult res =
                retrieveServiceLocked(service, resolvedType, callingPackage,
                        callingPid, callingUid, userId, true, callerFg, false, false);
            if (res == null) {
                return null;
            }
            if (res.record == null) {
                return new ComponentName("!", res.permission != null
                        ? res.permission : "private to package");
            }
    		// 每个应用端都会有一个 ServiceRecord 对象
            ServiceRecord r = res.record;
    		// 。。。。
    		// new 了一个 ServiceRecord.StartItem 添加到 pendingStarts ,这个是为了启动后调用 onStartCommond() 用
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                    service, neededGrants, callingUid));
    		// 最后调用了 startServiceInnerLocked() 函数
    		ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
            return cmp;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    startServiceLocked 获取到的 ServiceRecord 是每个应用都会有的一个对象,记录了应用内运行的或者将要运行的Service 信息。然后把将要启动的Service创建一个 ServiceRecord.StartItem对象添加到代执行列表pendingStarts中,最后调用 startServiceInnerLocked 继续启动流程

    • startServiceInnerLocked()
        ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
                boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
    	// 调用了 bringUpServiceLocked() 继续流程
    	String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • bringUpServiceLocked()
        private String bringUpServiceLocked(ServiceRecord r,....){
    		// 首先查看 Service 是否启动了 app 代表 Service 所在的进程
            if (r.app != null && r.app.thread != null) {
            // 如果启动了则 调用sendServiceArgsLocked() 其内部线从通过pendingStarts取到Service,然后通过 binder 调用回调到应用端的 Service 的 onStartCommand() 方法。
                sendServiceArgsLocked(r, execInFg, false);
                return null;
            }
            // 下面是 Service 还没有启动的情况
            ProcessRecord app;
    		// 先判断进程是否启动了
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            // 如果进程已经启动
            if (app != null && app.thread != null) {
                    try {
                        app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);	
                        // 调用 realStartServiceLocked() 真正的启动 Service 去
                        realStartServiceLocked(r, app, execInFg);
                        // 然后结束方法 返回 null
                        return null;
                    } 
                }
                // 如果进程未启动 或者 app 还没有就绪
    	if (app == null && !permissionsReviewRequired) {
    	// 调用 startProcessLocked() 去先启动进程
                if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                        hostingType, r.name, false, isolated, false)) == null) {
                    bringDownServiceLocked(r);
                    return msg;
                }
            }
        // 然后将 ServiceRecord 添加到 mPendingServices列表中;mPendingServices 是用来等进程启动后再来处理 Service 的启动。
            if (!mPendingServices.contains(r)) {
                mPendingServices.add(r);
            }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    回顾一下之前讲过的进程启动流程
    Android Application 的理解
    Zygote 启动应用程序流程
    Android启动流程大致如下:
    在这里插入图片描述
    当应用启动之后,应用会通过 attachApplication() 处理一些应用组件。

    private final boolean attachApplicationLocked(IApplicationThread thread,
                int pid, int callingUid, long startSeq) {
    	// 内部会调用这行代码 继续处理 Service 的信息
    	mServices.attachApplicationLocked(app, processName);
    	return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • ActiveServices 的 mServices.attachApplicationLocked(app, processName);
        boolean attachApplicationLocked(ProcessRecord proc, String processName)
                throws RemoteException {
            boolean didSomething = false;
            if (mPendingServices.size() > 0) {
                ServiceRecord sr = null;
                // for 循环里处理每一个 service 信息
                    for (int i=0; i<mPendingServices.size(); i++) {
                        // ... 
                        realStartServiceLocked(sr, proc, sr.createdFromFg);
                    }
            }
           	// ... 
            return didSomething;
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    attachApplicationLocked() 内部通过 for 循环为每个 Service 调用了 realStartServiceLocked() 函数

    • realStartServiceLocked() 真正启动 service 的方法
        private final void realStartServiceLocked(ServiceRecord r,
                ProcessRecord app, boolean execInFg) throws RemoteException {
           		// app.thread为 binder 调用,调用到了 应用端的ApplicationThread 的 scheduleCreateService() 函数
           		// 然后执行 onCreate() 回调 ServiceRecord 其实是一个 binder 对象传回给了客户端,应用端给保存了下来
                app.thread.scheduleCreateService(r, r.serviceInfo,
                        mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                        app.repProcState);
                // 调用 sendServiceArgsLocked() 回调到应用端的 onStartCommond() 函数
       	        sendServiceArgsLocked(r, execInFg, true);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    realStartServiceLocked() 函数先是通过 IPC 调用了客户端的 ApplicationThread 的 scheduleCreateService() 函数进行创建 Service 同时调用 Service 的 onCreate() 函数,binder 调用时将 ServiceRecord 传回客户端。

    • scheduleCreateService() 函数
            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);
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    其发送了 handler 信息,将 CreateServiceData() 传入 ,Handler 接收的时候调用了 handleCreateService((CreateServiceData)msg.obj); 函数,所以接下来直接看此函数内部时如何处理的。

    • handleCreateService()
        private void handleCreateService(CreateServiceData data) {
            LoadedApk packageInfo = getPackageInfoNoCheck(
                    data.info.applicationInfo, data.compatInfo);
            Service service = null;
            try {
            	// 先通过 ClassLoader 创建 Service 类
                java.lang.ClassLoader cl = packageInfo.getClassLoader();
                service = packageInfo.getAppFactory()
                        .instantiateService(cl, data.info.name, data.intent);
            }
            try {
              	// 先创建 context 对象
                ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
                context.setOuterContext(service);
    			// 创建 application 对象,创建好直接返回 application 对象
                Application app = packageInfo.makeApplication(false, mInstrumentation);
                // 调用 Service 的 attach() 函数
                service.attach(context, this, data.info.name, data.token, app,
                        ActivityManager.getService());
                // 调用 service.onCreate(); 函数
                service.onCreate();
                // 将 data.token 就是之前说的那个 ServiceRecord 存储 map 中
                mServices.put(data.token, service);
                try {
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            } 
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • sendServiceArgsLocked() 是怎么触发 onStartCommond() 函数的
        private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
                boolean oomAdjusted) throws TransactionTooLargeException {
            final int N = r.pendingStarts.size();
            
            try {
                r.app.thread.scheduleServiceArgs(r, slice);
            }
            // ...
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    sendServiceArgsLocked 中通过 IPC 操作调用到了客户端 ApplicationThread 中的 scheduleServiceArgs() 函数

    • scheduleServiceArgs()
            public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
                List<ServiceStartArgs> list = args.getList();
    
                for (int i = 0; i < list.size(); i++) {
                    ServiceStartArgs ssa = list.get(i);
                    ServiceArgsData s = new ServiceArgsData();
                    s.token = token;
                    //...
                    sendMessage(H.SERVICE_ARGS, s);
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在 scheduleServiceArgs 中 封装了 ServiceStartArgs 后通过 Hander 发送了 SERVICE_ARGS 消息。接收后的方法如下

                    case SERVICE_ARGS:
                        handleServiceArgs((ServiceArgsData)msg.obj);
                        break;
    
    • 1
    • 2
    • 3
    • handleServiceArgs()
        private void handleServiceArgs(ServiceArgsData data) {
         // 先获取到 Service 
            Service s = mServices.get(data.token);
            if (s != null) {
                try {
                    int res;
                    if (!data.taskRemoved) {
                    // 调用的Service 的 onStartCommand() 所以 onStartCommand 是在主线程掉用的
                        res = s.onStartCommand(data.args, data.flags, data.startId);
                    } 
                    try {
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
                    } 
                    ensureJitEnabled();
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    总结一下启动流程

    网上找了几张图
    在这里插入图片描述

    • 进程角度来看都有哪些参与启动 Service
      在这里插入图片描述

    Service 的绑定原理

    bindService()

    回忆一下 bindService() 的用法

        // 定义 aidl 接口
        IMyAidlInterface myAidlInterface;
        // 创建 ServiceConnection
        private ServiceConnection serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                myAidlInterface = myAidlInterface.Stub.asInterface(service);
                 // 发起接口调用
                myAidlInterface.call();
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
    
            }
        };
    
        private void bindService() {
            // 调用 bindService
            Intent intent = new Intent(this, MyService.class);
            bindService(intent, serviceConnection, BIND_AUTO_CREATE);
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 总体流程图
      在这里插入图片描述

    • bindService() 流程

        @Override
        public boolean bindService(Intent service, ServiceConnection conn,
                int flags) {
            warnIfCallingFromSystemProcess();
            return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • bindServiceCommon()
        private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
                handler, UserHandle user) {
            IServiceConnection sd;
        
            if (mPackageInfo != null) {
            	// 根据一个 ServiceConnection 生成一个 IServiceConnection;
            	// 因为 ServiceConnection 只是一个普通的接口,无法进行跨进程传输。所以通过 ServiceConnection 生成了一个 binder 对象
                sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
            } 
            try {
                IBinder token = getActivityToken();
                // 通过上面为ServiceConnection生成的  binder 对象,生成了 IServiceConnection 传入给 AMS 的 bindeService
                int res = ActivityManager.getService().bindService(
                    mMainThread.getApplicationThread(), getActivityToken(), service,
                    service.resolveTypeIfNeeded(getContentResolver()),
                    sd, flags, getOpPackageName(), user.getIdentifier());
                return res != 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    bindServiceCommon() 先通过 getServiceDispatcher() 函数把 ServiceConnection 对象生成了一个 IServiceConnection 的 binder 对象,方便跨进程传输,IServiceConnection 引用了 ServiceConnection,所以可以跨进程调用。然后将 IServiceConnection 作为参数,调用了 AMS 的 bindService() 函数。

    • getServiceDispatcher()
    	// 入参传入了 ServiceConnection 返回值是一个 IServiceConnection 
        public final IServiceConnection getServiceDispatcher(ServiceConnection c,
                Context context, Handler handler, int flags) {
            synchronized (mServices) {
                LoadedApk.ServiceDispatcher sd = null;
             	// 先从 mServices 中获取ArrayMap 
                ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
                if (map != null) {
                   	// 如果存在则尝试获取一下 看看是否创建过
                    sd = map.get(c);
                }
                if (sd == null) {
                	// 如果 ServiceDispatcher == null 则创建一个对象出来
                    sd = new ServiceDispatcher(c, context, handler, flags);
    	            // 如果 map 也为 null 则创建一个 map 缓存数据添加到 mServices 中
                    if (map == null) {
                        map = new ArrayMap<>();
                        mServices.put(context, map);
                    }
                    map.put(c, sd);
                } else {
                    sd.validate(context, handler);
                }
                // sd.getIServiceConnection(); 就是生成 ServiceDispatcher 对象中的 binder 对象。
                return sd.getIServiceConnection();
            }
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • ServiceDispatcher 对象
            ServiceDispatcher(ServiceConnection conn,
                    Context context, Handler activityThread, int flags) {
                mIServiceConnection = new InnerConnection(this);
                mConnection = conn;
                mContext = context;
                mActivityThread = activityThread;
                // ...
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • InnerConnection 类,它是一个 IServiceConnection.Stub 可以跨进程传递
            private static class InnerConnection extends IServiceConnection.Stub {
                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);
                    }
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    InnerConnection 传入了 ServiceDispatcher 对象,并设置了成员变量对他进行弱引用,当AMS 调用 connected 方法,mDispatcher 后去到 ServiceDispatcher ,然后调用 connected 方法。

    • sd.connected(name, service, dead);
            public void connected(ComponentName name, IBinder service, boolean dead) {
                if (mActivityThread != null) {
                	// 最后也会走 doConnected() 
                    mActivityThread.post(new RunConnection(name, service, 0, dead));
                } else {
                    doConnected(name, service, dead);
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • doConnected(name, service, dead);
           public void doConnected(ComponentName name, IBinder service, boolean dead) {
                ServiceDispatcher.ConnectionInfo old;
                ServiceDispatcher.ConnectionInfo info;
                synchronized (this) {
                	// 缓存中取 ServiceDispatcher.ConnectionInfo
                    old = mActiveConnections.get(name);
                    if (old != null && old.binder == service) {
                    // 如果缓存过 则直接 return 防止 onServiceConnected() 重复调用
                        return;
                    }
                    // service != null 代表绑定上了
                    if (service != null) {
                    	// 创建 ConnectionInfo 对象
                        info = new ConnectionInfo();
                        info.binder = service;
                        	//。。。	
                        try {
                           // 添加到缓存
                            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 {
                    // 如果 service == null 代表已经断开 直接 清除缓存
                        mActiveConnections.remove(name);
                    }
                }
                
                    if (old != null) {
                    	// 这里面是代表 内部原理是 如果 binder 对象挂了 就会回调 onServiceDisconnected ,所以除了系统回收 要不然一般也收不到 onServiceDisconnected() 的回调
                        old.binder.unlinkToDeath(old.deathMonitor, 0);
                    }
                // If there was an old service, it is now disconnected.
                if (old != null) {
                	// 如果绑定过 old 但是 old.binder != service
                	// 那么上面没有 return 到,代表已经断开了 直接 onServiceDisconnected 
                	// 基本上这种情况 onServiceDisconnected 方法也接收不到;
                    mConnection.onServiceDisconnected(name);
                }
                // If there is a new viable service, it is now connected.
                if (service != null) {
                	// 绑定调用 onServiceConnected
                    mConnection.onServiceConnected(name, service);
                } 
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    在这里插入图片描述
    IServiceConnection 和 ServiceConnection 并不是一对一的关系;一个 Context 和 一个 ServiceConnection 共同构成一个数据和 ServiceConnection关联,意思就是 同一个 ServiceConnection ,用不同的 Context 绑定的话会对应不同的 IServiceConnection;同样的 同一个 Context 绑定不同的 ServiceConnection 也是不同的 IServiceConnection。

    • 接下来看看 ActivityManager.getService().bindService() 到底是怎么绑定的
        public int bindService(IApplicationThread caller, IBinder token, Intent service,
                String resolvedType, IServiceConnection connection, int flags, String callingPackage,
                int userId) throws TransactionTooLargeException {
            synchronized(this) {
                return mServices.bindServiceLocked(caller, token, service,
                        resolvedType, connection, flags, callingPackage, userId);
            }
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    bindServiceLocked()

        int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
                String resolvedType, final IServiceConnection connection,...){
            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
            	// 这个方法就是创建service的
    			bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired)
    		}
    		// 如果已经准备好了 并且已经报告给了AMS 
    		if (s.app != null && b.intent.received) {
    			// 直接返回给应用端
    			c.conn.connected(s.name, b.intent.binder, false);
    		} else if (!b.intent.requested) {
    		//	 去请求 AMS
               requestServiceBindingLocked(s, b.intent, callerFg, false);
            }
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    bringUpServiceLocked() 这个函数上面 startService 的时候已经讲过了。区别是 bindeService 不会触发 onStartCommond() 回调。 那么 看看上面方法中的 requestServiceBindingLocked() 函数

    • requestServiceBindingLocked()
        private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
                boolean execInFg, boolean rebind) throws TransactionTooLargeException {
                // 先判断 service 是否启动了
            if (r.app == null || r.app.thread == null) {
                // If service is not currently running, can't yet bind.
                return false;
            }
            // 判断是否绑定了 binder 对象  或者 是否触发了 rebind ;并且 需要 i.apps.size() > 0 代表当前有应用需要绑定
            if ((!i.requested || rebind) && i.apps.size() > 0) {
                try {
                    r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                            r.app.repProcState);
                }
            }
            return true;
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 调用应用端 r.app.thread.scheduleBindService() 最终会通过 handler 调用到 handleBindService()
        private void handleBindService(BindServiceData data) {
            Service s = mServices.get(data.token);
            if (DEBUG_SERVICE)
                Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
            if (s != null) {
                try {
                    data.intent.setExtrasClassLoader(s.getClassLoader());
                    data.intent.prepareToEnterProcess();
                    try {
                    	// 通过判断传回来的数据判断 onBind 还是 onRebind
                        if (!data.rebind) {
                            IBinder binder = s.onBind(data.intent);
                            // 通过 binder 调用 发布到 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);
                        }
                        ensureJitEnabled();
                    }
                } 
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • AMS 的 publishService() 会调用到 mServices.publishServiceLocked((ServiceRecord)token, intent, service);
       void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
            final long origId = Binder.clearCallingIdentity();
            try {
                if (r != null) {
                    Intent.FilterComparison filter
                            = new Intent.FilterComparison(intent);
                            // 通过 intent 先找到 IntentBindRecord 对象
                    IntentBindRecord b = r.bindings.get(filter);
                    if (b != null && !b.received) {
                        b.binder = service;// 保存 binder 对象
                        b.requested = true; // 表示是否请求过 bidner 对象
                        b.received = true; // 表示是否已经收到 binder 对象了
                        // for 循环找到所有匹配的 对象 调用 connected 把binder 对象返回给应用端
                        for (int conni=r.connections.size()-1; conni>=0; conni--) {
                            ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
                            for (int i=0; i<clist.size(); i++) {
                                ConnectionRecord c = clist.get(i);
                                if (!filter.equals(c.binding.intent.intent)) {
                                    continue;
                                }
                              
                                try {
                                    c.conn.connected(r.name, service, false);
                                } catch (Exception e) {
                                    Slog.w(TAG, "Failure sending service " + r.name +
                                          " to connection " + c.conn.asBinder() +
                                          " (in " + c.binding.client.processName + ")", e);
                                }
                            }
                        }
                    }
    
                    serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
                }
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    onRebind() 什么时候调用的

    • bindServiceLocked() 中有一行代码
        int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,...){
    		// service 已经启动 并且已经接收到了 binder 对象
    		if (s.app != null && b.intent.received) {
    				// intent 下只有一个 进程绑定  && doRebind 参数为 true
                    if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                    	// 最后一个参数为 true 表示要调用 onRebind
                        requestServiceBindingLocked(s, b.intent, callerFg, true);
                    }
    		}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    doRebind 参数和unbindServiceLocked 有关

        boolean unbindServiceLocked(IServiceConnection connection) {
            IBinder binder = connection.asBinder();
         	//通过 binder 取出 ConnectionRecord 列表
            ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
        
            try {
                while (clist.size() > 0) {
                    ConnectionRecord r = clist.get(0);
                    // 依次调用 removeConnectionLocked 函数
                    removeConnectionLocked(r, null, null);
                    if (clist.size() > 0 && clist.get(0) == r) {
                        clist.remove(0);
                    }
                }
            } 
            return true;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • removeConnectionLocked()
        void removeConnectionLocked(
        	// 如果Service还在 并且binde的 已经没有了进程来bind了
    		if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
                        && b.intent.hasBound) {
                    try {
                        // 则 Service 执行 scheduleUnbindService 回调
                        s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
                    }
                }
    
    
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • handleUnbindService()
        private void handleUnbindService(BindServiceData data) {
            Service s = mServices.get(data.token);
            if (s != null) {
                try {
                    data.intent.setExtrasClassLoader(s.getClassLoader());
                    data.intent.prepareToEnterProcess();
                   	// 一般返回false 除非重写这个方法
                    boolean doRebind = s.onUnbind(data.intent);
                    try {
                        if (doRebind) {
                            ActivityManager.getService().unbindFinished(
                                    data.token, data.intent, doRebind);
                        } else {
                            ActivityManager.getService().serviceDoneExecuting(
                                    data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                        }
                    }
                } 
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    当没有应用还在bindService以后,调用 ActivityManager.getService().unbindFinished() 的话内部会把 doRebind 属性设置为 true ,那么下次再调用 bindService 的时候会执行 onRebind() 函数

  • 相关阅读:
    Spring 初始导读
    程序员公司对公司保密协议
    前端学习--React(1)
    Shell系统学习之数组
    SAP Dump:RFC callback call rejected by positive list
    《MongoDB》Mongo Shell中的基本操作-文档查询
    虚拟机挂起后再解挂后网络图标消失,没有网络/虚拟机ubuntu系统没有网络
    linux系统编程之一
    Spring循环依赖
    六大设计原则
  • 原文地址:https://blog.csdn.net/ldxlz224/article/details/127504343