bindService过程

相关进程
1. client进程
2. system_server进程,主要是在AMS和ActiveService里面处理

3. service进程


首先由client进程发起

frameworks/base/core/java/android/app/ContextImpl.java
frameworks/base/core/java/android/content/ContextWrapper.java
activity或者service调用bindService()方法后进入ContextWrapper.java,然后再进入ContextImpl.java,最后在ContextImpl.java里面执行bindServiceCommon()方法

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
        UserHandle user) {
    IServiceConnection sd;
    ...
    if (mPackageInfo != null) {
        sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
                mMainThread.getHandler(), flags);
    } else {
        ...
    }
    
    try {
        ...

        int res = ActivityManagerNative.getDefault().bindService(
            mMainThread.getApplicationThread(), getActivityToken(), service,
            service.resolveTypeIfNeeded(getContentResolver()),
            sd, flags, getOpPackageName(), user.getIdentifier());
        ...
        
        return res != 0;
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
}
1) 首先创建LoadedApk.ServiceDispatcher.InnerConnection对象sd,该对象是专门用来与servcie链接的Binder对象.

        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) throws RemoteException {
                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
                if (sd != null) {
                    sd.connected(name, service);
                }
            }
        }
IServiceConnection.Stub是IServiceConnection.aidl文件编译后自动生成的类,专门用于binder通信.

2) 然后调用ActivityManager的bindService()方法进入AMS执行.
   重点参数: mMainThread.getApplicationThread() 是client进程的ApplicationThread对象,该对象是个binder,AMS用他来获取client进程的ProcessRecord.
            sd 是InnerConnection对象,也是一个Binder,AMS通过他最终回调client进程的onServiceConnected()方法,并将service的binder代理对象传给client.
可以看到client只是发起绑定请求,并把参数传递给AMS.核心参数是client进程的ApplicationThread对象和InnerConnection对象.

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

注意:现在进入system_server进程.

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
frameworks/base/core/java/android/app/ApplicationThreadProxy.java(ApplicationThreadProxy类其实是在ApplicationThreadNative.java文件里面)

进入系统进程,通过AMS的bindService()方法进入ActiveServices.java的bindServiceLocked().

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

            final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
            ActivityRecord activity = null;

            ......

            final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
        
            ServiceLookupResult res =
                retrieveServiceLocked(service, resolvedType, callingPackage,
                        Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);
            //获取service的ServiceRecord
            ServiceRecord s = res.record;

            ......
            
            //创建AppBindRecord和ConnectionRecord
            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
            ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent);

            //将新的链接加到链接列表中
            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);
            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);
 
            //启动service           
            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {
                    return 0;
                }
            }

            //更新service所在进程的oomAdj和Lru,也就是优先级.
            if (s.app != null) {
                if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                    s.app.treatLikeActivity = true;
                }
                // This could have made the service more important.
                mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities
                        || s.app.treatLikeActivity, b.client);
                mAm.updateOomAdjLocked(s.app);
            }

            if (s.app != null && b.intent.received) {
                // 若Service已经和client进程的其他组件绑定,那么AMS就持有他的binder,直接通过InnerConnection接口调用client的connected()方法,最终回调onServiceConnected()方法并将service的binder传给client,完成绑定.
                try {
                    c.conn.connected(s.name, b.intent.binder);
                } catch (Exception e) {
                    Slog.w(TAG, "Failure sending service " + s.shortName
                            + " to connection " + c.conn.asBinder()
                            + " (in " + c.binding.client.processName + ")", e);
                }

                // If this is the first app connected back to this binding,
                // and the service had previously asked to be told when
                // rebound, then do so.
                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                    requestServiceBindingLocked(s, b.intent, callerFg, true);
                }
            } else if (!b.intent.requested) {
                requestServiceBindingLocked(s, b.intent, callerFg, false);
            }

            getServiceMap(s.userId).ensureNotStartingBackground(s);

        } finally {
            Binder.restoreCallingIdentity(origId);
        }

        return 1;
    }
在该方法里面主要做了这几件事:
1) 获取service的ServiceRecord
2) 创建AppBindRecord和ConnectionRecord
3) 将新的链接加到service的链接列表中
4) 启动service(如果需要的话)
5) 更新service所在进程的oomAdj和Lru,也就是进程优先级.
6) 判断Service是否已经和client进程的其他组件绑定.如果已经绑定,直接通过InnerConnection接口调用client的connected()方法,最终回调onServiceConnected()方法并将service的binder代理对象BinderProxy传给client,完成绑定.

