Service绑定形式启动过程

Posted 流云易采

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Service绑定形式启动过程相关的知识,希望对你有一定的参考价值。

一、绑定形式Service的使用 1)定义一个Service,注意重写onBind方法,返回一个IBinder对象

public class MyService extends Service 
    public static final String LOG_TAG = "LOG_TAG";

    private MyBinder mBinder = new MyBinder();

    public class MyBinder extends Binder 
        public MyService getService() 
            return MyService.this;
        
    

    @Override
    public void onCreate() 
        super.onCreate();
        Log.d(LOG_TAG, "onCreate");
    

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) 
        Log.d(LOG_TAG, "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    

    @Nullable
    @Override
    public IBinder onBind(Intent intent) 
        Log.d(LOG_TAG, "onBind");
        return mBinder;
    

    @Override
    public boolean onUnbind(Intent intent) 
        Log.d(LOG_TAG, "onUnbind");
        return super.onUnbind(intent);
    

    @Override
    public void onDestroy() 
        super.onDestroy();
        Log.d(LOG_TAG, "onDestroy");
    


2)注意在manifest中注册service

<service android:name=".MyService"/>
 

3)在Activity中bindService:

public class ServiceActivity extends AppCompatActivity 
    private MyService mService;

    // 定义ServiceConnection
    private ServiceConnection conn = new ServiceConnection() 
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) 
            // 通过定义的Binder来获取Service实例来供使用
            mService = ((MyService.MyBinder) service).getService();
            Log.w(MyService.LOG_TAG, "Activity onServiceConnected");
        

        @Override
        public void onServiceDisconnected(ComponentName name) 
            mService = null;
            // 当Service被意外销毁时
            Log.w(MyService.LOG_TAG, "Activity onServiceDisconnected");
        
    ;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.empty_ayout);
    

    @Override
    protected void onResume() 
        super.onResume();
        // bindService
        Intent intent = new Intent(this, MyService.class);
        bindService(intent, conn, Context.BIND_AUTO_CREATE);
        Log.w(MyService.LOG_TAG, "Activity bindService");
    

    @Override
    protected void onPause() 
        super.onPause();
        // 进行unbind
        unbindService(conn);
        Log.w(MyService.LOG_TAG, "Activity unbindService");
    

二、Service绑定形式源码分析 1)ContextWrapper#bindService:

/** @path: \\frameworks\\base\\core\\java\\android\\content\\ContextWrapper.java **/
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) 
    // @value Context mBase;
    return mBase.bindService(service, conn, flags);
和启动形式相仿,接下来调用ContextImpl.bindService;


2) ContextImpl#bindService:

/** @path: \\frameworks\\base\\core\\java\\android\\app\\ContextImpl.java**/
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) 
    warnIfCallingFromSystemProcess();
    return bindServiceCommon(service, conn, flags, Process.myUserHandle());

3) ContextImpl#bindServiceCommon:

/** @path: \\frameworks\\base\\core\\java\\android\\app\\ContextImpl.java**/
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
                                  UserHandle user) 
    IServiceConnection sd;
    if (conn == null) 
        throw new IllegalArgumentException("connection is null");
    
    if (mPackageInfo != null) 
        // 将ServiceConnection封装成为IServiceConnection
        sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
                mMainThread.getHandler(), 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
                < Build.VERSION_CODES.ICE_CREAM_SANDWICH) 
            flags |= BIND_WAIVE_PRIORITY;
        
        service.prepareToLeaveProcess();
        // 调用bindService来绑定启动Service
        int res = ActivityManagerNative.getDefault().bindService(
                mMainThread.getApplicationThread(), getActivityToken(),
                service, service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, user.getIdentifier());
        if (res < 0) 
            throw new SecurityException(
                    "Not allowed to bind to service " + service);
        
        return res != 0;
     catch (RemoteException e) 
        return false;
    
代码中首先将ServiceConnection对象转化成为IServiceConnection。因为Service与客户端建立的连接,可能是跨进程的,系统在绑定Service过程中可能通过IServiceConnection来调用ServiceConnection中的onServiceConnection方法,该过程可能是跨进程的,IServiceConnection是个AIDL文件;

之后再通过ActivityManagerNative.getDefault().bindService来开始绑定Service操作。


先来看第一步,由于mPackageInfo的类型为LoadedApk;
final LoadedApk mPackageInfo;
3.1)LoadedApk#getServiceDispatcher:

