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

Android源码之SurfaceFlinger的启动(二)

阅读更多
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函数来创建一个
    第25-28行(Thread->run)会调用androidCreateRawThreadEtc函数来创建一个线程. 关于androidCreateRawThreadEtc函数的详细分析可以参考page7文件.
    当创建完一个新线程之后, 这个线程就会以_threadLoop函数作为入口来执行, 关于Thread的_threadLoop函数的详细分析可以参考page8文件.
    由_threadLoop函数的分析可以知道, 这里会首先调用SurfaceFlinger的readyToRun函数, 关于SurfaceFlinger的readyToRun函数的详细分析可以参考page9文件.
page7
在这里, 我们看一下Thread的androidCreateRawThreadEtc函数的实现:
    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 }

第37-38行(Thread->androidCreateRawThreadEtc)会调用pthread_create函数来创建一个线程, 并以entryFunction作为线程的入口函数.
page8
    在这篇文章里, 我们分析一下Thread的_threadLoop函数的实现:
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 }
    第18-38行(Thread->_threadLoop)会判断如果线程第一次执行会首先执行readyToRun函数, 紧接着会不停地执行threadLoop函数.
page9
    在这篇文章里, 我们分析一下SurfaceFlinger的readyToRun函数的实现:
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 }
    第12-13行(SurfaceFlinger->readyToRun)会创建一个HWComposer对象来初始化成员变量mHwc, mHwc是底层操作Fb文件的.
    第24-48行(SurfaceFlinger->readyToRun)会为每一个显示设备申请一个DisplayDevice对象,
    第62行(SurfaceFlinger->readyToRun)会创建一个EventThread对象, 并初始化成员变量mEventThread. 关于EventThread的创建过程可以参考page10文件.
    因为mEventThread是一个Sp类型的成员变量, 因此这里会导致EventThread的onFirstRef函数的调用, 关于EventThread的onFirstRef函数的详细分析可以参考page11文件.

    第63行(SurfaceFlinger->readyToRun)会调用MessageQueue的setEventThread函数来和EventThread创建连接, 关于MessageQueue的setEventThread函数的详细分析可以参考page12文件.
page10
    在这篇文章里, 我们来看一下EventThread的创建过程.我们先来看一下EventThread类的继承体系:
    class EventThread : public Thread
    很显然, EventThread只是一个线程.

    EventThread类的构造函数的定义如下:
    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 }
分享到:
评论

