Binder 与 四大组件工作原理 其一

Binder

Binder的组成结构

Binder的架构如图所示
在这里插入图片描述

ServiceManager负责把Binder Server注册到一个容器中。

我们可以这样理解Client、Server 、ServiceManager、Binder Driver之间的关系:

把ServiceManager比喻成电话局,存储着每个住宅的座机电话。张三给李四打电话,拨打电话号码,会转接到电话局,电话局的接线员查询到这个号码的地址,因为李四的电话号码之间在电话局注册过,所以能够拨通;如果没有注册,就会提示该号码不存在。

张三就是Client,李四就是Server,电话局就是ServiceManager,而接线员就是Binder Driver。

Binder的通信过程

Binder的通信过程和交互路线如下图所示
在这里插入图片描述

  1. Server 在 ServiceManager 这个容器中注册

  2. Client 想要调用 Server 的 add 方法,就需要先获取 Server 对象, 但是 ServiceManager 不会把真正的 Server 对象返回给 Client,而是把 Server 的一个代理对象返回给 Client ,也就是 Proxy

  3. Client 调用 Proxy 的 add 方法,Binder驱动会帮他去调用 Server 的 add 方法,并把结果返回给 Client 。

在这里插入图片描述

AIDL

创建 Book 类

在主包下面建一个 aidl 包专门存放进程通讯用到的数据, Book 类继承 Parcelable 接口(原因:AIDL 只能传送继承 Parcelable 接口的类)

package com.example.zs.ipcdemo.aidl;

import android.os.Parcel;
import android.os.Parcelable;

public class Book implements Parcelable {
    private String bookId;
    private String bookName;

    public String getBookId() {
        return bookId;
    }

    public void setBookId(String bookId) {
        this.bookId = bookId;
    }

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public static Creator<Book> getCREATOR() {
        return CREATOR;
    }

    public Book(String bookId, String bookName) {
        this.bookId = bookId;
        this.bookName = bookName;
    }

    protected Book(Parcel in) {
        bookId = in.readString();
        bookName = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(bookId);
        dest.writeString(bookName);
    }

    public void readFromParcel(Parcel in) {
        bookId = in.readString();
        bookName = in.readString();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<Book> CREATOR = new Creator<Book>() {
        @Override
        public Book createFromParcel(Parcel in) {
            return new Book(in);
        }

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
    };
}

创建 Book.aidl 、IBookManager.aidl

为什么要有 Book.aidl 类,因为只有将类在 aidl 中声明时候,AIDL 才能调用 Book 类。所以说要让 AIDL 能够传送自定义类需要 1、继承 Parcelable 接口 2、创建同名 .aidl 文件声明自己。

package com.example.zs.ipcdemo.aidl;

parcelable Book;

IBookManager.aidl 设置让客户端允许调用的接口。

package com.example.zs.ipcdemo.aidl;

import com.example.zs.ipcdemo.aidl.Book;

interface IBookManager{
    List<Book> getBookList();
    void addBook(in Book book);
}

这里面有个地方要注意一下 addBook 方法中有 in 这个类型,下面我们简单说一下 AIDL 文件中 in 类型out 类型和 inout 数据的区别。

