在Android系统中,一个Activity对应一个应用程序窗口,任何一个Activity的启动都是由AMS服务和应用程序进程相互配合来完成的。AMS服务统一调度系统中所有进程的Activity启动,而每个Activity的启动过程则由其所属进程来完成。AMS服务通过realStartActivityLocked函数来通知应用程序进程启动某个Activity:
frameworks\base\services\java\com\android\server\am\ ActivityStack.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
final
boolean
realStartActivityLocked(ActivityRecord r,
ProcessRecord app,
boolean
andResume,
boolean
checkConfig)
throws
RemoteException {
...
//系统参数发送变化,通知Activity
if
(checkConfig) {
①Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(mService.mConfiguration,
r.mayFreezeScreenLocked(app) ? r.appToken :
null
);
mService.updateConfigurationLocked(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
{
...
//通知应用程序进程加载Activity
②app.thread.scheduleLaunchActivity(
new
Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
new
Configuration(mService.mConfiguration),
r.compat, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward(), profileFile, profileFd,
profileAutoStop);
...
}
catch
(RemoteException e) {
...
}
if
(mMainStack) {
mService.startSetupActivityLocked();
}
return
true
;
}
|
AMS通过realStartActivityLocked函数来调度应用程序进程启动一个Activity,参数r为即将启动的Activity在AMS服务中的描述符,参数app为Activity运行所在的应用程序进程在AMS服务中的描述符。函数通过IApplicationThread代理对象ApplicationThreadProxy通知应用程序进程启动r对应的Activity,应用程序进程完成Activity的加载等准备工作后,AMS最后启动该Activity。启动Activity的创建等工作是在应用程序进程中完成的,AMS是通过IApplicationThread接口和应用程序进程通信的。r.appToken 在AMS服务端的类型为Token,是IApplicationToken的Binder本地对象。
frameworks\base\core\java\android\app\ ActivityThread.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public
final
void
scheduleLaunchActivity(Intent intent, IBinder token,
int
ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
Bundle state, List<resultinfo> pendingResults,
List<intent> pendingNewIntents,
boolean
notResumed,
boolean
isForward,
String profileName, ParcelFileDescriptor profileFd,
boolean
autoStopProfiler) {
//将AMS服务传过来的参数封装为ActivityClientRecord对象
ActivityClientRecord r =
new
ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profileFile = profileName;
r.profileFd = profileFd;
r.autoStopProfiler = autoStopProfiler;
updatePendingConfiguration(curConfig);
//使用异步消息方式实现Activity的启动
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}
</intent></resultinfo>
|
参数token从AMS服务端经过Binder传输到应用程序进程后,变为IApplicationToken的Binder代理对象,类型为IApplicationToken.Proxy,这是因为AMS和应用程序运行在不同的进程中。
通过queueOrSendMessage函数将Binder跨进程调用转换为应用程序进程中的异步消息处理
frameworks\base\core\java\android\app\ ActivityThread.java
1
2
3
4
5
6
7
8
9
10
11
12
13
|
private
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.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r,
null
);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
break
;
}
}
}
|
LAUNCH_ACTIVITY消息在应用程序主线程消息循环中得到处理,应用程序通过handleLaunchActivity函数来启动Activity。到此AMS服务就完成了Activity的调度任务,将Activity的启动过程完全交给了应用程序进程来完成。
frameworks\base\core\java\android\app\ ActivityThread.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
private
void
handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//主线程空闲时会定时执行垃圾回收,主线程当前要完成启动Activity的任务,因此这里先暂停GC
unscheduleGcIdler();
if
(r.profileFd !=
null
) {
mProfiler.setProfiler(r.profileFile, r.profileFd);
mProfiler.startProfiling();
mProfiler.autoStopProfiler = r.autoStopProfiler;
}
// Make sure we are running with the most recent config.
①handleConfigurationChanged(
null
,
null
);
//创建Activity
②Activity a = performLaunchActivity(r, customIntent);
if
(a !=
null
) {
r.createdConfig =
new
Configuration(mConfiguration);
Bundle oldState = r.state;
//启动Activity
③handleResumeActivity(r.token,
false
, r.isForward);
...
}
else
{
...
}
}
|
performLaunchActivity
应用程序进程通过performLaunchActivity函数将即将要启动的Activity加载到当前进程空间来,同时为启动Activity做准备。
frameworks\base\core\java\android\app\ ActivityThread.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
private
Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
if
(r.packageInfo ==
null
) {
//通过Activity所在的应用程序信息及该Activity对应的CompatibilityInfo信息从PMS服务中查询当前Activity的包信息
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,Context.CONTEXT_INCLUDE_CODE);
}
//获取当前Activity的组件信息
ComponentName component = r.intent.getComponent();
if
(component ==
null
) {
component = r.intent.resolveActivity(mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if
(r.activityInfo.targetActivity !=
null
) {
//packageName为启动Activity的包名,targetActivity为Activity的类名
component =
new
ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
//通过类反射方式加载即将启动的Activity
Activity activity =
null
;
try
{
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
①activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
if
(r.state !=
null
) {
r.state.setClassLoader(cl);
}
}
catch
(Exception e) {
...
}
try
{
//通过单例模式为应用程序进程创建Application对象
②Application app = r.packageInfo.makeApplication(
false
, mInstrumentation);
if
(activity !=
null
) {
//为当前Activity创建上下文对象ContextImpl
ContextImpl appContext =
new
ContextImpl();
//上下文初始化
③appContext.init(r.packageInfo, 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(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
...
//调用Activity的OnCreate函数
⑤mInstrumentation.callActivityOnCreate(activity, r.state);
...
//将Activity保存到ActivityClientRecord中,ActivityClientRecord为Activity在应用程序进程中的描述符
r.activity = activity;
...
}
r.paused =
true
;
//ActivityThread的成员变量mActivities保存了当前应用程序进程中的所有Activity的描述符
mActivities.put(r.token, r);
}
catch
(SuperNotCalledException e) {
...
}
return
activity;
}
|
在该函数中,首先通过PMS服务查找到即将启动的Activity的包名信息,然后通过类反射方式创建一个该Activity实例,同时为应用程序启动的每一个Activity创建一个LoadedApk实例对象,应用程序进程中创建的所有LoadedApk对象保存在ActivityThread的成员变量mPackages中。接着通过LoadedApk对象的makeApplication函数,使用单例模式创建Application对象,因此在android应用程序进程中有且只有一个Application实例。然后为当前启动的Activity创建一个ContextImpl上下文对象,并初始化该上下文,到此我们可以知道,启动一个Activity需要以下对象:
1) XXActivity对象,需要启动的Activity;
2) LoadedApk对象,每个启动的Activity都拥有属于自身的LoadedApk对象;
3) ContextImpl对象,每个启动的Activity都拥有属于自身的ContextImpl对象;
4) Application对象,应用程序进程中有且只有一个实例,和Activity是一对多的关系;
加载Activity类
1
2
3
4
5
6
|
public
Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws
InstantiationException, IllegalAccessException,
ClassNotFoundException {
return
(Activity)cl.loadClass(className).newInstance();
}
|
这里通过类反射的方式来加载要启动的Activity实例对象。
LoadedApk构造过程
首先介绍一下LoadedApk对象的构造过程:
frameworks\base\core\java\android\app\ ActivityThread.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
public
final
LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
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
;
if
(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_LIBRARY_FILES, UserId.myUserId());
}
catch
(RemoteException e) {
// Ignore
}
//使用另一个重载函数创建LoadedApk对象
if
(ai !=
null
) {
return
getPackageInfo(ai, compatInfo, flags);
}
return
null
;
}
</loadedapk>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public
final
LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo,
int
flags) {
boolean
includeCode = (flags&Context.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_IGNORE_SECURITY))
== Context.CONTEXT_INCLUDE_CODE) {
...
}
return
getPackageInfo(ai, compatInfo,
null
, securityViolation, includeCode);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
private
LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader,
boolean
securityViolation,
boolean
includeCode) {
//再次从对应的成员变量中查找LoadedApk实例
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
&& !packageInfo.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.packageName,
new
WeakReference<loadedapk>(packageInfo));
}
else
{
mResourcePackages.put(aInfo.packageName,
new
WeakReference<loadedapk>(packageInfo));
}
}
return
packageInfo;
}
}
</loadedapk></loadedapk></loadedapk>
|
frameworks\base\core\java\android\app\LoadedApk.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
public
LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
CompatibilityInfo 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 ? 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
?
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.mSystemContext =
ContextImpl.createSystemContext(mainThread);
ActivityThread.mSystemContext.getResources().updateConfiguration(
mainThread.getConfiguration(),
mainThread.getDisplayMetricsLocked(compatInfo,
false
),
compatInfo);
}
mClassLoader = ActivityThread.mSystemContext.getClassLoader();
mResources = ActivityThread.mSystemContext.getResources();
}
}
|
从以上LoadedApk的构造函数可以看出,LoadedApk类记录了Activity运行所在的ActivityThread、Activity所在的应用程序信息、Activity的包名、Activity的资源路径、Activity的库路径、Activity的数据存储路径、类加载器和应用程序所使用的资源等信息。
Application构造过程
当Activity为应用程序进程启动的第一个Activity,因此需要构造一个Application对象
frameworks\base\core\java\android\app\LoadedApk.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
public
Application makeApplication(
boolean
forceDefaultAppClass,
Instrumentation instrumentation) {
//在应用程序进程空间以单例模式创建Application对象
if
(mApplication !=
null
) {
return
mApplication;
}
Application app =
null
;
//得到应用程序的Application类名
String appClass = mApplicationInfo.className;
//如果应用程序没用重写Application,则使用Android默认的Application类
if
(forceDefaultAppClass || (appClass ==
null
)) {
appClass =
"android.app.Application"
;
}
try
{
java.lang.ClassLoader cl = getClassLoader();
//为Application实例创建一个上下文对象ContextImpl
①ContextImpl appContext =
new
ContextImpl();
//初始化上下文
②appContext.init(
this
,
null
, mActivityThread);
//创建Application实例对象
③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.callApplicationOnCreate(app);
}
catch
(Exception e) {
...
}
}
return
app;
}
|
在应用程序开发过程中,当我们重写了Application类后,应用程序加载运行的是我们定义的Application类,否则就加载运行默认的Application类。从Application对象的构造过程就可以解释为什么应用程序启动后首先执行的是Application的OnCreate函数。在实例化Application对象时,同样创建并初始化了一个ContextImpl上下文对象。
ContextImpl构造过程
前面我们介绍了,每一个Activity拥有一个上下文对象ContextImpl,每一个Application对象也拥有一个ContextImpl上下文对象,那么ContextImpl对象又是如何构造的呢?
frameworks\base\core\java\android\app\ ContextImpl.java
1
2
3
|
ContextImpl() {
mOuterContext =
this
;
}
|
ContextImpl的构造过程什么也没干,通过调用ContextImpl的init函数进行初始化
1
2
3
|
final
void
init(LoadedApk packageInfo,IBinder activityToken, ActivityThread mainThread) {
init(packageInfo, activityToken, mainThread,
null
,
null
);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
final
void
init(LoadedApk packageInfo,IBinder activityToken, ActivityThread mainThread,
Resources container, String basePackageName) {
mPackageInfo = packageInfo;
mBasePackageName = basePackageName !=
null
? basePackageName : packageInfo.mPackageName;
mResources = mPackageInfo.getResources(mainThread);
if
(mResources !=
null
&& container !=
null
&& container.getCompatibilityInfo().applicationScale !=
mResources.getCompatibilityInfo().applicationScale) {
mResources = mainThread.getTopLevelResources(
mPackageInfo.getResDir(), container.getCompatibilityInfo());
}
mMainThread = mainThread;
mContentResolver =
new
ApplicationContentResolver(
this
, mainThread);
setActivityToken(activityToken);
}
|
从ContextImpl的初始化函数中可以知道,ContextImpl记录了应用程序的包名信息、应用程序的资源信息、应用程序的主线程、ContentResolver及Activity对应的IApplicationToken.Proxy,当然对应Application对象所拥有的ContextImpl上下文就没有对应的Token了。通过前面的分析我们可以知道各个对象之间的关系:
对象Attach过程
Activity所需要的对象都创建好了,就需要将Activity和Application对象、ContextImpl对象绑定在一起。
frameworks\base\core\java\android\app\ Activity.java
1
2
3
4
5
6
7
|
final
void
attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token,
Application application, Intent intent, ActivityInfo info, 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对象;
aThread:Activity运行所在的主线程描述符ActivityThread;
instr:用于监控Activity运行状态的Instrumentation对象;
token:用于和AMS服务通信的IApplicationToken.Proxy代理对象;
application:Activity运行所在进程的Application对象;
parent:启动当前Activity的Activity;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
final
void
attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token,
int
ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config) {
//将上下文对象ContextImpl保存到Activity的成员变量中
attachBaseContext(context);
//每个Activity都拥有一个FragmentManager,这里就是将当前Activity设置到FragmentManager中管理
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);
}
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();
mActivityInfo = 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
) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
}
|
在该attach函数中主要做了以下几件事:
1) 将Activity设置到FragmentManager中;
2) 根据参数初始化Activity的成员变量;
3) 为Activity创建窗口Window对象;
4) 为Window创建窗口管理器;
到此为止应用程序进程为启动的Activity对象创建了以下不同的实例对象,它们之间的关系如下:
应用程序窗口创建过程
frameworks\base\core\java\com\android\internal\policy\ PolicyManager.java
1
2
3
|
public
static
Window makeNewWindow(Context context) {
return
sPolicy.makeNewWindow(context);
}
|
通过Policy类的makeNewWindow函数来创建一个应用程序窗口
1
2
3
4
5
6
7
8
9
10
11
|
private
static
final
String POLICY_IMPL_CLASS_NAME =
"com.android.internal.policy.impl.Policy"
;
private
static
final
IPolicy sPolicy;
static
{
try
{
Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
sPolicy = (IPolicy)policyClass.newInstance();
}
catch
(ClassNotFoundException ex) {
...
}
}
|
frameworks\base\policy\src\com\android\internal\policy\impl\ Policy.java
1
2
3
|
public
Window makeNewWindow(Context context) {
return
new
PhoneWindow(context);
}
|
应用程序窗口的创建过程其实就是构造一个PhoneWindow对象。PhoneWindow类是通过静态方式加载到应用程序进程空间的。
1
2
3
4
5
6
7
8
9
|
private
static
final
String[] preload_classes = {
"com.android.internal.policy.impl.PhoneLayoutInflater"
,
"com.android.internal.policy.impl.PhoneWindow"
,
"com.android.internal.policy.impl.PhoneWindow$1"
,
"com.android.internal.policy.impl.PhoneWindow$ContextMenuCallback"
,
"com.android.internal.policy.impl.PhoneWindow$DecorView"
,
"com.android.internal.policy.impl.PhoneWindow$PanelFeatureState"
,
"com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState"
,
};
|
1
2
3
4
5
6
7
8
9
|
static
{
for
(String s : preload_classes) {
try
{
Class.forName(s);
}
catch
(ClassNotFoundException ex) {
Log.e(TAG,
"Could not preload class for phone policy: "
+ s);
}
}
}
|
PhoneWindow的构造过程
1
2
3
4
5
|
public
PhoneWindow(Context context) {
super
(context);
mAlternativePanelStyle=getContext().getResources().getBoolean(com.android.internal.R.bool.config_alternativePanelStyle);
mLayoutInflater = LayoutInflater.from(context);
}
|
构造过程比较简单,只是得到布局加载服务对象。
窗口管理器创建过程
通过前面的分析我们可以知道,在Activity启动过程中,会为Activity创建一个窗口对象PhoneWindow,应用程序有了窗口那就需要有一个窗口管理器来管理这些窗口,因此在Activity启动过程中还会创建一个WindowManager对象。
frameworks\base\core\java\android\view\ Window.java
1
2
3
4
5
6
7
8
9
10
11
|
public
void
setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean
hardwareAccelerated) {
mAppToken = appToken;
// IApplicationToken.Proxy代理对象
mAppName = appName;
//得到WindowManagerImpl实例,
if
(wm ==
null
) {
wm = WindowManagerImpl.getDefault();
}
//为每个启动的Activity创建一个轻量级的窗口管理器LocalWindowManager
mWindowManager =
new
LocalWindowManager(wm, hardwareAccelerated);
}
|
WindowManagerImpl为重量级的窗口管理器,应用程序进程中有且只有一个WindowManagerImpl实例,它管理了应用程序进程中创建的所有PhoneWindow窗口。Activity并没有直接引用WindowManagerImpl实例,Android系统为每一个启动的Activity创建了一个轻量级的窗口管理器LocalWindowManager,每个Activity通过LocalWindowManager来访问WindowManagerImpl,它们三者之间的关系如下图所示:
WindowManagerImpl以单例模式创建,应用程序进程中有且只有一个WindowManagerImpl实例
frameworks\base\core\java\android\view\ WindowManagerImpl.java
1
2
3
4
|
private
final
static
WindowManagerImpl sWindowManager =
new
WindowManagerImpl();
public
static
WindowManagerImpl getDefault() {
return
sWindowManager;
}
|
应用程序进程会为每一个Activity创建一个LocalWindowManager实例对象
frameworks\base\core\java\android\view\ Window.java
1
2
3
4
5
|
LocalWindowManager(WindowManager wm,
boolean
hardwareAccelerated) {
super
(wm, getCompatInfo(mContext));
mHardwareAccelerated = hardwareAccelerated ||
SystemProperties.getBoolean(PROPERTY_HARDWARE_UI,
false
);
}
|
frameworks\base\core\java\android\view\ WindowManagerImpl.java
1
2
3
4
5
6
7
8
9
10
11
|
CompatModeWrapper(WindowManager wm, CompatibilityInfoHolder ci) {
mWindowManager = wm
instanceof
CompatModeWrapper
? ((CompatModeWrapper)wm).mWindowManager : (WindowManagerImpl)wm;
if
(ci ==
null
) {
mDefaultDisplay = mWindowManager.getDefaultDisplay();
}
else
{
mDefaultDisplay = Display.createCompatibleDisplay(
mWindowManager.getDefaultDisplay().getDisplayId(), ci);
}
mCompatibilityInfo = ci;
}
|
1
2
3
|
public
Display getDefaultDisplay() {
return
new
Display(Display.DEFAULT_DISPLAY,
null
);
}
|
frameworks\base\core\java\android\view\Display.java
1
2
3
4
5
6
7
8
9
10
11
|
Display(
int
display, CompatibilityInfoHolder compatInfo) {
synchronized
(sStaticInit) {
if
(!sInitialized) {
nativeClassInit();
sInitialized =
true
;
}
}
mCompatibilityInfo = compatInfo !=
null
? compatInfo :
new
CompatibilityInfoHolder();
mDisplay = display;
init(display);
}
|
构造Display对象时需要初始化该对象。
frameworks\base\core\jni\android_view_Display.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
static
void
android_view_Display_init(
JNIEnv* env, jobject clazz, jint dpy)
{
DisplayInfo info;
if
(headless) {
// initialize dummy display with reasonable values
info.pixelFormatInfo.format =
1
;
// RGB_8888
info.fps =
60
;
info.density =
160
;
info.xdpi =
160
;
info.ydpi =
160
;
}
else
{
status_t err = SurfaceComposerClient::getDisplayInfo(DisplayID(dpy), &info);
if
(err <
0
) {
jniThrowException(env,
"java/lang/IllegalArgumentException"
, NULL);
return
;
}
}
env->SetIntField(clazz, offsets.pixelFormat,info.pixelFormatInfo.format);
env->SetFloatField(clazz, offsets.fps, info.fps);
env->SetFloatField(clazz, offsets.density, info.density);
env->SetFloatField(clazz, offsets.xdpi, info.xdpi);
env->SetFloatField(clazz, offsets.ydpi, info.ydpi);
}
|
Display的初始化过程很简单,就是通过SurfaceComposerClient请求SurfaceFlinger得到显示屏的基本信息。
frameworks\native\libs\gui\ SurfaceComposerClient.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
status_t SurfaceComposerClient::getDisplayInfo(
DisplayID dpy, DisplayInfo* info)
{
if
(uint32_t(dpy)>=NUM_DISPLAY_MAX)
return
BAD_VALUE;
volatile
surface_flinger_cblk_t
const
* cblk = get_cblk();
volatile
display_cblk_t
const
* dcblk = cblk->displays + dpy;
info->w = dcblk->w;
info->h = dcblk->h;
info->orientation = dcblk->orientation;
info->xdpi = dcblk->xdpi;
info->ydpi = dcblk->ydpi;
info->fps = dcblk->fps;
info->density = dcblk->density;
return
getPixelFormatInfo(dcblk->format, &(info->pixelFormatInfo));
}
|
我们知道在SurfaceFlinger启动过程中,创建了一块匿名共享内存来保存显示屏的基本信息,这里就是通过访问这块匿名共享内存来读取显示屏信息。到此一个Activity所需要的窗口对象就创建完成了,在应用程序窗口的创建过程中一共创建了以下几个对象:
Activity视图对象的创建过程
在Activity的attach函数中完成应用程序窗口的创建后,通过Instrumentation回调Activity的OnCreate函数来为当前Activity加载布局文件,进一步创建视图对象。
frameworks\base\core\java\android\app\Instrumentation.java
1
2
3
4
5
|
public
void
callActivityOnCreate(Activity activity, Bundle icicle) {
...
activity.performCreate(icicle);
...
}
|
frameworks\base\core\java\android\app\Activity.java
1
2
3
4
5
6
|
final
void
performCreate(Bundle icicle) {
onCreate(icicle);
mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
com.android.internal.R.styleable.Window_windowNoDisplay,
false
);
mFragments.dispatchActivityCreated();
}
|
我们知道在应用程序开发中,需要重写Activity的OnCreate函数:
Packages\apps\xxx\src\com\xxx\ xxxActivity.java
1
2
3
4
5
|
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
...
}
|
在OnCreate函数中通过setContentView来设置Activity的布局文件,就是生成该Activity的所有视图对象。
frameworks\base\core\java\android\app\Activity.java
1
2
3
4
5
|
public
void
setContentView(View view, ViewGroup.LayoutParams params) {
getWindow().setContentView(view, params);
//初始化动作条
initActionBar();
}
|
getWindow()函数得到前面创建的窗口对象PhoneWindow,通过PhoneWindow来设置Activity的视图。
frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindow.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public
void
setContentView(
int
layoutResID) {
//如果窗口顶级视图对象为空,则创建窗口视图对象
if
(mContentParent ==
null
) {
installDecor();
}
else
{
//否则只是移除该视图对象中的其他视图
mContentParent.removeAllViews();
}
//加载布局文件,并将布局文件中的所有视图对象添加到mContentParent容器中
mLayoutInflater.inflate(layoutResID, mContentParent);
final
Callback cb = getCallback();
if
(cb !=
null
&& !isDestroyed()) {
cb.onContentChanged();
}
}
|
PhoneWindow的成员变量mContentParent的类型为ViewGroup,是窗口内容存放的地方
frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindow.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
private
void
installDecor() {
if
(mDecor ==
null
) {
①mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(
true
);
if
(!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures !=
0
) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
}
if
(mContentParent ==
null
) {
②mContentParent = generateLayout(mDecor);
mDecor.makeOptionalFitsSystemWindows();
//应用程序窗口标题栏
mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
if
(mTitleView !=
null
) {
...
}
else
{
//应用程序窗口动作条
mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
if
(mActionBar !=
null
) {
...
}
}
}
}
|
通过函数generateDecor()来创建一个DecorView对象
1
2
3
|
protected
DecorView generateDecor() {
return
new
DecorView(getContext(), -
1
);
}
|
接着通过generateLayout(mDecor)来创建视图对象容器mContentParent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
protected
ViewGroup generateLayout(DecorView decor) {
//通过读取属性配置文件设置窗口风格
if
(a.getBoolean(com.android.internal.R.styleable.Window_windowActionBarOverlay,
false
)) {
requestFeature(FEATURE_ACTION_BAR_OVERLAY);
}
...
//通过读取属性配置文件设置窗口标志
if
(a.getBoolean(com.android.internal.R.styleable.Window_windowFullscreen,
false
)) {
setFlags(FLAG_FULLSCREEN,FLAG_FULLSCREEN&(~getForcedWindowFlags()));
}
...
WindowManager.LayoutParams params = getAttributes();
...
mDecor.startChanging();
//根据窗口主题风格选择不同的布局文件layoutResource
...
//加载布局文件
①View in = mLayoutInflater.inflate(layoutResource,
null
);
//添加到DecorView中
②decor.addView(in,
new
ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
//从窗口视图中找出窗口内容视图对象
③ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
...
mDecor.finishChanging();
return
contentParent;
}
|
到此Activity的所有视图对象都已经创建完毕,DecorView是Activity的顶级视图,由窗口PhoneWindow对象持有,在DecorView视图对象中添加了一个ViewGroup容器组件contentParent,所有用户定义视图组件将被添加到该容器中。