美文网首页Android进阶之路Android开发Android开发
Android中的IPC方式——Binder(三)

Android中的IPC方式——Binder(三)

作者: Golden888 | 来源:发表于2019-07-08 16:50 被阅读4次

    Android中的IPC方式——Binder(一)
    Android中的IPC方式——Binder(二)
    基于Android5.1.1分析,因为API26以后底层相关代码变动。

    在client 中 通过bindservice来启动,来看下bindservice源码。
    其具体是在
    /frameworks/base/core/java/android/app/ContextImpl.java

    @Override
    public boolean bindService(Intent service, ServiceConnection conn,int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
    }
    
    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
        UserHandle user) {
        ...
        int res = ActivityManagerNative.getDefault().bindService(
        mMainThread.getApplicationThread(), getActivityToken(),
        service, service.resolveTypeIfNeeded(getContentResolver()),
        sd, flags, user.getIdentifier());
        ...
    }
    

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

    public abstract class ActivityManagerNative extends Binder implements IActivityManager{
        /**
        *  //最终返回的还是一个ActivityManagerProxy对象
        */
        static public IActivityManager asInterface(IBinder obj) {
            if (obj == null) {
                return null;
            }
            IActivityManager in =
                (IActivityManager)obj.queryLocalInterface(descriptor);
            if (in != null) {
                return in;
            }
    
            //这里面的Binder类型的obj参数会作为ActivityManagerProxy的成员变量保存为mRemote成员变量,负责进行IPC通信
            return new ActivityManagerProxy(obj);
        }
    
        /**
        *  //从类声明上,我们可以看到ActivityManagerNative是Binder的一个子类,而且实现了IActivityManager接口
        */
        static public IActivityManager getDefault() {
            return gDefault.get();
        }
        //通过单例模式获取一个IActivityManager对象,这个对象通过asInterface(b)获得 
        private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>(){
            protected IActivityManager create(){
            IBinder b = ServiceManager.getService("activity"); 
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b); 
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
                return am;
            }
        };
    
    }
    

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

    public interface IActivityManager extends IInterface {
        ...
        public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType,IServiceConnection connection, int flags, int userId) throws RemoteException;
        public boolean unbindService(IServiceConnection connection) throws RemoteException;
        ...
    }
    

    ActivityManagerNative.getDefault()获得IActivityManager,IActivitymanager继承于IInterface,这个结构是不是跟我们之前看的IStudentManager很像,那么IActivityManager.bindservice(),应该由它的静态内部类Proxy来实现。但是IActivityManager内部类并没有,其实是通过其他类来实现同样功能只是名称换了。这个类就是ActivityManagerNative。

    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);
                    int res = bindService(app, token, service, resolvedType, conn, fl, userId);
                    reply.writeNoException();
                    reply.writeInt(res);
                    return true;
    
                }
        }
        ...
        
        
        class ActivityManagerProxy implements IActivityManager{
            ...
            public ActivityManagerProxy(IBinder remote){
                mRemote = remote;
            }
            public IBinder asBinder()
            {
                return mRemote;
            }
            ...
            
        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);
                data.writeStrongBinder(connection.asBinder());
                data.writeInt(flags);
                data.writeInt(userId);
                mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
                reply.readException();
                int res = reply.readInt();
                data.recycle();
                reply.recycle();
                return res;
        }
    }
    

    可以看到ActivityManagerNative继承Binder实现IActivityManager,ActivityManagerNative就相当于Stub。
    ActivityManagerProxy就是Proxy。

    通过调用到的mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);调用到Stub中的onTranact(),而Stub的具体实现类则是Activity'ManagerService,最后就是在ActivityManagerService中的bindservice()

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

    public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
        
        final ActiveServices mServices;
        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);
            }
        }
    }
    

    bindservice主要分为四种情况

    • server整个进程都没有启动
    • server进程启动了,但是里面的service没有创建
    • server进程启动了,里面的service也创建了,但是没有绑定过,回调onBind()
    • server进程启动了,里面的service创建了,也被绑定过,回调onRebind()

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

    public final class ActiveServices {
        ...
        int bindServiceLocked(IApplicationThread caller, IBinder token,Intent service,  String resolvedType,IServiceConnection connection, int flags, int userId) {
            ...
            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {
                    return 0;
                }
            }
            ...
            //进程启动service也创建的情况下并且绑定了, 回调onRebind()  
            if (s.app != null && b.intent.received) {
                // Service is already running, so we can immediately
                // publish the connection.
                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);
            }
            ...
        }
        ...
        //server整个进程都没有启动,server进程启动了,但是里面的service没有创建  
        private final String bringUpServiceLocked(ServiceRecord r,int intentFlags,              boolean execInFg, boolean whileRestarting) {
            
            if (!isolated) {
                app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
                if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
                if (app != null && app.thread != null) {//进程启动了service没有创建
                    try {
                        app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                        realStartServiceLocked(r, app, execInFg);
                        return null;
                    } catch (RemoteException e) {
                        Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                    }
    
                    // If a dead object exception was thrown -- fall through to
                    // restart the application.
                }
            }
            //进程未启动的情况
            if (app == null) {
                if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                        "service", r.name, false, isolated, false)) == null) {
                    String msg = "Unable to launch app "
                            + r.appInfo.packageName + "/"
                            + r.appInfo.uid + " for service "
                            + r.intent.getIntent() + ": process is bad";
                    Slog.w(TAG, msg);
                    bringDownServiceLocked(r);
                    return msg;
                }
                if (isolated) {
                    r.isolatedProc = app;
                }
            }
        }
        
        private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
            ...
              app.thread.scheduleCreateService(r, r.serviceInfo,                                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
            ...
        }
    }
    

    对应的上述四种情况

    • server整个进程都没有启动
      bindServiceLocked()->bringUpServiceLocked() 通过mAm.startProcessLocked()启动进程,bringDownServiceLocked(r);来启动服务。

    • server进程启动了,但是里面的service没有创建
      bindServiceLocked()->bringUpServiceLocked()->realStartServiceLocked(r, app, execInFg);后续跟一下

    • server进程启动了,里面的service也创建了,但是没有绑定过,回调onBind()

      bindServiceLocked()->requestServiceBindingLocked(s, b.intent, callerFg, false);

    • server进程启动了,里面的service创建了,也被绑定过,回调onRebind()
      bindServiceLocked()->requestServiceBindingLocked(s, b.intent, callerFg, true);

    第一种情况没什么好说的,看一下第二种情况,从上面代码看到realStartServiceLocked()调用了scheduleCreateService()

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

    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);
    }
     public void handleMessage(Message msg) {
         ...
        case CREATE_SERVICE:
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
            handleCreateService((CreateServiceData)msg.obj);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            break;
        ...
     }
     private void handleCreateService(CreateServiceData data) {
         ...
         try {
                java.lang.ClassLoader cl = packageInfo.getClassLoader();
                service = (Service) cl.loadClass(data.info.name).newInstance();
            } catch (Exception e) {
                if (!mInstrumentation.onException(service, e)) {
                    throw new RuntimeException(
                        "Unable to instantiate service " + data.info.name
                        + ": " + e.toString(), e);
                }
            }
        ...
    
     }
    

    这里可以看到最后通过反射来创建service。

    第三、四种情况,都是调用的从ActiveService中requestServiceBindingLocked()只是最后一个参数不一样。

    /frameworks/base/services/core/java/com/android/server/am/ActiveServices.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;
        }
        if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
                bumpServiceExecutingLocked(r, execInFg, "bind");
                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
                if (!rebind) {
                    i.requested = true;
                }
                i.hasBound = true;
                i.doRebind = false;
            } catch (RemoteException e) {
                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
                return false;
            }
        }
        return true;
    }
    

    发现跟调用到ActivityThread.javascheduleBindService()

    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);
    }
    
    public void handleMessage(Message msg) {
         ...
     case BIND_SERVICE:
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
        handleBindService((BindServiceData)msg.obj);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        break;
        ...
     }
     private void handleBindService(BindServiceData data) {
            Service s = mServices.get(data.token);
            if (DEBUG_SERVICE)
                Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
            if (s != null) {
                try {
                    data.intent.setExtrasClassLoader(s.getClassLoader());
                    data.intent.prepareToEnterProcess();
                    try {
                        if (!data.rebind) {
                            IBinder binder = s.onBind(data.intent);
                           //重点
                            ActivityManagerNative.getDefault().publishService(
                                    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);
                    }
                }
            }
        }
    

    最后调用handleBindService()首先从mServices在这个map去取服务,服务不为空后,根据flag来判断调用onBind()还是 onReind(),s.onBind(data.intent)返回Binder。这个可以根据前面aidl使用的部分,service在OnBind()方法需要返回一个IBineder,而这个IBinder是 IStudentManager.Stub,由Service实现。

    /frameworks/base/services/core/java/com/android/server/am/ActiveServices.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);
        }
    }
    

    /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.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);
        }
    }
    

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

    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
        ConnectionRecord c = clist.get(i);
        ...
        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);
        }
        ....
    }
    

    到这里可以看到我们在service实现的onBind方法返回的 IBinder对象通过publishService()->publishServiceLocked()传递。

    ConnectionRecord.java

    final class ConnectionRecord {
        final AppBindRecord binding;    // The application/service binding.
        final ActivityRecord activity;  // If non-null, the owning activity.
        final IServiceConnection conn; 
        ...
    }
    

    c.conn.connected(r.name, service);传递的service 就是我们刚刚的IBinder,c.conn最终指的是IServiceConnection,具体实现为

    /frameworks/base/core/java/android/app/LoadedApk.javaLoadedApk.ServiceDispatcher.InnerConnection

    static final class ServiceDispatcher {
     ...
        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);
                }
            }
        }
    ...
    public void connected(ComponentName name, IBinder service) {
            if (mActivityThread != null) {
                mActivityThread.post(new RunConnection(name, service, 0));
            } else {
                doConnected(name, service);
            }
        }
    }  
    
    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;
    }
    
    public void doConnected(ComponentName name, IBinder service) {
        ...
        // If there was an old service, it is not disconnected.
        if (old != null) {
            mConnection.onServiceDisconnected(name);
        }
        // If there is a new service, it is now connected.
        if (service != null) {
            mConnection.onServiceConnected(name, service);
        }
    }
    
    

    mActivityThread.post(new RunConnection(name, service, 0));在RunConnection的run方法中调用了doConnected方法,doConnected()中调用了onServiceDisconnected()onServiceConnected()

    这个就是由我们client端创建serviceConnetion时需要实现的方法。这样最终在客户端的onServiceConnected()获取了由service实现的IBinder。

    整个的流程走完了,在我们刚刚分析中无论是AMS 还是 后面的IService 基本上都看到了类似 Binder的 方式。

    AIDL接口 Stub Proxy Stub实现类
    IStudentManager.aidl IStudentManager.Stub IStudentManager.Proxy StudentManagerService
    IActivityManager ActivityManagerNative ActivityManagerProxy ActivityManagerService

    在我们的实际项目中会使用到非常多的系统服务,这时候也是需要进行进程间通信,他们都存在不同的进程中,如果都通过aidl方式来调用就会很繁琐。所以Android给我提供了ServiceManager来统一管理。

    相关文章

      网友评论

        本文标题:Android中的IPC方式——Binder(三)

        本文链接:https://www.haomeiwen.com/subject/nudahctx.html