欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android Activity 启动过程详解(上)

程序员文章站 2022-06-24 19:47:43
App 启动 Activity 时,需要向系统发送请求启动信号,处理该请求的服务就是 AMS (ActivityManagerService),这个操作是跨进程的。 init 解析 rc 脚本启动 Zygote,其所在进程 app_process (后改名 zygote )的 ZygoteInit 通过 forkSystemServer 创建一个进程,来启动各种系统服务,这里就包含 AMS。...

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 ,之后就会跨进程调用 ActivityManagerService 的 startActivity 方法了(在 android10 内,AMS 的 startActivity 又会调用 mActivityTaskManager.startActivity ,将启动 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 的通信;之后就可以获取到结果了(这里的 IBinder 就是 AMS 的IBinder 对象了),因为这里是一种阻塞式函数调用,因为是进程间通信,结果并不会马上就能获取到,所以 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;
    }
 }

⑪ 接下来我们就来看 AMS 内 startActivity 是如何实现的呢?能够看到 AMS 将实现委托给了 ATMS,这样做的好处是职责变得更单一了,避免 AMS 过于臃肿,符合 OO 设计原则。

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

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 开发艺术探索:中国工信出版集团

本文地址:https://blog.csdn.net/MingJieZuo/article/details/108532581