Activity启动分析

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发送事件通知了。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Activity启动模式是Android应用程序中非常重要的概念,它决定了Activity启动方式和生命周期的管理方式。在Android中,Activity启动模式主要有以下几种: 1. standard:标准模式。默认情况下,每次启动Activity时都会创建一个新实例,并放入任务栈中。如果该Activity已经存在任务栈中,则会将该Activity放到栈顶,并重新调用其onCreate()方法。 2. singleTop:栈顶复用模式。如果新启动Activity已经存在任务栈的栈顶,则不会创建新实例,而是将已有的实例作为当前任务的Activity,并调用其onNewIntent()方法。如果新启动Activity不在栈顶,则会创建新实例,并将其放到任务栈的栈顶。 3. singleTask:栈内复用模式。如果新启动Activity已经存在任务栈中,则不会创建新实例,而是将已有的实例作为当前任务的Activity,并将其上面的Activity全部出栈,调用其onNewIntent()方法。如果新启动Activity不存在任务栈中,则会创建新实例,并放到任务栈的栈顶。 4. singleInstance:单例模式。在一个新的任务栈中创建Activity,并且该任务栈中只有该Activity实例。如果该Activity已经存在于其他任务栈中,则会将该任务栈中的该Activity实例移动到新的任务栈中。 下面是Activity的源码分析: 1. standard模式 在Activity的源码中,标准模式是默认的启动模式。当我们使用startActivity()方法启动一个Activity时,会调用ActivityStackSupervisor类中的startActivityLocked()方法。在该方法中,会通过ActivityStack类的findTaskLocked()方法查找是否存在当前Activity所在的任务栈。如果存在,则会将当前Activity放到该任务栈的栈顶,并调用其onCreate()方法。如果不存在,则会创建一个新的任务栈,并将当前Activity放到该任务栈的栈顶。 2. singleTop模式 当我们在Manifest文件中设置Activity启动模式为singleTop时,会在ActivityInfo中保存该信息。在ActivityStackSupervisor类的startActivityLocked()方法中,会通过ActivityStack类的findTaskLocked()方法查找是否存在当前Activity所在的任务栈,并判断当前Activity是否在栈顶。如果在栈顶,则会调用其onNewIntent()方法。如果不在栈顶,则会创建一个新的实例,并放到该任务栈的栈顶。 3. singleTask模式 当我们在Manifest文件中设置Activity启动模式为singleTask时,会在ActivityInfo中保存该信息。在ActivityStackSupervisor类的startActivityLocked()方法中,会通过ActivityStack类的findTaskLocked()方法查找是否存在当前Activity所在的任务栈。如果存在,则会找到该任务栈中的栈顶Activity,并将其上面的所有Activity出栈。然后将当前Activity放到该任务栈的栈顶,并调用其onNewIntent()方法。如果不存在,则会创建一个新的任务栈,并将当前Activity放到该任务栈的栈顶。 4. singleInstance模式 当我们在Manifest文件中设置Activity启动模式为singleInstance时,会在ActivityInfo中保存该信息。在ActivityStackSupervisor类的startActivityLocked()方法中,会创建一个新的任务栈,并将当前Activity放到该任务栈的栈顶。如果该Activity已经存在于其他任务栈中,则会将该任务栈中的该Activity实例移动到新的任务栈中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值