activity的启动分析
来源:互联网 发布:淘宝上的东方购物代购 编辑:程序博客网 时间:2024/05/22 17:10
1. Activity简介
一个Activity是用户要做的一件单一工作。它包括与用户交互的所有功能,因此它负责创建Window,以便你通过setContentView放置你的UI。其所有派生类将实现以下两个方法:
1) onCreate:初始化你的activity,通常调用setContentView设置定义UI的资源,并且通过findViewById获取UI中的控件,以便程序控制控件的内容或状态。
2) onPause:当用户离开此activity时,进行的一些处理工作,如通过android.content.ContentProvider提交修改过的数据。
Activity派生关系及关键成员变量如下所示:
- public class Activity extends ContextThemeWrapper
- implements LayoutInflater.Factory2,
- Window.Callback, KeyEvent.Callback,
- OnCreateContextMenuListener, ComponentCallbacks2 {
- private static final String TAG = "Activity";
- ...
- private Application mApplication;
- Intent mIntent;
- ActivityInfo mActivityInfo;
- ...
- ActivityThread mMainThread; //是新建的应用程序的主线程
- ...
- private Window mWindow; //实质上是一个PhoneWindow
- private WindowManager mWindowManager; //实质上是一个LocalWindowManager
- ...
- View mDecor = null; //实质上是一个DecorView
- ...
- }
2. Activity相关类图谱
Activity(应用程序)端的类图谱如下图所示:
3. 应用程序(Activity派生类)的启动流程
在Android系统中,应用程序是由Activity组成的,因此,应用程序的启动过程实际上就是:应用程序中的默认Activity的启动过程,ActivityManagerService组件负责为Android应用程序创建新的进程,启动过程中,把Launcher置为pause状态,并启动新的Activity,其流程如下:
1) Launcher.java@startActivitySafely
2) Activity.java@startActivity
3) Activity.java@startActivityForResult
4) Instrumentation.java@execStartActivity
其中ActivityManagerNative.getDefault返回ActivityManagerService的Proxy:ActivityManagerProxy
5) ActivityManagerProxy.startActivity (ActivityManagerNative.java)
6) ActivityManagerService.java@startActivity
7) ActivityStack.java@startActivityMayWai
8) ActivityStack.java@startActivityLocked
9) ActivityStack.java@startActivityUncheckedLocked
10) ActivityStack.java@startActivityLocked
11) ActivityStack.java@resumeTopActivityLocked
12) ActivityStack.java@.startPausingLocked
13) ApplicationThreadNative.java@schedulePauseActivity
14) ActivityThread.java@schedulePauseActivity
15) ActivityThread.java@queueOrSendMessage
16) ActivityThread.java@handleMessage
17) ActivityThread.java@handlePauseActivity
Puase的Launcher
18) ActivityThread.java@handlePauseActivity
19) ActivityManagerProxy.activityPaused(ActivityManagerNative.java)
20) ActivityManagerService.java@activityPaused
21) ActivityStack.java@activityPaused
22) ActivityStack.java@completePauseLocked
23) ActivityStack.java@resumeTopActivityLokced
24) ActivityStack.java@startSpecificActivityLocked
25) ActivityManagerService.java@startProcessLocked
26) Process.java@start("android.app.ActivityThread",...)//加载并执行ActivityThread静态成员函数main
27) RuntimeInit.java@invokeStaticMain
- /**
- * Invokes a static "main(argv[]) method on class "className".
- * Converts various failing exceptions into RuntimeExceptions, with
- * the assumption that they will then cause the VM instance to exit.
- *
- * @param className Fully-qualified class name
- * @param argv Argument vector for main()
- */
- private static void invokeStaticMain(String className, String[] argv)
- throws ZygoteInit.MethodAndArgsCaller {
- Class<?> cl;
- try {
- cl = Class.forName(className);
- } catch (ClassNotFoundException ex) {
- throw new RuntimeException(
- "Missing class when invoking static main " + className,
- ex);
- }
- Method m;
- try {
- m = cl.getMethod("main", new Class[] { String[].class });
- } catch (NoSuchMethodException ex) {
- throw new RuntimeException(
- "Missing static main on " + className, ex);
- } catch (SecurityException ex) {
- throw new RuntimeException(
- "Problem getting static main on " + className, ex);
- }
- int modifiers = m.getModifiers();
- if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
- throw new RuntimeException(
- "Main method is not public and static on " + className);
- }
- /*
- * This throw gets caught in ZygoteInit.main(), which responds
- * by invoking the exception's run() method. This arrangement
- * clears up all the stack frames that were required in setting
- * up the process.
- */
- throw new ZygoteInit.MethodAndArgsCaller(m, argv);
- }
28) ActivityThread.java@main
- public static void main(String[] args) {
- SamplingProfilerIntegration.start();
- // CloseGuard defaults to true and can be quite spammy. We
- // disable it here, but selectively enable it later (via
- // StrictMode) on debug builds, but using DropBox, not logs.
- CloseGuard.setEnabled(false);
- Process.setArgV0("<pre-initialized>");
- Looper.prepareMainLooper();
- if (sMainThreadHandler == null) {
- sMainThreadHandler = new Handler();
- }
- ActivityThread thread = new ActivityThread();
- thread.attach(false);
- if (false) {
- Looper.myLooper().setMessageLogging(new
- LogPrinter(Log.DEBUG, "ActivityThread"));
- }
- Looper.loop();
- throw new RuntimeException("Main thread loop unexpectedly exited");
- }
进程中创建一个ActivityThread实例,然后调用它的attach函数,接着就进入消息循环了,直到最后进程退出。
29) ActivityManagerProxy.attachApplication(mAppThread) <ActivityManagerNative.java>
ActivityManagerProxy为IActivityManager的Bp,通过它发送消息给ActivityManagerService
参数为ApplicationThread,它的方法主要是向queue中发送消息
ApplicationThread->ApplicationThreadNative->Binder->IBinder
30) ActivityManagerService.java@attachApplication
31) ActivityManagerService.java@attachApplicationLocked
32) ActivityStack.java@realStartActivityLocked
33) ApplicationThreadProxy.scheduleLaunchActivity (ApplicationThreadNative.java)
34) ApplicationThread.scheduleLaunchActivity (ActivityThread.java)
此处创建了一个ActivityClientRecord实例
35) H.handleMessage (ActivityThread.java)
36) ActivityThread.java@handleLaunchActivity
37.1) ActivityThread.java@performLaunchActivity (performLaunchActivity函数加载用户自定义的Activity的派生类,并执行其onCreate函数,当然它将返回此Activity对象)
1) Activity.java@attach
1.1) PolicyManager.makeNewWindow: 创建PhoneWindow并保存在Activity.mWindow中(见Policy.java)
1.2) 把此Activity设置为Window.mCallback (它负责分发事件)
1.3) 获取WindowManager并保存在Activity.mWindowManager
mWindowManager = mWindow.getWindowManager();
它实质上返回的是LocalWindowManager
37.2) ActivityThread.java@handleResumeActivity (让Activity进入Resumed状态,即调用这个Activity的onResume函数)
1) 创建DecorView: r.window.getDecorView (PhoneWindow.getDecorView)
2) 获得WindowManager: (ViewManager wm = a.getWindowManager())
3) 把主View “DecorView”增加到WindowManager( wm.addView(decor, l) )
WindowManagerImpl.java@addView
3.1) 首先检查要增加的View是否在WindowManagerImpl.mViews中
3.2) 创建WindowManagerImpl中的mViews、mRoots、mParams,然后再把当前DecorView的相关参数保存到数组中:
- //WindowManagerImpl.java
- private void addView(View view, ViewGroup.LayoutParams params,
- CompatibilityInfoHolder cih, boolean nest) {
- ViewRootImpl root;
- root = new ViewRootImpl(view.getContext());
- ...
- mViews = new View[1];
- mRoots = new ViewRootImpl[1];
- mParams = new WindowManager.LayoutParams[1];
- ...
- mViews[index] = view;
- mRoots[index] = root;
- mParams[index] = wparams;
- ...
- root.setView(view, wparams, panelParentView);
- }
3.3) root.setView(view, wparams, panelParentView) (ViewRootImpl.java)
ViewRootImpl是View等级结构中的最高级对象,它实现了View与WindowManagerService之间需要的协议。其主要成员变量如下:
- //ViewRootImpl.java
- public final class ViewRootImpl extends Handler implements ViewParent,
- View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
- ...
- static IWindowSession sWindowSession;
- ...
- final W mWindow;
- ...
- }
• IWindowSession
它是通过调用IWindowManager.openSession获取,当WindowManagerService执行openSession时,它实质上创建了一个Session,并返回其Proxy给ViewRootImpl,并保存在SWindowSession中。具体如下图所示:
• W
它的定义如下:
- static class W extends IWindow.Stub
它是IWindow.Stub的实现类,其它进程可通过IWindow来访问它,WindowManagerService将调用此接口来访问ViewRootImpl。
3.3.1) ViewRootImpl.setView (ViewRootImpl.java):
为方便描述,下面把ViewRootImpl.setView单独进行描述。
4. ViewRootImpl.setView
其代码如下:
- public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
- synchronized (this) {
- if (mView == null) {
- ...
- // Schedule the first layout -before- adding to the window
- // manager, to make sure we do the relayout before receiving
- // any other events from the system.
- // 通知InputManager,这个Activity窗口是当前被激活的窗口,最终其Handle被保存在InputDispatcher中
- requestLayout();
- if ((mWindowAttributes.inputFeatures
- & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
- // An input channel specifies the file descriptors
- // used to send input events to
- // a window in another process.
- mInputChannel = new InputChannel();
- }
- try {
- mOrigWindowType = mWindowAttributes.type;
- // 把键盘消息接收通道的一端注册在InputManager中,
- // 在服务器端,Session.add->WindowManagerService.addWindow中
- // 调用InputChannel.openInputChannelPair创建InputChannel对,
- // 通过ashmem分配了共享内存区域、创建一个fd并复制、每端2个
- // pipe,一个用于收,一个用于发,用于事件同步,而不是真正的消息,
- // 真正的消息通过ashmem传递, 这样每端有一个fd,两个pipe
- res = sWindowSession.add(mWindow, mSeq, mWindowAttributes,
- getHostVisibility(), mAttachInfo.mContentInsets,
- mInputChannel);
- }
- ...
- if (mInputChannel != null) {
- if (mInputQueueCallback != null) {
- // An input queue provides a mechanism for an application to receive incoming
- // input events. Currently only usable from native code.
- mInputQueue = new InputQueue(mInputChannel);
- mInputQueueCallback.onInputQueueCreated(mInputQueue);
- } else {
- // 把事件消息接收通道的另一端注册在本应用程序的消息循环(Looper)中。
- // 这样,当InputManager监控到有事件消息时,就会先找到当前被激活的窗口,
- // 然后找到其在InputManager中对应的事件消息接收通道(pipe和对应的本地fd),
- // 通过这个通道在InputManager中的一端来通知在应用程序消息循环中的另一端,
- // 就把事件消息分发给当前激活的Activity窗口了。
- InputQueue.registerInputChannel(mInputChannel, mInputHandler,
- Looper.myQueue());
- }
- }
- } //end mView == null
- }
- }
相关分析见上面的注释。
4.1 通知WindowManagerService当前窗口是激活窗口
通知WindowManagerService当前窗口是激活窗口通过调用requestLayout()来实现。具体调用流程如下:
1) ViewRootImpl.java@setView
2) ViewRootImpl.java@requestLayout
3) ViewRootImpl.java@scheduleTraversals(发送消息DO_TRAVERSAL)
4) ViewRootImpl.java@handleMessage (case DO_TRAVERSAL:)
5) ViewRootImpl.java@performTraversals
(遍历mView<实质为DecorView,在ActivityThread.java中创建,同时被保存在WindowManagerImpl.mViews[0]中>树)
6) ViewRootImpl.java@relayoutWindow
7) IWindowSession.relayout (sWindowSession.relayout)
8) Session.java@relayout
9) WindowManagerService.java@relayoutWindow
10) InputMonitor.java@updateInputWindowsLw
(mInputMonitor.updateInputWindowsLw(true /*force*/),负责输入事件和焦点管理,
这个函数将当前系统中带有InputChannel的Activity窗口都设置为InputManager的输入窗口)
11) InputManger.java@setInputWindows
(mService.mInputManager.setInputWindows(mInputWindowHandles))
12) com_android_server_InputManager.cpp@android_server_InputManager_nativeSetInputWindows
13) NativeInputManager::setInputWindows (com_android_server_InputManager.cpp)
(首先将Java层的WindowHandle转换成C++层的InputWindowHandle,
然后放在windowHandles向量中,最后将这些输入窗口列表设置到InputDispatcher中去。
14) InputDispatcher::setInputWindows (InputDispatcher.cpp)
(调用mInputManager->getDispatcher()->setInputWindows(windowHandles);
它把mFocusedWindowHandle置为当前具有焦点的窗口,其代码如下:)
- void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
- {
- Vector<sp<InputWindowHandle> > oldWindowHandles = mWindowHandles;
- mWindowHandles = inputWindowHandles;
- sp<InputWindowHandle> newFocusedWindowHandle;
- bool foundHoveredWindow = false;
- for (size_t i = 0; i < mWindowHandles.size(); i++) {
- const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
- if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == NULL) {
- mWindowHandles.removeAt(i--);
- continue;
- }
- if (windowHandle->getInfo()->hasFocus) {
- // 找点具有焦点的窗口
- newFocusedWindowHandle = windowHandle;
- }
- if (windowHandle == mLastHoverWindowHandle) {
- foundHoveredWindow = true;
- }
- }
- if (!foundHoveredWindow) {
- mLastHoverWindowHandle = NULL;
- }
- // 当焦点窗口发生变化时执行
- // (mFocusedWindowHandle表示当前的激活窗口
- if (mFocusedWindowHandle != newFocusedWindowHandle) {
- if (mFocusedWindowHandle != NULL) {
- sp<InputChannel> focusedInputChannel = mFocusedWindowHandle->getInputChannel();
- if (focusedInputChannel != NULL) {
- CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
- "focus left window");
- synthesizeCancelationEventsForInputChannelLocked(
- focusedInputChannel, options);
- }
- }
- // 设置新的焦点窗口
- mFocusedWindowHandle = newFocusedWindowHandle;
- }
- } // release lock
- // Wake up poll loop since it may need to make new input dispatching choices.
- mLooper->wake();
- }
至此,InputManager就把当前激活的Activity窗口保存在 InputDispatcher的mFocusedWindowHandle中了,后面就可以把键盘消息分发给它来处理。
4.2 注册事件接收通道InputChannel到WindowManagerService中
实质上注册到了:InputDispatcher的mConnectionsByReceiveFd中。
其相关代码如下:
- public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
- synchronized (this) {
- if (mView == null) {
- ...
- if ((mWindowAttributes.inputFeatures
- & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
- // An input channel specifies the file descriptors
- // used to send input events to
- // a window in another process.
- mInputChannel = new InputChannel();
- }
- try {
- mOrigWindowType = mWindowAttributes.type;
- // 把键盘消息接收通道的一端注册在InputManager中,
- // 在服务器端,Session.add->WindowManagerService.addWindow中
- // 调用InputChannel.openInputChannelPair创建InputChannel对,
- // 通过ashmem分配了共享内存区域、创建一个fd并复制、每端2个
- // pipe,一个用于收,一个用于发,用于事件同步,而不是真正的消息,
- // 真正的消息通过ashmem传递, 这样每端有一个fd,两个pipe
- res = sWindowSession.add(mWindow, mSeq, mWindowAttributes,
- getHostVisibility(), mAttachInfo.mContentInsets,
- mInputChannel);
- }
- ...
- } //end mView == null
- }
- }
其调用流程如下:
1) sWindowSession.add (ViewRootImpl.java)
2) Session.java@add
3) WindowManagerService.java@addWindow
详细分析见下面的注释。
- // WindowManagerService.java
- public int addWindow(Session session, IWindow client, int seq,
- WindowManager.LayoutParams attrs, int viewVisibility,
- Rect outContentInsets, InputChannel outInputChannel) {
- ...
- WindowState attachedWindow = null;
- WindowState win = null;
- long origId;
- synchronized(mWindowMap) {
- // WindowManagerService会为当前Activity窗口创建一个WindowState
- // 对象win,用来记录这个Activity窗口的状态信息。
- win = new WindowState(this, session, client, token,
- attachedWindow, seq, attrs, viewVisibility);
- if (win.mDeathRecipient == null) {
- // Client has apparently died, so there is no reason to
- // continue.
- Slog.w(TAG, "Adding window client " + client.asBinder()
- + " that is dead, aborting.");
- return WindowManagerImpl.ADD_APP_EXITING;
- }
- // outInputChannel为在ViewRootImpl.setView中创建的mInputChannel
- if (outInputChannel != null && (attrs.inputFeatures
- & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
- // 生成窗口的名字
- String name = win.makeInputChannelName();
- // 将创建InputChannel对,每个包含一个ashmem fd, 发送pipe,接收pipe
- // WindowManagerService保存一个,另一个由outInputChannel参数带回给应用程序
- InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
- // 把inputChannels[0]保存在WindowState的mInputChannel和
- // mInputWindowHandle.inputChannel中
- win.setInputChannel(inputChannels[0]);
- // 把InputChannel[1]转换到outInputChannel中,以便返回给Activity应用程序
- inputChannels[1].transferTo(outInputChannel);
- // 把服务器端的输入通道注册到mInputManager,以作为输入事件的目标
- mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
- }
- ...
- }
- Binder.restoreCallingIdentity(origId);
- return res;
- }
- // InputTransport.h
- class InputChannel : public RefBase {
- // C++层InputChanel成员变量
- private:
- String8 mName; //通道的名称
- int32_t mAshmemFd; // 匿名共享内存文件描述符
- int32_t mReceivePipeFd; // 管道的读端文件描述符
- int32_t mSendPipeFd; // 管道的写端文件描述符
- };
4) InputManager.java@registerInputChannel
(即:mInputManager.registerInputChannel(win.mInputChannel,win.mInputWindowHandle))
5) com_android_server_InputManager.cpp@android_server_InputManager_nativeRegisterInputChannel
根据从Java层传来的InputChannel和InputWindowHandle,获取C++层的对应对象,然后调用下面的函数
6) NativeInputManager::registerInputChannel (com_android_server_InputManager.cpp)
7) InputDispatcher::registerInputChannel (InputDispatcher.cpp),其相关代码及注释如下:
- status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
- { // acquire lock
- AutoMutex _l(mLock);
- // 检查InputChannel是否已经注册过了
- if (getConnectionIndexLocked(inputChannel) >= 0) {
- LOGW("Attempted to register already registered input channel '%s'",
- inputChannel->getName().string());
- return BAD_VALUE;
- }
- // 创建Connection对象,它保存了3个参数到内部的成员变量中
- sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);
- // 调用InputPublisher::initialize,获取ashmem,并通过mmap内存映射到用户空间,
- // 用户空间的地址保存在InputPublisher::mSharedMessage中
- // 定义为:InputMessage* mSharedMessage;
- status_t status = connection->initialize();
- if (status) {
- LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
- inputChannel->getName().string(), status);
- return status;
- }
- // 获取读管道fd
- int32_t receiveFd = inputChannel->getReceivePipeFd();
- // 以receiveFd为key,把connection增加到mConnectionsByReceiveFd向量表中
- mConnectionsByReceiveFd.add(receiveFd, connection);
- // 如果此inputChannel要接收所有事件的备份,则把它增加到mMonitoringChannels中
- if (monitor) {
- mMonitoringChannels.push(inputChannel);
- }
- // 把读管道fd增加到mLooper中,以方便通过epoll_ctl监控此fd
- // 是否有数据读取,若有则调用handleReceiveCallback处理
- mLooper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
- runCommandsLockedInterruptible();
- } // release lock
- return OK;
- }
至此,注册事件接收通道已经完成,即注册到InputDispatcher的mConnectionsByReceiveFd中,并监控了其读通道。
4.3 注册事件接收通道InputChannel到Activity应用程序
入口处相关代码如下:
- public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
- synchronized (this) {
- if (mView == null) {
- ...
- // Schedule the first layout -before- adding to the window
- // manager, to make sure we do the relayout before receiving
- // any other events from the system.
- // 通知InputManager,这个Activity窗口是当前被激活的窗口,最终其Handle被保存在InputDispatcher中
- requestLayout(); //4.1
- if ((mWindowAttributes.inputFeatures
- & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
- // An input channel specifies the file descriptors
- // used to send input events to
- // a window in another process.
- mInputChannel = new InputChannel();
- }
- ...
- if (view instanceof RootViewSurfaceTaker) {
- mInputQueueCallback =
- ((RootViewSurfaceTaker)view).willYouTakeTheInputQueue();
- }
- if (mInputChannel != null) {
- if (mInputQueueCallback != null) {
- // An input queue provides a mechanism for an application to receive incoming
- // input events. Currently only usable from native code.
- mInputQueue = new InputQueue(mInputChannel);
- mInputQueueCallback.onInputQueueCreated(mInputQueue);
- } else {
- // 把事件消息接收通道的另一端注册在本应用程序的消息循环(Looper)中。
- // 这样,当InputManager监控到有事件消息时,就会先找到当前被激活的窗口,
- // 然后找到其在InputManager中对应的事件消息接收通道(pipe和对应的本地fd),
- // 通过这个通道在InputManager中的一端来通知在应用程序消息循环中的另一端,
- // 就把事件消息分发给当前激活的Activity窗口了。
- InputQueue.registerInputChannel(mInputChannel, mInputHandler,
- Looper.myQueue()); // 4.3
- }
- }
- } //end mView == null
- }
- }
这里的变量view一般不为RootViewSurfaceTaker的实例,因此它执行下面的语句:
- InputQueue.registerInputChannel(mInputChannel, mInputHandler,
- Looper.myQueue());
mInputHandler是一个回调对象,当有键盘输入事件时,这个mInputHandler的handleKey函数就会被调用,Looper.myQueue函数返回的便是应用程序主线程的消息队列,其函数调用流程如下:
1) InputQueue.java@registerInputChannel (注册输入通道和handler)
2) nativeRegisterInputChannel
3) android_view_InputQueue_nativeRegisterInputChannel (android_view_InputQueue.cpp)
4) NativeInputQueue::registerInputChannel (android_view_InputQueue.cpp),相关代码如下:
- status_t NativeInputQueue::registerInputChannel(JNIEnv* env, jobject inputChannelObj,
- jobject inputHandlerObj, jobject messageQueueObj) {
- // 根据Java InputChannel获取C++ InputChannel
- sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
- inputChannelObj);
- ...
- // 从messageQueue中获取Looper
- sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
- { // acquire lock
- AutoMutex _l(mLock);
- // 检查此InputChannel是否已经注册
- if (getConnectionIndex(inputChannel) >= 0) {
- LOGW("Attempted to register already registered input channel '%s'",
- inputChannel->getName().string());
- return BAD_VALUE;
- }
- uint16_t connectionId = mNextConnectionId++;
- // 创建NativeInputQueue.Connection,
- // 与Server端创建的InputDispatcher.Connection不一样
- sp<Connection> connection = new Connection(connectionId, inputChannel, looper);
- // a) 从mChannel获取ashmemFd
- // b) 通过mmap把ashmemFd指向的内存映射到用户空间
- // 并保存在mSharedMessage中 (InputMessage* mSharedMessage;)
- status_t result = connection->inputConsumer.initialize();
- if (result) {
- LOGW("Failed to initialize input consumer for input channel '%s', status=%d",
- inputChannel->getName().string(), result);
- return result;
- }
- connection->inputHandlerObjGlobal = env->NewGlobalRef(inputHandlerObj);
- int32_t receiveFd = inputChannel->getReceivePipeFd();
- // 把此connection加入向量列表中
- mConnectionsByReceiveFd.add(receiveFd, connection);
- // 让客户端线程监控接收fd是否有数据可读
- looper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
- } // release lock
- android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
- handleInputChannelDisposed, this);
- return OK;
- }
至此已经把客户端的接收通道注册到NativeInputQueue.mConnectionsByReceiveFd中,并监控了其读通道。
目前,Activity的整个启动过程已经分析完毕,Activity可以向WindowManagerService发送请求;WindowManagerService也可以向Activity发送事件通知了。- activity的启动分析
- activity的启动过程分析
- Activity 的启动流程分析
- Activity的启动流程分析
- activity的启动模式分析
- Activity的启动模式分析-之一
- Activity的启动模式分析-之二
- Activity的启动模式分析-之三
- 分析Activity的四种启动模式
- Android源码分析-Activity的启动过程
- Android源码分析-Activity的启动过程 .
- Android源码分析-Activity的启动过程
- Android源码分析-Activity的启动过程
- Android源码分析-Activity的启动过程
- Android源码分析-Activity的启动过程
- Activity启动模式的深入分析
- 源码分析Activity启动的流程
- Android源码分析-Activity的启动过程
- postgresql 索引类型
- 俄罗斯本地支付Yandex.Money
- 一个最基本的最简单的WEB工程结构
- UIImage的两种加载方式
- Word插件
- activity的启动分析
- Frogger(最短路_floyd变形)
- Java 抽象类,接口
- 浅谈HTTP中Get与Post的区别
- 如何查询mysql数据库里某个字段在哪张表中
- Git:代码冲突常见解决方法
- memcpy和memmove的函数内部实现
- 俄罗斯本地支付QiWi
- hadoop shell常用命令