The startup of SurfaceFlinger of Android source code (2)

page6
我们看一下Thread的run函数的实现:
    1 status_t Thread::run(const char* name, int32_t priority, size_t stack)
    2 {
    3     Mutex::Autolock _l(mLock);
    4
    5     if (mRunning) {
    6         // thread already started
    7         return INVALID_OPERATION;
    8     }
    9
    10     // reset status and exitPending to their default value, so we can
    11     // try again after an error happened (either below, or in readyToRun())
    12     mStatus = NO_ERROR;
    13     mExitPending = false;
    14     mThread = thread_id_t(-1);
    15
    16     // hold a strong reference on ourself
    17     mHoldSelf = this;
    18
    19     mRunning = true;
    20
    21     bool res;
    22     if (mCanCallJava) {
    23         res = createThreadEtc(_threadLoop,
    24                 this, name, priority, stack, &mThread);
    25     } else {
    26         res = androidCreateRawThreadEtc(_threadLoop,
    27                 this, name, priority, stack, &mThread);
    28     }
    29
    30     if (res == false) {
    31         mStatus = UNKNOWN_ERROR;   // something happened!
    32         mRunning = false;
    33         mThread = thread_id_t(-1);
    34         mHoldSelf.clear();  // "this" may have gone away after this.
    35
    36         return UNKNOWN_ERROR;
    37     }
    38
    39     // Do not refer to mStatus here: The thread is already running (may, in fact
    40     // already have exited with a valid mStatus result). The NO_ERROR indication
    41     // here merely indicates successfully starting the thread and does not
    42     // imply successful termination/execution.
    43     return NO_ERROR;
    44
    45     // Exiting scope of mLock is a memory barrier and allows new thread to run
    46 }

    第22-24行(Thread->run)会调用createThreadEtc函数来创建一个
    Lines 25-28 (Thread->run) will call the androidCreateRawThreadEtc function to create a thread. For a detailed analysis of the androidCreateRawThreadEtc function, please refer to the page7 file.
    When a new thread is created, the thread will use the _threadLoop function as the entry point. Execution, for the detailed analysis of the _threadLoop function of Thread, please refer to the page8 file.
    From the analysis of the _threadLoop function, we can know that the readyToRun function of SurfaceFlinger will be called first. For the detailed analysis of the readyToRun function of SurfaceFlinger, please refer to the page9 file.
page7
is here , Let's take a look at the implementation of Thread's androidCreateRawThreadEtc function:
    1 int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
    2 void *userData,
    3 const char* threadName,
    4 int32_t threadPriority,
    5 size_t threadStackSize,
    6                                android_thread_id_t *threadId)
    7 {
    8     pthread_attr_t attr;
    9     pthread_attr_init(&attr);
    10     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    11
    12 #ifdef HAVE_ANDROID_OS  /* valgrind is rejecting RT-priority create reqs */
    13     if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) {
    14         // Now that the pthread_t has a method to find the associated
    15         // android_thread_id_t (pid) from pthread_t, it would be possible to avoid
    16         // this trampoline in some cases as the parent could set the properties
    17         // for the child.  However, there would be a race condition because the
    18         // child becomes ready immediately, and it doesn't work for the name.
    19         // prctl(PR_SET_NAME) only works for self; prctl(PR_SET_THREAD_NAME) was
    20         // proposed but not yet accepted.
    21         thread_data_t* t = new thread_data_t;
    22         t->priority = threadPriority;
    23         t->threadName = threadName ? strdup(threadName) : NULL;
    24         t->entryFunction = entryFunction;
    25         t->userData = userData;
    26         entryFunction = (android_thread_func_t)&thread_data_t::trampoline;
    27         userData = t;
    28     }
    29 #endif
    30
    31     if (threadStackSize) {
    32         pthread_attr_setstacksize(&attr, threadStackSize);
    33     }
    34
    35     errno = 0;
    36     pthread_t thread;
    37     int result = pthread_create(&thread, &attr,
    38                     (android_pthread_entry)entryFunction, userData);
    39     pthread_attr_destroy(&attr);
    40     if (result != 0) {
    41         ALOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
    42              "(android threadPriority=%d)",
    43             entryFunction, result, errno, threadPriority);
    44         return 0;
    45 }
    46
    47 // Note that *threadID is directly available to the parent only, as it is
    48 // assigned after the child starts. Use memory barrier / lock if the child
    49 // or other threads also need access.
    50 if (threadId != NULL) {
    51 *threadId = (android_thread_id_t)thread; // XXX: this is not portable
    52 }
    53 return 1;
    54 }

