Android 源码分析 bindService 启动

Posted 小图包

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 源码分析 bindService 启动相关的知识,希望对你有一定的参考价值。

bindService 绑定服务过程

我们直接看 ContextWrapper 类中的 bindService 函数

//ContextWrapper.java
public class ContextWrapper extends Context {
    Context mBase;
  ...
    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        return mBase.bindService(service, conn, flags);
    }
  
  ...
}

这里调用方式跟 startService 相似,都是调用 ContextImpl 内部函数,直接看 ContextImpl 的 bindService 函数

//ContextImpl.java
    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
                Process.myUserHandle());
    }

我们看 bindServiceCommon,代码如下:

//ContextImp.java
    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) {
...
        
         1. 调用 LoadApk 类型的对象 mPackageInfo 的 getServiceDispatcher 函数,它的主要作用就是将 ServiceConnection 封装为 IServiceConncet 类型的对象 sd, 从 IServiceConnection 的名字
         我们就能得知它实现了 Binder 机制,这样 Service 的绑定就支持了跨进程。
         
        if (mPackageInfo != null) {
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        } else {
            throw new RuntimeException("Not supported in system context");
        }
        validateServiceIntent(service);
        try {
            IBinder token = getActivityToken();
            if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
                    && mPackageInfo.getApplicationInfo().targetSdkVersion
                    < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                flags |= BIND_WAIVE_PRIORITY;
            }
            service.prepareToLeaveProcess(this);
            
             2. 获得 AMS 的代理,调用 bindService 函数,将会传递到 AMS 中
             
            int res = ActivityManager.getService().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());
            if (res < 0) {
                throw new SecurityException(
                        "Not allowed to bind to service " + service);
            }
            return res != 0;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
调用 IActivityManager 的 bindService 函数,最终也还是会回到 AMS 中 bindService 函数,下

Service 绑定过程

收到 ContextImp 向 AMS 发送过来的 bindService 请求,代码如下

//AMS.java

    /**
     * 通过 ContextImpl 调用,中间进程间通信传递过来的
     */
    public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String callingPackage, int userId) throws TransactionTooLargeException {
			...
        synchronized(this) {
            //调用 ActiveService 的 bindServiceLocked 函数 
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
    }

回调到 AMS 的 bindService 函数中,内部又调用 ActiveService 的 bindServiceLocked 函数进行传递,这里可以看到 ActiveService 不管是 start 还是 bind 最后都是在 ActiveService 中处理 Service 的启动逻辑。下面调用代码如下:


 

//ActiveServie.java

    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {
						....

             1. 调用 ServiceRecord 的 retrieveAppBindingLocked 函数来获取 AppBindRecord 
                retrieveAppBindingLocked 函数内部创建 IntentBindRecord ,并对 IntentBindRecord 的成员变量进行赋值。
             
            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
            ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent);

            IBinder binder = connection.asBinder();
					...

            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                
                 2. 在 bringUpServiceLocked 函数的内部中调用了 realStartServiceLocked 函数,最终由 ActivityThread 来调用 Service 的 onCreate 函数启动 Service.
                 
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                        permissionsReviewRequired) != null) {
                    return 0;
                }
            }

          ....

            
             3. 表示 Server 已经运行,其中 s 是 ServiceRecord 对象,app 是 ProcessRecord 类型对象,b.intent.received 表示当前应用程序进程已经接收到绑定服务的 Service 是返回回来的 Binder,
             
            if (s.app != null && b.intent.received) {
                // Service is already running, so we can immediately
                // publish the connection.
                try {
                    
                    4. 调用 IServiceConnect 的connected 函数,具体实现在 @see ServiceDispatcher.InnerConnection,
                     
                    c.conn.connected(s.name, b.intent.binder, false);
                } catch (Exception e) {
                  ...
                }

                
                5. 如果当前应用程序进程是第一个与 Service 进行绑定的,并且 Service 已经调用过 onUnBind 函数,则需要调用注释 
                 
                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                    
                      6. 调用内部 requestServiceBindingLocked 函数
                     
                    requestServiceBindingLocked(s, b.intent, callerFg, true);
                }
            } else if (!b.intent.requested) {7. 如果应用程序进程的 Client 端没有发送过绑定 Service 的请求,则会调用注释 8 
                
                 8.表示不是重新绑定
                 
                requestServiceBindingLocked(s, b.intent, callerFg, false);
            }
            getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return 1;
    }

我们看注释 6 如果当前应用程序进程是第一个与 Service 进行绑定的,并且 Service 已经调用过 onUnBind 函数。

//ActiveServices.java
    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        if (r.app == null || r.app.thread == null) {
            // If service is not currently running, can't yet bind.
            return false;
        }
        if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested
                + " rebind=" + rebind);
        /**
         * 1. i.requested 表示是否发送过绑定的请求,这里上上一步知道是发送过的,因为 为 false, rebind 为true ,所以前面为 true,
         *    i.apps.size() 其中 i 是 IntentBindRecord 对象,AMS 会为每个绑定 Service 的Intent 分配一个 IntentBindRecord 类型的对象。
         */
        if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
                bumpServiceExecutingLocked(r, execInFg, "bind");
                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
              	//2. 调用 IApplicationThread 对象
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
                if (!rebind) {
                    i.requested = true;
                }
                i.hasBound = true;
                i.doRebind = false;
            } catch (TransactionTooLargeException e) {
             		...
                throw e;
            } catch (RemoteException e) {
              ...
                return false;
            }
        }
        return true;
    }