/** @path: \\frameworks\\base\\core\\java\\android\\app\\LoadedApk.java**/
public final IServiceConnection getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags) 
    synchronized (mServices) 
        ServiceDispatcher sd = null;
        // 以ServiceConnection为关键字,将ServiceDispatcher与erviceConnection建立关联保存起来
        // 还可以看到保存的ArrayMap最终会以Context为关键字保存在一个变量mServices中
        /** @value :private final ArrayMap<Context, ArrayMap<ServiceConnection, ServiceDispatcher>> mServices
                                 = new ArrayMap<Context, ArrayMap<ServiceConnection, ServiceDispatcher>>();**/
        ArrayMap<ServiceConnection, ServiceDispatcher> map = mServices.get(context);
        // 先尝试进行获取
        if (map != null) 
            sd = map.get(c);
        
        // 如果已存在直接返回,未存在则进行创建
        if (sd == null) 
            // 创建一个新的ServiceDispatcher
            sd = new ServiceDispatcher(c, context, handler, flags);
            // 如果map为空,则创建一个ArrayMap并保存到mServices中
            if (map == null) 
                map = new ArrayMap<ServiceConnection, ServiceDispatcher>();
                mServices.put(context, map);
            
            // 将对应的ServiceConnection与ServiceDispatcher保存到一个map中
            map.put(c, sd);
         else 
            sd.validate(context, handler);
        
        // 返回一个IServiceConnection类型
        return sd.getIServiceConnection();
    
方法中的参数:

ServiceConnection c  == 即Service中自定义的ServiceConnection对象

Context context         == 传入的为getOuterContext(),即mOuterContext,ContextImpl类型,指向一个Activity组件

Handler handler        == 传入参数为mMainThread.getHandler();

mMainThread的类型为ActivityThread:

final ActivityThread mMainThread;
/** @path: \\frameworks\\base\\core\\java\\android\\app\\ActivityThread.java**/
final H mH = new H();
final Handler getHandler() 
    return mH;
可以看到最终用来发送启动service消息到主线程的Handler H。

继续来看sd.getIServiceConnection();ServiceDispatcher是LoadedApk的内部类。

先来看ServiceDispatcher的构造函数:

3.2)LoadedApk#ServiceDispatcher#ServiceDispatcher:

/** @path: \\frameworks\\base\\core\\java\\android\\app\\LoadedApk.java**/
static final class ServiceDispatcher 
    private final InnerConnection mIServiceConnection;
    private final ServiceConnection mConnection;
    private final Context mContext;
    private final Handler mActivityThread;
    private final ServiceConnectionLeaked mLocation;
    private final int mFlags;

    private static class InnerConnection extends IServiceConnection.Stub 
        final WeakReference<ServiceDispatcher> mDispatcher;

        InnerConnection(ServiceDispatcher sd) 
            mDispatcher = new WeakReference<ServiceDispatcher>(sd);
        

        public void connected(ComponentName name, IBinder service) throws RemoteException 
            ServiceDispatcher sd = mDispatcher.get();
            if (sd != null) 
                sd.connected(name, service);
            
        
    
    
    ServiceDispatcher(ServiceConnection conn, Context context, Handler activityThread, int flags) 
        mIServiceConnection = new InnerConnection(this);
        mConnection = conn;
        mContext = context;
        mActivityThread = activityThread;
        mLocation = new ServiceConnectionLeaked(null);
        mLocation.fillInStackTrace();
        mFlags = flags;
    
    可以看到InnerConnection继承了IServiceConnection.Stub,IServiceConnection是个aidl,因此将本地的ServiceConnection封装成为ServiceDispatcher#InnerConnection,可以用以进程间的通信。


3.3)LoadedApk#ServiceDispatcher#getIServiceConnection:

/** @path: \\frameworks\\base\\core\\java\\android\\app\\LoadedApk.java**/
static final class ServiceDispatcher 
    private final InnerConnection mIServiceConnection;
    IServiceConnection getIServiceConnection() 
        return mIServiceConnection;
    
getIServiceConnection逻辑较为简单,即是返回新创建的InnerConnection,因此sd的编译时类型为IServiceConnection,运行时类型为ServiceDispatcher.InnerConnection:


分析完ServiceConnection,下面接着分析ActivityManagerNative.getDefault().bindService,由前面得知ActivityManagerNative.getDefault()的类型为AMS的代理:ActivityManagerProxy;则下面调用的是ActivityManagerProxy.bindService;
4、ActivityManagerProxy#bindService: 调用:

ActivityManagerNative.getDefault().bindService(
        mMainThread.getApplicationThread(), getActivityToken(),
service, service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, user.getIdentifier());
源代码: 

/** @path:  \\frameworks\\base\\core\\java\\android\\app\\ActivityManagerNative.java**/
class ActivityManagerProxy implements IActivityManager 
    public int bindService(IApplicationThread caller, IBinder token,
                           Intent service, String resolvedType, IServiceConnection connection,
                           int flags, int userId) throws RemoteException 
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeStrongBinder(token);
        service.writeToParcel(data, 0);
        data.writeString(resolvedType);
        // 可以看到将ServiceConnection写入到data中,发送给AMS
        data.writeStrongBinder(connection.asBinder());
        data.writeInt(flags);
        data.writeInt(userId);
        // 发送BIND_SERVICE_TRANSACTION IPC通信请求
        mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        int res = reply.readInt();
        data.recycle();
        reply.recycle();
        return res;
    
将前面获取到的sd以Binder方式发送给AMS,并发送 BIND_SERVICE_TRANSACTION IPC通信请求。

接下来到ActivityManagerNative中去处理:


5、ActivityManagerNative#onTransact:

/** @path:  \\frameworks\\base\\core\\java\\android\\app\\ActivityManagerNative.java**/
public abstract class ActivityManagerNative extends Binder implements IActivityManager 
    @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException 
        switch (code) 
            case BIND_SERVICE_TRANSACTION: 
                data.enforceInterface(IActivityManager.descriptor);
                IBinder b = data.readStrongBinder();
                IApplicationThread app = ApplicationThreadNative.asInterface(b);
                IBinder token = data.readStrongBinder();
                Intent service = Intent.CREATOR.createFromParcel(data);
                String resolvedType = data.readString();
                b = data.readStrongBinder();
                int fl = data.readInt();
                int userId = data.readInt();
                IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
                // 处理IPC请求函数
                int res = bindService(app, token, service, resolvedType, conn, fl, userId);
                reply.writeNoException();
                reply.writeInt(res);
                return true;
            
        
    
接下来使用ActivityManagerNative的子类ActivityManagerService来具体处理该应用请求:


6、ActivityManagerService#bindService:

/** @path: \\frameworks\\base\\services\\core\\java\\com\\android\\server\\am\\ActivityManagerService.java**/
public int bindService(IApplicationThread caller, IBinder token,
                       Intent service, String resolvedType,
                       IServiceConnection connection, int flags, int userId) 
    enforceNotIsolatedCaller("bindService");

    // Refuse possible leaked file descriptors
    if (service != null && service.hasFileDescriptors() == true) 
        throw new IllegalArgumentException("File descriptors passed in Intent");
    

    synchronized(this) 
        return mServices.bindServiceLocked(caller, token, service, resolvedType,
                connection, flags, userId);
    
和启动形式一样,最后交给ActiveServices去处理;


7、ActiveServices#bindServiceLocked:

/** @path: \\frameworks\\base\\services\\core\\java\\com\\android\\server\\am\\ActiveServices.java**/
int bindServiceLocked(IApplicationThread caller, IBinder token,
                      Intent service, String resolvedType,
                      IServiceConnection connection, int flags, int userId) 
    // 该ProcessRecord描述的是请求绑定该Service组件的Activity组件所运行的应用进程
    final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);

    // 获得ActivityRecord用来描述该Activity组件
    ActivityRecord activity = null;
    if (token != null) 
        activity = ActivityRecord.isInStackLocked(token);
        if (activity == null) 
            return 0;
        
    

    .....

    // 将待启动的Service组件信息封装成ServiceLookupResult
    ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType,
                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);
    .....
    // ServiceRecord用来记录该Service组件的相关信息
    ServiceRecord s = res.record;

    final long origId = Binder.clearCallingIdentity();

    try 
        .....
        // 获得AppBindRecord,表示service对应的组件绑定在callerApp所描述的应用进程中
        AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
        
        // 用来描述activity对应的Activity组件通过connection绑定到b(AppBindRecord)所对应的应用进程中的Service组件
        ConnectionRecord c = new ConnectionRecord(b, activity,
                connection, flags, clientLabel, clientIntent);
        
        IBinder binder = connection.asBinder();
        // 因为该Service组件可能被同一应用中的多个Activity组件使用同一个connection来绑定
        // 因此该Binder可能对应多个ConnectionRecord对象
        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);
        if (activity != null) 
            if (activity.connections == null) 
                activity.connections = new HashSet<ConnectionRecord>();
            
            activity.connections.add(c);
        
        b.client.connections.add(c);
        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);

        if ((flags&Context.BIND_AUTO_CREATE) != 0) 
            s.lastActivity = SystemClock.uptimeMillis();
            // bringUpServiceLocked启动Service组件
            if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) 
                return 0;
            
        
        ......
     finally 
    

    return 1;