  • in :客户端的参数输入:是把实参的值赋值给行参 那么对行参的修改,不会影响实参的值 。
  • out :服务端的参数输入:传递以后,行参和实参都是同一个对象,只是他们名字不同而已,对行参的修改将影响实参的值。
  • inout:这个可以叫输入输出参数,客户端可输入、服务端也可输入。客户端输入了参数到服务端后,服务端也可对该参数进行修改等,最后在客户端上得到的是服务端输出的参数。

我们手动 ReBuild 一下我们的项目系统在这个目录下app\build\generated\source\aidl\debug 为我们自动生成 IBookManger.java ,接下来让我们看一下 IBookManger.java 的庐山真面目。

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: E:\\GitHub\\IPCDemo\\app\\src\\main\\aidl\\com\\example\\zs\\ipcdemo\\aidl\\IBookManager.aidl
 */
package com.example.zs.ipcdemo.aidl;

public interface IBookManager extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.example.zs.ipcdemo.aidl.IBookManager {
        private static final java.lang.String DESCRIPTOR = "com.example.zs.ipcdemo.aidl.IBookManager";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.example.zs.ipcdemo.aidl.IBookManager interface,
         * generating a proxy if needed.
         */
        public static com.example.zs.ipcdemo.aidl.IBookManager asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.example.zs.ipcdemo.aidl.IBookManager))) {
                return ((com.example.zs.ipcdemo.aidl.IBookManager) iin);
            }
            return new com.example.zs.ipcdemo.aidl.IBookManager.Stub.Proxy(obj);
        }

        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_getBookList: {
                    data.enforceInterface(DESCRIPTOR);
                    java.util.List<com.example.zs.ipcdemo.aidl.Book> _result = this.getBookList();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
                case TRANSACTION_addBook: {
                    data.enforceInterface(DESCRIPTOR);
                    com.example.zs.ipcdemo.aidl.Book _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = com.example.zs.ipcdemo.aidl.Book.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addBook(_arg0);
                    reply.writeNoException();
                    return true;
                }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.example.zs.ipcdemo.aidl.IBookManager {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            @Override
            public java.util.List<com.example.zs.ipcdemo.aidl.Book> getBookList() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<com.example.zs.ipcdemo.aidl.Book> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.example.zs.ipcdemo.aidl.Book.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public void addBook(com.example.zs.ipcdemo.aidl.Book book) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((book != null)) {
                        _data.writeInt(1);
                        book.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            @Override
            public void registerListener(com.example.zs.ipcdemo.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeStrongBinder((((listener != null)) ? (listener.asBinder()) : (null)));
                    mRemote.transact(Stub.TRANSACTION_registerListener, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            @Override
            public void unregisterListener(com.example.zs.ipcdemo.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeStrongBinder((((listener != null)) ? (listener.asBinder()) : (null)));
                    mRemote.transact(Stub.TRANSACTION_unregisterListener, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }

        static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);

    }

    public java.util.List<com.example.zs.ipcdemo.aidl.Book> getBookList() throws android.os.RemoteException;

    public void addBook(com.example.zs.ipcdemo.aidl.Book book) throws android.os.RemoteException;
}

刚看有点蒙逼,别急我们一步一步分析,IBookManager 文件中,包括 IBookManager.aidl 的两个接口,以及 Stub 和 Proxy 两个实现了 IBookManager 接口的类,其中 Stub 是定义在 IBookManager 接口中的,而 Proxy 则定义在 Stub 类中。

在这里插入图片描述

Client 执行流程

1、当服务连接建立完成后,客户端执行代码。IBookManager.Stub.asInterface(service) 这句代码的作用是判断传入的参数 IBinder 对象和自己是否在同一个进程如果不是则把这个IBinder 参数包装成一个 Proxy 对象,这时调用 StubgetBookList() 方法,间接调用 ProxygetBookList() 方法,看一下代码。

// 连接服务
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(final ComponentName name, IBinder service) {
            //  IBinder 通过 asInterface 判断
            //  asInterface方法的作用是判断参数——也就是IBinder对象,和自己是否在同一个进程:
            //  是: 则直接转换、直接使用,接下来就跟 Binder 跨进程通信无关啦
            //  否: 则把这个IBinder参数包装成一个 Proxy 对象,这时调用 Stub 的方法,间接调用Proxy的方法
            IBookManager bookManager = IBookManager.Stub.asInterface(service);
            try {
                mBookManager = bookManager;
                bookManager.getBookList();
                Log.d(TAG, "get books count:" + bookManager.getBookList().size());
                bookManager.registerListener(arrivedListener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mBookManager = null;
        }
    };
public static com.example.zs.ipcdemo.aidl.IBookManager asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            // 作用是判断传入的参数 IBinder 对象和自己是否在同一个进程
            if (((iin != null) && (iin instanceof com.example.zs.ipcdemo.aidl.IBookManager))) {
                return ((com.example.zs.ipcdemo.aidl.IBookManager) iin);
            }
            return new com.example.zs.ipcdemo.aidl.IBookManager.Stub.Proxy(obj);
        }

2、Proxy 在自己的 getBookList() 方法中,会使用 Parcelable 来准备数据,把函数名称、函数参数都写入 _data,让 _reply 接收函数返回值。最后使用 IBindertransact() 方法,把数据就传给 BinderServer 端了。

 @Override
            public java.util.List<com.example.zs.ipcdemo.aidl.Book> getBookList() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<com.example.zs.ipcdemo.aidl.Book> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    // 通知服务器调用该方法
                    mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
                    
                    /** 调用mRemote.transact()方法后,Binder驱动会挂起当前客户端线程,
                     * 并向服务端发送一个消息,这个消息就包括客户端传递的参数。
                     * 服务端接收到消息,解析数据执行完相关任务后会把执行结果写入reply中,
                    **/ 然后向Binder驱动发送一个notify消息,Binder驱动从挂起处唤醒客户端线程继续执行。
                    
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.example.zs.ipcdemo.aidl.Book.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

mRemote指什么?
当一个Server Binder被创建时其在Binder驱动中同时会创建一个mRemote引用指向该Server。Client端要访问Server时首先要获取Server在Binder中的引用mRemote,获取引用后就可以通过mRemote.transact()方法向服务端发送消息。

transact做了以下几件事

  • 以线程间消息通信的模式向服务端发送客户端传递过来的参数。
  • 挂起当前客户端线程,等待服务端线程执行完毕后的通知(notify)
  • 接收服务端线程通知,继续执行客户端线程,并返回执行结果
Server 执行流程

Server 则是通过 onTransact() 方法接收 Client 进程传过来的数据,包括函数名称、函数参数,找到对应的函数,这里是 getBookList() ,把参数喂进去,得到结果,返回。所以 onTransact() 函数经历了读数据、执行要调用的函数、把执行结果再写数据的过程。

 @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                // 客户端调用指令 getBookList()
                case TRANSACTION_getBookList: {
                    data.enforceInterface(DESCRIPTOR);
                    // 调用本地服务 getBookList() 方法
                    java.util.List<com.example.zs.ipcdemo.aidl.Book> _result = this.getBookList();
                    reply.writeNoException();
                    // 将数据传给客户端
                    reply.writeTypedList(_result);
                    return true;
                }
                case TRANSACTION_addBook: {
                    data.enforceInterface(DESCRIPTOR);
                    com.example.zs.ipcdemo.aidl.Book _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = com.example.zs.ipcdemo.aidl.Book.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addBook(_arg0);
                    reply.writeNoException();
                    return true;
                }
            return super.onTransact(code, data, reply, flags);
        }

四大组件的工作原理

Activity的工作原理
App是怎样启动的

在手机屏幕上点击某个App的图标,假设是斗鱼app,这个APP的首页面就会展示在我们面前,看似简单的操作,背后经历了Activity和AMS的反反复复的通信过程。首选要搞清楚手机屏幕是一个Activity,这个Activity所在的app,业界称之为Launcher,Launcher是各大手机厂商提供的。

Launcher为每个app的图标提供了启动这个app所需要的Intent信息,如:包名、首页面地址、category等等,这些信息是app安装的时候,PackageManagerService从各个apk包中的AndroidManifest文件中读取到的。

启动流程

①Launcher通知ATMS,要启动斗鱼app,而且指定了启动app的哪个页面

②ATMS收到消息后,把要启动的页面记录下来

③Launcher当前页面进入Paused状态,然后通知ATMS,“你去找对应的app吧”

④ATMS检查斗鱼app是否已经启动了,是,则唤起斗鱼app,否,就要启动一个新的进程,ATMS所在的新进程中创建一个ActivityThread对象,启动相对应的main函数

⑤app启动后,通知ATMS,“我启动好了”

⑥ATMS翻出之前记录下的值(要启动的页面),告诉斗鱼app,启动这个页面

⑦斗鱼app启动首页,创建Context并与首页Activity关联,然后调用启动页面的Activity的onCreate函数

流程至此完成,分为两部分,1~3 阶段:Launcher和AMS相互通信,4~7阶段:斗鱼app与AMS相互通信

第一阶段:Launcher通知ATMS

点击Launcher上的app之后,会调用Launcher的startActivitySafely方法,其实还是会调用Activity的startActivity方法,startActivity方法中需要传入参数Intent,intent中带着要启动app所需要的关键信息,如:启动的页面类名等等,所以为什么要在Manifest中给首页面指定的action和category呢,就是在启动的时候Launcher会找到这个关键信息进行启动

packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
# Launcher.java
@Override
public boolean startActivitySafely(View v, Intent intent, ItemInfo item,
        @Nullable String sourceContainer) {
    if (!hasBeenResumed()) {
		
        addOnResumeCallback(() -> startActivitySafely(v, intent, item, sourceContainer));
        if (mOnDeferredActivityLaunchCallback != null) {
            mOnDeferredActivityLaunchCallback.run();
            mOnDeferredActivityLaunchCallback = null;
        }
        return true;
    }

   // 调用了父类BaseDraggingActivity的startActivitySafely,最终会执行到父类Activity的startActivity
    boolean success = super.startActivitySafely(v, intent, item, sourceContainer);
    if (success && v instanceof BubbleTextView) {

        BubbleTextView btv = (BubbleTextView) v;
        btv.setStayPressed(true);
        addOnResumeCallback(btv);
    }
    return success;
}

最终调用到Activity的startActivity方法:

# Activity.java
@Override
public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)
        && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY)) {
        if (TextUtils.equals(getPackageName(),
                             intent.resolveActivity(getPackageManager()).getPackageName())) {
            // Apply Autofill restore mechanism on the started activity by startActivity()
            final IBinder token =
                mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
            // Remove restore ability from current activity
            mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
            mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY);
            // Put restore token
            intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
            intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true);
        }
    }
    if (options != null) {
        //-1为requestCode表明不需要知道是否启动成功
        startActivityForResult(intent, -1, options);
    } else {
        startActivityForResult(intent, -1);
    }
}

