zoukankan      html  css  js  c++  java
  • Android Framework中的线程Thread及它的threadLoop方法

    当初跟踪Camera的代码中的时候一直追到了HAL层,而在Framework中的代码看见了许很多多的Thread。它们普遍的特点就是有一个threadLoop方法。依照字面的意思应该是这个线程能够循环处理数据。相应我想到到了java上层中的HandlerThread,这个预计也差点儿相同,但当时心里总有一个疙瘩。想弄清楚它为什么能够循环。还有它究竟是怎么循环起来的?

    Android中java世界的Thread

    我们先来看看java是怎么创建一个线程的。这个是最舒服的,也是我最熟悉的。

    
    new Thread(new Runnable() {
    
            @Override
            public void run() {
                // TODO Auto-generated method stub
                    ...
            }
    }).start();
    

    当然,你也能够在android中创建一个消息循环的HandlerThread

    HandlerThread mThread = new HandlerThread("test");
    mThread.start();
    Handler mHandler = new Handler(mThread.getLooper()){
    
            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                super.handleMessage(msg);
            }
    
    };
    

    上面中通过mHandler发送消息就能够在mThread中处理了。而且这个mThread不是UIThread,不会堵塞主线程。


    HandlerThread是一个好东西,在源代码中处处可见,希望对此不熟悉的新手及时去学习下它的使用方法。

    Linux下c语言的Thread

    java世界的Thread非常方便,那么c呢?
    Android基于linux所以,多线程编程也应该基于linux下的多线程。linux下的c语言用pthread。大家能够看这篇文章。
    linux下C/C++,多线程pthread

    我把里面的样例改良了一下
    test.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <unistd.h>
    
    //线程函数
    void *test(void *ptr)
    {
        int i;
        for(i=0;i<8;i++)
        {
            printf("the pthread running ,count: %d
    ",i);
            sleep(1); 
        }
    
    }
    
    
    int main(void)
    {
        pthread_t pId;
        int i,ret;
        //创建子线程,线程id为pId
        ret = pthread_create(&pId,NULL,test,NULL);
    
        if(ret != 0)
        {
            printf("create pthread error!
    ");
            exit(1);
        }
    
        for(i=0;i < 5;i++)
        {
            printf("main thread running ,count : %d
    ",i);
            sleep(1);
        }
    
        printf("main thread will exit when pthread is over
    ");
        //等待线程pId的完毕
        pthread_join(pId,NULL);
        printf("main thread  exit
    ");
    
        return 0;
    
    }

    然后编译

    gcc -o test test.c -lpthread
    ./test

    执行结果例如以下

    main thread running ,count : 0
    the pthread running ,count: 0
    main thread running ,count : 1
    the pthread running ,count: 1
    main thread running ,count : 2
    the pthread running ,count: 2
    main thread running ,count : 3
    the pthread running ,count: 3
    main thread running ,count : 4
    the pthread running ,count: 4
    main thread will exit when pthread is over
    the pthread running ,count: 5
    the pthread running ,count: 6
    the pthread running ,count: 7
    main thread  exit
    

    样例比較简单,主要是创建一个线程。然后主线程等待子线程执行完毕再退出。

    Android Framework中的Thread

    以下焦点回到文章的主题其中,我们来看看Framework中经常使用的Thread是个何种形态。
    先看看活生生的样例。
    在源代码中搜索threadLoop,当然也能够搜索thread,然后随便挑选一个Thread子类进行研究。

    这里挑选
    /frameworks/av/services/audioflinger/AudioWatchdog.h

    #ifndef AUDIO_WATCHDOG_H
    #define AUDIO_WATCHDOG_H
    
    #include <time.h>
    #include <utils/Thread.h>
    
    namespace android {
    
    ......
    
    class AudioWatchdog : public Thread {
    
    public:
        AudioWatchdog(unsigned periodMs = 50) : Thread(false /*canCallJava*/), mPaused(false),
                mPeriodNs(periodMs * 1000000), mMaxCycleNs(mPeriodNs * 2),
                // mOldTs
                // mLogTs initialized below
                mOldTsValid(false), mUnderruns(0), mLogs(0), mDump(&mDummyDump)
            {
    #define MIN_TIME_BETWEEN_LOGS_SEC 60
                // force an immediate log on first underrun
                mLogTs.tv_sec = MIN_TIME_BETWEEN_LOGS_SEC;
                mLogTs.tv_nsec = 0;
            }
        virtual         ~AudioWatchdog() { }
    
         // Do not call Thread::requestExitAndWait() without first calling requestExit().
        // Thread::requestExitAndWait() is not virtual, and the implementation doesn't do enough.
        virtual void        requestExit();
    
        // FIXME merge API and implementation with AudioTrackThread
        void            pause();        // suspend thread from execution at next loop boundary
        void            resume();       // allow thread to execute, if not requested to exit
    
        // Where to store the dump, or NULL to not update
        void            setDump(AudioWatchdogDump* dump);
    
    private:
        virtual bool    threadLoop();
    
        Mutex           mMyLock;        // Thread::mLock is private
        Condition       mMyCond;        // Thread::mThreadExitedCondition is private
        bool            mPaused;        // whether thread is currently paused
    
        ......
    };
    
    }   // namespace android
    
    #endif  // AUDIO_WATCHDOG_H

    我们能够看到AudioWatchDog确实是Thread的子类,那好。以下看实现。
    /frameworks/av/services/audioflinger/AudioWatchdog.cpp

    #define LOG_TAG "AudioWatchdog"
    //#define LOG_NDEBUG 0
    
    #include <utils/Log.h>
    #include "AudioWatchdog.h"
    
    namespace android {
    
    
    bool AudioWatchdog::threadLoop()
    {
        {
            AutoMutex _l(mMyLock);
            if (mPaused) {
                mMyCond.wait(mMyLock);
                // ignore previous timestamp after resume()
                mOldTsValid = false;
                // force an immediate log on first underrun after resume()
                mLogTs.tv_sec = MIN_TIME_BETWEEN_LOGS_SEC;
                mLogTs.tv_nsec = 0;
                // caller will check for exitPending()
                return true;
            }
        }
        struct timespec newTs;
        int rc = clock_gettime(CLOCK_MONOTONIC, &newTs);
        if (rc != 0) {
            pause();
            return false;
        }
        if (!mOldTsValid) {
            mOldTs = newTs;
            mOldTsValid = true;
            return true;
        }
        time_t sec = newTs.tv_sec - mOldTs.tv_sec;
        long nsec = newTs.tv_nsec - mOldTs.tv_nsec;
        if (nsec < 0) {
            --sec;
            nsec += 1000000000;
        }
        mOldTs = newTs;
        // cycleNs is same as sec*1e9 + nsec, but limited to about 4 seconds
        uint32_t cycleNs = nsec;
        if (sec > 0) {
            if (sec < 4) {
                cycleNs += sec * 1000000000;
            } else {
                cycleNs = 4000000000u;
            }
        }
        mLogTs.tv_sec += sec;
        if ((mLogTs.tv_nsec += nsec) >= 1000000000) {
            mLogTs.tv_sec++;
            mLogTs.tv_nsec -= 1000000000;
        }
        if (cycleNs > mMaxCycleNs) {
            mDump->mUnderruns = ++mUnderruns;
            if (mLogTs.tv_sec >= MIN_TIME_BETWEEN_LOGS_SEC) {
                mDump->mLogs = ++mLogs;
                mDump->mMostRecent = time(NULL);
                ALOGW("Insufficient CPU for load: expected=%.1f actual=%.1f ms; underruns=%u logs=%u",
                    mPeriodNs * 1e-6, cycleNs * 1e-6, mUnderruns, mLogs);
                mLogTs.tv_sec = 0;
                mLogTs.tv_nsec = 0;
            }
        }
        struct timespec req;
        req.tv_sec = 0;
        req.tv_nsec = mPeriodNs;
        rc = nanosleep(&req, NULL);
        if (!((rc == 0) || (rc == -1 && errno == EINTR))) {
            pause();
            return false;
        }
        return true;
    }
    
    void AudioWatchdog::requestExit()
    {
        // must be in this order to avoid a race condition
        Thread::requestExit();
        resume();
    }
    
    void AudioWatchdog::pause()
    {
        AutoMutex _l(mMyLock);
        mPaused = true;
    }
    
    void AudioWatchdog::resume()
    {
        AutoMutex _l(mMyLock);
        if (mPaused) {
            mPaused = false;
            mMyCond.signal();
        }
    }
    
    }   // namespace android

    非常明显,它的核心方法就是threadLoop(),在本文中我们不关心它具体的功能。仅仅想确定它是怎么启动的呢?又是怎么循环执行的呢?带着疑问我又在源代码中搜索关键字AudioWatchdog
    结果发现有两个地方引用了。

    /frameworks/av/services/audioflinger/AudioFlinger.h
    /frameworks/av/services/audioflinger/AudioFlinger.cpp

    在AudioFlinger.h中MixerThread中有个AudioWatchdog的sp对象

    
     class MixerThread : public PlaybackThread {
        public:
            MixerThread (const sp<AudioFlinger>& audioFlinger,
                         AudioStreamOut* output,
                         audio_io_handle_t id,
                         audio_devices_t device,
                         type_t type = MIXER);
            virtual             ~MixerThread();
    
    
    
    
    
        protected:
    
    
                        AudioMixer* mAudioMixer;    // normal mixer
        private:
    
                        sp<AudioWatchdog> mAudioWatchdog; // non-0 if there is an audio watchdog thread
    
    
        };
    

    我们再看代码
    /frameworks/av/services/audioflinger/AudioFlinger.cpp

    AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
            audio_io_handle_t id, audio_devices_t device, type_t type)
        :   PlaybackThread(audioFlinger, output, id, device, type),
            // mAudioMixer below
            // mFastMixer below
            mFastMixerFutex(0)
            // mOutputSink below
            // mPipeSink below
            // mNormalSink below
    {
    
    ......
    #ifdef AUDIO_WATCHDOG
            // create and start the watchdog
            mAudioWatchdog = new AudioWatchdog();
            mAudioWatchdog->setDump(&mAudioWatchdogDump);
            //AudioWatchdog的run方法在此调用,所以线程启动
            mAudioWatchdog->run("AudioWatchdog", PRIORITY_URGENT_AUDIO);
            tid = mAudioWatchdog->getTid();
            err = requestPriority(getpid_cached, tid, kPriorityFastMixer);
            if (err != 0) {
                ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d",
                        kPriorityFastMixer, getpid_cached, tid, err);
            }
    #endif
    
    ......
    }

    删掉不相关代码,我们看到AudioWatchdog对象确实创建了,而且调用了它的run方法。在java中Thread的run方法就是启动,这个也应该如此。可是如之前的源代码所看到的AudioWatchdog.cpp中并没有实现run方法,怎么办呢?别紧张,它还有父类Thread.

    /frameworks/native/include/utils/Thread.h

    
    #ifndef _LIBS_UTILS_THREAD_H
    #define _LIBS_UTILS_THREAD_H
    
    #include <stdint.h>
    #include <sys/types.h>
    #include <time.h>
    
    #if defined(HAVE_PTHREADS)
    # include <pthread.h>
    #endif
    
    #include <utils/Condition.h>
    #include <utils/Errors.h>
    #include <utils/Mutex.h>
    #include <utils/RefBase.h>
    #include <utils/Timers.h>
    #include <utils/ThreadDefs.h>
    
    // ---------------------------------------------------------------------------
    namespace android {
    // ---------------------------------------------------------------------------
    
    class Thread : virtual public RefBase
    {
    public:
        // Create a Thread object, but doesn't create or start the associated
        // thread. See the run() method.
                            Thread(bool canCallJava = true);
        virtual             ~Thread();
    
        // Start the thread in threadLoop() which needs to be implemented.
        virtual status_t    run(    const char* name = 0,
                                    int32_t priority = PRIORITY_DEFAULT,
                                    size_t stack = 0);
    
        // Ask this object's thread to exit. This function is asynchronous, when the
        // function returns the thread might still be running. Of course, this
        // function can be called from a different thread.
        virtual void        requestExit();
    
        // Good place to do one-time initializations
        virtual status_t    readyToRun();
    
        // Call requestExit() and wait until this object's thread exits.
        // BE VERY CAREFUL of deadlocks. In particular, it would be silly to call
        // this function from this object's thread. Will return WOULD_BLOCK in
        // that case.
                status_t    requestExitAndWait();
    
        // Wait until this object's thread exits. Returns immediately if not yet running.
        // Do not call from this object's thread; will return WOULD_BLOCK in that case.
                status_t    join();
    
    #ifdef HAVE_ANDROID_OS
        // Return the thread's kernel ID, same as the thread itself calling gettid() or
        // androidGetTid(), or -1 if the thread is not running.
                pid_t       getTid() const;
    #endif
    
    protected:
        // exitPending() returns true if requestExit() has been called.
                bool        exitPending() const;
    
    private:
        // Derived class must implement threadLoop(). The thread starts its life
        // here. There are two ways of using the Thread object:
        // 1) loop: if threadLoop() returns true, it will be called again if
        //          requestExit() wasn't called.
        // 2) once: if threadLoop() returns false, the thread will exit upon return.
        virtual bool        threadLoop() = 0;
    
    private:
        Thread& operator=(const Thread&);
        static  int             _threadLoop(void* user);
        const   bool            mCanCallJava;
        // always hold mLock when reading or writing
                thread_id_t     mThread;
        mutable Mutex           mLock;
                Condition       mThreadExitedCondition;
                status_t        mStatus;
        // note that all accesses of mExitPending and mRunning need to hold mLock
        volatile bool           mExitPending;
        volatile bool           mRunning;
                sp<Thread>      mHoldSelf;
    #ifdef HAVE_ANDROID_OS
        // legacy for debugging, not used by getTid() as it is set by the child thread
        // and so is not initialized until the child reaches that point
                pid_t           mTid;
    #endif
    };
    
    
    }; // namespace android
    
    // ---------------------------------------------------------------------------
    #endif // _LIBS_UTILS_THREAD_H
    // 

    能够看到确实有run方法。那以下看看它的实现

    status_t Thread::run(const char* name, int32_t priority, size_t stack)
    {
        Mutex::Autolock _l(mLock);
    
        if (mRunning) {
            // thread already started
            return INVALID_OPERATION;
        }
    
        // reset status and exitPending to their default value, so we can
        // try again after an error happened (either below, or in readyToRun())
        mStatus = NO_ERROR;
        mExitPending = false;
        mThread = thread_id_t(-1);
    
        // hold a strong reference on ourself
        mHoldSelf = this;
    
        mRunning = true;
    
        bool res;
        if (mCanCallJava) {
            res = createThreadEtc(_threadLoop,
                    this, name, priority, stack, &mThread);
        } else {
            res = androidCreateRawThreadEtc(_threadLoop,
                    this, name, priority, stack, &mThread);
        }
    
        if (res == false) {
            mStatus = UNKNOWN_ERROR;   // something happened!
            mRunning = false;
            mThread = thread_id_t(-1);
            mHoldSelf.clear();  // "this" may have gone away after this.
    
            return UNKNOWN_ERROR;
        }
    
        // Do not refer to mStatus here: The thread is already running (may, in fact
        // already have exited with a valid mStatus result). The NO_ERROR indication
        // here merely indicates successfully starting the thread and does not
        // imply successful termination/execution.
        return NO_ERROR;
    
        // Exiting scope of mLock is a memory barrier and allows new thread to run
    }
    
    

    run()方法中有这么一段

    if (mCanCallJava) {
            res = createThreadEtc(_threadLoop,
                    this, name, priority, stack, &mThread);
        } else {
            res = androidCreateRawThreadEtc(_threadLoop,
                    this, name, priority, stack, &mThread);
        }

    mCanCallJava的意思是能不能被JNI层调用,然后依据值去创建Thread,这里有两个分支,我们就选择createThreadEtc()
    终于代码会走到这里

    int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
                                   void *userData,
                                   const char* threadName,
                                   int32_t threadPriority,
                                   size_t threadStackSize,
                                   android_thread_id_t *threadId)
    {
        ......
            entryFunction = (android_thread_func_t)&thread_data_t::trampoline;
            userData = t;
        }
    #endif
    
        if (threadStackSize) {
            pthread_attr_setstacksize(&attr, threadStackSize);
        }
    
        errno = 0;
        pthread_t thread;
        //在此创建,文章开头我有写样例怎么用c语言创建一个线程
        int result = pthread_create(&thread, &attr,
                        (android_pthread_entry)entryFunction, userData);
        pthread_attr_destroy(&attr);
        if (result != 0) {
            ALOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)
    "
                 "(android threadPriority=%d)",
                entryFunction, result, errno, threadPriority);
            return 0;
        }
    
        ......
        return 1;
    }

    删除了不相关代码,大家看看是不是非常熟悉啊。我在文章開始的部分就写出了linux下c语言pthread创建线程的样例,大家能够回头看看。也就是pthread_create()

    这里面传进来的entryFunction是Thread中的_threadLoop()

    int Thread::_threadLoop(void* user)
    {
        Thread* const self = static_cast<Thread*>(user);
    
        sp<Thread> strong(self->mHoldSelf);
        wp<Thread> weak(strong);
        self->mHoldSelf.clear();
    
    #ifdef HAVE_ANDROID_OS
        // this is very useful for debugging with gdb
        self->mTid = gettid();
    #endif
    
        bool first = true;
    
        do {
            bool result;
            if (first) {
                first = false;
                self->mStatus = self->readyToRun();
                result = (self->mStatus == NO_ERROR);
    
                if (result && !self->exitPending()) {
                    // Binder threads (and maybe others) rely on threadLoop
                    // running at least once after a successful ::readyToRun()
                    // (unless, of course, the thread has already been asked to exit
                    // at that point).
                    // This is because threads are essentially used like this:
                    //   (new ThreadSubclass())->run();
                    // The caller therefore does not retain a strong reference to
                    // the thread and the thread would simply disappear after the
                    // successful ::readyToRun() call instead of entering the
                    // threadLoop at least once.
                    //调用threadLoop()
                    result = self->threadLoop();
                }
            } else {
                result = self->threadLoop();
            }
    
            // establish a scope for mLock
            {
            Mutex::Autolock _l(self->mLock);
            if (result == false || self->mExitPending) {
                self->mExitPending = true;
                self->mRunning = false;
                // clear thread ID so that requestExitAndWait() does not exit if
                // called by a new thread using the same thread ID as this one.
                self->mThread = thread_id_t(-1);
                // note that interested observers blocked in requestExitAndWait are
                // awoken by broadcast, but blocked on mLock until break exits scope
                self->mThreadExitedCondition.broadcast();
                break;
            }
            }
    
            // Release our strong reference, to let a chance to the thread
            // to die a peaceful death.
            strong.clear();
            // And immediately, re-acquire a strong reference for the next loop
            strong = weak.promote();
        } while(strong != 0);
    
        return 0;
    }

    _threadLoop()这种方法就是Thread的最大秘密,它是一个while循环。

    1、创建线程时。会sp和wp一次线程本身。


    2、假设是第一次执行会执行线程的readyToRun()方法,再执行threadLoop(),否则,直接执行threadLoop()。
    3、threadLoop()方法有返回值,假设threadLoop()返回false的时候,线程会做清理工作。然后退出while循环,结束执行。

    所以在这里。我開始时的疑问—为什么线程Thread中的threadLoop()能够循环处理数据就到此做了说明。
    Thread被创建,
    Thread中的run被调用。
    __threadLoop()被调用,
    readyToRun()被调用。
    然后循环调用threadLoop()。


    而且在threadLoop()返回false时。能够退出循环。

    !!
    !!!
    还有。最关键的一点是threadLoop能够循环事实上是由于调用它的_threadLoop()方法里面有一个while循环

    特殊情况

    有的时候Android Framework中Thread的run()方法非常难发如今哪里被调用。如SurfaceFlinger它也是一个Thread子类。

    在源代码中搜索能够发现它的创建位置

    class SurfaceFlinger : public BinderService<SurfaceFlinger>,
                           public BnSurfaceComposer,
                           private IBinder::DeathRecipient,
                           private Thread,
                           private HWComposer::EventHandler
    {
    public:
        static char const* getServiceName() {
            return "SurfaceFlinger";
        }
    
        SurfaceFlinger();
    
    
        /* ------------------------------------------------------------------------
         * Thread interface
         */
        virtual bool threadLoop();
        virtual status_t readyToRun();
        virtual void onFirstRef();
    
    
    };
    
    // ---------------------------------------------------------------------------
    }; // namespace android
    
    #endif // ANDROID_SURFACE_FLINGER_H

    去找它创建的地方
    /frameworks/base/cmds/system_server/library/system_init.cpp

    extern "C" status_t system_init()
    {
        ALOGI("Entered system_init()");
    
        sp<ProcessState> proc(ProcessState::self());
    
        sp<IServiceManager> sm = defaultServiceManager();
        ALOGI("ServiceManager: %p
    ", sm.get());
    
    
    
        char propBuf[PROPERTY_VALUE_MAX];
        property_get("system_init.startsurfaceflinger", propBuf, "1");
        if (strcmp(propBuf, "1") == 0) {
            // Start the SurfaceFlinger
            SurfaceFlinger::instantiate();
        }
    
    
        // And now start the Android runtime.  We have to do this bit
        // of nastiness because the Android runtime initialization requires
        // some of the core system services to already be started.
        // All other servers should just start the Android runtime at
        // the beginning of their processes's main(), before calling
        // the init function.
        ALOGI("System server: starting Android runtime.
    ");
        AndroidRuntime* runtime = AndroidRuntime::getRuntime();
    
        ALOGI("System server: starting Android services.
    ");
        JNIEnv* env = runtime->getJNIEnv();
        if (env == NULL) {
            return UNKNOWN_ERROR;
        }
        jclass clazz = env->FindClass("com/android/server/SystemServer");
        if (clazz == NULL) {
            return UNKNOWN_ERROR;
        }
        jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");
        if (methodId == NULL) {
            return UNKNOWN_ERROR;
        }
        env->CallStaticVoidMethod(clazz, methodId);
    
        ALOGI("System server: entering thread pool.
    ");
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
        ALOGI("System server: exiting thread pool.
    ");
    
        return NO_ERROR;
    }

    我们能够看到

     SurfaceFlinger::instantiate();

    但它本身并没有实现instantiate()方法,那之类找它的父类了。
    /frameworks/native/include/binder/BinderService.h

    namespace android {
    
    template<typename SERVICE>
    class BinderService
    {
    public:
        static status_t publish(bool allowIsolated = false) {
            sp<IServiceManager> sm(defaultServiceManager());
            return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
        }
    
        static void publishAndJoinThreadPool(bool allowIsolated = false) {
            sp<IServiceManager> sm(defaultServiceManager());
            sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
            ProcessState::self()->startThreadPool();
            IPCThreadState::self()->joinThreadPool();
        }
    
        static void instantiate() { publish(); }
    
        static status_t shutdown() {
            return NO_ERROR;
        }
    };
    
    
    }; // namespace android
    // ---------------------------------------------------------------------------
    #endif // ANDROID_BINDER_SERVICE_H

    会调用publish()方法。
    而SERVICE在这里是一个模板类。在这里SERVICE自然相应SurfaceFlinger
    所以publish()会向ServiceManager加入一个Service这个Service就是Surfaceflinger。

    然后我们看SurfaceFlinger的构造函数
    /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

    SurfaceFlinger::SurfaceFlinger()
        :   BnSurfaceComposer(), Thread(false),
            mTransactionFlags(0),
            mTransactionPending(false),
            mAnimTransactionPending(false),
            mLayersRemoved(false),
            mRepaintEverything(0),
            mBootTime(systemTime()),
            mVisibleRegionsDirty(false),
            mHwWorkListDirty(false),
            mDebugRegion(0),
            mDebugDDMS(0),
            mDebugDisableHWC(0),
            mDebugDisableTransformHint(0),
            mDebugInSwapBuffers(0),
            mLastSwapBufferTime(0),
            mDebugInTransaction(0),
            mLastTransactionTime(0),
            mBootFinished(false)
    {
        ALOGI("SurfaceFlinger is starting");
    
        // debugging stuff...
        char value[PROPERTY_VALUE_MAX];
    
        property_get("debug.sf.showupdates", value, "0");
        mDebugRegion = atoi(value);
    
        property_get("debug.sf.ddms", value, "0");
        mDebugDDMS = atoi(value);
        if (mDebugDDMS) {
            if (!startDdmConnection()) {
                // start failed, and DDMS debugging not enabled
                mDebugDDMS = 0;
            }
        }
        ALOGI_IF(mDebugRegion, "showupdates enabled");
        ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
    }

    可是遗憾的是没有发现run()方法的影踪,没有办法仅仅得去父类构造方法看
    结果发现也没有!

    。。

    没有办法,继续在源代码中搜索SurfaceFlinger。结果发现与之相关的信息大多是sp<SurfaceFlinger>
    就看看sp吧。
    sp是Android在c++中搞得相似java中弱引用、强引用的一套指针概念,那应该是方便回收吧。
    而Android Framework中的c++世界,RefBase这个类有点像java中的Object.
    而sp是一个模板类。

    这部分内容。请看点击以下链接

    Android中的sp和wp指针

    上面的链接讲得还算具体。这里纠结sp的过多细节。长话短说。总之第一次对SurfaceFlinger引用调用sp<SurfaceFlinger>时会调用SurfaceFlinger的onFirstRef()方法。
    那好。看代码吧

    void SurfaceFlinger::onFirstRef()
    {
        mEventQueue.init(this);
        //run方法在此被调用
        run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
    
        // Wait for the main thread to be done with its initialization
        mReadyToRunBarrier.wait();
    }

    看见没有?run()方法在这里调用了。

    所以,在Framework中假设你找不到一个Thread在何处被启动,那么去它的onFirstRef()方法中去看看吧

  • 相关阅读:
    JAVA 正则表达式 (超详细)
    Windows命令-route
    Spring3 MVC请求参数获取的几种方法[转]
    Linux-支持中文
    Linux-Tmux使用初体验
    Linux命令-工作管理命令:&,ctrl+z,jobs,fg,bg
    Linux命令-服务管理命令:chkconfig
    Linux命令-文件系统常用命令:df,du,fsck,dumpe2fs
    Linux命令-用户管理:useradd,userdel,usermod,id,su,env,exit
    Linux命令-某个用户组下面的所有用户
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7388542.html
Copyright © 2011-2022 走看看