- 浏览: 22520 次
- 性别:
- 来自: 北京
最新评论
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 584page11 WindowManagerService ... -
Activity与WindowManagerService连接的过程(二)
2018-04-16 16:36 706page6 WindowManagerGlobal的getW ... -
Activity的ViewRoot的创建过程(三)
2017-11-06 14:25 707page7 在这篇文章里, 我们分析一下W类的构造过程. W ... -
Activity的ViewRoot的创建过程(二)
2017-11-06 14:29 869page4 我们看一下ViewRootImpl对象的创 ... -
Activity的ViewRoot的创建过程(一)
2017-11-06 14:27 1026page1 当一个Activity第一次激活的时候会为该Ac ... -
Activity的Window和WindowManager的创建过程(三)
2017-07-05 11:49 1298page9 在这里我们分析一下DisplayManager的 ... -
Activity的Window和WindowManager的创建过程(二)
2017-07-05 11:31 499page5 在这篇文章中, 我们分析一下ContextImp ... -
Activity的Window和WindowManager的创建过程(一)
2017-07-05 11:27 575page1 我们开始分析一下Activity的Window和 ... -
Acitivy创建Context的过程(二)
2017-06-21 14:11 452page4 在这里我们分析一下ContextImpl的ini ... -
Acitivy创建Context的过程(一)
2017-06-21 14:15 586page1 从本篇文章开始,我们分析一下Activity创建 ... -
应用程序进程与SurfaceFlinger的连接过程
2017-06-21 11:49 1025我们从SurfaceComposerClient对象的创建开始 ... -
Android源码之SurfaceFlinger的启动(三)
2017-04-20 11:09 1003page11 我们来看一下SurfaceFlinger ... -
Android源码之SurfaceFlinger的启动(二)
2017-04-18 15:15 813page6 我们看一下Thread的run函数的实现: ... -
Android源码之SurfaceFlinger的启动(一)
2017-04-17 10:07 908page1 在Android系统中, 显示系统在底层是通过S ... -
Android源码之Zygote
2015-12-15 11:45 481当ActivityManagerService启动一个应用程序 ... -
Android源码之Binder(五)
2015-12-04 09:19 1415Service组件在启动时,需要将自己注册到Service M ... -
Android源码之Binder(四)
2015-12-04 09:18 1803case BINDER_SET_MAX_THREADS: ... -
Android源码之Binder(三)
2015-12-04 09:17 881{ int ret; struct binder_pr ... -
Android源码之Binder(二)
2015-12-04 09:15 502分析完Binder驱动程序的打开和内存分配的过程之后,我们看一 ... -
Android源码之Binder(一)
2015-12-04 09:12 962在Android系统中,进程间通信使用的是Binder机制。B ...
相关推荐
WindowManagerService详解图
animations in WindowManagerService翻译的结果
Activity,Window,DecorView,ViewRootImpl,WindowManager,WindowManagerImpl,WindowManagerGlobal,WindowManagerService相关类图
深入理解WindowManagerService笔记
我们知道,在Android系统中,Activity是以堆栈的形式组织...从前面Android应用程序启动过程源代码分析一文可以知道,应用程序进程中的每一个Activity组件在Activity管理服务ActivityManagerService中都对应有一个Activi
Android系统采用一种称为Surface的UI架构为应用程序提供用户...这个PPT讲Android应用程序的Surface机制,阐述Activity、Window和View的关系,以及应用程序、WindowManagerService和SurfaceFlinger协作完成UI渲染的过程
DecorView通过PhoneWindow与WindowManagerService通信原理图 每个Activity都有一个Window对象,这个对象是PhoneWindow类型的。 每个Window对象里面都维护着一个WindowManager对象。 Activity里面添加一个View是通过...
有关4.0按键的处理流程,包括windowmanagerservice的激动启动等
这个PPT讲Android应用程序进程的启动和回收,主要涉及到Zygote进程、System Server进程,以及组件管理服务ActivityManagerService、窗口服务WindowManagerService,还有专用驱动Low Memory Killer。通过了解Android...
悬浮窗,大家应该也不陌生,凌驾于应用之上的一个小弹窗,实现上很简单,就是添加一个系统级别的窗口,Android中通过WindowManagerService( WMS)来管理所有的窗口,对于WMS来说,管你是Activity、Toast、Dialog,...
创建一个Window,需要通过WindowManager即可完成,WindowManager是外界访问Window的入口,Window具体实现位于WindowManagerService中,WindowManager和WindowManagerService的交互是一个IPC的过程。Android中,所有...
WindowManagerService.java : 作为应用与IMS的通信桥梁, 也作为InputDispatcher向AMS报告ANR的通信桥梁. ActivityManagerService.java :ANR 处理. Activity & Views :接收输入事件并处理.
系统服务是Android中非常重要的一部分, 像ActivityManagerService, PackageManagerService, WindowManagerService, 这些系统服务都是Framework层的关键服务, 本篇文章主要讲一下如何基于Android源码添加一个系统服务...
Android控件TextView的实现...实际上,每一个视图都是一个控件,这些控制可以将自己的UI绘制在窗口的绘图表面上,同时还可以与用户进行交互,即获得用户的键盘或者触摸屏输入。在本文中,我们就详细分析窗口控件的上
Android 事件捕捉和处理流程分析 ,在Android系统中,键盘按键事件是由WindowManagerService服务来管理的,然后再以消息的形式来分发给应用程序处理,不过和普通消息不一样,它是由硬件中断触发的;在上一篇文章...
创建Window Window即窗口,这个概念在AndroidFramework中的实现为android...在Android系统中,窗口是独占一个Surface实例的显示区域,每个窗口的Surface由WindowManagerService分配。我们可以把Surface看作一块画布,应