Android系统Activity窗口启动过程_第1页
Android系统Activity窗口启动过程_第2页
Android系统Activity窗口启动过程_第3页
Android系统Activity窗口启动过程_第4页
Android系统Activity窗口启动过程_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、在Android系统中,一个Activity对应一个应用程序窗口,任何一个Activity的启动都是由AMS服务和应用程序进程相互配合来完成的。AMS服务统一调度系统中所有进程的Activity启动,而每个Activity的启动过程则由其所属进程来完成。AMS服务通过realStartActivityLocked函数来通知应用程序进程启动某个Activity:frameworks/base/services/java/com/android/server/am/ ActivityStack.javafinal boolean realStartActivityLocked(ActivityRe

2、cord r,ProcessRecord app, boolean andResume, boolean checkConfig)throws RemoteException ./系统参数发送变化,通知Activityif (checkConfig) Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(mService.mConfiguration,r.mayFreezeScreenLocked(app) ? r.appToken : null);mService.updateConfigu

3、rationLocked(config, r, false, false);/将进程描述符设置到启动的Activity描述符中r.app = app;app.waitingToKill = null;/将启动的Activity添加到进程启动的Activity列表中int idx = app.activities.indexOf(r);if (idx < 0) app.activities.add(r);mService.updateLruProcessLocked(app, true, true);try ./通知应用程序进程加载Activityapp.thread.scheduleLa

4、unchActivity(new Intent(ent), r.appToken,System.identityHashCode(r), ,new Configuration(mService.mConfiguration),pat, r.icicle, results, newIntents, !andResume,mService.isNextTransitionForward(), profileFile, profileFd,profileAutoStop);. catch (RemoteException e) .if (mMainStack) mService

5、.startSetupActivityLocked();return true;AMS通过realStartActivityLocked函数来调度应用程序进程启动一个Activity,参数r为即将启动的Activity在AMS服务中的描述符,参数app为Activity运行所在的应用程序进程在AMS服务中的描述符。函数通过IApplicationThread代理对象ApplicationThreadProxy通知应用程序进程启动r对应的Activity,应用程序进程完成Activity的加载等准备工作后,AMS最后启动该Activity。启动Activity的创建等工作是在应用程序进程中完成的

6、,AMS是通过IApplicationThread接口和应用程序进程通信的。r.appToken 在AMS服务端的类型为Token,是IApplicationToken的Binder本地对象。frameworks/base/core/java/android/app/ ActivityThread.javapublic final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,ActivityInfo info, Configuration curConfig, CompatibilityInfo com

7、patInfo,Bundle state, List<ResultInfo> pendingResults,List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) /将AMS服务传过来的参数封装为ActivityClientRecord对象ActivityClientRecord r = new ActivityClientRecor

8、d();r.token = token;r.ident = ident;ent = intent;r.activityInfo = info;patInfo = compatInfo;r.state = state;r.pendingResults = pendingResults;r.pendingIntents = pendingNewIntents;r.startsNotResumed = notResumed;r.isForward = isForward;fileFile = profileName;fileFd = profileFd;r.autoSt

9、opProfiler = autoStopProfiler;updatePendingConfiguration(curConfig);/使用异步消息方式实现Activity的启动queueOrSendMessage(H.LAUNCH_ACTIVITY, r);参数token从AMS服务端经过Binder传输到应用程序进程后,变为IApplicationToken的Binder代理对象,类型为IApplicationToken.Proxy,这是因为AMS和应用程序运行在不同的进程中。通过queueOrSendMessage函数将Binder跨进程调用转换为应用程序进程中的异步消息处理frame

10、works/base/core/java/android/app/ ActivityThread.javaprivate class H extends Handler public void handleMessage(Message msg) switch (msg.what) case LAUNCH_ACTIVITY: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");ActivityClientRecord r = (ActivityClientRecord)msg.obj;r.p

11、ackageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, patInfo);handleLaunchActivity(r, null);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break;LAUNCH_ACTIVITY消息在应用程序主线程消息循环中得到处理,应用程序通过handleLaunchActivity函数来启动Activity。到此AMS服务就完成了Activity的调度任务,将Activity的启动过程完全交给了应用程序进程来完成。framework