Lines 37-38 (Thread->androidCreateRawThreadEtc) will call the pthread_create function to create a Thread, and use entryFunction as the entry function of thread.
page8
    In this article, we analyze the implementation of Thread's _threadLoop function:
1 int Thread::_threadLoop(void* user)
    2 {
    3     Thread* const self = static_cast<Thread*>(user);
    4
    5     sp<Thread> strong(self->mHoldSelf);
    6     wp<Thread> weak(strong);
    7     self->mHoldSelf.clear();
    8
    9 #ifdef HAVE_ANDROID_OS
    10     // this is very useful for debugging with gdb
    11     self->mTid = gettid();
    12 #endif
    13
    14     bool first = true;
    15
    16     do {
    17         bool result;
    18         if (first) {
    19             first = false;
    20             self->mStatus = self->readyToRun();
    21             result = (self->mStatus == NO_ERROR);
    22
    23             if (result && !self->exitPending()) {
    24                 // Binder threads (and maybe others) rely on threadLoop
    25                 // running at least once after a successful ::readyToRun()
    26                 // (unless, of course, the thread has already been asked to exit
    27                 // at that point).
    28                 // This is because threads are essentially used like this:
    29                 //   (new ThreadSubclass())->run();
    30                 // The caller therefore does not retain a strong reference to
    31                 // the thread and the thread would simply disappear after the
    32                 // successful ::readyToRun() call instead of entering the
    33                 // threadLoop at least once.
    34                 result = self->threadLoop();
    35             }
    36         } else {
    37             result = self->threadLoop();
    38         }
    39
    40         // establish a scope for mLock
    41         {
    42         Mutex::Autolock _l(self->mLock);
    43         if (result == false || self->mExitPending) {
    44             self->mExitPending = true;
    45             self->mRunning = false;
    46             // clear thread ID so that requestExitAndWait() does not exit if
    47             // called by a new thread using the same thread ID as this one.
    48             self->mThread = thread_id_t(-1);
    49             // note that interested observers blocked in requestExitAndWait are
    50             // awoken by broadcast, but blocked on mLock until break exits scope
    51             self->mThreadExitedCondition.broadcast();
    52             break;
    53         }
    54         }
    55
    56         // Release our strong reference, to let a chance to the thread
    57         // to die a peaceful death.
    58         strong.clear();
    59         // And immediately, re-acquire a strong reference for the next loop
    60 strong = weak.promote();
    61 } while(strong != 0);
    62
    63 return 0;
    64 }
    Lines 18-38 (Thread->_threadLoop) will judge that if the thread is executed for the first time, the readyToRun function will be executed first , and then the threadLoop function will be executed continuously.
page9
    In this article, we analyze the implementation of SurfaceFlinger's readyToRun function:
1 status_t SurfaceFlinger::readyToRun()
    2 {
    3 ALOGI( "SurfaceFlinger's main thread ready to run. "
    4 "Initializing graphics H/W...");
    5
    6 // initialize EGL for the default display
    7 mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    8 eglInitialize(mEGLDisplay, NULL, NULL);
    9
    10     // Initialize the H/W composer object.  There may or may not be an
    11     // actual hardware composer underneath.
    12     mHwc = new HWComposer(this,
    13             *static_cast<HWComposer::EventHandler *>(this));
    14
    15     // initialize the config and context
    16     EGLint format = mHwc->getVisualID();
    17     mEGLConfig  = selectEGLConfig(mEGLDisplay, format);
    18     mEGLContext = createGLContext(mEGLDisplay, mEGLConfig);
    19
    20     LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
    21             "couldn't create EGLContext");
    22
    23     // initialize our non-virtual displays
    24     for (size_t i=0 ; i<DisplayDevice::NUM_DISPLAY_TYPES ; i++) {
    25         DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
    26         mDefaultDisplays[i] = new BBinder();
    27         wp<IBinder> token = mDefaultDisplays[i];
    28
    29         // set-up the displays that are already connected
    30         if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
    31             // All non-virtual displays are currently considered secure.
    32             bool isSecure = true;
    33             mCurrentState.displays.add(token, DisplayDeviceState(type));
    34             sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i);
    35             sp<SurfaceTextureClient> stc = new SurfaceTextureClient(
    36                         static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue()));
    37             sp<DisplayDevice> hw = new DisplayDevice(this,
    38                     type, isSecure, token, stc, fbs, mEGLConfig);
    39             if (i > DisplayDevice::DISPLAY_PRIMARY) {
    40                 // FIXME: currently we don't get blank/unblank requests
    41                 // for displays other than the main display, so we always
    42                 // assume a connected display is unblanked.
    43                 ALOGD("marking display %d as acquired/unblanked", i);
    44                 hw->acquireScreen();
    45             }
    46             mDisplays.add(token, hw);
    47         }
    48     }
    49
    50     //  we need a GL context current in a few places, when initializing
    51     //  OpenGL ES (see below), or creating a layer,
    52     //  or when a texture is (asynchronously) destroyed, and for that
    53     //  we need a valid surface, so it's convenient to use the main display
    54     //  for that.
    55     sp<const DisplayDevice> hw(getDefaultDisplayDevice());
    56
    57     //  initialize OpenGL ES
    58     DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
    59     initializeGL(mEGLDisplay);
    60
    61     // start the EventThread
    62     mEventThread = new EventThread(this);
    63     mEventQueue.setEventThread(mEventThread);
    64
    65     // initialize our drawing state
    66     mDrawingState = mCurrentState;
    67
    68
    69     // We're now ready to accept clients...
    70     mReadyToRunBarrier.open();
    71
    72     // set initial conditions (e.g. unblank default device)
    73     initializeDisplays();
    74
    75     // start boot animation
    76     startBootAnim();
    77
    78     return NO_ERROR;
    79 }
    Lines 12-13 (SurfaceFlinger->readyToRun) will create a HWComposer object to initialize the member variable mHwc, mHwc is the underlying operation Fb file.
    Lines 24-48 (SurfaceFlinger->readyToRun) will apply for a DisplayDevice for each display device Object,
    line 62 (SurfaceFlinger->readyToRun) will create an EventThread object and initialize the member variable mEventThread. For the creation process of EventThread, please refer to the page10 file.
    Because mEventThread is a member variable of type Sp, this will cause onFirstRef of EventThread For the function call, please refer to the page11 file for a detailed analysis of the onFirstRef function of the EventThread.

    Line 63 (SurfaceFlinger->readyToRun) will call the setEventThread function of the MessageQueue to create a connection with the EventThread. For a detailed analysis of the setEventThread function of the MessageQueue, please refer to the page12 file .
page10In
    this article, let's take a look at the creation process of EventThread. Let's first look at the inheritance system of the EventThread class:
    class EventThread : public Thread
    Obviously, EventThread is just a thread.

    The definition of the constructor of the EventThread class is as follows:
    1 EventThread::EventThread(const sp<SurfaceFlinger>& flinger)
    2     : mFlinger(flinger),
    3       mUseSoftwareVSync(false),
    4       mDebugVsyncEnabled(false) {
    5
    6     for (int32_t i=0 ; i<HWC_DISPLAY_TYPES_SUPPORTED ; i++) {
    7         mVSyncEvent[i].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
    8         mVSyncEvent[i].header.id = 0;
    9         mVSyncEvent[i].header.timestamp = 0;
    10         mVSyncEvent[i].vsync.count =  0;
    11     }
    12 }

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326228613&siteId=291194637