启动app时候,调来调去最终会调用Activity的startActivityForResult方法,startActivityForResult的代码如下:

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        //启动app时,因为是启动的第一个activity,所以mParent为空
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            //执行Instrumentation的execStartActivity
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                //向ActivityThread发送上一步的返回值
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            //省略部分代码
        } else {
            //省略部分代码
        }
    }

每个activity都持有一个Instrumentation对象,mMainThread变量,这是一个ActivityThread类型的变量,就是主线程,也就是UI线程,它代表了整个app,读者不禁要问,ActivityThread代表了App应用程序,那么Application类代表什么?其实,Application对于android系统来说并没有那么重要,它只是个上下文,Application是app的上下文,ContextActivity的上下文。

这个函数中传入了mMainThread.getApplicationThread(),它获取到的是ActivityThread的内部类ApplicationThread,这是一个Binder对象,代表了launcher所在的app进程,mToken也是一个Binder对象,代表launcher这个Activity,也通过Instumentation传给ATMS,ATMS查询记录就知道是谁向ATMS发送请求了,之后ATMS通过此对象(ApplicationThread)与app通信

查看mInstrumentation.execStartActivity方法,借助execStartActivity,Activity会把数据传递给ActivityTaskManager
ActivityTaskManager.getService()通过AIDL的方式得到IActivityTaskManager,它是ActivityTaskManagerService的binder引用,这里远程调用了ActivityTaskManagerService的功能,它是一个实现了IInterface的接口,里面定义了四大组件的生命周期,启动Activity的时候,和ATMS通信机制是AIDL方式。

# Instrumentation.java

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
   ...

    try {
		// 流程就从Launcher进程进入到AMS所在的SystemServer进程了
        int result = ActivityTaskManager.getService().startActivity(whoThread,
                who.getBasePackageName(), who.getAttributionTag(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()), token,
                target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
       ...
    }
    return null;
}

//=========ActivityTaskManager.java=========
public static IActivityTaskManager getService() {
    return IActivityTaskManagerSingleton.get();
}

@UnsupportedAppUsage(trackingBug = 129726065)
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton = new Singleton<IActivityTaskManager>() {
    @Override
    protected IActivityTaskManager create() {
        final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
        return IActivityTaskManager.Stub.asInterface(b);
    }
};


//=================Singleton.java=========
        /**
         * Singleton helper class for lazily initialization.
         * ......
         */
        public abstract class Singleton<T> {
            private T mInstance;

            protected abstract T create();

            public final T get() {
                synchronized (this) {
                    if (mInstance == null) {
                        mInstance = create();
                    }
                    return mInstance;
                }
            }
        }

IActivityTaskManager是一个代理ATMS端Binder的对象,之后ATMS开始startActivity。 到这里Launcher向ATMS请求启动一个Activity的流程就结束了。

第二阶段:ATMS处理Launcher传过来的信息

1:Launcher通过AIDL和AMS进行通信,肯定每次是做不同的事,比如这次Launcher要启动斗鱼app,那么Launcher的startActivity方法最终都会通过拿到ATSM的代理IActivityTaskManager调用的startActivity,之后进入system server进程中的ATMS startActivity,ATMS 经过收集Intent信息知道要启动哪个Activity

2:AMS说:“好了,我知道了”,然后会检查AndroidManifest文件,检查是否存在要启动的Activity,如果不存在就抛出Activity not found异常信息

3:AMS通知Launcher:“没你什么事了,洗洗睡吧”,那么AMS是通过什么途径告诉Launcher的呢?结论是:AMS通过IApplicationThread的代理发送消息,而App端则通过ApplicationThread来接受这个消息,还是AIDL的方式。

回到代码,ActivityTaskManagerServicestartActivity 调用最终调用了startActivityAsUser,通过一系列 builder 获取 ActivityStarter 并设置对应参数,最终执行ActivityStarter的 execute方法,execute 函数的作用就是根据前面提供的的请求参数并开始启动应用

private int startActivityAsUser(IApplicationThread caller, String callingPackage,
            @Nullable String callingFeatureId, Intent intent, String resolvedType,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
        assertPackageMatchesCallingUid(callingPackage);
        enforceNotIsolatedCaller("startActivityAsUser");

        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        // TODO: Switch to user app stacks here.
        // getActivityStartController().obtainStarter获取到的是ActivityStarter
        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setCallingFeatureId(callingFeatureId)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setUserId(userId)
                .execute();

    }