12、s/base/core/java/android/app/ ActivityThread.javaprivate void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) /主线程空闲时会定时执行垃圾回收,主线程当前要完成启动Activity的任务,因此这里先暂停GCunscheduleGcIdler();if (fileFd != null) mProfiler.setProfiler(fileFile, fileFd);mProfiler.startProfiling();mP

13、rofiler.autoStopProfiler = r.autoStopProfiler;/ Make sure we are running with the most recent config.handleConfigurationChanged(null, null);/创建ActivityActivity a = performLaunchActivity(r, customIntent);if (a != null) r.createdConfig = new Configuration(mConfiguration);Bundle oldState = r.state;/启动A

14、ctivityhandleResumeActivity(r.token, false, r.isForward);.else.performLaunchActivity应用程序进程通过performLaunchActivity函数将即将要启动的Activity加载到当前进程空间来,同时为启动Activity做准备。frameworks/base/core/java/android/app/ ActivityThread.javaprivate Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent)

15、ActivityInfo aInfo = r.activityInfo;if (r.packageInfo = null) /通过Activity所在的应用程序信息及该Activity对应的CompatibilityInfo信息从PMS服务中查询当前Activity的包信息r.packageInfo = getPackageInfo(aInfo.applicationInfo, patInfo,Context.CONTEXT_INCLUDE_CODE);/获取当前Activity的组件信息ComponentName component = ent.getComponent();if

16、(component = null) component = ent.resolveActivity(mInitialApplication.getPackageManager();ent.setComponent(component);if (r.activityInfo.targetActivity != null) /packageName为启动Activity的包名,targetActivity为Activity的类名component = new ComponentName(r.activityInfo.packageName,r.activityInfo.tar

17、getActivity);/通过类反射方式加载即将启动的ActivityActivity activity = null;try java.lang.ClassLoader cl = r.packageInfo.getClassLoader();activity = mInstrumentation.newActivity(cl, component.getClassName(), ent);StrictMode.incrementExpectedActivityCount(activity.getClass();ent.setExtrasClassLoader(cl);i

18、f (r.state != null) r.state.setClassLoader(cl); catch (Exception e) .try /通过单例模式为应用程序进程创建Application对象Application app = r.packageInfo.makeApplication(false, mInstrumentation);if (activity != null) /为当前Activity创建上下文对象ContextImplContextImpl appContext = new ContextImpl();/上下文初始化appContext.init(r.packa

19、geInfo, r.token, this);appContext.setOuterContext(activity);CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager();.Configuration config = new Configuration(mCompatConfiguration);/将当前启动的Activity和上下文ContextImpl、Application绑定activity.attach(appContext, this, getInstrumentation(),

20、 r.token,r.ident, app, ent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config);./调用Activity的OnCreate函数mInstrumentation.callActivityOnCreate(activity, r.state);./将Activity保存到ActivityClientRecord中,ActivityClientRecord为Activity在应用程序进程中的描述符r.activity = activity;.

21、r.paused = true;/ActivityThread的成员变量mActivities保存了当前应用程序进程中的所有Activity的描述符mActivities.put(r.token, r); catch (SuperNotCalledException e) .return activity;在该函数中,首先通过PMS服务查找到即将启动的Activity的包名信息,然后通过类反射方式创建一个该Activity实例,同时为应用程序启动的每一个Activity创建一个LoadedApk实例对象,应用程序进程中创建的所有LoadedApk对象保存在ActivityThread的成员变量

22、mPackages中。接着通过LoadedApk对象的makeApplication函数,使用单例模式创建Application对象,因此在android应用程序进程中有且只有一个Application实例。然后为当前启动的Activity创建一个ContextImpl上下文对象,并初始化该上下文,到此我们可以知道,启动一个Activity需要以下对象:1)      XXActivity对象,需要启动的Activity;2)      LoadedApk对象,每个启动的Activity都拥有属

