当前位置: 首页 > news >正文

四. AMS源码分析

AMS
主要负责四大组件的启动、切换和调度以及应用程序的管理和调度工作.
ActivityManager的组成主要分为以下几个部分:

  • 服务代理:
    ActivityManagerProxy实现,用于与Server端提供的系统服务进行进程间通信
  • 服务中枢:
    ActivityManagerNative,继承自Binder并实现了IActivityManager,他提供了服务接口和Binder接口的相互转化,并在内部存储服务代理对象,并提供了getDefault`方法返回服务代理.
  • Client端:
    ActivityManager封装了一部分服务接口给Client端调用.ActivityManager内部通过ActivityManagerNativegetDefault方法,可以得到一个ActivityManagerProxy对象的引用,进而通过该代理类对象调用远程服务的方法.
  • Server端:
    ActivityManagerService实现,提供Server端的系统服务

SystemServer进程如何管理SystemService?
SystemService是一个抽象类,将具体服务的一些公共方法抽离出来(如:onStart()方法),方便SystemServiceManager管理所有的服务;
所有的服务要么直接继承自SystemService,要么定义一个内部类LifeCycle继承自SystemService并在内部类中,将当前服务(如:AMS)类作为一个成员变量;
我们在通过SystemServiceManager调用startService()方法启动服务的时候,就会调用抽象类SystemServiceonStart()方法,最后的实现就是由相应服务去实现.
如:AMSLifeCycle内部类的onStart()方法、BatterServiceonStart()方法.

AMS的启动流程
通过SystemService的启动引导服务方法startBootstrapServices(),然后通过SystemServiceMangerstartService()方法,最终会调用到AMSstart()方法,完成AMS的启动.
AMS启动时实现了哪些功能: @AMS.start()

  • mProcessCpuThread.start();//启动CPU监控线程
  • mBatteryStatsService.publish();//注册电池状态和权限管理服务
  • mProcessCpuInitLatch.await();//等待mProcessCpuInitLatch完成初始化,释放锁,初始化期间禁止访问

SystemServer中启动AMS也完成了一些初始化任务:

  • mActivityManagerService.initPowerManagement();//初始化电源管理
  • mActivityManagerService.setSystemProcess();//设置为系统进程
    • 将一些服务添加到ServiceManager进程集合中,如:GraphicsBinder、DbBinder、ProcessInfoService、PermissionController等.

由于AMS管理的服务很多,四大组件都是通过AMS来管理的;所以将Activity的管理抽离出来交给ATMS来管理,但是AMS同时会管理ATMS,通过在AMS中持有ATMS的成员变量.
public ActivityTaskManagerService mActivityTaskManager;

App的启动流程
App的启动流程中涉及到4个进程,不同的进程进间采取了BinderSoket的通信机制,同一个进程中有采用了Handler的通信方式.

  • Launcher进程
    • ServiceManager集合中获取到AMSIBinder对象转化的代理类ActivityManagerProxy,通过Binder通信机制,向SystemServer进程中的AMS服务发送启动app主页面的请求startActivity().
  • SystemServer进程
    • 接收到Launcher进程发送过来的启动app首页的请求;
      app已经存在于后台,直接通过SystemServer进程去启动我们的app进程中的主页;
      app不存在,此时SystemServer进程需要向Zygote进程发送soket消息,请求创建app进程.
  • Zygote进程
    • 通过ZygoteServer接收SystemServer进程发送来的创建App进程的soket消息,通过fork创建App进程.
  • App进程
    • App进程创建成功后,从ServiceManager集合中取出AMSIBinder对象的代理类ActivityManagerProxy;
    • 通过Binder通信机制和SystemServer进程通信,通过AMS的代理类调用SystemServer进程中的AMS服务;
    • 调用AMS的启动App主页方法realStartActivityLocked(),该方法会获取到App进程ApplicationThread服务的代理类ApplicationThreadProxy;
    • SystemServer进程通过Binder进程间通信机制与App进程通信,通过SystemServer进程中的代理类ApplicationThreadProxy,调用App进程中的ApplicationThread服务的scheduleLaunchActivity()方法;
    • 然后通过App进程中的ApplicationThread发送Handler消息LAUNCHER_ACTIVITYActivityThread,在ActivityThread中调用handleLaunchActivity方法,调用ActivityonCreate()方法.

AMS源码分析
SystemServer进程要启动App进程的首页时,当发现App没有运行在后台,则需要通知Zygote进程去创建一个App进程出来,此时会调用AMSstartProcess() 方法创建进行.

  • (ProcessList)mProcessList @AMS.java
    • AMS类中包含一个ProcessRecord的集合ProcessList,用于管理一个个进程ProcessRecord.
      final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>();
    • ProcessRecord是一个进程,里面包含了进程的相关信息.
  • startProcess() @ProcessList.java
    • 启动进程
  • Process.start() @Process.java
    • Process是一个进程ProcessRecord的工具类,相当于我们平时写的Utils,里面包含了静态方法
  • (ZygoteProcess)ZYGOTE_PROCESS.start() @ProcessList.java
    • ZygoteProcess同样是一个工具类,这里会调用到ZygoteProcess.start()方法
  • startViaZygote() @ZygoteProcess.java
  • zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),zygotePolicyFlags, argsForZygote); @ZygoteProcess.java
  • attemptUsapSendArgsAndGetResult(zygoteState, msgStr); @ZygoteProcess.java
    • 通过Socket获取到输出流和输出流,发送和接收消息(目标:ZygoteServer)
  • (BufferWriter)usapWriter.write(msgStr);
    • 通过sokect将拼接好的命令通过字符流发送给Zygote服务器(ZygoteServer)
    • ZygoteServer接收到sokect消息后,在connection.processOneCommand(this)方法中,会去解析参数msgStr->args,然后通过fork创建进程:
      pid = Zygote.forkAndSpecialize()
    • 进程创建成功后,会将pid和usingWrapper这两个参数发送给客户端,以便下面通过输入流读取这两个参数:
      (DataOutputStream)mSocketOutStream.writeInt(pid);
      (DataOutputStream)mSocketOutStream.writeBoolean(usingWrapper);
    • result.pid = (DataInputStream)usapReader.readInt();
      • 通过读取soket返回消息中的pid,判断进程是否创建成功
      try (LocalSocket usapSessionSocket = zygoteState.getUsapSessionSocket()) {final BufferedWriter usapWriter =new BufferedWriter(new OutputStreamWriter(usapSessionSocket.getOutputStream()),Zygote.SOCKET_BUFFER_SIZE);final DataInputStream usapReader =new DataInputStream(usapSessionSocket.getInputStream());//通过输出流写入拼接的命令usapWriter.write(msgStr);usapWriter.flush();Process.ProcessStartResult result = new Process.ProcessStartResult();//通过输入流读取数据中的pid,如果pid>=0则返回,//pid=0表示孩子进程创建成功,pid>0表示zygote进程创建成功,pid=-1表示fork创建进程失败result.pid = usapReader.readInt();// USAPs can't be used to spawn processes that need wrappers.result.usingWrapper = false;if (result.pid >= 0) {return result;} else {throw new ZygoteStartFailedEx("USAP specialization failed");}}
      

AMS如何启动进程
AMS中有一个管理进程的类ProcessList,通过这个ProcessList去启动一个个的进程ProcessRecord,进程的启动入口就是AMSstartProcessLocked().
AMS启动进程的流程如下:

AMS启动一个进程其实是打开这个App的首页面,当发现这个首页所在的进程不存在,则会发送sokect消息给Zygote进程;Zygote进程中的ZygoteServer在接收到这条socket消息后,通过fork去创建出app进程(下面的代码只分析到发送一条sokect消息给Zygote服务器)

  • startProcessAsync() @ATMS
    • ATMS作为AMS中一个专门用于管理Activity的启动与切换的工具,这里面就包含了启动一个Activity的方法,这里的Activity被封装成了ActivityRecord
  • ActivityManagerInternal::startProcess() @ATMS
    • ActivityManagerInternal的实现类,是AMS中的内部类LocalService,LocalService包含类这个startProcess()方法
  • startProcess() @ActivityManagerService.LocalService
  • startProcessLocked() @ActivityManagerService.LocalService
  • startProcessLocked() @AMS
    • 这个方法返回值是ProcessRecord
  • ProcessRecord proc = mProcessList.startProcessLocked(); @AMS
    • 通过这个方法作为一个入口去启动一个进程,最终返回该进程
    • 这个方法参数中包含了进程名字:processName、应用信息:ApplicationInfo等
    • 这个方法返回值是一个进程ProcessRecord,也就是一个App进程
  • startProcessLocked() @ProcessList
    • 这里会调用多个相同名字的startProcessLocked()方法,但是参数不同,最终会调用到startProcess()方法
  • Process.ProcessStartResult startResult = startProcess() @ProcessList
  • Process.start() @ProcessList
    • 这是进程ProcessRecord的一个工具类,里面是一些静态方法,类似于我们平时写的Utils工具类
  • (ZygoteProcess)ZYGOTE_PROCESS.start() @ZygoteProcess.java
    • 这是Zygote进程的一个工具类
    • 包含一个内部类ZygoteState,这个类里面包含一些和ZygoteServer进行socket通信的属性,如:mZygoteSocketAddress、mUsapSocketAddress、mZygoteSessionSocket、mZygoteInputStream、mZygoteOutputWriter等
  • ZygoteProcess.start() @ZygoteProcess.java
  • startViaZygote() @ZygoteProcess.java
  • zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), zygotePolicyFlags, argsForZygote); @ZygoteProcess.java
    • openZygoteSocketIfNeeded(abi):这个方法会去连接ZygoteServer服务器,以便发送和接收socket消息,连接ZygoteServer代码如下:
      zygoteSessionSocket.connect(zygoteSocketAddress); @ZygoteProcess.java
    • argsForZygote:拼接很多参数,在通过socket将该消息发送给Zygote进程中的ZygoteServer服务器后,会解析出这条消息中的参数信息
  • attemptZygoteSendArgsAndGetResult() @ZygoteProcess.java
    • 通过输出流将消息发送给ZygoteServer服务器,Zygote进程通过fork创建孩子进程,然后通过输入流读取ZygoteServer服务器返回的数据,源码分析如下:
      private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {try {//通过输出流将这条消息msgStr发送给ZygoteServer服务器,然后通过fork创建app进程final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;//在进程创建成功后,ZygoteServer服务器恢复消息,然后通过输入流读取返回的数据final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;//数据是先写入到缓冲区里zygoteWriter.write(msgStr);//发送消息//flush()方法将输入流和输出流中的缓冲进行刷新,使缓冲区中的元素即时做输入和输出,而不必等缓冲区满zygoteWriter.flush();// Always read the entire result from the input stream to avoid leaving// bytes in the stream for future process starts to accidentally stumble// upon.Process.ProcessStartResult result = new Process.ProcessStartResult();result.pid = zygoteInputStream.readInt();result.usingWrapper = zygoteInputStream.readBoolean();if (result.pid < 0) {throw new ZygoteStartFailedEx("fork() failed");}return result;} catch (IOException ex) {zygoteState.close();Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "+ ex.toString());throw new ZygoteStartFailedEx(ex);}
      }
      

Zygote进程中的ZygoteServer里面有一个死循环,不停的在轮询有没有发送来的sokect消息,当有消息发送过来的时候,就会去处理这条socket消息.下面是Zygote进程在初始化时main()方法里创建的ZygoteServer服务器,这是一个Socket服务器.

//创建ZygoteServer Socket服务器
zygoteServer = new ZygoteServer(isPrimaryZygote);
//开启一个死循环,不停遍历有没有发送来的socket消息,接收到socket消息则会fork出一个进程
caller = zygoteServer.runSelectLoop(abiList);
//返回的被封装成了一个Runnable对象,后面会调用他的run方法,
//最终会调用到Runnable的实现类RuntimeInit.MethodAndArgsCaller的run方法.
//该方法中会通过反射去调用ActivityThread类的main函数:
//mMethod.invoke(null, new Object[] { mArgs });
caller.run();//最终执行创建的App进程的初始化操作,也就是ActivityThread的main方法

Zygote进程接收到Soket消息并fork出App进程的流程如下:

  • runSelectLoop() @ZygoteServer.java
    • 遍历有没有发送过来的socket消息
    • 返回值是一个Runnable对象,这个对象被封装在了MethodAndArgsCaller
  • (ZygoteConnection)connection.processOneCommand(this); @ZygoteServer.java
    • 处理发送来的这条消息
  • processOneCommand(ZygoteServer zygoteServer) @ZygoteConnection.java
    • 解析发送来的socket消息中的参数:
      String[] args = Zygote.readArgumentList(mSocketReader);
  • int pid = Zygote.forkAndSpecialize()
    • 通过fork创建孩子进程和zygote进程,孩子进程的pid=0,zygote进程的pid>0,fork方法最终会调到native层中的fork()方法,这个方法会去调用Linux层里的fork()方法.
    • 在孩子进程创建成功后,pid=0的逻辑判断中会去调用handleChildProc()方法,该方法最终会调用ActivityThread的main函数,流程如下:
  • handleChildProc() @ZygoteConnection.java
  • ZygoteInit.zygoteInit() @ZygoteConnection.java
    + 这里进入!isZygote的逻辑判断代码块
  • RuntimeInit.applicationInit() @RuntimeInit.java
  • findStaticMain(args.startClass, args.startArgs, classLoader); @RuntimeInit.java
  • return new MethodAndArgsCaller(m, argv);
    • MethodAndArgsCallerRuntimeInit的一个内部类,他继承自Runnable
    • 这里会创建一个MethodAndArgsCaller作为Runnable的实现类返回,最终就是调用MethodAndArgsCallerrun()方法;
      • 这个方法可以在创建SystemServer进程时,调用SystemServer的main函数
      • 这个方法还可以在创建App进程时,调用ActivityThread的main函数(我们这里是分析的创建App进程,所以走这一步)
    • 这里为什么是ActivityThread的main函数,是因为在AMS发送socket消息里面拼接的参数就是ActivityThread?这里我还没找到方法去验证.
    • 这里孩子进程先创建,然后创建zygote进程,在zygote进程创建完成后,调用的方法handleParentProc()中,会将Zygote进程的数据通过流的形式发送出去,代码如下:
      mSocketOutStream.writeInt(pid);
      mSocketOutStream.writeBoolean(usingWrapper);

最终,ZygoteProcess中的attemptZygoteSendArgsAndGetResult()方法中,会获取到ZygoteServer中通过fork()创建的进程信息,比如:pidusingWrapper.

总结:

  • AMS通过持有的进程管理类ProcessList的启动进程方法mProcessList.startProcessLocked(),作为启动进程的入口,期间会调用到Process和ZygoteProcess这两个工具类的start()方法,最终在ZygoteProcess中,通过流的方式将拼接的参数发送给Zygote进程中的ZygoteServer服务器
  • ZygoteServer是一个Socket服务器,里面有一个死循环用于接收socket消息,在接收到socket消息后就会去解析消息中的参数,然后通过fork()先后创建孩子进程(App进程)和zygote进程并返回进程的pid;然后根据进程的pid=0去处理孩子进程(App进程),最终通过反射调用到ActivityThread的main函数中去;处理完孩子进程(App进程)后,会去处理创建的zygote进程,并发送sokect消息给SystemServer进程中的AMS,告诉AMS创建的进程pid和usingWrapper.

App进程启动后,attach过程

  • main() @ActivityThread.java
    • 创建一个ActivityThread,然后调用attach()方法
    • 创建一个Looper并执行loop()方法,让App进程一直处于运行状态
  • (ActivityThread)thread.attach(false, startSeq); @ActivityThread.java
  • (AMS)mgr.attachApplication(mAppThread, startSeq); @ActivityThread.java
    • mgr参数说明:其实就是AMS
      final IActivityManager mgr = ActivityManager.getService();
    • mAppThread参数说明:是一个ApplicationThread对象,他作为ActivityThread的内部类存在.ApplicationThread继承自IApplicationThread.Stub,所以我们可以把他作为一个IBinder对象.
    • 这个方法最终将一个App进程IBinder对象注册到SystemServer进程中的AMS服务中.于是乎,SystemServer进程就可以通过App进程的IBinder服务的代理类,通过Binder机制实现跨进程通信,App进程相当于是Server端,而SystemServer进程相当于是Client端.
  • attachApplicationLocked(thread, callingPid, callingUid, startSeq); @AMS
    • (IApplicationThread)thread.bindApplication() @AMS
      • 将IBinder绑定到AMS
      • thread:这是一个AIDL生成的Java类IApplicationThread,作为一个服务器,需要由他的Stub类的子类来完成具体的实现.
      • 会调用ActivtyThread.ApplicationThread类中的bindApplication()方法,这里会通过Handler发送消息BIND_APPLICATION,在主线程中调用handleBindApplication(data)做一些处理:
        • installContentProviders(app, data.providers);//创建四大组件之ContentProvider
        • (Application)app = data.info.makeApplication(data.restrictedBackupMode, null);//创建Application,并调用他的attach()方法
        • mInstrumentation.callApplicationOnCreate(app);//执行Application的生命周期
    • (ProcessRecord)app.makeActive(thread, mProcessStats); @AMS
      • 将(IApplicationThread)_thread对象赋值给ProcessRecord中的thread对象;解析:_thread是App进程中ActivityThread内部类ApplicationThread的IBinder对象,ProcessRecord是SystemServer进程中的AMS里的ProcessList中的一个进程.所以,这里的赋值操作,是为了方便实现跨进程通信,实现SystemServer进程中的AMS去直接使用App进程中的IApplicationThread对象.
    • mProcessList.updateLruProcessLocked(app, false, null); @AMS
      • 将ProcessRecord添加到ProcessList中去,也就是将进程ProcessRecord添加到AMS的进程管理类ProcessList集合中去,这里的ProcessRecord进程就相当于是我们的App进程.
    • (ActivityTaskManagerInternal)mAtmInternal.attachApplication(app.getWindowProcessController()); @AMS
      • ATMS中内部类LocalService继承自ActivityTaskManagerInternal
      • 这里会调用到ATMS中的LocalService内部类中的attachApplication()方法
      • 最终在ATMS中执行Activity的启动流程,流程如下:
        • (RootWindowContainer)mRootWindowContainer.attachApplication(wpc); @ATMS
        • attachApplication() @RootWindowContainer.java
        • RootWindowContainer::startActivityForAttachedApplicationIfNeeded @RootWindowContainer.java
        • (ActivityStackSupervisor)mStackSupervisor.realStartActivityLocked() @RootWindowContainer.java
        • realStartActivityLocked() @ActivityStackSupervisor.java
          • 这个方法会将启动的Activity初始状态标记为LaunchActivityItem,最终状态标记为ResumeActivityItem,代码如下:
            // Create activity launch transaction.
            final ClientTransaction clientTransaction = ClientTransaction.obtain(proc.getThread(), r.appToken);//TODO 这里将ClientTransaction添加回调,回调的状态是LaunchActivityItem
            clientTransaction.addCallback(LaunchActivityItem.obtain());
            // Set desired final state.
            final ActivityLifecycleItem lifecycleItem;
            //TODO 传递过来的andResume为true,这里会将最终的状态标记成ResumeActivityItem
            if (andResume) {lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
            } else {lifecycleItem = PauseActivityItem.obtain();
            }
            clientTransaction.setLifecycleStateRequest(lifecycleItem);// Schedule transaction.
            mService.getLifecycleManager().scheduleTransaction(clientTransaction);
            
        • 在启动Activity的时候,最终调用到TransactionExecutorexecute(clientTransaction)方法时,里面的两个方法,executeCallbacks(transaction)executeLifecycleState(transaction),分别在执行ClientTransactionItemexecute()方法和ActivityLifecycleItemexecute()方法时,最终就会分别调用到实现类LaunchActivityItemResumeActivityItemexecute()方法.

AMS是如何管理App进程的?
AMS类中包含一个管理进程的变量mProcessList,ProcessList是用来管理手机中所有的App进程的,每一个App进程就是一个ProcessRecord,而ProcessRecord中包含一个变量(IApplicationThread)thread,IApplicationThread相当于是一个Server端的IBinder对象,我们将这个IBinder对象注册到AMS中去;AMS要访问App进程,(SystemServer进程中的)AMS只需要通过IBinder对象的代理类(IBinder的Proxy)即可与App进程实现跨进程通信,从而实现AMS对每一个App进程的管理.

Activity的启动流程(总结)
比如:ActivityA要启动ActivityB

  • 解析ActivityB启动的参数
  • 然后通过ActivityStack栈来管理和启动ActivityB
    • 所有的Activity都是通过一个栈(ActivityStack)来管理的和启动,每一个Activity会被封装成ActivityRecord
    • 将ActivityStackSupervisor(管理ActivityStack栈)封装成ClientTransaction事务,然后发送给App进程
    • 目前还在AMS中,也就是SystemServer进程
  • 跨通信的流程,使用Binder来实现:ClientTransaction
  • Application进程拿到ClientTransaction事务,然后去处理ActivityB
  • ActivityA:执行onStop生命周期

Activity启动流程详细流程:

  • startActivityAsUser() @ATMS.LocalService
  • startActivityAsUser() @ATMS
  • getActivityStartController().obtainStarter(intent, "startActivityAsUser")... .execute(); @ATMS
    • getActivityStartController()返回的是ActivityStarterControler对象
    • obtainStarter()会返回一个ActivityStarter对象,这里使用完ActivityStarter会将其数据清空,放入一个ActivityStarter缓存持中;这个原理类似于RecyclerView的缓存池
    • 里面省略的set方法都是给ActivityStarter.Request内部类赋值
    • execute()取出里面省略的set方法给ActivityStarter.Request中赋值的参数,然后处理这些参数
  • executeRequest(mRequest) @ActivityStarter.java
    • 根据这些参数创建出需要启动Activity对象的ActivityRecord,代码如下:
      ActivityRecord r = new ActivityRecord(...);
  • startActivityUnchecked() @ActivityStarter.java
  • startActivityInner() @ActivityStarter.java
    • (ActivityStack)mTargetStack.startActivityLocked()//启动黑白屏页面
  • (RootWindowContainer)mRootWindowContainer.resumeFocusedStacksTopActivities() @ActivityStarter.java
  • (ActivityStack)focusedStack.resumeTopActivityUncheckedLocked() @RootWindowContainer.java
  • resumeTopActivityInnerLocked() @ActivityStack
    • startPausingLocked(userLeaving, false /* uiSleeping */, next);
      执行当前Activity的onPause生命周期,next参数分析:
      ActivityRecord next = topRunningActivity(true);
  • (ActivityStackSupervisor)mStackSupervisor.startSpecificActivity(next, true, false); @ActivityStack.java
  • startSpecificActivity() @ActivityStackSupervisor.java
    • 判断要启动页面的进程是否存在逻辑代码块:
      if (wpc != null && wpc.hasThread()) {try {//需要启动的页面所在进程存在,就会调用这个方法,这里涉及到App的冷启动和热启动realStartActivityLocked(r, wpc, andResume, checkConfig);return;} catch (RemoteException e) {}knownToBeDead = true;
      }
      /**这里省略其他代码*/
      //如果需要启动的页面的进程还不存在,我们需要去创建该页面所在的进程,也就是创建app进程
      mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
      
  • realStartActivityLocked(r, wpc, andResume, checkConfig); @ActivityStackSupervisor.java
    • 这里我们是在同一个app中启动页面,所以进程已经存在了,所以进入上面的if代码块,执行realStartActivityLocked()方法
    • 构建ClientTransaction对象
      final ClientTransaction clientTransaction = ClientTransaction.obtain( proc.getThread(), r.appToken);
  • (ATMS)mService.getLifecycleManager().scheduleTransaction(clientTransaction); @ActivityStackSupervisor.java
    • 在(AMS)ATMS中去处理ClientTransation
  • scheduleTransaction() @ClientLifecycleManager.java
  • schedule() @ClientTransaction.java
    • (IApplicationThread)mClient.scheduleTransaction(this);
    • 这里的IApplicationThread是ActivityThread的内部类ApplicationThread,而this就是当前封装的ClientTransaction对象,所以最终会调用到ActivityThread.ApplicationThread类中的scheduleTransaction()方法.
  • scheduleTransaction() @ActivityThread.ApplicationThread
    • ActivityThread.this.scheduleTransaction(transaction);
      这个方法内部会调用ActivityThread的scheduleTransaction(),这个类没有实现scheduleTransaction方法,是由他的父类ClientTransactionHandler来实现的scheduleTransaction()方法.
  • scheduleTransaction() @ClientTransactionHandler.java
    • sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
      IBinder(ActivityThread.Application继承自IBinder的Stub类)是在子线程中,这个方法中会通过Handler发送一条消息交给主线程去处理,具体的处理这条消息的地方是在子类ActivityThread中完成的.
  • (TransactionExecutor)mTransactionExecutor.execute(transaction) @ActivityThread.java
  • execute() @TransactionExecutor.java
    • 最终在这个方法中去管理我们Activity的生命周期
      //这里transaction是ClientTransaction,
      //他是从IBinder子线程传递给ActivityThread主线程的一条消息
      executeCallbacks(transaction);
      executeLifecycleState(transaction);
      
    • executeCallbacks(transaction) @TransactionExecutor.java
      • item.execute(mTransactionHandler, token, mPendingActions); @TransactionExecutor.java
        • 这个方法会执行到LaunchActivityItemexecute方法
      • execute() @LaunchActivityItem.java
        • 这个方法中会构建一个ActivityClientRecord,这是ActivityThread的一个内部类,代码如下:
          ActivityClientRecord r = new ActivityClientRecord(...);
      • (ClientTransactionHandler)client.handleLaunchActivity(r, pendingActions, null); @LaunchActivityItem.java
        • 最终会交给ClientTransactionHandler的实现类ActivityThread来处理handleLaunchActivity()方法.
      • handleLaunchActivity() @ActivityThread.java
      • Activity a = performLaunchActivity(r, customIntent); @ActivityThread.java
        • 通过Instrumentation来创建一个Activity,实现方式是通过反射
          activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
        • 获取到我们在ActivityThread.ApplicationThread中通过bindApplication()方法创建的Application对象
        • 调用activity.attach()方法,这个方法会为我们的Activity创建PhoneWindow,赋值mUiThread、mMainThread、mApplication、mIntent、mActivityInfo等.
        • 然后执行Activity的onCreate生命周期
          mInstrumentation.callActivityOnCreate(activity, r.state);
        • ActivityClientRecord中的生命周期状态设置为onCreate,
          (ActivityThread.ActivityClientRecord)r.setState(ON_CREATE);
    • executeLifecycleState(transaction) @TransactionExecutor.java
      • cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);
        这个方法中,会通过计算,去执行上面executeCallbacks(transaction)方法最后执行到的ON_CREATE生命周期,与ON_RESUME生命周期之间的生命周期方法,也就是ON_START生命周期方法.
      • lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        这个方法会去执行ResumeActivityItem中的execute()方法.
        • execute() @ResumeActivityItem.java
        • handleResumeActivity() @ClientTransactionHandler
          • 最终是交给他的实现类ActivityThread来执行handleResumeActivity方法
        • handleResumeActivity() @ActivityThread.java
        • performResumeActivity(token, finalStateRequest, reason); @ActivityThread.java
        • (ActivityThread.ActivityClientRecord)r.activity.performResume(r.startsNotResumed, reason); @ActivityThread.ActivityClientRecord.Activity
        • mInstrumentation.callActivityOnResume(this); @Activity.java
        • activity.onResume(); @Instrumentation.java
        • onResume() @Activity.java

总结:

  • 我们通过ATMS.LocalService的startActivityAsUser()方法作为入口去启动一个新的页面Activity;
  • 然后通过ActivityStarter去解析设置的参数,并将我们要启动的Activity封装成一个ActivityRecord,然后通过ActivityStarter执行当前Activity的onPause生命周期;
  • 然后通过ActivityStackSupervisor(Activity栈的管理类)调用startSpecificActivity方法去启动指定的页面,这个方法中会判断启动页面的进程是否存在;
  • 如果Activity所在进程不存在,则会去创建App进程;
  • 若启动的Activity所在进程存在,则调用realStartActivityLocked()方法去启动这个页面,这个方法中会构建ClientTransaction对象,作为一条消息从子线程ApplicationThread发送给主线程ActivtyThread去处理;
    最终将这个消息中的ClientTransaction对象交给TransactionExecutor的execute()方法去处理,这个execute方法中包含了两个方法,分别处理LAUNCH事件和ONRUME事件;
  • LAUNCH事件最终会执行到ON_CREATE生命周期;
  • 而在执行ON_RESUME生命周期前,会有一个方法计算这ON_CREATE和ON_RESUME之间的生命周期ON_START,并执行ON_START生命周期方法;
  • 最终完成了启动页面Activity的onCreate、onStart和onResume生命周期方法的执行.

扩展:
执行Activity的生命周期方法最终会交给ActivityThread,具体的实现是由Instrumentaction类来完成的,他会执行Activity和Application的生命周期方法.

Activity启动过程中的一些工具类

  • ActivityStarter
    用于启动Activity,并解析Activity启动时的参数,这个类中包含了一个内部类DefaultFactory,这个内部类里面包含了一些属性:ActivityStartController、ActivityTaskManagerService、ActivityStackSupervisor和ActivityStartInterceptor,在构造函数中给这些变量赋值,从而可以通过这个内部类的实例获取到这些参数的值;
  • ActivityStarterControler
    ActivityStarter的控制器,用于创建ActivityStarter;ATMS中包含了一个ActivityStartController成员变量
  • ActivityRecord
    在底层每一个Activity都被封装成了一个个的ActivityRecord,这个对象中会包含了我们Activity的相关信息
  • ActivityStack
    这是一个栈,用于管理我们app的所有Activity,也就是管理所有的ActivityRecord
  • ActivityStackSupervisor
    这是Activity栈的监管器
  • ClientTransaction
    ClientTransaction是用于跨进程通信的事务,Activity栈的监管器ActivityStackSupervisor会被封装成一个事务.
    这个类包含了一些属性:
    • List mActivityCallbacks:要启动的Activity要执行的生命周期集合,如:onCreate、onStart和onResume
    • ActivityLifecycleItem mLifecycleStateRequest:要启动的Activity最终停留在哪个生命周期上,如:onResume
    • IApplicationThread mClient:app进程的IBinder对象?
    • IBinder mActivityToken:Activity的IBinder对象?

相关文章:

四. AMS源码分析

AMS 主要负责四大组件的启动、切换和调度以及应用程序的管理和调度工作. ActivityManager的组成主要分为以下几个部分: 服务代理: 由ActivityManagerProxy实现,用于与Server端提供的系统服务进行进程间通信服务中枢: ActivityManagerNative,继承自Binder并实现了IActivityMana…...

OpenGL进阶 | 绘制一个三角形

一、准备绘图数据 VBO&#xff08;Vertex Buffer Object&#xff09; 在opengl中&#xff0c;所有的数据都要放在显存中&#xff0c;通过VBO&#xff08;Vertex Buffer Object&#xff09;可将CPU数据传到GPU。 VBO&#xff08;Vertex Buffer Object&#xff09;是OpenGL中的一…...

CSAPP Lab3- bufbomb

实验目标 &#xff08;1&#xff09;掌握函数调用时的栈帧结构 &#xff08;2&#xff09;利用输入缓冲区的溢出漏洞&#xff0c;将攻击代码嵌入当前程序的栈帧中&#xff0c;使得程序执行我们所期望的过程 实验代码 &#xff08;1&#xff09;makecookie&#xff1a;生成c…...

分布式系统之CAP定理介绍

前言 在分布式系统的设计和实现中&#xff0c;CAP定理是一个非常重要的概念。本文将介绍CAP定理的概念、含义和应用。 什么是 CAP 定理&#xff1f; CAP定理是分布式系统设计中的一个基本原则&#xff0c;它指出&#xff0c;在分布式系统中&#xff0c;一致性&#xff08;Consi…...

vcomp140.dll怎么安装?提示vcomp140.dll丢失怎样修复?

在用电脑玩游戏或者打开软件工作的时候&#xff0c;电脑提示vcomp140.dll丢失无法执行此代码&#xff0c;是什么回事呢&#xff1f;需要怎么修复呢&#xff1f;不用紧张&#xff0c;小编今天就把vcomp140.dll文件修复方法分享给大家。我总结了几个修复经验&#xff1b; vcomp14…...

CA OpenSSL自签名证书(服务器/客户端)

参考文章 https://juejin.cn/post/7092789498823573518 https://blog.csdn.net/mengting2040/article/details/120001810 目录 使用 OpenSSL 生成证书创建根证书创建 Root Pair创建 Root Key创建 Root Crt 创建服务器端证书创建服务器端keyip需要换成自己服务器的外网ip地址&am…...

计算机视觉(4)—— 未有深度学习之前

目录 四、未有深度学习之前 4.1 图像分割 4.1.1 基于阈值分割 4.1.2 基于边缘分割 4.1.3 基于区域分割 &#xff08;1&#xff09;区域生长法 &#xff08;2&#xff09;分水岭算法 4.1.4 基于图论分割 &#xff08;1&#xff09;Graph Cuts 分割 ​&#xff08;2&…...

怎么获取winform中动态代码生成的控件的状态

winform怎么获取动态代码生成窗口里面的控件的属性状态 MainForm中调用 private void ShowPropertyForm() { PropertyForm form new PropertyForm(selectedShape); form.ShowDialog(); pictureBox1.Refresh(); …...

Windows安装Maven并配置环境

Windows下安装和配置Maven的步骤 介绍&#xff1a;步骤&#xff1a;步骤 1&#xff1a;下载Maven步骤 2&#xff1a;解压缩Maven分发包步骤 3&#xff1a;设置环境变量步骤 4&#xff1a;验证安装 结论&#xff1a; 介绍&#xff1a; Maven是一个非常流行的构建和项目管理工具…...

致力于中小企业JavaEE企业级快速开发平台、后台框架平台

一、开源项目简介 J2eeFAST 是一个 Java EE 企业级快速开发平台&#xff0c; 致力于打造中小企业最好用的开源免费的后台框架平台 。系统基于&#xff08;Spring Boot、Spring MVC、Apache Shiro、MyBatis-Plus、Freemarker、Bootstrap、AdminLTE&#xff09;经典技术开发&…...

【神经网络】tensorflow实验9--分类问题

1. 实验目的 ①掌握逻辑回归的基本原理&#xff0c;实现分类器&#xff0c;完成多分类任务&#xff1b; ②掌握逻辑回归中的平方损失函数、交叉熵损失函数以及平均交叉熵损失函数。 2. 实验内容 ①能够使用TensorFlow计算Sigmoid函数、准确率、交叉熵损失函数等&#xff0c…...

LeetCode2. 两数相加

写在前面&#xff1a; 题目链接&#xff1a;LeetCode2两数相加 编程语言&#xff1a;C 题目难度&#xff1a;中等 一、题目描述 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 …...

基于无线传感网络(WSN)的目标跟踪技术(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 无线传感器网络由于其自组织性、鲁棒性及节点数量巨大的特点,非常适合于目标跟踪。无线传感器网络中的移动目标跟踪实际上就是…...

百度发布首个可信AI工具集TrustAI,助力数据分析与增强

百度发布首个集分析与增强于一体的可信AI工具集TrustAI&#xff0c;该工具集旨在帮助用户快速、准确地对各种类型的数据进行分析和增强&#xff0c;从而提高数据的价值和可信度。 随着人工智能技术的快速发展&#xff0c;数据的价值和重要性日益凸显。然而&#xff0c;在数据处…...

电力系统负荷与电价预测优化模型(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

asp.net+C#超市商品进销存管理系统

本超市商品管理系统主要超市内部提供服务&#xff0c;系统分为管理员员工两部分。 本研究课题重点主要包括了下面几大模块&#xff1a;管用户登录&#xff0c;员工管理&#xff0c;商品管理&#xff0c;进货管理&#xff0c;销售管理&#xff0c;供应商信息&#xff0c;会员信…...

轻量级K8s发行版的五大优势,助力企业快速拥抱边缘计算

随着物联网和移动设备的普及&#xff0c;边缘计算已成为当前信息技术领域的热门话题。为了满足这一需求&#xff0c;越来越多的企业开始探索使用容器化技术来打造轻量级的K8s发行版。这种发行版可以更加灵活地部署在物理边缘&#xff0c;提供更快速、更稳定的服务。 在这篇文章…...

【深入理解redis】数据结构

文章目录 动态字符串SDS字符串编码类型 intsetDictZipListZipList的连锁更新问题 QuickListSkipListRedisObjectStringListSet结构ZSETHash Redis 共有 5 种基本数据结构&#xff1a;String&#xff08;字符串&#xff09;、List&#xff08;列表&#xff09;、Set&#xff08;…...

《计算机网络—自顶向下方法》 第三章Wireshark实验:DNS协议分析

域名系统 DNS(Domain Name System) 是互联网使用的命名系统&#xff0c;用于把便于大家使用的机器名字转换为 IP 地址。许多应用层软件经常直接使用 DNS&#xff0c;但计算机的用户只是间接而不是直接使用域名系统。 互联网采用层次结构的命名树作为主机的名字&#xff0c;并使…...

JUC(十二)-线程中断相关问题(LockSupport,sleep,InterruptException)

JUC线程中断相关问题总结 线程中断相关问题总结 JUC线程中断相关问题总结一、 sleep 和线程中断之间的关系和特点结论测试验证代码如下 二、 LockSupport 和线程中断之间的关系结论测试验证代码如下 一、 sleep 和线程中断之间的关系和特点 结论 线程调用 Thread.sleep之后会进…...

Kotlin高级协程

Kotlin高级协程 一.前言二.先从线程说起三.协程的设计思想四.协程特点&#xff1a;优雅的实现移步任务五.协程基本使用六.协程和线程相比有什么特点&#xff0c;如何优雅的实现异步任务 一.前言 在文章正式上干货之前&#xff0c;先说一点背景吧&#xff1b;我是 Kotlin 协程官…...

车载软件架构——闲聊几句AUTOSAR BSW(四)

我是穿拖鞋的汉子,魔都中坚持长期主义的工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 我们并不必要为了和谐,而时刻保持通情达理;我们需要具备的是,偶尔有肚量欣然承认在某些方面我们可能会有些不可理喻。该有主见的时候能掷地有声地镇得住场…...

Linux:rpm查询安装 yum安装

环境&#xff1a; 需要插入安装镜像 镜像内有所需的安装库 我这里使用的虚拟机直接连接光盘 连接的光盘挂载在/dev/cdrom 由于我们无法直接进入&#xff0c;所以选择把/dev/cdrom挂载到别的地方即可 mount /dev/cdrom /123 将/dev/cdrom 挂载到 /123 目录下 Packages下就是…...

Android音视频开发之音频录制和播放

1.封装音频录制工具类&#xff1a; public class RecorderAudioManagerUtils {private static volatile RecorderAudioManagerUtils mInstance;public static RecorderAudioManagerUtils getInstance() {if (mInstance null) {synchronized (RecorderAudioManagerUtils.class…...

Java之单例模式

目录 一.上节内容 1.什么是线程安全 2.线程不安全的原因 3.JMM(Java内存模型) 4.synchronized锁 5.锁对象 6.volatile关键字 7.wait()和notify() 8.Java中线程安全的类 二.单例模式 1.什么是单例 2.怎么设计一个单例 1.口头约定 2.使用编程语言的特性 三.饿汉模式…...

【分组码系列】线性分组码的网格图和维特比译码

线性分组码的网格图 由于码字的比特位是统计独立的,所以编码过程可以利用有限状态机来描述,它能精确地确定初始和最终状态。可以利用网格图进一步描述编码过程[36],采用维特比算法进行最大似然译码. 在GF(2)上定义线性分组码(n,k)。相应的(n-k)Xn维校验阵可以写成 令码字为系…...

代码命名规范是真优雅呀!代码如诗

日常编码中&#xff0c;代码的命名是个大的学问。能快速的看懂开源软件的代码结构和意图&#xff0c;也是一项必备的能力。那它们有什么规律呢&#xff1f; Java项目的代码结构&#xff0c;能够体现它的设计理念。Java采用长命名的方式来规范类的命名&#xff0c;能够自己表达…...

你不知道的自动化?使用自动化测试在项目中创造高业务价值...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 脱离数据支撑谈价…...

通过实现一个简单的 JavaScript 猜数字大小的游戏,介绍如何进行布局样式处理

JavaScript 猜数字大小是一个非常简单、却又经典的游戏&#xff0c;可以锻炼玩家的逻辑思维能力。在这个游戏中&#xff0c;电脑会随机生成一个数字&#xff0c;玩家需要根据提示逐步猜出正确的数字。接下来&#xff0c;我们将通过实现一个简单的 JavaScript 猜数字大小游戏来介…...

Java设计模式(二十二)策略模式

一、概述 策略模式是一种行为型设计模式&#xff0c;它允许在运行时选择算法的行为。策略模式通过将算法封装成独立的策略类&#xff0c;使得它们可以相互替换&#xff0c;而不影响使用算法的客户端。这样可以使客户端代码与具体算法的实现细节解耦&#xff0c;提高了代码的可…...