相关推荐

    安卓系统源码 (android 14 rar)

    《安卓系统源码详解——基于Android 14的探索与学习》 Android系统源码是开发者深入了解操作系统工作原理、定制个性化系统以及优化应用性能的重要工具。Android 14的源码,作为Android发展历程中的一个重要版本,为...

    android源码第二季(mars)

    总的来说,《Android源码第二季(Mars)》是一场深入Android内核的探索之旅,通过学习这个项目,开发者不仅能提高代码质量,还能增强对系统优化的理解,为开发更出色的Android应用打下坚实基础。配合网上的教学视频...

    android源码开发实战9.05.zip

    在Android源码开发实战9.05的资料中,我们可以深入探索Android操作系统的内部机制,了解如何基于Android 9.0 (Pie)进行定制和优化。Android源码开发是理解系统工作原理、改进性能和实现自定义功能的关键。以下是根据...

    android 源码 source15

    在Android源码中,系统的启动从bootloader开始,经过kernel加载,然后进入init进程。这个过程中涉及的源码包括bootable/recovery、system/core/init等目录下的文件。init进程负责初始化系统服务、启动Zygote进程,...

    安卓Android源码——MyFeiGe.zip

    《安卓Android源码解析——以MyFeiGe项目为例》 在移动开发领域,安卓(Android)操作系统无疑占据了主导地位,其开源的特性使得开发者能够深入理解系统内部工作原理,并根据需求进行定制化开发。本篇文章将围绕...

    android vnc server 源码

    这部分源码涉及到Android的系统服务交互,如SurfaceFlinger服务,用于获取屏幕的像素数据。 3. **编码与解码**: VNC协议支持多种编码方式,如RAW、COPYRECT、TIGHT等,用于高效地传输屏幕变化。源码中会有对应的...

    安卓Android源码——胜利大逃亡.zip

    "安卓Android源码——胜利大逃亡.zip"可能是一个关于探索和理解Android操作系统核心机制的资料包,其中包含了第15章的内容。这个章节可能涉及到Android系统的某个特定主题,如系统启动流程、进程管理、内存管理或者...

    android4高级编程源码

    6. **Service管理**:Service是Android中后台运行的服务,源码可以帮助开发者了解Service的启动、绑定过程,以及如何合理地设计和使用Service来实现后台任务。 7. **ContentProvider**:ContentProvider是数据共享...

    android源码

    二、Android源码分析 深入理解源码有助于开发者解决性能问题、定制系统、开发自定义ROM等。关键模块如: 1. 系统启动流程:从bootloader到Zygote进程,再到System Server,理解启动过程有助于优化系统启动速度。 2....

    android源码开发实战6.12.zip

    《Android源码开发实战6.12》是针对Android系统深度开发的一份宝贵资源,它涵盖了从基础到高级的各种主题,旨在帮助开发者更好地理解和利用Android的底层机制。在这个压缩包中,主要包含的是第六章第十二节的内容。...

    C++版Android实时投屏软件系统源码,安卓手机投屏软件源码,无需root权限.zip

    在本资源中,我们关注的是一个C++编写的Android实时投屏软件系统源码,名为QtScrcpy-dev。这个软件允许用户将安卓手机的屏幕实时传输到其他设备上,而无需对手机进行root操作。这是一项非常实用的技术,尤其对于...

    android源码开发实战8.11.zip

    在Android源码开发实战8.11这个主题中,我们主要探讨的是如何深入理解并实践Android系统的源代码,以提升应用程序开发的效率和质量。在这个过程中,开发者将有机会接触到Android系统的底层机制,包括系统启动流程、...

    android源码core文件夹下的文件(包含资源)

    深入理解和分析Android源码中的"core"目录,有助于开发者更深入地了解Android系统的运行机制。 1. **系统库**:在"core"文件夹中,你可以找到多个关键的系统库,如libcore、libc、libart等。libcore是Java层的基础...

    android源码开发实战16.01.zip

    在Android源码开发实战课程中,我们通常会深入探索Android操作系统的内部机制,理解系统级服务的实现原理,以及如何利用这些知识进行定制化开发。这个压缩包"android源码开发实战16.01.zip"可能包含了第16讲至第1...

    android源码中system 部分

    综上所述,Android源码中的system部分是整个系统的核心,它通过C++接口实现了与硬件的交互、系统服务的管理、安全策略的执行等一系列关键功能,构成了Android系统的基础架构。理解和研究这部分代码对于深入理解...

    《深入浅出Google Android》源码

    此外,Android使用SurfaceFlinger进行图形渲染,源码分析能帮助开发者理解动画、视图层次和GPU渲染的细节。 4. **系统服务** Android系统服务如电源管理、网络连接、位置服务等在源码中都有体现。通过研究源码,...

    android framework源码

    Android Framework源码是Android操作系统核心组件之一,它构成了Android应用层与系统服务之间的桥梁。深入理解Android Framework源码对于开发者来说至关重要,因为它可以帮助我们更好地掌握Android系统的运行机制,...

    UNLOCKING ANDROID源码

    Android源码的分析与研究对于开发人员来说至关重要,它揭示了Android系统的底层运行机制,包括系统启动流程、进程管理、内存管理、图形渲染、安全机制等各个方面。通过学习源码,我们可以: 1. **理解系统启动**:...

    Android的源码和勘误

    首先,Android源码的探索是一项深入的技术研究。Android作为一个开源项目,其源码包含了从底层驱动到上层应用程序框架的全部内容。主要分为以下几个部分: 1. **Linux内核**:Android构建在定制版的Linux内核之上,...

Global site tag (gtag.js) - Google Analytics