23、于自身的LoadedApk对象;3)      ContextImpl对象,每个启动的Activity都拥有属于自身的ContextImpl对象;4)      Application对象,应用程序进程中有且只有一个实例,和Activity是一对多的关系;加载Activity类public Activity newActivity(ClassLoader cl, String className,Intent intent)throws InstantiationException, Illeg

24、alAccessException,ClassNotFoundException return (Activity)cl.loadClass(className).newInstance();这里通过类反射的方式来加载要启动的Activity实例对象。LoadedApk构造过程首先介绍一下LoadedApk对象的构造过程:frameworks/base/core/java/android/app/ ActivityThread.javapublic final LoadedApk getPackageInfo(String packageName, CompatibilityInfo comp

25、atInfo,int flags) synchronized (mPackages) /通过Activity的包名从对应的成员变量中查找LoadedApk对象WeakReference<LoadedApk> ref;if (flags&Context.CONTEXT_INCLUDE_CODE) != 0) ref = mPackages.get(packageName); else ref = mResourcePackages.get(packageName);LoadedApk packageInfo = ref != null ? ref.get() : null;i

26、f (packageInfo != null && (packageInfo.mResources = null| packageInfo.mResources.getAssets().isUpToDate() .return packageInfo;/如果没有,则为当前Activity创建对应的LoadedApk对象ApplicationInfo ai = null;try /通过包名在PMS服务中查找应用程序信息ai = getPackageManager().getApplicationInfo(packageName,PackageManager.GET_SHARED_

27、LIBRARY_FILES, UserId.myUserId(); catch (RemoteException e) / Ignore/使用另一个重载函数创建LoadedApk对象if (ai != null) return getPackageInfo(ai, compatInfo, flags);return null;public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo,int flags) boolean includeCode = (flags&Conte

28、xt.CONTEXT_INCLUDE_CODE) != 0;boolean securityViolation = includeCode && ai.uid != 0&& ai.uid != Process.SYSTEM_UID && (mBoundApplication != null? !UserId.isSameApp(ai.uid, mBoundApplication.appInfo.uid): true);if (flags&(Context.CONTEXT_INCLUDE_CODE|Context.CONTEXT_IGNOR

29、E_SECURITY)= Context.CONTEXT_INCLUDE_CODE) .return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode);private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,ClassLoader baseLoader, boolean securityViolation, boolean includeCode) /再次从对应的成员变量中查找LoadedApk