先来看一个函数:retrieveAppBindingLocked:

public AppBindRecord retrieveAppBindingLocked(Intent intent,
        ProcessRecord app) 
    Intent.FilterComparison filter = new Intent.FilterComparison(intent);
    IntentBindRecord i = bindings.get(filter);
    if (i == null) 
        i = new IntentBindRecord(this, filter);
        bindings.put(filter, i);
    
    // 将ProcessRecord与Service组件建立起关联
    AppBindRecord a = i.apps.get(app);
    if (a != null) 
        return a;
    
    a = new AppBindRecord(this, i, app);
    i.apps.put(app, a);
    return a;

Service组件的启动机制深入学习》一文中的分析知,接下来调用bringUpServiceLocked方法来启动Service组件,接着调用realStartServiceLocked在app所描述的进程中启动该Activity组件:


注意realStartServiceLocked中有一步:

8、ActiveServices#realStartServiceLocked:

/** @path: \\frameworks\\base\\services\\core\\java\\com\\android\\server\\am\\ActiveServices.java**/
private final void realStartServiceLocked(ServiceRecord r,
                                          ProcessRecord app, boolean execInFg) throws RemoteException 
    ......
    try 
        ....
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                app.repProcState);
        ....
     catch (DeadObjectException e) 
     finally 
    

    ....
    // 这里执行进行绑定操作
    requestServiceBindingsLocked(r, execInFg);
    ....
可以看到通过scheduleCreateService启动Service组件之后,调用requestServiceBindingsLocked来执行绑定操作,由前面知启动方式的execInfg为false,即不需要绑定;

下面通过 scheduleCreateService启动Service组件的流程和Service组件的启动机制深入学习》中分析的启动流程相同;接下来分析Service组件启动之后,执行的绑定操作:


9、ActiveServices#requestBindingsLocked:

/** @path: \\frameworks\\base\\services\\core\\java\\com\\android\\server\\am\\ActiveServices.java**/
private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg) 
    // 由前面知,r.bindings中保存了一系列Service组件和app之间的绑定关系
    for (int i=r.bindings.size()-1; i>=0; i--) 
        // 执行遍历,将Service绑定到这些ProcessRecord中
        IntentBindRecord ibr = r.bindings.valueAt(i);
        if (!requestServiceBindingLocked(r, ibr, execInFg, false)) 
            break;
        
    

10、 ActiveServices#requestBindingsLocked:

/** @path: \\frameworks\\base\\services\\core\\java\\com\\android\\server\\am\\ServiceRecord.java**/
private final boolean requestServiceBindingLocked(ServiceRecord r,
                                                  IntentBindRecord i, boolean execInFg, boolean rebind) 
    if (r.app == null || r.app.thread == null) 
        // If service is not currently running, can't yet bind.
        return false;
    
    // rebind参数用以标示是否需要重新绑定
    if ((!i.requested || rebind) && i.apps.size() > 0) 
        try 
            bumpServiceExecutingLocked(r, execInFg, "bind");
            r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            // 接下来调用scheduleBindService去绑定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) 
            if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
            return false;
        
    
    return true;
代码逻辑较为简单,需要重新绑定或者i.apps中仍然有为执行完的绑定任务,都继续调用scheduleBindService来执行绑定任务;


r.app.thread的实际运行时类型为ApplicationThreadProxy。

11、 ApplicationThreadProxy#scheduleBindService:

/** @path: \\frameworks\\base\\core\\java\\android\\app\\ApplicationThreadNative.java**/
class ApplicationThreadProxy implements IApplicationThread 
    public final void scheduleBindService(IBinder token, Intent intent, boolean rebind,
                                          int processState) throws RemoteException 
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(token);
        intent.writeToParcel(data, 0);
        data.writeInt(rebind ? 1 : 0);
        data.writeInt(processState);
        mRemote.transact(SCHEDULE_BIND_SERVICE_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    
发送一个 SCHEDULE_BIND_SERVICE_TRANSACTION类型的IPC请求;


12、ApplicationThreadNative#onTransact:

/** @path: \\frameworks\\base\\core\\java\\android\\app\\ApplicationThreadNative.java**/
public abstract class ApplicationThreadNative extends Binder
        implements IApplicationThread 
    @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException 
        switch (code) 
            case SCHEDULE_BIND_SERVICE_TRANSACTION: 
                data.enforceInterface(IApplicationThread.descriptor);
                IBinder token = data.readStrongBinder();
                Intent intent = Intent.CREATOR.createFromParcel(data);
                boolean rebind = data.readInt() != 0;
                int processState = data.readInt();
                scheduleBindService(token, intent, rebind, processState);
                return true;
            
        
    

可以看到接下里调用子类ApplicationThread的scheduleBindService;


13:ApplicationThread#scheduleBindService:

/** @path: \\frameworks\\base\\core\\java\\android\\app\\ActivityThread.java**/
private class ApplicationThread extends ApplicationThreadNative 
    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);
    
类似得,通过H发送一个BIND_SERVICE请求,直接来看响应函数;


14、H:

/** @path: \\frameworks\\base\\core\\java\\android\\app\\ActivityThread.java**/
private class H extends Handler 
    public static final int BIND_SERVICE            = 121;

    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) 
        // data.token指向了一个ServiceRecord
        // 由启动过程知,mServices保存了所有启动后的Service,这里通过data.token关键字进行获取
        Service s = mServices.get(data.token);
        if (s != null) 
            try 
                data.intent.setExtrasClassLoader(s.getClassLoader());
                data.intent.prepareToEnterProcess();
                try 
                    if (!data.rebind) 
                        // 可以看到这里就是自定义Service时重写的onBind函数
                        IBinder binder = s.onBind(data.intent);
                        // 继续通过publishService来实现
                        ActivityManagerNative.getDefault().publishService(
                                data.token, data.intent, binder);
                     else  // 调用rebind情况
                        s.onRebind(data.intent);
                        ActivityManagerNative.getDefault().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    
                    ensureJitEnabled();
                 catch (RemoteException ex) 
                
             catch (Exception e) 
                .......
            
        
    
可以看到系统先根据 data.token为关键字,获取相应的Service,然后调用onBind,这里的onBind即是在自定义Service中重写的onBind方法,获取该方法中返回的Binder对象。

然后继续调用ActivityManagerNative.getDefault().publishService来处理;

由前面易知ActivityManagerNative.getDefault()的实际类型为ActivityManagerProxy:


15、ActivityManagerProxy#publishService:

/** @path:  \\frameworks\\base\\core\\java\\android\\app\\ActivityManagerNative.java**/
class ActivityManagerProxy implements IActivityManager 
    public void publishService(IBinder token,
                               Intent intent, IBinder service) throws RemoteException 
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(token);
        intent.writeToParcel(data, 0);
        data.writeStrongBinder(service);
        mRemote.transact(PUBLISH_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    

发送一个 PUBLISH_SERVICE_TRANSACTION类型的IPC请求给AMS;

中间跳转过程省略,AMS处理PUBLISH_SERVICE_TRANSACTION类型请求的方法为:ActivityManagerService.publishService


16、ActivityManagerService#publishService:

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);
    
这里会首先判断传入的参数是否为ServiceRecord,如果不是,则直接报错;

然后交托给ActiveServices的publishServiceLocked去处理;


17、ActiveServices#publishServiceLocked:

/** @path: \\frameworks\\base\\services\\core\\java\\com\\android\\server\\am\\ActiveServices.java**/
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) 
    final long origId = Binder.clearCallingIdentity();
    try 
        if (r != null) 
            Intent.FilterComparison filter
                    = new Intent.FilterComparison(intent);
            // 获得对应的IntentBindRecord对象
            IntentBindRecord b = r.bindings.get(filter);
            if (b != null && !b.received) 
                b.binder = service;
                b.requested = true;
                b.received = true; // 用来表示Services组件是否已经传递给AMS了,如果否则进入此处理函数中
                for (int conni=r.connections.size()-1; conni>=0; conni--) 
                    // 获取ConnectionRecord
                    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是InnerConnection对象,调用其connected函数来进行连接
                            c.conn.connected(r.name, service);
                         catch (Exception e) 
                        
                    
                
            

            serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
        
     finally 
        Binder.restoreCallingIdentity(origId);
    