会调用注释 2 ,通过 IApplicationThread 与 ActivityThread 应用程序进程通信,代码如下:

//ActivityThread#ApplicationThread.java
 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;
...
  					//1. 
            sendMessage(H.BIND_SERVICE, s);
        }
//ActivityThread.java
    private void sendMessage(int what, Object obj) {
        
         继续调用内部重载函数 what = H.LAUNCH_ACTIVITY
         

        sendMessage(what, obj, 0, 0, false);
    }

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        
         2. 通过 H 的 Handler 将 what = H.LAUNCH_ACTIVITY 消息 what 发送出去
         
        mH.sendMessage(msg);
    }

这里跟 startService 一样最后都是 通过 H 来通知bindService,下面代码如下:

//ActivityThread.java
//ActivityThread.java
public final class ActivityThread {
//初始化 H 类
final H mH = new H();
  
    /**
     * H 继承自 handler 是应用程序进程中主线程的消息管理类
     */
    private class H extends Handler {
      ...
        
      public static final int CREATE_SERVICE  = 114;
      
     .... 
  		public void handleMessage(Message msg) {
       ...
                
      case BIND_SERVICE:
       //调用 handleBindService
				handleBindService((BindServiceData)msg.obj);
       break;
       ...
     }
    }
  
}

接下来我们看 handleUnbindService 函数具体实现:

//ActivityThread.java
    private void handleBindService(BindServiceData data) {
        /**
         * 1. 获取需要绑定的 Service
         */
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                data.intent.setExtrasClassLoader(s.getClassLoader());
                data.intent.prepareToEnterProcess();
                try {
                    /**
                     * 2.没有经过绑定
                     */
                    if (!data.rebind) {
                        /**
                         * 3. 调动 Service 生命周期 onBind 函数
                         */
                        IBinder binder = s.onBind(data.intent);
                        /**
                         * 4. 调用 AMS 的 publishService 函数
                         */
                        ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    } else {
                        /**
                         * 5.如果已经经过绑定调用 onRebind 生命周期函数
                         */
                        s.onRebind(data.intent);
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                    ensureJitEnabled();
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            } catch (Exception e) {
                ...
            }
        }
    }

这一步算是对 Service 进行开始执行生命周期函数了,如果 data.rebind 为 false 那么说明没有绑定,执行 s.onBind(data.intent); 生命周期函数,下面我们来看注释 4 调用 AMS 的 publishService ,代码如下:

//AMS.java
    public void publishService(IBinder token, Intent intent, IBinder service) {
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        synchronized(this) {
            if (!(token instanceof ServiceRecord)) {
                throw new IllegalArgumentException("Invalid service token");
            }
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }

内部调用 ActiveServices 的 publishServiceLocked 函数

//ActiveServices.java

    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        final long origId = Binder.clearCallingIdentity();
        try {
         ...
            if (r != null) {
                Intent.FilterComparison filter
                        = new Intent.FilterComparison(intent);
                IntentBindRecord b = r.bindings.get(filter);
              ...
                    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);
                           .....
                            try {
                              
                              //1. 
                                c.conn.connected(r.name, service, false);
                            } catch (Exception e) {
                                ...
                            }
                        }
                    }
                }
                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

在注释1 处调用了 ServiceDispatcher 类型的 sd 对象的 connected 函数,代码如下:

//LoadedApk.java
        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) {
                  //1. 
                    sd.connected(name, service, dead);
                }
            }
        }

        public void connected(ComponentName name, IBinder service, boolean dead) {
            if (mActivityThread != null) {
              //2. 
                mActivityThread.post(new RunConnection(name, service, 0, dead));
            } else {
                doConnected(name, service, dead);
            }
        }

这里首先通过进程间通信 AMS 发到 InnerConnection 的 connected 函数,然后调用 LoadedApk 的 connected 函数,最后执行 注释 2 的 post 函数, 代码如下:

//LoadedApk.java

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

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

调用 doConnected 函数,代码如下:

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

            synchronized (this) {
            ...

            // If there was an old service, it is now disconnected.
            if (old != null) {
                mConnection.onServiceDisconnected(name);
            }
            if (dead) {
                mConnection.onBindingDied(name);
            }
            // If there is a new service, it is now connected.
            if (service != null) {
                /**
                 * 1. 调用了 ServiceConnection 类型的对象 mConnection 的 onServiceConnected 函数,这样在客户端实现了 ServiceConnection 接口,那么就会被执行。
                 */
                mConnection.onServiceConnected(name, service);
            }
        }

通过上面代码的注释 1 我们知道,只要客户端通过如下代码绑定,那么就会回调到 onServiceConnected 回调,

        bindService(new Intent(XXXX,XXXX), new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.d(TAG,"绑定成功");
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
 								Log.d(TAG,"绑定失败,或者取消绑定");
            }
        })

至此,整个 bindService 过程就分析完成。

以上是关于Android 源码分析 bindService 启动的主要内容,如果未能解决你的问题,请参考以下文章

Android 源码分析 bindService 启动

Android10Q/11R/12S Service bindService系统源码分析1-千里马framework

Android10Q/11R/12S Service bindService系统源码分析1-千里马framework

Android 四大组件 - bindService 的通信过程

Android服务之bindService源代码分析

Android里Service的bindService()和startService()混合使用深入分析