`
zzu_007
  • 浏览: 23898 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Activity与WindowManagerService连接的过程(一)

阅读更多
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文件.

分享到:
评论

相关推荐

    联想 viewroot简介

    2. **GUI绘制流程**:当Activity与WindowManagerService成功建立连接后,ViewRoot将开始执行GUI的绘制过程。这一过程涉及到多个步骤,包括但不限于更新窗口状态、绘制视图层级以及最终的屏幕渲染。 #### 结论 View...

    Android应用程序窗口(Activity) · 老罗的Android之旅(总结) · 看云1

    与WindowManagerService的连接过程是Activity将View添加到屏幕上的关键步骤。WindowManagerService是Android系统的系统服务,它负责管理所有的窗口,并处理窗口的显示和隐藏。 在绘制过程中,Android使用Surface来...

    Android 启动过程详解

    2. **Android服务启动**:SystemServer启动后,会依次启动一系列重要的Android服务,如`ActivityManagerService`、`WindowManagerService`、`PackageManagerService`等。 3. **Home应用启动**:一旦SystemServer及其...

    Android核心剖析之Framework概述

    Android的Framework层作为操作系统的核心组成部分,扮演着连接硬件抽象层(HAL)与应用程序之间的桥梁角色,它不仅提供了丰富的API供开发者调用,还负责管理和调度应用程序的生命周期。本章节深入探讨Android ...

    Android之Input子系统事件分发流程 - CSDN博客1

    在步骤3,`mWindowSession.addToDisplay()` 被调用,这个方法会将新视图添加到显示列表,并且将之前创建的InputChannel与服务端建立连接。`mWindowSession` 是一个IWindowSession接口的实现,它是由`...

    android 客户进程的注册(2)

    每当添加一个新窗口时,会调用WindowManagerService的`performLayoutLockedInner`方法,这个过程会将窗口信息传递给Input系统。Input系统会将这些信息存储在一个列表中,以便后续的事件派发。这个传递过程涉及多个...

    android binder架构

    Binder架构由一个轻量级的远程过程调用(RPC)机制实现,它将数据封装成事务,并在服务端执行这些事务。 首先,Binder驱动是Binder架构的核心组件。它是一个位于内核空间的驱动程序,负责处理不同进程间的通信请求。...

    Monkey源码分析

    - **IWindowManager与WindowManagerService的Binder通信**:了解IWindowManager与WindowManagerService之间的通信机制对于深入理解事件注入的过程至关重要。这两者通过Binder框架实现了跨进程调用,从而使得Monkey...

    Google Android Internal

    4. **System Server**:这是一个核心服务进程,负责启动系统级的服务,如ActivityManagerService、WindowManagerService等。 5. **User Applications**:随着系统服务的启动,用户应用程序也开始运行。 #### 层间...

    Android核心分析(pdf)

    - **RIL接口:** RIL是连接上层应用与底层硬件的桥梁,Java层如何与RIL交互以完成通话操作。 - **RIL实例:** 通过具体的RIL实例来演示通话流程的具体实现。 **GSMCallTracker:** - **GSM呼叫跟踪:** ...

    安卓Android源码——WelcomeLauncher.rar

    - WindowManagerService (WMS):管理窗口堆栈,负责显示WelcomeLauncher的界面。 - ContentProvider:如果WelcomeLauncher需要访问系统数据,可能会用到ContentProvider来共享数据。 4. **自定义与扩展**: - ...

    本人自学Android技术

    1. **ActivityManagerService (AMS)**:这是Android系统的核心服务之一,负责管理和调度应用的生命周期。 2. **WindowManagerService (WMS)**:处理窗口管理,包括屏幕布局、显示和隐藏等操作。 3. **ViewSystem**:...

    Android主要机制深入分析.pdf

    Android操作系统作为一款被广泛应用在智能手机、平板电脑等移动设备上的软件,自2008年推出以来,已经经历了多次更新与迭代,形成了一个功能丰富、架构复杂的庞大系统。深入分析Android的机制,对于理解其运行原理和...

    window和windowManager1

    `ViewRootImpl`是连接Android应用程序与系统服务`WindowManagerService`的关键类。每当一个新的View需要添加到Window时,就会创建一个`ViewRootImpl`实例。它负责处理视图的生命周期,包括设置视图、请求布局更新...

    Android初始化流程简要分析.do

    **启动系统服务**:如ActivityManagerService、WindowManagerService、PackageManagerService等。 - **Start services:** - **ADBD(Android Debug Bridge Daemon)**:用于开发者通过命令行与设备进行通信,如...

    深入理解Android中的Window和WindowManager

    在Android中,无论是Activity、Dialog还是Toast,其界面都挂载在一个或多个Window上。WindowManager则是与Window交互的接口,它允许开发者添加、更新和移除Window。 WindowManagerService是管理所有Window的核心...

    Android 屏幕锁源码

    在Android系统的层次结构中,屏幕锁与`ActivityManagerService`、`WindowManagerService`等核心服务协同工作,确保系统在不同状态间的平滑切换。 通过分析`Android 屏幕锁源码`,我们可以学习到Android系统如何处理...

    Android底层架构研究

    Activity是Android应用程序中最基本的组件之一,它代表了一个屏幕上的界面。Activity的生命周期管理、启动模式和状态保存是保证用户体验流畅的关键。 ### **22. AndoirdGDI之基本原理及其总体框架** GDI(Graphics...

    android启动优化.pdf

    `SystemServer`进程负责初始化和管理大量的系统服务,如`ActivityManagerService`、`WindowManagerService`等,这些服务对于系统的正常运行至关重要。 ##### 5. **Home界面启动** - **定义**:`Home`界面的启动...

Global site tag (gtag.js) - Google Analytics