Android Activity 启动过程详解(上) 思维破局:挣钱其实没那么难,关键是方式要对 大数据赋能全产业链 为市民提供“一杯好奶” 运用大数据实现节能减排精准化 2020最新拼多多Java面试版,五面拿到28K的Offer 中国电信(安徽)大数据产业园落户南岗科技园 打造华东区域云计算领头羊 深度解读!阿里腾讯滴滴字节首选,新一代大数据引擎Flink厉害在哪?附学习礼包 网络编程5:socket服务端和客户端代码实现 微信小程序 蓝牙重连异常 errCode:10004,errMsg:notifyBLECharacteristicValueChange:fail setNot 蓝桥杯--第八届省赛试题-电子钟程序设计 【TCP回声服务器】一篇文章帮助你看懂TCP! 关于国标GB28181流媒体协议视频平台EasyGBS设备无法接入平台的问题排查 机器学习16 -- Lifelong Learning 终生学习 Vuex中发送mock请求返回数据 JS 正则表达式详解 学习笔记 花了30分钟,给女朋友们写了个最近抖音很火的3D立体动态相册 这 16 个 CSS 伪类,助你提升布局效率! Mysql系列第八讲 详解排序和分页(order by & limit)及存在的坑 SQL语句的一些应用语句 介绍三个开发技术小知识点 数据库系统概论(1) Mysql备份和恢复的类型,备份恢复的几种方法! --个人整理 MySql数据库基本操作(一) 前八月融合创新提升服务,大数据搭建信息网 长三角税收一体化按下“快进键” 一些建议:给当年刚做程序员的我 谁是物联网江湖明日之星?答案是新CIoT 企业信用有效“变现” 江苏银行物联网金融规模达185亿 2020年中国5G物联网行业:中国通信运营商5G投资达1.23万亿元-可下载 搭建 GFS 分布式文件系统-----实操 排障集锦:九九八十一难之第十五难!-------------史上最全rsync报错详解 docker系列1---docker隔离和限制技术 Linux系统安全及应用加固———最适合新手学,新手都能看懂!超详细的理论+超详细的实验!呕心沥血之作完成! LAMP架构集成ownCloud搭建私有云盘 Shell脚本正则表达式(一) Linux第一人称侵入进程的好地方 Windows DOS常用命令(持续更新完善) 大数据驱动新材料研发 变革从内而发,一站式大数据平台和多模数据库雄起 雕佛像、打棒球、开飞机、去北极,这个90后程序员有点不一样 12项特色功能构建施工现场“物联网” 400亿美元!英伟达收购Arm 软银套现离场物联网梦醒 卫星物联网再次引发热议,原因在这里 信用飞:航旅行业数字化前景可期,大数据预防砍头息乱象 大数据加持自动驾驶产业发展 上海智能网联汽车公共数据中心揭牌 恒久科技(002808.SZ):子公司闽保信息与鸿达兴业签署智能制造及大数据平台综合应用项目战略合作框架协议 工业平板电脑如何在物联网中发挥作用? 400亿美元!英伟达收购Arm 软银套现离场物联网梦醒 “数字心脏”动态解析消费密码——国家级消费市场大数据联合实验 重庆:大数据智能化牵引产业结构调整质效提升 分析物联网技术在智能家居中的应用场景
您的位置:首页 >程序人生 >

Android Activity 启动过程详解(上)

你想要找的activity知识都在这里了 一份超详细的Fragment知识总结 FragmentManager与FragmentTransaction底层实现 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 方法。

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

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

@Overridepublic 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 时,会抛出异常信息,这就不再细看了。

@UnsupportedAppUsagepublic 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>() {@Overrideprotected 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 发起查询。

@UnsupportedAppUsagepublic 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,具体代码见下:

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

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

@UnsupportedAppUsagestatic 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;}@UnsupportedAppUsagepublic 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;}...@UnsupportedAppUsageprivate 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 设计原则。

@Overridepublic 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 方法:

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

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。