【Android】03. 启动一个 Activity 并把相关信息传递到ActivityManager

318 阅读3分钟

回顾 01. APP 进程启动和 ActivityThread 的关系 知道 Activity 被创建后会执行 attach() 方法。这个方法会把当前的 ActivityThread 实例和 Instrumentation 实例关联给新创建的 Activity。

查看 activity.startActivity 源码

首先我们从 startActivity() 看起,无论怎么样,最终都会走到这里。

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            // 这里才是执行启动Activity
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
        // 省略一些代码.....  
    }

从上面代码可以看出 mInstrumentation.execStartActivity 才是真正的执行启动 activity; 再看下源码

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        // 省略一些代码 .....
        try {
           // 这里启动 startActivity
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

我们可以看到ActivityManagerNative.getDefault()这个才调用 startActivity 的地方;

然后我们再去看下 Instrumentation 这个类,我们就会发现有很多 callActivityOnXXXX 方法,从方法名不难看出,这些主要是 activity 的生命周期方法管理,真正调用还是在 ActivityThread 里面;

ActivityManagerNative.getDefault()

查看一下 ActivityManagerNative.getDefault() 是个什么;

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            // 获得一个 IBinder
            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;
        }
    };


    /**
     * Cast a Binder object into an activity manager interface, generating
     * a proxy if needed.
     */
    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        // 再次查询了一遍,跨进程查询
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
        // 跨进程查询不到,就本地做一个代理
        return new ActivityManagerProxy(obj);
    }

从以上 2 端代码可以发现主要是想获得IActivityManager, 这个对象主要是在 ServiceManager 中获得的一个 IBinder, 如果本地没有就生成一个代理;

这里需要说明一下IBinder 是跨进程访问的;至于是为什么,以后再说;

这里列举一下几个关键类;

  1. Activity
  2. ActivityManagerNative
  3. IActivityManager
  4. ServiceManager
  5. IBinder (跨进程访问主要桥接类)
  6. ActivityManagerProxy

我们从简单的 activity.startActivity 出发。查看了想要启动下一个 Activity 的时候必须经过一下几步的关键路径;

--> mInstrumentation 
--> ActivityManagerNative.getDefault()
--> Binder obj = ServiceManager.getService("activity")
--> IActivityManager in =  (IActivityManager)obj.queryLocalInterface(descriptor)// 这个其实是个跨进程查询

如果查询不到,就在 app 进程代理出一个 IActivityManager (ActivityManagerProxy)
-->in.startActivity()
-->mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);

以上是对启动一个 activty 到把相关参数传递到Binder.transact 的整个过程(切记这里就开始跨进程调用了); transact(START_ACTIVITY_TRANSACTION, data, reply, 0);这里的 data 包含了很多 Intent 和 activity 的相关信息;为了让文章看起来不是很累就先把当前进程里面的先捋清楚,关于跨进程先不说;

其他结论

android.os.ServiceManager 是 framework 中的类;需要下载 framework 代码查看一下不难发现 ServiceManager 有个 HashMap;

private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();
//.... 省略代码...

// 看的出来ServiceManager.getService("activity");
public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().getService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

ServiceManager 把 ActivityManager 管理在这个缓存里面,所以应该有很多其他的IBinder (也有可能是其他的Manager,以后展开)

疑问

  1. 当 startActivity 后
    mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0); 这个地方执行到哪里去了,怎么样启动 activity 让它展示呢??

  2. 从目前来看,应该还没有创建 activity 的 Window 吧?

    第 1 个问题: mRemote.transact 到这里,其实他已经执行到其他进程去了,本地代码其实只是个代理;

    第 2 个问题: 其实真正创建 Activity 的 window 应该是在 ActivityThread 的 performLaunchActivity() 里面,但是怎么过来呢??还记得 ActivityThread 里的 Looper 吗?那里一直在循环着呢,他其实在哪里等消息呢,只要Looper接收到 Message 就可以处理 performLaunchActivity 了,到底是怎么接收呢? ActivityThread 有个private class H extends Handler这个类;具体流程就等下一篇再叙说吧。我不喜欢一篇写的太长了