ActivityStarter

ActivityStarter:专门负责一个 Activity 的启动操作。它的主要作用包括解析 Intent、创建 ActivityRecord、如果有可能还要创建 TaskRecord
obtainStarter 返回的类型是 ActivityStarter,其 execute 函数的作用就是根据前面提供的的请求参数并开始启动应用。

关键调用路径:

execute ===>> executeRequest ====>> startActivityUnchecked ===>> startActivityInner

  • exexute: 处理 Activity 启动请求的接口;
  • executeRequest: 执行一系列权限检查,对于合法的请求才继续;
  • startActivityUnchecked: 调用该方法时表示大部分初步的权限检查已经完成,执行 Trace,以及异常处理;
  • startActivityInner: 启动 Activity,并更新全局的 task 栈帧信息;

忽略 ActivityStack、WindowContainer 等任务窗口管理的代码,只关注其中真正启动应用相关的:

  • mRootWindowContainer.resumeFocusedTasksTopActivities()

resumeFocusedStacksTopActivities()先将目标Activity Stack移到前台,然后创建好Activity后放到Stack里,用户就能直接看到了,所以,创建Activity的逻辑还在resumeFocusedStacksTopActivities()中

boolean resumeFocusedStacksTopActivities(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (!mStackSupervisor.readyToResume()) { return false;}
        ......
        if (targetStack != null && (targetStack.isTopStackInDisplayArea()
        || getTopDisplayFocusedStack() == targetStack)) {
    result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
ActivityStack

ActivityStack:管理TaskRecord的,包含了多个TaskRecord · ActivityStackSupervisor:管理ActivityStack
resumeTopActivityUncheckedLocked ===>> resumeTopActivityInnerLocked

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    ...
        if (mResumedActivity != null) {
      // 暂停Launcher
       pausing |= startPausingLocked(userLeaving, false , next);
    }
		// 启动Activity
        mStackSupervisor.startSpecificActivity(next, true, true);
    ...
}

startPausingLocked方法主要是通知Launcher进入Pause状态。前面我们了解了Launcher与ATMS的通信,现在我们看看ATMS是如何与Launcher通信的?


final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
        ActivityRecord resuming, boolean pauseImmediately) {
    ..........
    if (prev.app != null && prev.app.thread != null) {//条件满足
    ............
        try {
            ............
 
            //下面的代码,就是暂停Launcher,这是AMS与ActivityThread交互的内容,暂时不讨论
            //prev.appToken为IApplicationToken.Stub,prev.finishing为false,userLeaving为true,异步执行
            mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
                    PauseActivityItem.obtain(prev.finishing, userLeaving,
                            prev.configChangeFlags, pauseImmediately));
            .........
        }
    } else {
        ............
    }
............

mService是ATMS
mService.getLifecycleManager()返回的是ClientLifecycleManager;
PauseActivityItem继承自ActivityLifecycleItem,它封装了一系列将要进行IPC的操作;

ClientLifecycleManager

该类能够组合多个生命周期转换请求和/或回调,并将它们作为单个事务执行。主要作用就是生命周期的管理调用。

void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
        @NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
    //ClientTransaction封装传进来的参数
    final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
            stateRequest);
    //执行传输操作
    scheduleTransaction(clientTransaction);
}
 
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    //client就是IApplicationThread
    final IApplicationThread client = transaction.getClient();
    //下面这句代码就是跨进程了
    transaction.schedule();
    if (!(client instanceof Binder)) {
        transaction.recycle();
    }
}

调用ClientTransaction .schedule():

public void schedule() throws RemoteException {
    //mClient就是IApplicationThread,接下来会通过IPC的方式调用
    //Launcher的ActivityThread.ApplicationThread.scheduleTransaction方法;
    //从AMS进程,进入App进程
    mClient.scheduleTransaction(this);
}

这里开始,实际就是从系统进程回到了应用进程。

IApplicationThread:是系统进程持有的app进程中ApplicationThread的Binder代理对象。

mClient.scheduleTransaction()方法的实现在客户端的ApplicationThread中,接下来就要进入ActivityThread.ApplicationThread了;

ApplicationThread

ApplicationThread:ActivityThread的内部类。AMS通过binder代理调用到ApplicationThread中的方法后,通过主线程(ActivityThread中的main方法)中开启的handler消息轮询来通知主线程调用相关方法。主线程的相关生命周期方法的具体实现会委托给Instrumentation类实现,在Instrumentation类中,会调用具体组件的相关生命周期方法。

public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    //终于从AMS进程,进入到了App进程
    ActivityThread.this.scheduleTransaction(transaction);
}
 
void scheduleTransaction(ClientTransaction transaction) {
    //准备工作,它会执行ActivityLifecycleItem的preExecute()方法,这里就是PauseActivityItem
    transaction.preExecute(this);
    //发送通知,由ActivityThread接收
    sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}

ApplicationThread向ActivityThread的H发送了一个EXECUTE_TRANSACTION消息,ActivityThread与ApplicationThread之间通过Handler来通信。


case EXECUTE_TRANSACTION:
    //取出传递过来的ClientTransaction
    final ClientTransaction transaction = (ClientTransaction) msg.obj;
    //执行transaction
    mTransactionExecutor.execute(transaction);
    if (isSystem()) {
        transaction.recycle();
    }
    break;

拿到ATMS端的ClientTransaction,调用mTransactionExecutor.execute(transaction):

