App的启动过程(1)framework侧-startActivity的判断处理流程

来源:互联网 发布:淘宝怎么隐藏真实姓名 编辑:程序博客网 时间:2024/06/09 16:37

app从启动到画出来整个流程,这一系列文档是针对这个做的笔记,可能有点乱,有不准确的地方,还请指正!

 

通过点击桌面图标,可以启动这个应用程序制定的一个Activity,后面会调用到ActivityManagerServiceStartActivity的函数。经过一些判断和准备,如果顺利,AMS最终尝试启动制定的ActivityAndroid规定,在新的Activity启动前,原先处于resumed状态的activity会被pause。将一个activity置为pause,是通过这个activity所属进程的ApplicationThread中方法schedulePauseActivity完成的,applicationThread是应用程序跟AMS通信的一个Binder通道,在主线程ActivityThread中。

         当收到pause请求后,这个进程ActivityThread主线程会进一步处理,出来调用Activity.onPause()等方法外,还会通知WindowManagerService,因为这会引起界面发生变化。然后,进程会通知AMS它的pause请求已经完成了,可以让AMS接着执行startActivity的操作。

         如果要启动的Activity所属进程不存在,AMS还要先把进程叫起来,这是有Process.start实现的,通过参数启动应用程序的主线程ActivityThread,调用主线程的main函数。主线程启动做好初始化后,会调用attachApplication通知AMS,然后AMS会查看是否有顶层可见的Activity在等待这个进程来启动,如果有,AMS通过ApplicationThread.scheduleLaunchActivity请求应用进程启动这个activity,之后的工作就是应用进程来主导完成,activity的生命周期的调用,创建window,遍历view树等。

         结合源码解析启动过程。

第一阶段、framework侧的处理

         startActivity@ContextImpl.java–>到工具类:execStartActivity@Instrumentation.javaà到AMS:startActivity@ActivityManagerService.java

         其中AMS对象的获取是通过ActivityManagerNative的函数gDefault这个单例对象实现的,这里就涉及进程间通讯了,其中ActivityManagerProxyAMS在应用进程端的代表,AMS的真正实现在ActivityManagerNative中,

         /*ActivityManagerNative.java*/

   static public IActivityManager getDefault() { // IActivityManagerAMS的接口类

       return gDefault.get();

}

//这是获取AMS对象的地方,因为AMS是实名的binderServer,在Servicemanager中有注册,可以通过ServiceManager.getService("activity")来查找。

    private staticfinal Singleton<IActivityManager> gDefault = newSingleton<IActivityManager>() {

       protected IActivityManager create() {

           IBinder b = ServiceManager.getService("activity");

           IActivityManager am = asInterface(b);

           return am;//这里返回的实际是ActivityManagerProxy

       }

   };

}

ActivityManagerNative的作用之一是方便客户端取得一个ActivityManagerProxy,另一个作用就是为AMS的实现提供便利,就是说AMS只要继承ActivityManagerNative,就可以将客户端的业务请求码与内部实现函数连接起来,Binder通信中,客户端请求码必须要跟服务端一致。

public finalclass ActivityManagerService extends ActivityManagerNative{}