30、实例synchronized (mPackages) WeakReference<LoadedApk> ref;if (includeCode) ref = mPackages.get(aInfo.packageName); else ref = mResourcePackages.get(aInfo.packageName);LoadedApk packageInfo = ref != null ? ref.get() : null;if (packageInfo = null | (packageInfo.mResources != null&& !packag

31、eInfo.mResources.getAssets().isUpToDate() ./构造一个LoadedApk对象packageInfo =new LoadedApk(this, aInfo, compatInfo, this, baseLoader,securityViolation, includeCode &&(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);/保存LoadedApk实例到ActivityThread的相应成员变量中if (includeCode) mPackages.put(aInfo.pac

32、kageName,new WeakReference<LoadedApk>(packageInfo); else mResourcePackages.put(aInfo.packageName,new WeakReference<LoadedApk>(packageInfo);return packageInfo;frameworks/base/core/java/android/app/LoadedApk.javapublic LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,Compatib

33、ilityInfo compatInfo,ActivityThread mainThread, ClassLoader baseLoader,boolean securityViolation, boolean includeCode) mActivityThread = activityThread;mApplicationInfo = aInfo;mPackageName = aInfo.packageName;mAppDir = aInfo.sourceDir;final int myUid = Process.myUid();mResDir = aInfo.uid = myUid ?

34、aInfo.sourceDir: aInfo.publicSourceDir;if (!UserId.isSameUser(aInfo.uid, myUid) && !Process.isIsolated() aInfo.dataDir = PackageManager.getDataDirForUser(UserId.getUserId(myUid),mPackageName);mSharedLibraries = aInfo.sharedLibraryFiles;mDataDir = aInfo.dataDir;mDataDirFile = mDataDir != null

35、 ? new File(mDataDir) : null;mLibDir = aInfo.nativeLibraryDir;mBaseClassLoader = baseLoader;mSecurityViolation = securityViolation;mIncludeCode = includeCode;mCompatibilityInfo.set(compatInfo);if (mAppDir = null) /为应用程序进程创建一个ContextImpl上下文if (ActivityThread.mSystemContext = null) ActivityThread.mSys

36、temContext =ContextImpl.createSystemContext(mainThread);ActivityThread.mSystemContext.getResources().updateConfiguration( mainThread.getConfiguration(), mainThread.getDisplayMetricsLocked(compatInfo, false), compatInfo);mClassLoader = ActivityThread.mSystemContext.getClassLoader();mResources = Activ

37、ityThread.mSystemContext.getResources();从以上LoadedApk的构造函数可以看出,LoadedApk类记录了Activity运行所在的ActivityThread、Activity所在的应用程序信息、Activity的包名、Activity的资源路径、Activity的库路径、Activity的数据存储路径、类加载器和应用程序所使用的资源等信息。Application构造过程当Activity为应用程序进程启动的第一个Activity,因此需要构造一个Application对象frameworks/base/core/java/android/app/

38、LoadedApk.javapublic Application makeApplication(boolean forceDefaultAppClass,Instrumentation instrumentation) /在应用程序进程空间以单例模式创建Application对象if (mApplication != null) return mApplication;Application app = null;/得到应用程序的Application类名String appClass = mApplicationInfo.className;/如果应用程序没用重写Application,则

39、使用Android默认的Application类if (forceDefaultAppClass | (appClass = null) appClass = "android.app.Application"try java.lang.ClassLoader cl = getClassLoader();/为Application实例创建一个上下文对象ContextImplContextImpl appContext = new ContextImpl();/初始化上下文appContext.init(this, null, mActivityThread);/创建Appl

40、ication实例对象app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);appContext.setOuterContext(app); catch (Exception e) .mActivityThread.mAllApplications.add(app);mApplication = app;if (instrumentation != null) try /调用Application的OnCreate函数instrumentation.callApplicationOnCre

41、ate(app); catch (Exception e) .return app;在应用程序开发过程中,当我们重写了Application类后,应用程序加载运行的是我们定义的Application类,否则就加载运行默认的Application类。从Application对象的构造过程就可以解释为什么应用程序启动后首先执行的是Application的OnCreate函数。在实例化Application对象时,同样创建并初始化了一个ContextImpl上下文对象。ContextImpl构造过程前面我们介绍了,每一个Activity拥有一个上下文对象ContextImpl,每一个Applicat

42、ion对象也拥有一个ContextImpl上下文对象,那么ContextImpl对象又是如何构造的呢?frameworks/base/core/java/android/app/ ContextImpl.javaContextImpl() mOuterContext = this;ContextImpl的构造过程什么也没干,通过调用ContextImpl的init函数进行初始化final void init(LoadedApk packageInfo,IBinder activityToken, ActivityThread mainThread) init(packageInfo, acti

43、vityToken, mainThread, null, null);final void init(LoadedApk packageInfo,IBinder activityToken, ActivityThread mainThread,Resources container, String basePackageName) mPackageInfo = packageInfo;mBasePackageName = basePackageName != null ? basePackageName : packageInfo.mPackageName;mResources = mPack

44、ageInfo.getResources(mainThread);if (mResources != null && container != null&& container.getCompatibilityInfo().applicationScale !=mResources.getCompatibilityInfo().applicationScale) mResources = mainThread.getTopLevelResources(mPackageInfo.getResDir(), container.getCompatibilityInfo

45、();mMainThread = mainThread;mContentResolver = new ApplicationContentResolver(this, mainThread);setActivityToken(activityToken);从ContextImpl的初始化函数中可以知道,ContextImpl记录了应用程序的包名信息、应用程序的资源信息、应用程序的主线程、ContentResolver及Activity对应的IApplicationToken.Proxy,当然对应Application对象所拥有的ContextImpl上下文就没有对应的Token了。通过前面的分

46、析我们可以知道各个对象之间的关系:对象Attach过程Activity所需要的对象都创建好了,就需要将Activity和Application对象、ContextImpl对象绑定在一起。frameworks/base/core/java/android/app/ Activity.javafinal void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token,Application application, Intent intent, ActivityInfo info,

47、CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances,Configuration config) attach(context, aThread, instr, token, 0, application, intent, info, title, parent, id,lastNonConfigurationInstances, config);context:Activity的上下文对象,就是前面创建的ContextImpl对象;aThr

48、ead:Activity运行所在的主线程描述符ActivityThread;instr:用于监控Activity运行状态的Instrumentation对象;token:用于和AMS服务通信的IApplicationToken.Proxy代理对象;application:Activity运行所在进程的Application对象;parent:启动当前Activity的Activity;final void attach(Context context, ActivityThread aThread,Instrumentation instr, IBinder token, int ident,

49、Application application, Intent intent, ActivityInfo info,CharSequence title, Activity parent, String id,NonConfigurationInstances lastNonConfigurationInstances,Configuration config) /将上下文对象ContextImpl保存到Activity的成员变量中attachBaseContext(context);/每个Activity都拥有一个FragmentManager,这里就是将当前Activity设置到Fragm

50、entManager中管理mFragments.attachActivity(this);/创建窗口对象mWindow = PolicyManager.makeNewWindow(this);mWindow.setCallback(this);mWindow.getLayoutInflater().setPrivateFactory(this);if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) mWindow.setSoftInputMode(info.softInputMode

51、);if (info.uiOptions != 0) mWindow.setUiOptions(info.uiOptions);/记录应用程序的UI线程mUiThread = Thread.currentThread();/记录应用程序的ActivityThread对象mMainThread = aThread;mInstrumentation = instr;mToken = token;mIdent = ident;mApplication = application;mIntent = intent;mComponent = intent.getComponent();mActivity

52、Info = info;mTitle = title;mParent = parent;mEmbeddedID = id;mLastNonConfigurationInstances = lastNonConfigurationInstances;/为Activity所在的窗口创建窗口管理器mWindow.setWindowManager(null, mToken, mComponent.flattenToString(),(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);if (mParent != null) m

53、Window.setContainer(mParent.getWindow();mWindowManager = mWindow.getWindowManager();mCurrentConfig = config;在该attach函数中主要做了以下几件事:1)        将Activity设置到FragmentManager中;2)        根据参数初始化Activity的成员变量;3)     

54、;   为Activity创建窗口Window对象;4)        为Window创建窗口管理器;到此为止应用程序进程为启动的Activity对象创建了以下不同的实例对象,它们之间的关系如下:应用程序窗口创建过程frameworks/base/core/java/com/android/internal/policy/ PolicyManager.javapublic static Window makeNewWindow(Context context) return sPolicy.makeNew

55、Window(context);通过Policy类的makeNewWindow函数来创建一个应用程序窗口private static final String POLICY_IMPL_CLASS_NAME ="ernal.policy.impl.Policy"private static final IPolicy sPolicy;static try Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);sPolicy = (IPolicy)policyClass.newInsta

56、nce(); catch (ClassNotFoundException ex) .frameworks/base/policy/src/com/android/internal/policy/impl/ Policy.javapublic Window makeNewWindow(Context context) return new PhoneWindow(context);应用程序窗口的创建过程其实就是构造一个PhoneWindow对象。PhoneWindow类是通过静态方式加载到应用程序进程空间的。private static final String preload_classes

57、= "ernal.policy.impl.PhoneLayoutInflater","ernal.policy.impl.PhoneWindow","ernal.policy.impl.PhoneWindow$1","ernal.policy.impl.PhoneWindow$ContextMenuCallback","ernal.policy.impl.PhoneWindow$DecorView","ernal.policy.impl.PhoneWindow$PanelFeatureState","ernal.policy.impl.PhoneWindow$PanelFeatureState$SavedState",;static for

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论