可以看到代码中主要的是获取到之前保存的  ConnectionRecord对象,然后调用其conn变量(InnerConnection对象,其实际类型为自定义的ServiceConnection封装成的ServiceDispatcher.ServiceConnection)的connected方法进行连接;

同时可以看到同一个ServiceConnection只会连接一次,因为ConnectionRecord对象的received变量会置为true,下一调用onBind时,并不会继续跳入到绑定逻辑代码中执行connect操作;


18、LoadedApk#ServiceDispatcher#InnerConnection#connected:

/** @path: \\frameworks\\base\\core\\java\\android\\app\\LoadedApk.java**/
static final class ServiceDispatcher 
    private static class InnerConnection extends IServiceConnection.Stub 
        final WeakReference<ServiceDispatcher> mDispatcher;

        InnerConnection(ServiceDispatcher sd) 
            mDispatcher = new WeakReference<ServiceDispatcher>(sd);
        

        public void connected(ComponentName name, IBinder service) throws RemoteException 
            ServiceDispatcher sd = mDispatcher.get();
            if (sd != null) 
                sd.connected(name, service);
            
        
    
最终又会去调用 ServiceDispatcher的connected函数;


19、LoadedApk#ServiceDispatcher#connected:

/** @path: \\frameworks\\base\\core\\java\\android\\app\\LoadedApk.java**/
static final class ServiceDispatcher 
    public void connected(ComponentName name, IBinder service) 
        if (mActivityThread != null) 
            mActivityThread.post(new RunConnection(name, service, 0));
         else 
            doConnected(name, service);
        
    
由前面知mActivityThread变量即为H,这里将一个RunConnection发送到主线程中去运行;


20、RunConnection:

/** @path: \\frameworks\\base\\core\\java\\android\\app\\LoadedApk.java**/
static final class ServiceDispatcher 
    private final class RunConnection implements Runnable 
        RunConnection(ComponentName name, IBinder service, int command) 
            mName = name;
            mService = service;
            mCommand = command;
        

        public void run() 
            // 根据命令的不同,执行绑定和取消绑定操作
            if (mCommand == 0) 
                doConnected(mName, mService);
             else if (mCommand == 1) 
                doDeath(mName, mService);
            
        

        final ComponentName mName;
        final IBinder mService;
        final int mCommand;
    
RunConnection是一个Runnable,其具体的执行逻辑在run中,根据命令Command的不同,执行绑定和取消绑定操作;由19步值,command为0,则执行doConnected;


21、ServiceDispatcher#doConnected: 

/** @path: \\frameworks\\base\\core\\java\\android\\app\\LoadedApk.java**/
static final class ServiceDispatcher 
    private final ServiceConnection mConnection;
    public void doConnected(ComponentName name, IBinder service) 
        .......
        // If there is a new service, it is now connected.
        if (service != null) 
            mConnection.onServiceConnected(name, service);
        
    

    public void doDeath(ComponentName name, IBinder service) 
        mConnection.onServiceDisconnected(name);
    

ServiceDispatcher中保存了在代码中自定义的ServiceConnection,这里的绑定工作即是通过调用其onServiceConnected 来完成;


22、自定义的ServiceConnection:

// 定义ServiceConnection
private ServiceConnection conn = new ServiceConnection() 
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) 
        // 通过定义的Binder来获取Service实例来供使用
        mService = ((MyService.MyBinder) service).getService();
        Log.w(MyService.LOG_TAG, "Activity onServiceConnected");
    

    @Override
    public void onServiceDisconnected(ComponentName name) 
        mService = null;
        // 当Service被意外销毁时
        Log.w(MyService.LOG_TAG, "Activity onServiceDisconnected");
    
;
接下来就可以根据获取到的Service实例来直接对Service进行操作;


以上是关于Service绑定形式启动过程的主要内容,如果未能解决你的问题,请参考以下文章

Service工作过程

Service的启动,绑定,绑定后通信,跨应用绑定,跨应用绑定后通信

Android学习记录04——绑定形式

Android应用组件 —— Service

-四大组件的工作过程读书笔记

Laravel Service Provider 概念详解