public void execute(ClientTransaction transaction) {
    //token就是IApplicationToken.Stub
    final IBinder token = transaction.getActivityToken();
 
    //执行Callbacks,后面分析的LaunchActivityItem就是在这里执行的,本例中暂时没有Callbacks
    executeCallbacks(transaction);
 
    //我们要看的是这个
    executeLifecycleState(transaction);
    mPendingActions.clear();
}
private void executeLifecycleState(ClientTransaction transaction) {
        //得到ActivityLifecycleItem,本例中是PauseActivityItem
        final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
        if (lifecycleItem == null) {
            // No lifecycle request, return early.
            return;
        }
        log("Resolving lifecycle state: " + lifecycleItem);
 
        //得到token
        final IBinder token = transaction.getActivityToken();
        final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
 
        if (r == null) {
            // Ignore requests for non-existent client records for now.
            return;
        }
 
        //Activity.onStart方法就是在这里面调用的,后面会看到;
        //本次流程中的lifecycleItem是PauseActivityItem,所以lifecycleItem.getTargetState()为4;
        cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);
 
        //将动作传递给lifecycleItem执行,lifecycleItem在AMS进程当中,这里又进行了IPC
        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        //上面的execute方法主要是app进程中的pause操作,当app进程中的pause操作结束之后,需要通知AMS进程,进行下一步操作
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
    }

①cycleToPath():
比如某一个Activity A,它现在的生命周期是onCreate阶段,用1来表示;lifecycleItem.getTargetState()跟lifecycleItem的类型有关,PauseActivityItem与ResumeActivityItem的getTargetState()返回值是不一样的,假如这里的lifecycleItem是ResumeActivityItem,ResumeActivityItem对应的生命周期是Activity的onResume,那lifecycleItem.getTargetState()的返回值是3,由于onCreate代表1,1和3之间差个2,所以onCreate和onResume中间还差一个生命周期,这个生命周期就是onStart();

经过一系列的方法调用 execute ===>> executeLifecycleState ===> cycleToPath ===> lifecycleItem.execute
调用到了PauseActivityItem.execute()方法

PauseActivityItem.java
public void execute(ClientTransactionHandler client, IBinder token,
        PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
    //client是在app进程中的,ActivityThread实现了ClientTransactionHandler.handlePauseActivity()方法
    client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions,
            "PAUSE_ACTIVITY_ITEM");
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

又回到了ActivityThread.handlePauseActivity():

ActivityThread.java
public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
        int configChanges, PendingTransactionActions pendingActions, String reason) {
    ActivityClientRecord r = mActivities.get(token);
    if (r != null) {
        if (userLeaving) {//成立
            //调用onUserInteraction()和onUserLeaveHint()函数
            performUserLeavingActivity(r);
        }
 
        r.activity.mConfigChangeFlags |= configChanges;
        //执行暂停Launcher的操作
        performPauseActivity(r, finished, reason, pendingActions);
 
        // Make sure any pending writes are now committed.
        //isPreHoneycomb()判断SDK版本是否是HONEYCOMB之前的版本
        if (r.isPreHoneycomb()) {
            //等待要暂停的应用进程的异步操作完成,保持数据完整
            QueuedWork.waitToFinish();
        }
        mSomeActivitiesChanged = true;
    }
}
private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
        PendingTransactionActions pendingActions) {
    ...
    final boolean shouldSaveState = !r.activity.mFinished && r.isPreHoneycomb();
    //暂停前保存状态
    if (shouldSaveState) {
        //调用onSaveInstanceState()保存Activity的状态
        callActivityOnSaveInstanceState(r);
    }
 
    //真正的暂停执行操作在这里
    performPauseActivityIfNeeded(r, reason);
 
    //通知OnActivityPausedListener执行其监听操作
    ArrayList<OnActivityPausedListener> listeners;
    synchronized (mOnPauseListeners) {
        listeners = mOnPauseListeners.remove(r.activity);
    }
    int size = (listeners != null ? listeners.size() : 0);
    for (int i = 0; i < size; i++) {
        listeners.get(i).onPaused(r.activity);
    }
 
    final Bundle oldState = pendingActions != null ? pendingActions.getOldState() : null;
    if (oldState != null) {
        if (r.isPreHoneycomb()) {
            r.state = oldState;
        }
    }
 
    return shouldSaveState ? r.state : null;
}

继续看performPauseActivity()中的performPauseActivityIfNeeded(r, reason):

private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
 ...
    try {
        r.activity.mCalled = false;
        //重点在这里,Activity.onPause方法的调用
        mInstrumentation.callActivityOnPause(r.activity);
        ...
    } catch (SuperNotCalledException e) {
        throw e;
    } catch (Exception e) {
        if (!mInstrumentation.onException(r.activity, e)) {
            throw new RuntimeException("Unable to pause activity "
                    + safeToComponentShortString(r.intent) + ": " + e.toString(), e);
        }
    }
    //设置当前的状态为ON_PAUSE
    r.setState(ON_PAUSE);
}

ActivityThread将暂停工作委托给了Instrumentation,每个Activity都持有一个Instrumentation,最后又交给了Activity的performPause

Instrumentation.java
public void callActivityOnPause(Activity activity) {
    activity.performPause();
}
 
Activity.java
final void performPause() {
    mDoReportFullyDrawn = false;
    //改变Fragment的状态
    mFragments.dispatchPause();
    mCalled = false;
    //调用Activity的生命周期onPause()方法
    onPause();
    writeEventLog(LOG_AM_ON_PAUSE_CALLED, "performPause");
    //此时已经是非mResumed状态
    mResumed = false;
    if (!mCalled && getApplicationInfo().targetSdkVersion
            >= android.os.Build.VERSION_CODES.GINGERBREAD) {
        throw new SuperNotCalledException(
                "Activity " + mComponent.toShortString() +
                " did not call through to super.onPause()");
    }
}
总结

通过 IApplicationThread 的 schedulePauseActivity 方法发起 binder 跨进程调用,进入到应用进程的 ApplicationThread 的 schedulePauseActivity 方法(该方法运行在客户端的 binder 线程池里面),再经过 mH 将数据切换到应用进程的主进程中执行,由 ActivityThread 的 handlePauseActivity 方法处理,再经过 performPauseActivity 内部调用 Instrumentation 的 callActivityOnPause 方法,内部会调用 Activity 的 performPause 方法,会回调 Launcher 的 onPause 方法。

第三阶段:Launcher去休眠,然后通知ATMS,“我休眠了

当Launcher处于onPause状态后,需要通知AMS进程,进行下一步操作,调用PauseActivityItem.postExecute():

