- 浏览: 23898 次
- 性别:
- 来自: 北京
最新评论
page1
Activity组件在其窗口对象和视图对象创建完成之后, 就会请求与WindowManagerService建立一个连接, 即请求WindowManagerService为其增加一个WindowState对象, 用来描述它的窗口状态.
我们从两方面来看Activity组件与WindowManagerService服务之间的连接.一方面是从Activity组件到WindowManagerService服务的连接, 另一方面是从WindowManagerService服务到Activity组件的连接.
从Activity组件到WindowManagerService服务的连接是以Activity组件所在的应用程序进程为单位来进行的, 当一个应用程序进程在启动第一个Activity组件的时候它便会打开一个到WindowManagerService服务的连接,这个连接以应用程序进程从WindowManagerService服务处获得一个实现了IWindowSession接口的Session代理对象为标志.
从WindowManagerService服务到Activity组件的连接是以Activity组件为单位进行的, 在应用程序进程这一侧, 每一个Activity组件都关联一个实现了IWindow接口的W对象, 这个W对象在Activity组件的视图对象创建完成之后, 就会通过前面所获得的一个Session代理对象来传递给WindowManagerService服务, 而WindowManagerService服务接受到这个W对象之后, 就会在内部创建一个WindowState对象来描述与该W对象所关联的Activity组件的窗口状态, 并且以后就通过这个W对象来控制对应的Activity组件的窗口状态.
我们知道, 每一个Activity组件在ActivityManagerServices服务内部, 都对应有一个ActivityRecord对象.这样, 每一个Activity组件在应用程序进程, WindowManagerService服务和ActivityManagerService服务三者之间就分别建立了一对一的连接.
第一, 我们首先分析一下ActivityManagerService服务请求WindowManagerService服务为一个Activity组件创建一个AppWindowToken对象的过程, 关于这部分的内容可以参考page2文件.
经过上面的分析, 我们知道了每一个Activity组件在ActivityManagerService服务内部都有一个对应的ActivityRecord对象, 并且在WindowManagerService服务内部关联有一个AppWindowToken对象.
第二, 我们分析一下Activity与WindowManagerService建立连接的过程, 本质上是Session对象的创建过程,关于这部分的内容可以参考page5文件.
第三, 我们分析一下应用程序进程请求WindowManagerService服务为一个Activity组件创建一个WindowState对象的过程, 关于这部分的内容可以参考page9文件.
经过上面的分析, 我们了解了如下的事实:
为了显示一个Activity, 应用程序进程为它创建一个窗口(Window)对象, 一个视图(View)对象, 一个ViewRoot对象、一个W对象.
WindowManagerService服务为它创建一个AppWindowToken对象和一个WindowState对象, 一个SurfaceSession对象.
此外,WindowManagerService服务还为一个Activity组件所运行在的应用程序进程创建了一个Session对象.
page2
在这篇文章里,我们分析一下ActivityManagerService服务请求WindowManagerService服务为一个Activity组件创建一个AppWindowToken对象的过程, 我们从ActivityStack的startActivityLocked函数作为入口来分析, startActivityLocked函数的定义如下:
1 private final void startActivityLocked(ActivityRecord r, boolean newTask,
2 boolean doResume, boolean keepCurTransition, Bundle options) {
3 final int NH = mHistory.size();
4
5 int addPos = -1;
6
7 if (!newTask) {
8 // If starting in an existing task, find where that is...
9 boolean startIt = true;
10 for (int i = NH-1; i >= 0; i--) {
11 ActivityRecord p = mHistory.get(i);
12 if (p.finishing) {
13 continue;
14 }
15 if (p.task == r.task) {
16 // Here it is! Now, if this is not yet visible to the
17 // user, then just add it without starting; it will
18 // get started when the user navigates back to it.
19 addPos = i+1;
20 if (!startIt) {
21 if (DEBUG_ADD_REMOVE) {
22 RuntimeException here = new RuntimeException("here");
23 here.fillInStackTrace();
24 Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos,
25 here);
26 }
27 mHistory.add(addPos, r);
28 r.putInHistory();
29 mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
30 r.info.screenOrientation, r.fullscreen,
31 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
32 if (VALIDATE_TOKENS) {
33 validateAppTokensLocked();
34 }
35 ActivityOptions.abort(options);
36 return;
37 }
38 break;
39 }
40 if (p.fullscreen) {
41 startIt = false;
42 }
43 }
44 }
45
46 // Place a new activity at top of stack, so it is next to interact
47 // with the user.
48 if (addPos < 0) {
49 addPos = NH;
50 }
51
52 // If we are not placing the new activity frontmost, we do not want
53 // to deliver the onUserLeaving callback to the actual frontmost
54 // activity
55 if (addPos < NH) {
56 mUserLeaving = false;
57 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
58 }
59
60 // Slot the activity into the history stack and proceed
61 if (DEBUG_ADD_REMOVE) {
62 RuntimeException here = new RuntimeException("here");
63 here.fillInStackTrace();
64 Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos, here);
65 }
66 mHistory.add(addPos, r);
67 r.putInHistory();
68 r.frontOfTask = newTask;
69 if (NH > 0) {
70 // We want to show the starting preview window if we are
71 // switching to a new task, or the next activity's process is
72 // not currently running.
73 boolean showStartingIcon = newTask;
74 ProcessRecord proc = r.app;
75 if (proc == null) {
76 proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
77 }
78 if (proc == null || proc.thread == null) {
79 showStartingIcon = true;
80 }
81 if (DEBUG_TRANSITION) Slog.v(TAG,
82 "Prepare open transition: starting " + r);
83 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
84 mService.mWindowManager.prepareAppTransition(
85 WindowManagerPolicy.TRANSIT_NONE, keepCurTransition);
86 mNoAnimActivities.add(r);
87 } else {
88 mService.mWindowManager.prepareAppTransition(newTask
89 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
90 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
91 mNoAnimActivities.remove(r);
92 }
93 r.updateOptionsLocked(options);
94 mService.mWindowManager.addAppToken(
95 addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen,
96 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
97 boolean doShow = true;
98 if (newTask) {
99 // Even though this activity is starting fresh, we still need
100 // to reset it to make sure we apply affinities to move any
101 // existing activities from other tasks in to it.
102 // If the caller has requested that the target task be
103 // reset, then do so.
104 if ((r.intent.getFlags()
105 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
106 resetTaskIfNeededLocked(r, r);
107 doShow = topRunningNonDelayedActivityLocked(null) == r;
108 }
109 }
110 if (SHOW_APP_STARTING_PREVIEW && doShow) {
111 // Figure out if we are transitioning from another activity that is
112 // "has the same starting icon" as the next one. This allows the
113 // window manager to keep the previous window it had previously
114 // created, if it still had one.
115 ActivityRecord prev = mResumedActivity;
116 if (prev != null) {
117 // We don't want to reuse the previous starting preview if:
118 // (1) The current activity is in a different task.
119 if (prev.task != r.task) prev = null;
120 // (2) The current activity is already displayed.
121 else if (prev.nowVisible) prev = null;
122 }
123 mService.mWindowManager.setAppStartingWindow(
124 r.appToken, r.packageName, r.theme,
125 mService.compatibilityInfoForPackageLocked(
126 r.info.applicationInfo), r.nonLocalizedLabel,
127 r.labelRes, r.icon, r.windowFlags,
128 prev != null ? prev.appToken : null, showStartingIcon);
129 }
130 } else {
131 // If this is the first activity, don't do any fancy animations,
132 // because there is nothing for it to animate on top of.
133 mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
134 r.info.screenOrientation, r.fullscreen,
135 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
136 ActivityOptions.abort(options);
137 }
138 if (VALIDATE_TOKENS) {
139 validateAppTokensLocked();
140 }
141
142 if (doResume) {
143 resumeTopActivityLocked(null);
144 }
145 }
在这里我们主要关注addAppToken函数的实现, 关于WindowManagerService的addAppToken函数的详细分析可以参考page3文件.
page3
在这里我们分析一下WindowManagerService的addAppToken函数的实现, addAppToken函数的定义如下:
1 public void addAppToken(int addPos, IApplicationToken token,
2 int groupId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked) {
3 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4 "addAppToken()")) {
5 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6 }
7
8 // Get the dispatching timeout here while we are not holding any locks so that it
9 // can be cached by the AppWindowToken. The timeout value is used later by the
10 // input dispatcher in code that does hold locks. If we did not cache the value
11 // here we would run the chance of introducing a deadlock between the window manager
12 // (which holds locks while updating the input dispatcher state) and the activity manager
13 // (which holds locks while querying the application token).
14 long inputDispatchingTimeoutNanos;
15 try {
16 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;
17 } catch (RemoteException ex) {
18 Slog.w(TAG, "Could not get dispatching timeout.", ex);
19 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
20 }
21
22 synchronized(mWindowMap) {
23 AppWindowToken atoken = findAppWindowToken(token.asBinder());
24 if (atoken != null) {
25 Slog.w(TAG, "Attempted to add existing app token: " + token);
26 return;
27 }
28 atoken = new AppWindowToken(this, token);
29 atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
30 atoken.groupId = groupId;
31 atoken.appFullscreen = fullscreen;
32 atoken.showWhenLocked = showWhenLocked;
33 atoken.requestedOrientation = requestedOrientation;
34 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
35 + " at " + addPos);
36 mAppTokens.add(addPos, atoken);
37 addAppTokenToAnimating(addPos, atoken);
38 mTokenMap.put(token.asBinder(), atoken);
39
40 // Application tokens start out hidden.
41 atoken.hidden = true;
42 atoken.hiddenRequested = true;
43
44 //dump();
45 }
46 }
第3-6行(WindowManagerService->addAppToken)会进行权限检查, 当发现没有权限时,就抛出异常.
第14-20行(WindowManagerService->addAppToken)会得到ApplicationToken的inputDispatchingTimeout的时间, 这个值是会保存到AppWindowToken中去的.
第22行(WindowManagerService->addAppToken)会在mWindowMap上加锁, 为的是保护对mTokenMap的访问.
第23-27行(WindowManagerService->addAppToken)会调用findAppWindowToken函数来查找该Activity是否已经创建过AppWindowToken, 如果AppWindowToken已经存在就直接返回了. AppWindowToken的定义如下:
AppWindowToken findAppWindowToken(IBinder token) {
WindowToken wtoken = mTokenMap.get(token);
if (wtoken == null) {
return null;
}
return wtoken.appWindowToken;
}
findAppWindowToken函数的逻辑还是很简单的, 就是在mTokenMap中根据IApplicationToken来查找.
第28行(WindowManagerService->addAppToken)会new一个AppWindowToken对象, 而传入的参数是WindowManagerService和IApplicationToken. 关于AppWindowToken的创建过程可以参考page4文件.
page4
在这篇文章里我们分析一下AppWindowToken的创建过程,我们先来分析一下AppWindowToken类的继承层次.
class AppWindowToken extends WindowToken
AppWindowToken的构造函数的定义如下:
1 AppWindowToken(WindowManagerService _service, IApplicationToken _token) {
2 super(_service, _token.asBinder(),
3 WindowManager.LayoutParams.TYPE_APPLICATION, true);
4 appWindowToken = this;
5 appToken = _token;
6 mInputApplicationHandle = new InputApplicationHandle(this);
7 mAnimator = service.mAnimator;
8 mAppAnimator = new AppWindowAnimator(this);
9 }
第2-3行(AppWindowToken->AppWindowToken)会调用父类WindowToken的构造函数, 注意这里传入的参数type为WindowManager.LayoutParams.TYPE_APPLICATION.
WindowToken的构造函数的定义如下:
WindowToken(WindowManagerService _service, IBinder _token, int type, boolean _explicit) {
service = _service;
token = _token;
windowType = type;
explicit = _explicit;
}
第4-5行(AppWindowToken->AppWindowToken)会将IApplicationToken保存到appToken成员变量中. 由此可见, AppWindowToken其实是拿着IApplicationToken对象的.
page5
我们这里分析一下Activity与WindowManagerService建立连接的过程.
应用程序进程在启动第一个Activity组件的时候, 就会请求与WindowManagerService服务建立一个连接,以便可以配合WindowManagerService服务来管理系统中的所有窗口.
具体来说,就是应用程序进程在为它里面启动的第一个Activity组件的视图对象创建一个关联的ViewRoot对象的时候,就会向WindowManagerService服务请求返回一个类型为Session的Binder本地对象,这样应用程序进程就可以获得一个类型为Session的Binder代理对象, 以后就可以通过这个Binder代理对象和WindowManagerService服务进行通信了.
在ViewRoot对象的创建过程中,会尝试建立和WindowManagerService服务建立连接.那我们就从ViewRoot类的构造函数作为入口来分析:
ViewRootImpl类的构造函数的定义如下:
1 public ViewRootImpl(Context context, Display display) {
2 super();
3
4 if (MEASURE_LATENCY) {
5 if (lt == null) {
6 lt = new LatencyTimer(100, 1000);
7 }
8 }
9
10 // Initialize the statics when this class is first instantiated. This is
11 // done here instead of in the static block because Zygote does not
12 // allow the spawning of threads.
13 mWindowSession = WindowManagerGlobal.getWindowSession(context.getMainLooper());
14 mDisplay = display;
15
16 CompatibilityInfoHolder cih = display.getCompatibilityInfo();
17 mCompatibilityInfo = cih != null ? cih : new CompatibilityInfoHolder();
18
19 mThread = Thread.currentThread();
20 mLocation = new WindowLeaked(null);
21 mLocation.fillInStackTrace();
22 mWidth = -1;
23 mHeight = -1;
24 mDirty = new Rect();
25 mTempRect = new Rect();
26 mVisRect = new Rect();
27 mWinFrame = new Rect();
28 mWindow = new W(this);
29 mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
30 mInputMethodCallback = new InputMethodCallback(this);
31 mViewVisibility = View.GONE;
32 mTransparentRegion = new Region();
33 mPreviousTransparentRegion = new Region();
34 mFirst = true; // true for the first time the view is added
35 mAdded = false;
36 mAccessibilityManager = AccessibilityManager.getInstance(context);
37 mAccessibilityInteractionConnectionManager =
38 new AccessibilityInteractionConnectionManager();
39 mAccessibilityManager.addAccessibilityStateChangeListener(
40 mAccessibilityInteractionConnectionManager);
41 mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);
42 mViewConfiguration = ViewConfiguration.get(context);
43 mDensity = context.getResources().getDisplayMetrics().densityDpi;
44 mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
45 mFallbackEventHandler = PolicyManager.makeNewFallbackEventHandler(context);
46 mProfileRendering = Boolean.parseBoolean(
47 SystemProperties.get(PROPERTY_PROFILE_RENDERING, "false"));
48 mChoreographer = Choreographer.getInstance();
49
50 PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
51 mAttachInfo.mScreenOn = powerManager.isScreenOn();
52 loadSystemProperties();
53 }
第13行(ViewRootImpl->ViewRootImpl)会调用WindowManagerGlobal的getWindowSession函数, 关于getWindowSession函数的详细分析可以参考page6文件.
Activity组件在其窗口对象和视图对象创建完成之后, 就会请求与WindowManagerService建立一个连接, 即请求WindowManagerService为其增加一个WindowState对象, 用来描述它的窗口状态.
我们从两方面来看Activity组件与WindowManagerService服务之间的连接.一方面是从Activity组件到WindowManagerService服务的连接, 另一方面是从WindowManagerService服务到Activity组件的连接.
从Activity组件到WindowManagerService服务的连接是以Activity组件所在的应用程序进程为单位来进行的, 当一个应用程序进程在启动第一个Activity组件的时候它便会打开一个到WindowManagerService服务的连接,这个连接以应用程序进程从WindowManagerService服务处获得一个实现了IWindowSession接口的Session代理对象为标志.
从WindowManagerService服务到Activity组件的连接是以Activity组件为单位进行的, 在应用程序进程这一侧, 每一个Activity组件都关联一个实现了IWindow接口的W对象, 这个W对象在Activity组件的视图对象创建完成之后, 就会通过前面所获得的一个Session代理对象来传递给WindowManagerService服务, 而WindowManagerService服务接受到这个W对象之后, 就会在内部创建一个WindowState对象来描述与该W对象所关联的Activity组件的窗口状态, 并且以后就通过这个W对象来控制对应的Activity组件的窗口状态.
我们知道, 每一个Activity组件在ActivityManagerServices服务内部, 都对应有一个ActivityRecord对象.这样, 每一个Activity组件在应用程序进程, WindowManagerService服务和ActivityManagerService服务三者之间就分别建立了一对一的连接.
第一, 我们首先分析一下ActivityManagerService服务请求WindowManagerService服务为一个Activity组件创建一个AppWindowToken对象的过程, 关于这部分的内容可以参考page2文件.
经过上面的分析, 我们知道了每一个Activity组件在ActivityManagerService服务内部都有一个对应的ActivityRecord对象, 并且在WindowManagerService服务内部关联有一个AppWindowToken对象.
第二, 我们分析一下Activity与WindowManagerService建立连接的过程, 本质上是Session对象的创建过程,关于这部分的内容可以参考page5文件.
第三, 我们分析一下应用程序进程请求WindowManagerService服务为一个Activity组件创建一个WindowState对象的过程, 关于这部分的内容可以参考page9文件.
经过上面的分析, 我们了解了如下的事实:
为了显示一个Activity, 应用程序进程为它创建一个窗口(Window)对象, 一个视图(View)对象, 一个ViewRoot对象、一个W对象.
WindowManagerService服务为它创建一个AppWindowToken对象和一个WindowState对象, 一个SurfaceSession对象.
此外,WindowManagerService服务还为一个Activity组件所运行在的应用程序进程创建了一个Session对象.
page2
在这篇文章里,我们分析一下ActivityManagerService服务请求WindowManagerService服务为一个Activity组件创建一个AppWindowToken对象的过程, 我们从ActivityStack的startActivityLocked函数作为入口来分析, startActivityLocked函数的定义如下:
1 private final void startActivityLocked(ActivityRecord r, boolean newTask,
2 boolean doResume, boolean keepCurTransition, Bundle options) {
3 final int NH = mHistory.size();
4
5 int addPos = -1;
6
7 if (!newTask) {
8 // If starting in an existing task, find where that is...
9 boolean startIt = true;
10 for (int i = NH-1; i >= 0; i--) {
11 ActivityRecord p = mHistory.get(i);
12 if (p.finishing) {
13 continue;
14 }
15 if (p.task == r.task) {
16 // Here it is! Now, if this is not yet visible to the
17 // user, then just add it without starting; it will
18 // get started when the user navigates back to it.
19 addPos = i+1;
20 if (!startIt) {
21 if (DEBUG_ADD_REMOVE) {
22 RuntimeException here = new RuntimeException("here");
23 here.fillInStackTrace();
24 Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos,
25 here);
26 }
27 mHistory.add(addPos, r);
28 r.putInHistory();
29 mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
30 r.info.screenOrientation, r.fullscreen,
31 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
32 if (VALIDATE_TOKENS) {
33 validateAppTokensLocked();
34 }
35 ActivityOptions.abort(options);
36 return;
37 }
38 break;
39 }
40 if (p.fullscreen) {
41 startIt = false;
42 }
43 }
44 }
45
46 // Place a new activity at top of stack, so it is next to interact
47 // with the user.
48 if (addPos < 0) {
49 addPos = NH;
50 }
51
52 // If we are not placing the new activity frontmost, we do not want
53 // to deliver the onUserLeaving callback to the actual frontmost
54 // activity
55 if (addPos < NH) {
56 mUserLeaving = false;
57 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
58 }
59
60 // Slot the activity into the history stack and proceed
61 if (DEBUG_ADD_REMOVE) {
62 RuntimeException here = new RuntimeException("here");
63 here.fillInStackTrace();
64 Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos, here);
65 }
66 mHistory.add(addPos, r);
67 r.putInHistory();
68 r.frontOfTask = newTask;
69 if (NH > 0) {
70 // We want to show the starting preview window if we are
71 // switching to a new task, or the next activity's process is
72 // not currently running.
73 boolean showStartingIcon = newTask;
74 ProcessRecord proc = r.app;
75 if (proc == null) {
76 proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
77 }
78 if (proc == null || proc.thread == null) {
79 showStartingIcon = true;
80 }
81 if (DEBUG_TRANSITION) Slog.v(TAG,
82 "Prepare open transition: starting " + r);
83 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
84 mService.mWindowManager.prepareAppTransition(
85 WindowManagerPolicy.TRANSIT_NONE, keepCurTransition);
86 mNoAnimActivities.add(r);
87 } else {
88 mService.mWindowManager.prepareAppTransition(newTask
89 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
90 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
91 mNoAnimActivities.remove(r);
92 }
93 r.updateOptionsLocked(options);
94 mService.mWindowManager.addAppToken(
95 addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen,
96 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
97 boolean doShow = true;
98 if (newTask) {
99 // Even though this activity is starting fresh, we still need
100 // to reset it to make sure we apply affinities to move any
101 // existing activities from other tasks in to it.
102 // If the caller has requested that the target task be
103 // reset, then do so.
104 if ((r.intent.getFlags()
105 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
106 resetTaskIfNeededLocked(r, r);
107 doShow = topRunningNonDelayedActivityLocked(null) == r;
108 }
109 }
110 if (SHOW_APP_STARTING_PREVIEW && doShow) {
111 // Figure out if we are transitioning from another activity that is
112 // "has the same starting icon" as the next one. This allows the
113 // window manager to keep the previous window it had previously
114 // created, if it still had one.
115 ActivityRecord prev = mResumedActivity;
116 if (prev != null) {
117 // We don't want to reuse the previous starting preview if:
118 // (1) The current activity is in a different task.
119 if (prev.task != r.task) prev = null;
120 // (2) The current activity is already displayed.
121 else if (prev.nowVisible) prev = null;
122 }
123 mService.mWindowManager.setAppStartingWindow(
124 r.appToken, r.packageName, r.theme,
125 mService.compatibilityInfoForPackageLocked(
126 r.info.applicationInfo), r.nonLocalizedLabel,
127 r.labelRes, r.icon, r.windowFlags,
128 prev != null ? prev.appToken : null, showStartingIcon);
129 }
130 } else {
131 // If this is the first activity, don't do any fancy animations,
132 // because there is nothing for it to animate on top of.
133 mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
134 r.info.screenOrientation, r.fullscreen,
135 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
136 ActivityOptions.abort(options);
137 }
138 if (VALIDATE_TOKENS) {
139 validateAppTokensLocked();
140 }
141
142 if (doResume) {
143 resumeTopActivityLocked(null);
144 }
145 }
在这里我们主要关注addAppToken函数的实现, 关于WindowManagerService的addAppToken函数的详细分析可以参考page3文件.
page3
在这里我们分析一下WindowManagerService的addAppToken函数的实现, addAppToken函数的定义如下:
1 public void addAppToken(int addPos, IApplicationToken token,
2 int groupId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked) {
3 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4 "addAppToken()")) {
5 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6 }
7
8 // Get the dispatching timeout here while we are not holding any locks so that it
9 // can be cached by the AppWindowToken. The timeout value is used later by the
10 // input dispatcher in code that does hold locks. If we did not cache the value
11 // here we would run the chance of introducing a deadlock between the window manager
12 // (which holds locks while updating the input dispatcher state) and the activity manager
13 // (which holds locks while querying the application token).
14 long inputDispatchingTimeoutNanos;
15 try {
16 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;
17 } catch (RemoteException ex) {
18 Slog.w(TAG, "Could not get dispatching timeout.", ex);
19 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
20 }
21
22 synchronized(mWindowMap) {
23 AppWindowToken atoken = findAppWindowToken(token.asBinder());
24 if (atoken != null) {
25 Slog.w(TAG, "Attempted to add existing app token: " + token);
26 return;
27 }
28 atoken = new AppWindowToken(this, token);
29 atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
30 atoken.groupId = groupId;
31 atoken.appFullscreen = fullscreen;
32 atoken.showWhenLocked = showWhenLocked;
33 atoken.requestedOrientation = requestedOrientation;
34 if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
35 + " at " + addPos);
36 mAppTokens.add(addPos, atoken);
37 addAppTokenToAnimating(addPos, atoken);
38 mTokenMap.put(token.asBinder(), atoken);
39
40 // Application tokens start out hidden.
41 atoken.hidden = true;
42 atoken.hiddenRequested = true;
43
44 //dump();
45 }
46 }
第3-6行(WindowManagerService->addAppToken)会进行权限检查, 当发现没有权限时,就抛出异常.
第14-20行(WindowManagerService->addAppToken)会得到ApplicationToken的inputDispatchingTimeout的时间, 这个值是会保存到AppWindowToken中去的.
第22行(WindowManagerService->addAppToken)会在mWindowMap上加锁, 为的是保护对mTokenMap的访问.
第23-27行(WindowManagerService->addAppToken)会调用findAppWindowToken函数来查找该Activity是否已经创建过AppWindowToken, 如果AppWindowToken已经存在就直接返回了. AppWindowToken的定义如下:
AppWindowToken findAppWindowToken(IBinder token) {
WindowToken wtoken = mTokenMap.get(token);
if (wtoken == null) {
return null;
}
return wtoken.appWindowToken;
}
findAppWindowToken函数的逻辑还是很简单的, 就是在mTokenMap中根据IApplicationToken来查找.
第28行(WindowManagerService->addAppToken)会new一个AppWindowToken对象, 而传入的参数是WindowManagerService和IApplicationToken. 关于AppWindowToken的创建过程可以参考page4文件.
page4
在这篇文章里我们分析一下AppWindowToken的创建过程,我们先来分析一下AppWindowToken类的继承层次.
class AppWindowToken extends WindowToken
AppWindowToken的构造函数的定义如下:
1 AppWindowToken(WindowManagerService _service, IApplicationToken _token) {
2 super(_service, _token.asBinder(),
3 WindowManager.LayoutParams.TYPE_APPLICATION, true);
4 appWindowToken = this;
5 appToken = _token;
6 mInputApplicationHandle = new InputApplicationHandle(this);
7 mAnimator = service.mAnimator;
8 mAppAnimator = new AppWindowAnimator(this);
9 }
第2-3行(AppWindowToken->AppWindowToken)会调用父类WindowToken的构造函数, 注意这里传入的参数type为WindowManager.LayoutParams.TYPE_APPLICATION.
WindowToken的构造函数的定义如下:
WindowToken(WindowManagerService _service, IBinder _token, int type, boolean _explicit) {
service = _service;
token = _token;
windowType = type;
explicit = _explicit;
}
第4-5行(AppWindowToken->AppWindowToken)会将IApplicationToken保存到appToken成员变量中. 由此可见, AppWindowToken其实是拿着IApplicationToken对象的.
page5
我们这里分析一下Activity与WindowManagerService建立连接的过程.
应用程序进程在启动第一个Activity组件的时候, 就会请求与WindowManagerService服务建立一个连接,以便可以配合WindowManagerService服务来管理系统中的所有窗口.
具体来说,就是应用程序进程在为它里面启动的第一个Activity组件的视图对象创建一个关联的ViewRoot对象的时候,就会向WindowManagerService服务请求返回一个类型为Session的Binder本地对象,这样应用程序进程就可以获得一个类型为Session的Binder代理对象, 以后就可以通过这个Binder代理对象和WindowManagerService服务进行通信了.
在ViewRoot对象的创建过程中,会尝试建立和WindowManagerService服务建立连接.那我们就从ViewRoot类的构造函数作为入口来分析:
ViewRootImpl类的构造函数的定义如下:
1 public ViewRootImpl(Context context, Display display) {
2 super();
3
4 if (MEASURE_LATENCY) {
5 if (lt == null) {
6 lt = new LatencyTimer(100, 1000);
7 }
8 }
9
10 // Initialize the statics when this class is first instantiated. This is
11 // done here instead of in the static block because Zygote does not
12 // allow the spawning of threads.
13 mWindowSession = WindowManagerGlobal.getWindowSession(context.getMainLooper());
14 mDisplay = display;
15
16 CompatibilityInfoHolder cih = display.getCompatibilityInfo();
17 mCompatibilityInfo = cih != null ? cih : new CompatibilityInfoHolder();
18
19 mThread = Thread.currentThread();
20 mLocation = new WindowLeaked(null);
21 mLocation.fillInStackTrace();
22 mWidth = -1;
23 mHeight = -1;
24 mDirty = new Rect();
25 mTempRect = new Rect();
26 mVisRect = new Rect();
27 mWinFrame = new Rect();
28 mWindow = new W(this);
29 mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
30 mInputMethodCallback = new InputMethodCallback(this);
31 mViewVisibility = View.GONE;
32 mTransparentRegion = new Region();
33 mPreviousTransparentRegion = new Region();
34 mFirst = true; // true for the first time the view is added
35 mAdded = false;
36 mAccessibilityManager = AccessibilityManager.getInstance(context);
37 mAccessibilityInteractionConnectionManager =
38 new AccessibilityInteractionConnectionManager();
39 mAccessibilityManager.addAccessibilityStateChangeListener(
40 mAccessibilityInteractionConnectionManager);
41 mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);
42 mViewConfiguration = ViewConfiguration.get(context);
43 mDensity = context.getResources().getDisplayMetrics().densityDpi;
44 mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
45 mFallbackEventHandler = PolicyManager.makeNewFallbackEventHandler(context);
46 mProfileRendering = Boolean.parseBoolean(
47 SystemProperties.get(PROPERTY_PROFILE_RENDERING, "false"));
48 mChoreographer = Choreographer.getInstance();
49
50 PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
51 mAttachInfo.mScreenOn = powerManager.isScreenOn();
52 loadSystemProperties();
53 }
第13行(ViewRootImpl->ViewRootImpl)会调用WindowManagerGlobal的getWindowSession函数, 关于getWindowSession函数的详细分析可以参考page6文件.
发表评论
-
Activity与WindowManagerService连接的过程(三)
2018-04-16 16:27 623page11 WindowManagerService ... -
Activity与WindowManagerService连接的过程(二)
2018-04-16 16:36 771page6 WindowManagerGlobal的getW ... -
Activity的ViewRoot的创建过程(三)
2017-11-06 14:25 742page7 在这篇文章里, 我们分析一下W类的构造过程. W ... -
Activity的ViewRoot的创建过程(二)
2017-11-06 14:29 942page4 我们看一下ViewRootImpl对象的创 ... -
Activity的ViewRoot的创建过程(一)
2017-11-06 14:27 1080page1 当一个Activity第一次激活的时候会为该Ac ... -
Activity的Window和WindowManager的创建过程(三)
2017-07-05 11:49 1335page9 在这里我们分析一下DisplayManager的 ... -
Activity的Window和WindowManager的创建过程(二)
2017-07-05 11:31 548page5 在这篇文章中, 我们分析一下ContextImp ... -
Activity的Window和WindowManager的创建过程(一)
2017-07-05 11:27 607page1 我们开始分析一下Activity的Window和 ... -
Acitivy创建Context的过程(二)
2017-06-21 14:11 514page4 在这里我们分析一下ContextImpl的ini ... -
Acitivy创建Context的过程(一)
2017-06-21 14:15 639page1 从本篇文章开始,我们分析一下Activity创建 ... -
应用程序进程与SurfaceFlinger的连接过程
2017-06-21 11:49 1063我们从SurfaceComposerClient对象的创建开始 ... -
Android源码之SurfaceFlinger的启动(三)
2017-04-20 11:09 1046page11 我们来看一下SurfaceFlinger ... -
Android源码之SurfaceFlinger的启动(二)
2017-04-18 15:15 883page6 我们看一下Thread的run函数的实现: ... -
Android源码之SurfaceFlinger的启动(一)
2017-04-17 10:07 1000page1 在Android系统中, 显示系统在底层是通过S ... -
Android源码之Zygote
2015-12-15 11:45 519当ActivityManagerService启动一个应用程序 ... -
Android源码之Binder(五)
2015-12-04 09:19 1515Service组件在启动时,需要将自己注册到Service M ... -
Android源码之Binder(四)
2015-12-04 09:18 1952case BINDER_SET_MAX_THREADS: ... -
Android源码之Binder(三)
2015-12-04 09:17 910{ int ret; struct binder_pr ... -
Android源码之Binder(二)
2015-12-04 09:15 550分析完Binder驱动程序的打开和内存分配的过程之后,我们看一 ... -
Android源码之Binder(一)
2015-12-04 09:12 996在Android系统中,进程间通信使用的是Binder机制。B ...
相关推荐
2. **GUI绘制流程**:当Activity与WindowManagerService成功建立连接后,ViewRoot将开始执行GUI的绘制过程。这一过程涉及到多个步骤,包括但不限于更新窗口状态、绘制视图层级以及最终的屏幕渲染。 #### 结论 View...
与WindowManagerService的连接过程是Activity将View添加到屏幕上的关键步骤。WindowManagerService是Android系统的系统服务,它负责管理所有的窗口,并处理窗口的显示和隐藏。 在绘制过程中,Android使用Surface来...
2. **Android服务启动**:SystemServer启动后,会依次启动一系列重要的Android服务,如`ActivityManagerService`、`WindowManagerService`、`PackageManagerService`等。 3. **Home应用启动**:一旦SystemServer及其...
Android的Framework层作为操作系统的核心组成部分,扮演着连接硬件抽象层(HAL)与应用程序之间的桥梁角色,它不仅提供了丰富的API供开发者调用,还负责管理和调度应用程序的生命周期。本章节深入探讨Android ...
在步骤3,`mWindowSession.addToDisplay()` 被调用,这个方法会将新视图添加到显示列表,并且将之前创建的InputChannel与服务端建立连接。`mWindowSession` 是一个IWindowSession接口的实现,它是由`...
每当添加一个新窗口时,会调用WindowManagerService的`performLayoutLockedInner`方法,这个过程会将窗口信息传递给Input系统。Input系统会将这些信息存储在一个列表中,以便后续的事件派发。这个传递过程涉及多个...
Binder架构由一个轻量级的远程过程调用(RPC)机制实现,它将数据封装成事务,并在服务端执行这些事务。 首先,Binder驱动是Binder架构的核心组件。它是一个位于内核空间的驱动程序,负责处理不同进程间的通信请求。...
- **IWindowManager与WindowManagerService的Binder通信**:了解IWindowManager与WindowManagerService之间的通信机制对于深入理解事件注入的过程至关重要。这两者通过Binder框架实现了跨进程调用,从而使得Monkey...
4. **System Server**:这是一个核心服务进程,负责启动系统级的服务,如ActivityManagerService、WindowManagerService等。 5. **User Applications**:随着系统服务的启动,用户应用程序也开始运行。 #### 层间...
- **RIL接口:** RIL是连接上层应用与底层硬件的桥梁,Java层如何与RIL交互以完成通话操作。 - **RIL实例:** 通过具体的RIL实例来演示通话流程的具体实现。 **GSMCallTracker:** - **GSM呼叫跟踪:** ...
- WindowManagerService (WMS):管理窗口堆栈,负责显示WelcomeLauncher的界面。 - ContentProvider:如果WelcomeLauncher需要访问系统数据,可能会用到ContentProvider来共享数据。 4. **自定义与扩展**: - ...
1. **ActivityManagerService (AMS)**:这是Android系统的核心服务之一,负责管理和调度应用的生命周期。 2. **WindowManagerService (WMS)**:处理窗口管理,包括屏幕布局、显示和隐藏等操作。 3. **ViewSystem**:...
Android操作系统作为一款被广泛应用在智能手机、平板电脑等移动设备上的软件,自2008年推出以来,已经经历了多次更新与迭代,形成了一个功能丰富、架构复杂的庞大系统。深入分析Android的机制,对于理解其运行原理和...
`ViewRootImpl`是连接Android应用程序与系统服务`WindowManagerService`的关键类。每当一个新的View需要添加到Window时,就会创建一个`ViewRootImpl`实例。它负责处理视图的生命周期,包括设置视图、请求布局更新...
**启动系统服务**:如ActivityManagerService、WindowManagerService、PackageManagerService等。 - **Start services:** - **ADBD(Android Debug Bridge Daemon)**:用于开发者通过命令行与设备进行通信,如...
在Android中,无论是Activity、Dialog还是Toast,其界面都挂载在一个或多个Window上。WindowManager则是与Window交互的接口,它允许开发者添加、更新和移除Window。 WindowManagerService是管理所有Window的核心...
在Android系统的层次结构中,屏幕锁与`ActivityManagerService`、`WindowManagerService`等核心服务协同工作,确保系统在不同状态间的平滑切换。 通过分析`Android 屏幕锁源码`,我们可以学习到Android系统如何处理...
Activity是Android应用程序中最基本的组件之一,它代表了一个屏幕上的界面。Activity的生命周期管理、启动模式和状态保存是保证用户体验流畅的关键。 ### **22. AndoirdGDI之基本原理及其总体框架** GDI(Graphics...
`SystemServer`进程负责初始化和管理大量的系统服务,如`ActivityManagerService`、`WindowManagerService`等,这些服务对于系统的正常运行至关重要。 ##### 5. **Home界面启动** - **定义**:`Home`界面的启动...