Android Activity 启动过程详解(上)

App 启动 Activity 时,需要向系统发送请求启动信号,处理该请求的服务就是 AMS (ActivityManagerService),这个操作是跨进程的。想想 上一篇 说的, init 解析 rc 脚本启动 Zygote,其所在进程 app_process (后改名 zygote )的 ZygoteInit 通过 forkSystemServer 创建一个进程,来启动各种系统服务,这里就包含 AMS;而 ZygoteInit 又通过 forkAndSpecialize 为每个新启动的应用程序生成自己独立的进程,并在 handleChildProc 方法中运行应用程序本身的代码,所以说启动 Activity 的过程是跨进程的。

我们通过 startActivity 方法来启动一个 Activity ,这里以显示调用为例:

    Intent intent = new Intent(this, DemoActivity.class);
    startActivity(intent);

① android.app.Activity#startActivity,startActivity 有几种重载方法,但都会调用 startActivityForResult 方法。

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

② android.app.Activity#startActivity(Intent intent, @Nullable Bundle options)

    @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);
        }
    }

③ android.app.Activity#startActivityForResult , 这里只需要关注 mParent == null 的即可,mParent 代表的是 ActivityGroup, ActivityGroup 开始被用来在一个界面中嵌入多个子 Activity,但在 API 13 被废弃了,被 Fragment 代替。

   public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            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());
            }
            ...
            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            ...
        }
    }

④ android.app.Instrumentation#execStartActivity ,之后就会跨进程调用 ActivityTaskManagerService 的 startActivity 方法了(在 android10 内,启动 Activity 的任务交给了 ATMS),具体代码实现见下。 checkStartActivityResult 方法的作用是检查启动 Activity 的结果,当无法正常启动一个 Activity 时,会抛出异常信息,这就不再细看了。

    @UnsupportedAppUsage
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
       ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityTaskManager.getService()
                .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;
    }

⑤ 接着分析上面的 ActivityTaskManager.getService() 方法,其中 Singleton 是单例模式类,当调用 get() 方法时,会进行内部判断:如果该对象已存在,则直接返回现有值,否则通过调用 create() 方法创建并返回 IActivityTaskManager 对象 。

    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);
                }
            };

⑥ 在这里是通过 ServiceManager.getService 来获取 ActivityManagerService 的 IBinder 对象的,当其中 sCache 用于记录 getService 的历史查询结果,getService 每次都会首先在这里翻阅记录,以加快查询速度,如果不存在,则通过 rawGetService 方法内的 getIServiceManager().getService(name) 向 SM 发起查询。

    @UnsupportedAppUsage
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return Binder.allowBlocking(rawGetService(name));
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

    private static IBinder rawGetService(String name) throws RemoteException {
        final long start = sStatLogger.getTime();
        final IBinder binder = getIServiceManager().getService(name);
        ...
        return binder;
    }

⑦ getIServiceManager 方法首先会判断 sServiceManager 是否为空,防止多次重复操作。之后通过 ServiceManagerNative.asInterface 来获取一个 IServiceManager 对象。这个 IServiceManager 对象就是负责与 Binder 驱动通信的 SM 代理 ServiceManagerProxy,具体代码见下:


    @UnsupportedAppUsage
    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }
        // Find the service manager
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
    }

⑧ asInterface 方法负责将 Binder 对象转换成 IServiceManager,并在必要的时候创建 ServiceManagerProxy,这就是我们 ServiceManager 的代理,来负责与 Binder 驱动通信。

    @UnsupportedAppUsage
    static public IServiceManager asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
        return new ServiceManagerProxy(obj);
    }

⑨ 在回到上面的 rawGetService 方法内的 getIServiceManager().getService(name) 方法,通过 SM 代理的 getService 方法,首先通过 Parcel 打包数据;接着通过 IBinder 的 transact 将请求发送出去,具体会通过 jni 调用对应的 BpBinder,进而使用 ProcessState 和 IPCThreadState 的相关接口,完成与 SM 的通信;之后就可以获取到结果了,因为这里是一种阻塞式函数调用,因为是进程间通信,结果并不会马上就能获取到,所以 Binder 驱动会先将调用者线程挂起,直到有了结果才会将它唤醒。