public void postExecute(ClientTransactionHandler client, IBinder token,
        PendingTransactionActions pendingActions) {
    if (mDontReport) {
        return;
    }
    try {
        //调用ATMS的activityPaused()方法
         ActivityTaskManager.getService().activityPaused(token);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
}
第四阶段:ATMS启动新的进程

ATMS接下来要启动斗鱼App的首页,因为此app不在后台进程中,所以要启动一个新的进程,这里调用的是Process.start方法,并且指定了ActivityThread的main函数为入口函数。

ActivityStack.resumeTopActivityInnerLocked ===>> startSpecificActivity

void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
    // 获取启动的activity进程信息
    final WindowProcessController wpc =
            mService.getProcessController(r.processName, r.info.applicationInfo.uid);

    boolean knownToBeDead = false;
    //如果进程存在,并且进程中有线程存在,就启动一个同应用的activity
    if (wpc != null && wpc.hasThread()) {
        try {
            realStartActivityLocked(r, wpc, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }

        // If a dead object exception was thrown -- fall through to
        // restart the application.
        knownToBeDead = true;
    }

    //否则通过AMS向Zygote进程请求创建新进程
    r.notifyUnknownVisibilityLaunchedForKeyguardTransition();

    final boolean isTop = andResume && r.isTopRunningActivity();
    mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}

第五阶段:新进程启动,以ActivityThread的main函数为入口

启动新进程,就是启动一个新的app,为这个进程创建ActivityThread对象,这就是我们熟悉的UI主线程。创建好UI线程后,立刻进入ActivityThread的main函数,接下来要做两件具有重大意义的事:

  • ①创建一个主线程Looper,也就是MainLooper,MainLooper就是在这里创建的

  • ②创建Applicaition,Application也是在这里创建的

public static void main(String[] args) {
    ............
 
    //设置临时进程名为<pre-initialized>
    Process.setArgV0("<pre-initialized>");
 
    //准备UI主线程的消息循环
    Looper.prepareMainLooper();
 
    ............
 
    //创建ActivityThread,并调用attach 方法,传入的参数为false
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);
 
    ............
 
    /// M: ANR Debug Mechanism
    mAnrAppManager.setMessageLogger(Looper.myLooper());
    //进入主线程消息循环
    Looper.loop();
 
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

创建了ActivityThread,并调用attach方法:

final ApplicationThread mAppThread = new ApplicationThread();
private void attach(boolean system, long startSeq) {
    ......
    if (!system) {
        //这一步是获取AMS实例
        final IActivityManager mgr = ActivityManager.getService();
        //然后跨进程通信
        mgr.attachApplication(mAppThread, startSeq);
    } 
}

通过获取AMS,进行跨进程通信,调用AMS的attachApplication方法

在AMS.attachApplication()中,会调用ActivityThread.ApplicationThread.bindApplication():

public final void bindApplication(String processName, .........) {
    ............
 
    //bindApplication将ActivityManagerService传入的数据封装到AppBindData中
    AppBindData data = new AppBindData();
    data.processName = processName;
 	............
 
    //通过BIND_APPLICATION消息发送给应用程序主线程的消息循环中,由ActivityThread的H.handleMessage处理。
    sendMessage(H.BIND_APPLICATION, data);
}
public void handleMessage(Message msg) {
    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    switch (msg.what) {
        case BIND_APPLICATION:
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
            AppBindData data = (AppBindData)msg.obj;
            handleBindApplication(data);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            break;
            ...
    }
}
private void handleBindApplication(AppBindData data) {
    ............
    // 创建一个对应的`LoadedApk`对象
       data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
  
 
    //创建并初始化应用程序的ContextImpl 
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    updateLocaleListFromAppContext(appContext,
            mResourcesManager.getConfiguration().getLocales());
 
    ............
 
 
    if (ii != null) {
        ............
    } else {
        //创建并且初始化mInstrumentation
        mInstrumentation = new Instrumentation();
        mInstrumentation.basicInit(this);
    }
 
    ............
 
    Application app;
    final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
    final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
    try {
        //创建应用程序Application,对应AndroidManifest.xml的Application
        app = data.info.makeApplication(data.restrictedBackupMode, null);
 
        app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);
 
        //将第一个Application视为进程的初始Application
        mInitialApplication = app;
 
        //安装该应用程序的ContentProvider
        if (!data.restrictedBackupMode) {
            if (!ArrayUtils.isEmpty(data.providers)) {
                installContentProviders(app, data.providers);
                mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
            }
        }
 
        try {
            //调用Instrumentation的onCreate方法
            mInstrumentation.onCreate(data.instrumentationArgs);
        }
        catch (Exception e) {
            ............
        }
        try {
            //调用Application的onCreate方法
            mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
           ............
        }
    } finally {
       ............
    }
    ............
}

//Application.java
public void onCreate() {
}

public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
        CompatibilityInfo compatInfo) {
    return getPackageInfo(ai, compatInfo, null, false, true, false);
}

通过 getPackageInfoNoCheck() 创建LoadedApk对象并保存在data.info。
通过data.info.makeApplication(data.restrictedBackupMode, null)创建了Application。
通过mInstrumentation.callApplicationOnCreate(app)调用了app.onCreate();,Application创建完成。

主线程在收到BIND_APPLICATION消息后,根据传递过来的ApplicationInfo创建一个对应的LoadedApk对象(标志当前apk信息),然后创建ContextImpl对象(标志当前进程环境),紧接着通过反射创建目标Application,并调用其attach方法,将ContextImpl对象设置为目标Applcation的上下文环境,最后调用Application的onCreate函数,做一些初始化工作

App的灵魂是ActivityTread,也就是主线程,app开发人员用不到,但使用反射是可以修改这个类的一些行为的。

APP的bindApplication,主要初始化了AppBindData,然后发送BIND_APPLICATION给APP的主线程BIND_APPLICATION,最后执行了handleBindApplication,该方法主要在App进程中对App的一些硬件资源配置申请的属性、App的文件夹等完成App基本信息的初始化

ATMS的attachApplication

创建App的最后就是要告诉ATMS,“我启动好了”,同时把自己的ActivityThread对象发送给ATMS,ATMS电话簿中就多了这个新的App登记信息,ATMS以后就通过这个ActivityThread对象,向这个App发送消息。这部分代码是在:

//ActivityManagerService.java:
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
    if (thread == null) {
        throw new SecurityException("Invalid application interface");
    }
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        Binder.restoreCallingIdentity(origId);
    }
}
 
@GuardedBy("this")
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
 
    // Find the application record that is being attached...  either via
    // the pid if we are running in multiple processes, or just pull the
    // next app record if we are emulating process with anonymous threads.
    ProcessRecord app;
    long startTime = SystemClock.uptimeMillis();
    long bindApplicationTimeMillis;
    if (pid != MY_PID && pid >= 0) {
        synchronized (mPidsSelfLocked) {
            app = mPidsSelfLocked.get(pid);
        }
    ......
    final String processName = app.processName;
    ......
    final BackupRecord backupTarget = mBackupTargets.get(app.userId);
    try {
        ......
        mAtmInternal.preBindApplication(app.getWindowProcessController());
        final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
        if (app.isolatedEntryPoint != null) {
            // This is an isolated process which should just call an entry point instead of
            // being bound to an application.
            thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
        } else if (instr2 != null) {
            thread.bindApplication(processName, appInfo, providers,
                    instr2.mClass,
                    profilerInfo, instr2.mArguments,
                    instr2.mWatcher,
                    instr2.mUiAutomationConnection, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.isPersistent(),
                    new Configuration(app.getWindowProcessController().getConfiguration()),
                    app.compat, getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, autofillOptions, contentCaptureOptions);
        } else {
            thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                    null, null, null, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.isPersistent(),
                    new Configuration(app.getWindowProcessController().getConfiguration()),
                    app.compat, getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, autofillOptions, contentCaptureOptions);
        }
        .......
    } catch (Exception e) {
        ......
    // See if the top visible activity is waiting to run in this process...
    if (normalMode) {
        try {
        // mAtmInternal.attachApplication()最终调用的是ATMS中的 attachApplication()。
            didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
            badApp = true;
        }
    }
    ......
    return true;
}

在ATMS的attachApplication()中,通过IPC的方式进行了ActivityThread.ApplicationThread.bindApplication()之后,会调用mStackSupervisor.attachApplicationLocked(app),mStackSupervisor就是ActivityStackSupervisor,最后调用ActivityStackSupervisor的realStartActivityLocked方法

  • 这里完善了ActivityRecord,设置了进程等信息。总体上可以理解,应为ActivityRecord、ProcessRecord等由AMS/ATMS管理,这里将application绑定到了ATMS。
  • 创建了ClientTransaction对象
  • 设置了ClientTransaction的callback,为一个创建的LaunchActivityItem对象
  • 设置生命周期,为创建的lifecycleItem对象
  • 通过mService.getLifecycleManager().scheduleTransaction(clientTransaction)发送请求。这里的mService为ATMS,这里的mService.getLifecycleManager()即ClientLifecycleManager。
  • 创建Application后,通过attachApplication()绑定到ATMS。当前还是在系统进程中。
第六阶段:ATMS告诉新App要启动哪个Activity

ATMS把传入的ActivityThread对象转为一个ApplicationThread对象,用于以后和这个App跨进程通信,在第六阶段AtMS从过去记录中翻出来要启动哪个Activity,然后通过ATP告诉App

在ActivityStackSupervisor的realStartActivityLocked方法中,通过mService.getLifecycleManager().scheduleTransaction(clientTransaction)发送请求,即调用了ClientLifecycleManager发送请求。
接下来的流程就和暂停Launcher时一样,查看ClientLifecycleManager的scheduleTransaction方法:

//ClientLifecycleManager.java:
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    final IApplicationThread client = transaction.getClient();
    transaction.schedule();
    if (!(client instanceof Binder)) {
        // If client is not an instance of Binder - it's a remote call and at this point it is
        // safe to recycle the object. All objects used for local calls will be recycled after
        // the transaction is executed on client in ActivityThread.
        transaction.recycle();
    }
}
 
//ClientTransaction.java
public void schedule() throws RemoteException {
    mClient.scheduleTransaction(this);
}

mClient是一个IApplicationThread接口,上面我们也分析到,它的实现是ApplicationThread,这里又回到了ActivityThread,

ApplicationThread.scheduleTransaction ===>> ClientTransactionHandler.scheduleTransaction

public abstract class ClientTransactionHandler {

    // Schedule phase related logic and handlers.

    /** Prepare and schedule transaction for execution. */
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }

scheduleTransaction方法中发送了EXECUTE_TRANSACTION消息给ActivityThread的H类处理

android.app.ActivityThread
// An executor that performs multi-step transactions.
private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);
......
class H extends Handler {
    ......
        case EXECUTE_TRANSACTION:
            final ClientTransaction transaction = (ClientTransaction) msg.obj;
            mTransactionExecutor.execute(transaction);
            if (isSystem()) {
                // Client transactions inside system process are recycled on the client side
                // instead of ClientLifecycleManager to avoid being cleared before this
                // message is handled.
                transaction.recycle();
            }
    ......
}

通过handleMessage来处理这个消息,里面又调用了TransactionExecutor的execute方法:

public void execute(ClientTransaction transaction) {
    ...
    executeCallbacks(transaction);
    executeLifecycleState(transaction);
    mPendingActions.clear();

}

public void executeCallbacks(ClientTransaction transaction) {
       final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
       ...

        final int size = callbacks.size();
        for (int i = 0; i < size; ++i) {
        // 在上面realStartActivityLocked()中,设置的callback是LaunchActivityItem对象。这里execute()最终执行到LaunchActivityItem的execute()。
            final ClientTransactionItem item = callbacks.get(i); 
            ...
            item.execute(mTransactionHandler, token, mPendingActions);  
        }
}

 private void executeLifecycleState(ClientTransaction transaction) {
        final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();

     //生命周期的过渡
        cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);

        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
 }

在上面realStartActivityLocked()中,设置的callback是LaunchActivityItem对象。这里execute()最终执行到LaunchActivityItem的execute()。

