AMS与ApplicationThread通信

1.引言

利用几个星期的时间,搞懂以下几个问题:

  • window 添加view的过程
  • ActivityThread启动Activity得过程
  • Instrumentation 类
  • WindowManager 和Window的关系
  • Dialog 和Activity 显示流程
  • ViewRootImp学习
  • WindowManagerImpl
  • WindowManagerService 与WindowManager的交互

2.正题

transact():将 IBinder object 的引用跨进程传递到服务端,服务端回应客户端也会带上相同的IBinder 引用。transact() 是一个同步的过程,当执行到transact()得时候,会陷入阻塞状态;例如A进程向B进程通信,会将一个IBinder对象通过transact()方法发送到进程B,进程B运算好后,会调用onTransact将运算结果返回的IBinder对象,都是同一个引用。

 public final boolean transact(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException {
        if (false) Log.v("Binder", "Transact: " + code + " to " + this);

        if (data != null) {
            data.setDataPosition(0);
        }
        boolean r = onTransact(code, data, reply, flags);
        if (reply != null) {
            reply.setDataPosition(0);
        }
        return r;
    }

code参数决定了是发送数据还是接收数据。

onTransact()方法:

 protected boolean onTransact(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException {
        if (code == INTERFACE_TRANSACTION) {
            reply.writeString(getInterfaceDescriptor());//推测是向远程进程发送数据
            return true;
        } else if (code == DUMP_TRANSACTION) {//Dump  TRANSACTION 英文单词是卸载交流,大概意思就是接收到远程服务器换回 的值,
            ParcelFileDescriptor fd = data.readFileDescriptor();
            String[] args = data.readStringArray();//读取返回的结果
            if (fd != null) {
                try {
                    dump(fd.getFileDescriptor(), args);
                } finally {
                    IoUtils.closeQuietly(fd);
                }
            }
            // Write the StrictMode header.
            if (reply != null) {
                reply.writeNoException();
            } else {
                StrictMode.clearGatheredViolations();
            }
            return true;
        } else if (code == SHELL_COMMAND_TRANSACTION) {
            ParcelFileDescriptor in = data.readFileDescriptor();
            ParcelFileDescriptor out = data.readFileDescriptor();
            ParcelFileDescriptor err = data.readFileDescriptor();
            String[] args = data.readStringArray();
            ShellCallback shellCallback = ShellCallback.CREATOR.createFromParcel(data);
            ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data);
            try {
                if (out != null) {
                    shellCommand(in != null ? in.getFileDescriptor() : null,
                            out.getFileDescriptor(),
                            err != null ? err.getFileDescriptor() : out.getFileDescriptor(),
                            args, shellCallback, resultReceiver);
                }
            } finally {
                IoUtils.closeQuietly(in);
                IoUtils.closeQuietly(out);
                IoUtils.closeQuietly(err);
                // Write the StrictMode header.
                if (reply != null) {
                    reply.writeNoException();
                } else {
                    StrictMode.clearGatheredViolations();
                }
            }
            return true;
        }
        return false;
    }

ActivityThread中的attach(false),方法涉及到通过Binder通信,如何进行通信的呢?

private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {
                    ensureJitEnabled();
                }
            });
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManagerNative.getDefault(); // 重点1
            try {
                mgr.attachApplication(mAppThread);// 重点2
            } catch (RemoteException ex) {
                // Ignore
            }
            // Watch for getting close to heap limit.
        .............//省略
}

下面的是AMS与ApplicationThread 通过Binder通信中,一些相关的类:


AMS与ApplicationThread通信_第1张图片
image.png

ActivityManagerNative.getDefault() 返回的就是ActivityManagerNative的内部类ActivityManagerProxy,这个代理的构造方法需要传入一个服务端的IBinder。

ActivityManagerNative得gDefault 内部create方法有这么一句代码:

IBinder b = ServiceManager.getService("activity");
然后通过:asInterface()方法得到ActivityManagerProxy。

ActivityManagerProxy的attachApplication(applicationThread)代码如下:

 public void attachApplication(IApplicationThread app) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(app.asBinder());
        mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }

mRemote 就是我们上面ServiceManager.getService("activity")返回的,也就是AMS得BinderProxy,这个BinderProxy会将ApplicationThread的binder 传递到AMS进程,那么AMS就相当于拥有了ApplicationThread得引用。那么就可以远程调用了、

当客户端调用了startActivity得时候,会通过ipc与AMS通信,然后AMS调用Application得handleLaunchActivity(上面分析得到,AMS持有ApplicationThread得Binder)。进而执行了一下几个方法

 Activity a = performLaunchActivity(r, customIntent);//方法1
 
handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);//方法2

mInstrumentation.callActivityOnPause(r.activity);//方法3

handleResumeActivity 放先回调Activity的onResume方法,之后在将DecorView添加进Window。

 if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }
}

关于java层Binder的调用顺序描述:
binder通信是一种client-server的通信结构,
1.从表面上来看,是client通过获得一个server的代理接口,对server进行直接调用;
2.实际上,代理接口中定义的方法与server中定义的方法是一一对应的;
3.client调用某个代理接口中的方法时,代理接口的方法会将client传递的参数打包成为Parcel对象;
4.代理接口将该Parcel发送给内核中的binder driver.
5.server会读取binder driver中的请求数据,如果是发送给自己的,解包Parcel对象,处理并将结果返回;
6.整个的调用过程是一个同步过程,在server处理的时候,client会block住。


AMS与ApplicationThread通信_第2张图片
image.png

参考文章:https://blog.csdn.net/coding_glacier/article/details/7520199
参考文章:http://weishu.me/2016/01/12/binder-index-for-newer/

你可能感兴趣的:(AMS与ApplicationThread通信)