//AMS果然是继承了ActivityManagerNative,直接面向应用程序的是ActivityManagerProxy,这个代理会利用Ibinder,进而使用ProcessStateIPCThreadState完成跟Binder驱动的通信,把请求传到服务端ActivityManagerService

         接着看AMS中的代码,AMS做的工作是以多个类似的startActivity函数完成的。

         /*ActivityManagerService.java*/

   public final int startActivity(IApplicationThread caller, StringcallingPackage,

            Intentintent, String resolvedType, IBinder resultTo, String resultWho, intrequestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {

       return startActivityAsUser(caller, callingPackage, intent, resolvedType,resultTo,

                resultWho, requestCode,startFlags, profilerInfo, bOptions,

                UserHandle.getCallingUserId());

    }

         UserHandle.getCallingUserId()表示调用者的用户ID。函数参数太长省略了。

public finalint startActivityAsUser(){

//检查调用者是否属于被隔离的对象

                   enforceNotIsolatedCaller("startActivity");

//检查调用者是否有权限执行这个操作

                   userId =mUserController.handleIncomingUser()

                   mActivityStarter.startActivityMayWait()

}       

/*ActivityStarter.java*/

final intstartActivityMayWait(){

//解析出符合Intent要求的目标Activity

                   ActivityInfoaInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

//判断目标Activity所属进程是不是重量级的

                   final ProcessRecord heavy =mService.mHeavyWeightProcess;

                   if (heavy != null &&(heavy.info.uid != aInfo.applicationInfo.uid

                            || !heavy.processName.equals(aInfo.processName))){}

//接着进一步调用startActivityLocked进一步做启动的工作

                   startActivityLocked();

}

//进入final intstartActivityLocked()函数

final intstartActivityLocked(){

//确保调用者进程时存在的,没有被系统kill,或者异常退出。

                   if (caller != null) {

                            callerApp =mService.getRecordForAppLocked(caller);

                            err =ActivityManager.START_PERMISSION_DENIED;}  }

//处理flagFLAG_ACTIVITY_FORWARD_RESULT,它具有跨越式传递的作用,如Activity-1启动了Activity-2,当Activity-2启动Activity-3时用了这个标志,Activity-3调用setResult时,result不会把结果传给Activity-2,而是传给Activity-1

                   if ((launchFlags &Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0) {  

                            resultWho =sourceRecord.resultWho;

                            requestCode =sourceRecord.requestCode;

}

 

//目标Activityinfo为空,没有目标Activity处理intent,都会报错返回

         if (err ==ActivityManager.START_SUCCESS && intent.getComponent() == null)

         if (err ==ActivityManager.START_SUCCESS && aInfo == null)

//还要做两项权限检查

         boolean abort =!mSupervisor.checkStartAnyActivityPermission()

         abort |=!mService.mIntentFirewall.checkStartActivity()

                   //生成一个ActivityRecord对象,记录各项判断结果,

ActivityRecord r = new ActivityRecord();

                   //进入startActivityUnchecked(),这个函数处理跟启动模式、Intent标志相关的属性

err = startActivityUnchecked()

}

//进入startActivityUnchecked()

private intstartActivityUnchecked(){

                   //计算启动flags,计算启动的stack

                            computeLaunchingTaskFlags();

                             computeSourceStack();

                   //然后就是各种flag的处理

//START_FLAG_ONLY_IF_NEEDED,FLAG_ACTIVITY_NEW_TASK,//FLAG_ACTIVITY_CLEAR_TASK…

//最后调用ActivityStack中的startActivityLocked

         mTargetStack.startActivityLocked();

}

//进入ActivityStack中的startActivityLocked()

final void startActivityLocked(){

                   //先要看Activity是不是在新task启动,即newTask的值,如果为false,要找出Activity在那个老的task中,找到后把将它加入history中,然后把它放在stack的顶层,才能与用户交互。

                            task.addActivityToTop(r);

                            r.putInHistory();

                   //是否要执行切换动画

                            if((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0)

                   //一个Activity的界面要显示出来,在wms中必须有记录,这个记录就是apptoken,在后面添加窗口时,wms会判断如果没有这个APPtoken,就不能成功添加窗口。

                            addConfigOverride()àmWindowManager.addAppToken();

                   //是否要显示启动窗口

                            if(SHOW_APP_STARTING_PREVIEW && doShow);                           

}

到这里startActivity的判断处理流程就执行完了


简单说下AMS的功能和启动:

ActivityManagerService的功能

1)组件状态的管理,四个组件的开启、关闭等一系列操作

2)组件状态查询,查询组件当前的运行情况

3Task相关的操作removeTaskmovetasktofront

4)其他一些系统运行信息的查询getMemeoryInfo


AMS是在systemserver中启动的


SystemServer.javaprivate void startBootstrapServices() {//这里会调用AMS的start方法。mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();//然后,进行初始化,并把一些服务添加到serviceManager中。mActivityManagerService.initPowerManagement();mActivityManagerService.setSystemProcess();mActivityManagerService.installSystemProviders();mActivityManagerService.setWindowManager(wm);mActivityManagerService.enterSafeMode();//下面这个调用会先执行AMS中的systemready方法,确保AMS启动ok了,才会执行这个回调,在这个回调中,systemserver接着执行系统服务的启动,在这里启动systemUI。mActivityManagerService.systemReady(new Runnable() {public void run() {mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);mActivityManagerService.startObservingNativeCrashes();startSystemUi(context);mSystemServiceManager.startBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);}});}

ActivityManagerService.javapublic void systemReady(final Runnable goingCallback) {//在AMS启动完成之前, mSystemReady是false的,synchronized(this) {if (mSystemReady) {goingCallback.run();return;}mSystemReady = true;}//下面是AMS的启动操作,包括启动home应用程序。retrieveSettings();readGrantedUriPermissionsLocked();…//这里去执行systemserver中的回调,继续systemserver中未完成的系统服务的启动。因为systemserver的后续运行要依赖AMS,所以在AMS还没就绪的情况下就冒然返回,可能造成系统宕机。if (goingCallback != null) goingCallback.run();...startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);startHomeActivityLocked(currentUserId, "systemReady");mStackSupervisor.resumeFocusedStackTopActivityLocked();}





原创粉丝点击