class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
    public IBinder asBinder() {
        return mRemote;
    }
    @UnsupportedAppUsage
    public IBinder getService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }
    ...
    @UnsupportedAppUsage
    private IBinder mRemote;
}

⑩ allowBlocking 的作用是判断当前 IBinder 是否为 BinderProxy,是则改变 mWarnOnBlocking 标志位。

    public static IBinder allowBlocking(IBinder binder) {
        try {
            if (binder instanceof BinderProxy) {
                ((BinderProxy) binder).mWarnOnBlocking = false;
            } else if (binder != null && binder.getInterfaceDescriptor() != null
                    && binder.queryLocalInterface(binder.getInterfaceDescriptor()) == null) {
                Log.w(TAG, "Unable to allow blocking on interface " + binder);
            }
        } catch (RemoteException ignored) {
        }
        return binder;
    }
 }

⑪ 接下来我们看下 ActivityTaskManagerService 的 startActivity(将 Activity 的启动从 AMS 委托给 ATMS 后,AMS 职责变得更单一了,避免了 AMS 过于臃肿),ActivityTaskManagerService 的 startActivity 方法又会调用 startActivityAsUser 方法:

    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

⑫ 这是 startActivityAsUser 的方法:其中 getActivityStartController() 方法会返回当前持有的 ActivityStartController 对象,obtainStarter 方法会调用 ActivityStarter 内部类 DefaultFactory 的 .obtain() 方法创建 ActivityStarter 对象,随后调用ActivityStarter 的 setIntent(intent).setReason(reason) 等的属性赋值,最后调用 ActivityStarter 的 execute 方法,这里就不展示代码了。

    int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
            boolean validateIncomingUser) {
        ...
        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();
    }

⑬ 其中 setMayWait 方法,会将 ActivityStarter 内部类 Request 的 mayWait 字段设置为 true :

    ActivityStarter setMayWait(int userId) {
        mRequest.mayWait = true;
        mRequest.userId = userId;
        return this;
    }

⑭ checkTargetUser 方法内,其中 validateIncomingUser 为 true, targetUserId 是当前调用者的用户ID 值,由 UserHandle.getCallingUserId() Binder 机制获取,UserHandle 是 aidl 文件,handleIncomingUser 会检查调用者是否有权利执行这一操作。

    int checkTargetUser(int targetUserId, boolean validateIncomingUser,
            int realCallingPid, int realCallingUid, String reason) {
        if (validateIncomingUser) {
            return mService.handleIncomingUser(
                    realCallingPid, realCallingUid, targetUserId, reason);
        } else {
            mService.mAmInternal.ensureNotSpecialUser(targetUserId);
            return targetUserId;
        }
    }

⑮ 这是 ActivityStarter 的 execute 的方法,会调用 startActivityMayWait 方法,mRequest.mayWait 是前面提到的启动参数。

    int execute() {
        try {
            if (mRequest.mayWait) {
                return startActivityMayWait(...);
            } else {
                ...
        } finally {
            onExecutionComplete();
        }
    }

⑯ 在 startActivityMayWait 方法内,会调用 26 个参数的 startActivity 方法,接着会调用 10 个参数的 startActivity 方法,接着会调用 startActivityUnchecked 方法,然后会调用 mTargetStack.startActivityLocked 方法,这样就将 Activity 的启动过程转移到了 ActivityStack 。

Todo: startActivityLocked 逻辑复杂,下篇会结合启动模式,来梳理下 AMS 是如何恢复上层 Activity 和 新旧 Activity 切换,并通知给调用者的。

参考
1、林学森,深入理解 Android 内核设计思想:人民邮电出版社
2、任玉刚,Android 开发艺术探索:中国工信出版集团

©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页