如果client进程没有组件已经与service绑定,就调用requestServiceBindingLocked()方法
该方法通过执行
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,r.app.repProcState);
进入ApplicationThreadProxy.java执行
    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();
    }
通过binder通信进入ApplicationThreadNative.java

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

注意:现在进入service进程.

frameworks/base/core/java/android/app/ApplicationThreadNative.java
frameworks/base/core/java/android/app/ActivityThread.java
首先调用ApplicationThreadNative.java的onTransact()方法

    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
     
               .......          

        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,他是ActivityThread.java的内部类,继承ApplicationThreadNative,运行在binder线程,专门用来接收AMS发过来的命令.

        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;

            if (DEBUG_SERVICE)
                Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
                        + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
            sendMessage(H.BIND_SERVICE, s);
        }
service进程主线程收到消息后对消息进行处理,调到ActivityThread的handleBindService()方法.

    private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                data.intent.setExtrasClassLoader(s.getClassLoader());
                data.intent.prepareToEnterProcess();
                try {
                    if (!data.rebind) {
                        IBinder binder = s.onBind(data.intent);                          (1)
                        ActivityManagerNative.getDefault().publishService(               (2)
                                data.token, data.intent, binder);
                    } else {
                        s.onRebind(data.intent);
                        ActivityManagerNative.getDefault().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                    ensureJitEnabled();
                } catch (RemoteException ex) {
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(s, e)) {
                    throw new RuntimeException(
                            "Unable to bind to service " + s
                            + " with " + data.intent + ": " + e.toString(), e);
                }
            }
        }
    }
(1)处调用service的onBind()方法获取service的Stub对象.Stub是binder通信的本地端.
(2)调用ActivityManager的publishService()方法进入AMS,并把service的Stub对象传过去.

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

注意:现在进入system_server进程.

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

通过AMS的publishService()方法进入ActiveService的publishServiceLocked()方法
该方法的核心语句:

                            try {
                                c.conn.connected(r.name, service);
                            } catch (Exception e) {
                                Slog.w(TAG, "Failure sending service " + r.name +
                                      " to connection " + c.conn.asBinder() +
                                      " (in " + c.binding.client.processName + ")", e);
                            }
及调用client进程InnerConnection对象connected方法回到client进程,其中参数service是service的binder代理对象BinderProxy. 这个BinderProxy是service的Stub经过Binder机制转换而来.

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

注意:现在回到client进程.

frameworks/base/core/java/android/app/LoadedApk.java

进入LoadedApk.ServiceDispatcher.InnerConnection的connected()方法
InnerConnection是ServiceDispatcher的内部类,ServiceDispatcher是LoadedApk的内部类.InnerConnection是一个binder,专门接收AMS的回调.
        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) throws RemoteException {
                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
                if (sd != null) {
                    sd.connected(name, service);
                }
            }
        }
最后调到doConnected()方法,并在该方法中执行 mConnection.onServiceConnected(name, service);这条语句回调方法,并将service的binder代理对象BinderProxy传给client进程发起绑定动作的组件.
到此,应用组件绑定其他进程中service的调用流程结束,其本质是client进程通过AMS获取其他进程中service的binder代理对象BinderProxy对象.拿到该对象后就可以进行RPC调用.

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

流程总结:
1. client进程通过调用bindService()方法进入AMS,并将client进程的ApplicationThread和InnerConnection对象传给AMS.这两个对象都是binder,AMS通过ApplicationThread获取client进程的ProcessRecord,通过InnerConnection回调 
   onServiceConnected()方法并把service的binder代理对象BinderProxy传给client进程.
2. AMS接收到绑定服务请求后,首先将链接加到service的连接列表中,判断是否需要启动service,判断是否已有client连接到目标service,如果已有连接,则直接回调onServiceConnected()方法并将service的binder传给client,完成绑定.如果
   没有连接,就向service所在进程发起连接请求.
3. service收到连接请求后, 首先通过service的onBind()方法获取service的stub对象,也就是Binder对象,然后调用ActivityManager的publishService()回到AMS,并将service的stub对象传给AMS.
4. AMS在收到service的stub对象后,将其转换为Binder代理对象BinderProxy,并调用client进程的connect方法回到client进程,并将service的BinderProxy传给client进程.
5. client进程最终调用onServiceConnected()方法将service的BinderProxy对象传给发起绑定请求的应用组件.


绑定的本质就是client进程通过AMS去service进程获取service的BinderProxy.






发布了37 篇原创文章 · 获赞 4 · 访问量 1万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览