//LaunchActivityItem.java:
@Override
public void execute(ClientTransactionHandler client, IBinder token,
        PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
    ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
            mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
            mPendingResults, mPendingNewIntents, mIsForward,
            mProfilerInfo, client, mAssistToken);
    client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

这里的client就是ActivityThread。所以走到了ActivityThread的handleLaunchActivity()

//ActivityThread.java:
public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, Intent customIntent) {
    ......
    final Activity a = performLaunchActivity(r, customIntent);
    ......
    return a;
}
 

接着看

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ......
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        // 创建Activity实例
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to instantiate activity " + component
                + ": " + e.toString(), e);
        }
    }
    ......
    执行attach,内部创建Window等
    activity.attach(appContext, this, getInstrumentation(), r.token,
        r.ident, app, r.intent, r.activityInfo, title, r.parent,
        r.embeddedID, r.lastNonConfigurationInstances, config,
        r.referrer, r.voiceInteractor, window, r.configCallback,
        r.assistToken);
    ......
        // 执行了Activity的onCreate()方法
        if (r.isPersistable()) {
            mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
        } else {
            mInstrumentation.callActivityOnCreate(activity, r.state);
        }
    ......
}

经过一系列的方法调用execute->executeCallbacks->cycleToPath->performLifecycleSequence,我们终于看到了熟悉的东西,一堆Activity的生命周期。

长话短说,主要流程为:

  • 创建应用上下文(Context),获取 ClassLoader;
  • 创建 Activity 对象,实质上是 classLoader.loadClass(name).newInstance(),这里会对 Activity 类进行初始化,调用对象的 方法,从而执行目标类里 static block 中的代码;
  • 根据应用的 AndroidManifest.xml 创建 Application对象,并调用其 onCreate 回调;
  • 调用对应 Activity 的 onCreate 回调;
第七阶段:启动斗鱼首页Activity

在这里插入图片描述

android.app.ActivityThread

@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, Intent customIntent) {
        ......
        final Activity a = performLaunchActivity(r, customIntent);
        ......
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ......
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        关键代码1
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to instantiate activity " + component
                + ": " + e.toString(), e);
        }
    }
    ......
    执行attach,内部创建Window等
    activity.attach(appContext, this, getInstrumentation(), r.token,
        r.ident, app, r.intent, r.activityInfo, title, r.parent,
        r.embeddedID, r.lastNonConfigurationInstances, config,
        r.referrer, r.voiceInteractor, window, r.configCallback,
        r.assistToken);
    ......
        关键代码2
        if (r.isPersistable()) {
            mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
        } else {
            mInstrumentation.callActivityOnCreate(activity, r.state);
        }
    ......
}

performLaunchActivity方法要做的是哪些事?

①通过Instrumentati0on的newActivity方法,创建要启动的Activity实例。

②为这个Acctivity创建一个上下文Context对象,并与Activity进行关联

③通过Instrumentaction的callActivityOnCreate方法,执行Activity的onCreate方法,从而启动Activity,至此App启动完毕,这个流程是经过多次握手,App和ATMS频繁的向对方发送消息,而发送消息的机制,是建立在Binder的基础之上的。

App内部的页面跳转

接下来我们看App内部页面的跳转。

从ActivityA跳转到ActivityB,其实可以把ActivityA看作是Launcher,那么这个跳转过程,和App的启动过程就很像了。

有了前面的分析基础,会发现,这个过程不需要重新启动一个新的进程,所以可以省略App启动过程中的一些步骤,流程简化为:

  1. ActivityA向AMS发送一个启动ActivityB的消息。
  2. AMS保存ActivityB的信息,然后通知App,你可以休眠了(onPaused)。
  3. ActivityA进入休眠,然后通知AMS,我休眠了。
  4. AMS发现ActivityB所在的进程就是ActivityA所在的进程,所以不需要重新启动新的进程,所以它就会通知App,启动ActivityB。
  5. App启动ActivityB。

在这里插入图片描述
以上的分析,仅限于ActivityA和ActivityB在相同的进程中,如果在Manifest中指定这两个Activity不在同一个进程中,那么就又是另一套流程了,但是整体流程大同小异。

Context家族史

Activity和Service都有Context,这三个类,还有Application,其实是亲戚一家子。
在这里插入图片描述

Activity因为有了一层Theme,所以中间有个ContextThemeWrapper,相当于它是Service和Application的侄子。

ContextWrapper只是一个包装类,没有任何具体的实现,真正的逻辑都在ContextImpl里面。

一个应用包含的Context个数:Service个数+Activity个数+1(Application类本身对应一个Context对象)。

应用程序中包含多个ContextImpl对象,而其内部变量mPackageInfo指向同一个PackageInfo对象。

Activity 和 Context的区别

我们就拿Activity举例子,看看Activity和Context的联系和区别。

我们知道,跳转到一个新的Activity要这么写:
在这里插入图片描述

我们还知道,也可以在Activity中使用getApplicationContext方法获取Context上下文信息,然后使用Context 的startActivity方法,启动一个新的Activity:
在这里插入图片描述
这二者的区别是什么?

Activity中:

@Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

在Activity中无论是使用哪一种startActivity方法都会调用到Activity自身的方法,所以是一样的。

然而在其他的Context子类,例如ContextImpl.java中的实现,会检查有没有设置Flag:FLAG_ACTIVITY_NEW_TASK,否则会报错:

ContextImpl中:

@Override
    public void startActivity(Intent intent, Bundle options) {
        warnIfCallingFromSystemProcess();

        // Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is
        // generally not allowed, except if the caller specifies the task id the activity should
        // be launched in. A bug was existed between N and O-MR1 which allowed this to work. We
        // maintain this for backwards compatibility.
        final int targetSdkVersion = getApplicationInfo().targetSdkVersion;

        if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
                && (targetSdkVersion < Build.VERSION_CODES.N
                        || targetSdkVersion >= Build.VERSION_CODES.P)
                && (options == null
                        || ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {
            throw new AndroidRuntimeException(
                    "Calling startActivity() from outside of an Activity "
                            + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                            + " Is this really what you want?");
        }
        mMainThread.getInstrumentation().execStartActivity(
                getOuterContext(), mMainThread.getApplicationThread(), null,
                (Activity) null, intent, -1, options);
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值