Choreographer Init

frameworks/base/core/java/android/view/ViewRootImpl.java

[ViewRootImpl.java–>ViewRootImpl.ViewRootImpl()]

  public ViewRootImpl(Context context, Display display) {        mContext = context;        mWindowSession = WindowManagerGlobal.getWindowSession();        mDisplay = display;        ......        /**           创建Choreographer         */        mChoreographer = Choreographer.getInstance();        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);        loadSystemProperties();    }

/frameworks/base/core/java/android/view/Choreographer.java

[Choreographer.java–>Choreographer.getInstance()]

  /**     * Gets the choreographer for the calling thread.  Must be called from     * a thread that already has a {@link android.os.Looper} associated with it.     *     * @return The choreographer for this thread.     * @throws IllegalStateException if the thread does not have a looper.     */    public static Choreographer getInstance() {        return sThreadInstance.get();    } ``` [Choreographer.java-->Choreographer.sThreadInstance()] ```   // Thread local storage for the choreographer.      private static final ThreadLocal sThreadInstance =              new ThreadLocal() {          @Override          protected Choreographer initialValue() {              Looper looper = Looper.myLooper();              if (looper == null) {                  throw new IllegalStateException("The current thread must have a looper!");              }              return new Choreographer(looper);          }      };

[Choreographer.java–>Choreographer.Choreographer()]

private Choreographer(Looper looper) {           mLooper = looper;           mHandler = new FrameHandler(looper);           mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;           mLastFrameTimeNanos = Long.MIN_VALUE;           mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());           mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];           for (int i = 0; i <= CALLBACK_LAST; i++) {               mCallbackQueues[i] = new CallbackQueue();           }       }

1.mLooper

2.mHandler

3.mDisplayEventReceiver

4.mCallbackQueues

1.mLooper

mLooper = looper –> looper = Looper.myLooper()

/frameworks/base/core/java/android/os/Looper.java

[Looper.java–>Looper.myLooper()]

    /**     * Return the Looper object associated with the current thread.  Returns     * null if the calling thread is not associated with a Looper.     */    /**       返回和当前线程绑定的Looper     */    public static @Nullable Looper myLooper() {        return sThreadLocal.get();    }

2.mHandler

mHandler = new FrameHandler(looper)

/frameworks/base/core/java/android/view/Choreographer.java

[Choreographer.java–>Choreographer.Choreographer().FrameHandler()]

  private final class FrameHandler extends Handler {        public FrameHandler(Looper looper) {            super(looper);        }        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case MSG_DO_FRAME:                    doFrame(System.nanoTime(), 0);                    break;                case MSG_DO_SCHEDULE_VSYNC:                    doScheduleVsync();                    break;                case MSG_DO_SCHEDULE_CALLBACK:                    doScheduleCallback(msg.arg1);                    break;            }        }    }

3.mDisplayEventReceiver

mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;

/frameworks/base/core/java/android/view/Choreographer.java
[Choreographer.java–>FrameDisplayEventReceiver]

    private final class FrameDisplayEventReceiver extends DisplayEventReceiver            implements Runnable {        private boolean mHavePendingVsync;        private long mTimestampNanos;        private int mFrame;        public FrameDisplayEventReceiver(Looper looper) {            super(looper);        }    }

frameworks/base/core/java/android/view/DisplayEventReceiver.java
[DisplayEventReceiver.java–>DisplayEventReceiver()]

    /**     * Creates a display event receiver.     *     * @param looper The looper to use when invoking callbacks.     */    public DisplayEventReceiver(Looper looper) {        if (looper == null) {            throw new IllegalArgumentException("looper must not be null");        }        mMessageQueue = looper.getQueue();        mReceiverPtr = nativeInit(new WeakReference(this), mMessageQueue);        mCloseGuard.open("dispose");    }

/frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp
[android_view_DisplayEventReceiver.cpp–>nativeInit()]

static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,        jobject messageQueueObj) {    /**       1. 获取messageQueue     */    sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);    if (messageQueue == NULL) {        jniThrowRuntimeException(env, "MessageQueue is not initialized.");        return 0;    }    /**      2. 创建一个NativeDisplayEventReceiver     */    sp receiver = new NativeDisplayEventReceiver(env,            receiverWeak, messageQueue);    /**      3. 调用NativeDisplayEventReceiver的initialize函数     */         status_t status = receiver->initialize();    if (status) {        String8 message;        message.appendFormat("Failed to initialize display event receiver.  status=%d", status);        jniThrowRuntimeException(env, message.string());        return 0;    }    receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object    /**       4. 返回一个NativeDisplayEventReceiver     */    return reinterpret_cast(receiver.get());}

3.1 messageQueue

3.2 NativeDisplayEventReceiver

[android_view_DisplayEventReceiver.cpp–>NativeDisplayEventReceiver]

class NativeDisplayEventReceiver : public DisplayEventDispatcher {public:    NativeDisplayEventReceiver(JNIEnv* env,            jobject receiverWeak, const sp& messageQueue);    void dispose();protected:    virtual ~NativeDisplayEventReceiver();private:    jobject mReceiverWeakGlobal;    sp mMessageQueue;    /**       NativeDisplayEventReceiver中有DisplayEventReceiver,则在创建NativeDisplayEventReceiver       对象时调用DisplayEventReceiver的构造方法     */    DisplayEventReceiver mReceiver;    bool mWaitingForVsync;    virtual void dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count);    virtual void dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected);};

/frameworks/native/libs/gui/DisplayEventReceiver.cpp
[DisplayEventReceiver.cpp–>DisplayEventReceiver()]

DisplayEventReceiver::DisplayEventReceiver() {    /**       1. 创建ISurfaceComposer     */    sp sf(ComposerService::getComposerService());    if (sf != NULL) {        /**           2. 调用ISurfaceComposer的createDisplayEventConnection()函数创建EventConnection         */        mEventConnection = sf->createDisplayEventConnection();        if (mEventConnection != NULL) {            /**               3. 调用getDataChannel函数,mDataChannel对应的是BitTube             */            mDataChannel = mEventConnection->getDataChannel();        }    }}

3.1.1ComposerService

/frameworks/native/include/private/gui/ComposerService.h
[ComposerService.h]

class ComposerService : public Singleton{    sp mComposerService;    sp mDeathObserver;    Mutex mLock;    ComposerService();    void connectLocked();    void composerServiceDied();    friend class Singleton;public:    // Get a connection to the Composer Service.  This will block until    // a connection is established.    static sp getComposerService();};

/frameworks/native/libs/gui/SurfaceComposerClient.cpp
[SurfaceComposerClient.cpp]

/**   ComposerService单例模式,在/system/core/include/utils/Singleton.h中有定义 */ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService);/**   ComposerService构造函数,调用connectLocked()函数 */ComposerService::ComposerService(): Singleton() {    Mutex::Autolock _l(mLock);    connectLocked();}/**   获取mComposerService,即SurfaceFlinger服务的连接 */void ComposerService::connectLocked() {    const String16 name("SurfaceFlinger");    /**       >sp mComposerService;       getService将mComposerService实例化成一个BpSurfaceComposer对象,定义在ISurfaceComposer.cpp中       其中这里的BpSurfaceComposer已经获得了SurfaceFlinger的service的在binder驱动中的handle值       mComposerService是一个 BpSurfaceComposer(new BpBinder(handle))对象        >getService是从ServiceManager进程中查找"SurfaceFlinger"的Binder对应的handle值,       返回的out型参数mComposerService对应的就是"SurfaceFlinger" binder 服务端的客户端Binder对象,通过这个       mComposerService就可以和"SurfaceFlinger"进行通信     */    while (getService(name, &mComposerService) != NO_ERROR) {        usleep(250000);    }    assert(mComposerService != NULL);    // Create the death listener.    class DeathObserver : public IBinder::DeathRecipient {        ComposerService& mComposerService;        virtual void binderDied(const wp& who) {            ALOGW("ComposerService remote (surfaceflinger) died [%p]",                  who.unsafe_get());            mComposerService.composerServiceDied();        }     public:        DeathObserver(ComposerService& mgr) : mComposerService(mgr) { }    };    mDeathObserver = new DeathObserver(*const_cast(this));    IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver);}/*static*/ sp ComposerService::getComposerService() {    /**       static方法获取单例模式下的BpSurfaceComposer(new BpBinder(handle))对象     */    ComposerService& instance = ComposerService::getInstance();    Mutex::Autolock _l(instance.mLock);    if (instance.mComposerService == NULL) {        ComposerService::getInstance().connectLocked();        assert(instance.mComposerService != NULL);        ALOGD("ComposerService reconnected");    }    return instance.mComposerService;}void ComposerService::composerServiceDied(){    Mutex::Autolock _l(mLock);    mComposerService = NULL;    mDeathObserver = NULL;}

/frameworks/native/include/binder/IServiceManager.h
[IServiceManager.h–>IServiceManager::getService()]

templatestatus_t getService(const String16& name, sp* outService){    /**       defaultServiceManager返回的进程范围内唯一的BpServiceManager,即       sm = new BpServiceManager(new BpBinder(0));     */    const sp sm = defaultServiceManager();    if (sm != NULL) {        /**            sm->getService(name): 会调用BpServiceManager中的getService函数,            经过binder驱动程序和service_manager守护进程进行通信,得到service名            称为name的service的handle值,返回的是一个BpBinder(handle)         */         /**            interface_cast(new BpBinder(handle))会创建一个BpINTERFACE对象,           */        *outService = interface_cast(sm->getService(name));        if ((*outService) != NULL) return NO_ERROR;    }    return NAME_NOT_FOUND;}

sm返回的是一个BpServiceManager对象,该对象是一个Binder的客户端,也就是Service_Manager
服务守护进程的Bp客户端,相当于是BpServiceManager(new BpBinder(0)),根据前面的服务名称
”SurfaceFlinger”,最终outService返回的是一个BpSurfaceComposer对象

/frameworks/native/services/surfaceflinger/SurfaceFlinger.h

[SurfaceFlinger.h]

 /**    SurfaceFlinger是BnSurfaceComposer的实现者,因此ComposerService::getComposerService()获取的服务,即是SurfaceFlinger  */class SurfaceFlinger : public BnSurfaceComposer,                       private IBinder::DeathRecipient,                       private HWComposer::EventHandler{

ComposerService::getComposerService()返回的是一个与SurfaceFlinger进程建立Binder进程通信的客户端,服务端就SurfaceFlinger对象本身

3.1.2mEventConnection

mEventConnection = sf->createDisplayEventConnection();

/frameworks/native/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
[SurfaceFlinger_hwc1.cpp–>SurfaceFlinger_hwc1::createDisplayEventConnection()]

/**    返回DisplayEventReceiver构造函数中的mEventConnection是一个BpDisplayEventConnection对象 */sp SurfaceFlinger::createDisplayEventConnection() {    return mEventThread->createEventConnection();}

/frameworks/native/services/surfaceflinger/EventThread.cpp

[EventThread.cpp–>EventThread::createEventConnection()]

sp EventThread::createEventConnection() const {    return new Connection(const_cast(this));}

[EventThread.cpp–>EventThread::Connection::Connection()]

/**   onnection的构造函数会创建一个BitTube对象,BitTube对象中包含一对互联的socket,   一端发送另一端就能收到。并将BitTube对象存储在EventThread::Connection.mChannel里面 */EventThread::Connection::Connection(        const sp& eventThread)    : count(-1), mEventThread(eventThread), mChannel(new BitTube()){}

frameworks/native/libs/gui/BitTube.cpp
[BitTube.cpp–>BitTube::BitTube()]

static const size_t DEFAULT_SOCKET_BUFFER_SIZE = 4 * 1024;BitTube::BitTube()    : mSendFd(-1), mReceiveFd(-1){    init(DEFAULT_SOCKET_BUFFER_SIZE, DEFAULT_SOCKET_BUFFER_SIZE);}

[BitTube.cpp–>BitTube::init()]

void BitTube::init(size_t rcvbuf, size_t sndbuf) {    int sockets[2];    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {        size_t size = DEFAULT_SOCKET_BUFFER_SIZE;        setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));        setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));        // sine we don't use the "return channel", we keep it small...        setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));        setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));        fcntl(sockets[0], F_SETFL, O_NONBLOCK);        fcntl(sockets[1], F_SETFL, O_NONBLOCK);        mReceiveFd = sockets[0];        mSendFd = sockets[1];    } else {        mReceiveFd = -errno;        ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));    }}

/frameworks/native/services/surfaceflinger/EventThread.h
[EventThread.h–>EventThread]

class EventThread : public Thread, private VSyncSource::Callback {    /**       Connection是一个BnDisplayEventConnection对象     */    class Connection : public BnDisplayEventConnection {    public:        Connection(const sp& eventThread);        status_t postEvent(const DisplayEventReceiver::Event& event);        // count >= 1 : continuous event. count is the vsync rate        // count == 0 : one-shot event that has not fired        // count ==-1 : one-shot event that fired this round / disabled        int32_t count;    private:        virtual ~Connection();        virtual void onFirstRef();        virtual sp getDataChannel() const;        virtual void setVsyncRate(uint32_t count);        virtual void requestNextVsync();    // asynchronous        sp const mEventThread;        /**           mChannel是一个BitTube         */        sp const mChannel;    };

3.1.3mDataChannel

mDataChannel= mEventConnection->getDataChannel();
BpDisplayEventConnection.getDataChannel() //IDisplayEventConnection.cpp –>BnDisplayEventConnection.onTransact //IDisplayEventConnection.cpp
–>EventThread::Connection.getDataChannel() //EventThread.cpp

/frameworks/native/services/surfaceflinger/EventThread.cpp

sp<BitTube> EventThread::Connection::getDataChannel() const {    return mChannel;}

[BnDisplayEventConnection.onTransact //IDisplayEventConnection.cpp]

status_t BnDisplayEventConnection::onTransact(    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){    switch(code) {        case GET_DATA_CHANNEL: {            /**               调用Connection.getDataChannel()函数返回前面创建的BitTube对象:             */            CHECK_INTERFACE(IDisplayEventConnection, data, reply);            sp channel(getDataChannel());            channel->writeToParcel(reply);            return NO_ERROR;        }        case SET_VSYNC_RATE: {            CHECK_INTERFACE(IDisplayEventConnection, data, reply);            setVsyncRate(data.readUint32());            return NO_ERROR;        }        case REQUEST_NEXT_VSYNC: {            CHECK_INTERFACE(IDisplayEventConnection, data, reply);            requestNextVsync();            return NO_ERROR;        }    }    return BBinder::onTransact(code, data, reply, flags);}

/frameworks/native/libs/gui/BitTube.cpp
[BitTube.cpp–>BitTube::writeToParcel()]

status_t BitTube::writeToParcel(Parcel* reply) const{    if (mReceiveFd < 0)        return -EINVAL;    status_t result = reply->writeDupFileDescriptor(mReceiveFd);    close(mReceiveFd);    mReceiveFd = -1;    return result;}

[BpDisplayEventConnection.getDataChannel() //IDisplayEventConnection.cpp]

    virtual sp<BitTube> getDataChannel() const    {        Parcel data, reply;        data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());        remote()->transact(GET_DATA_CHANNEL, data, &reply);        return new BitTube(reply);    }

frameworks/native/libs/gui/BitTube.cpp
[BitTube.cpp–>BitTube::BitTube(const Parcel& data)]

/**   构造函数从Parcel中读取前面在SurfaceFlinger进程中写入的socket接收端的描述符 */BitTube::BitTube(const Parcel& data)    : mSendFd(-1), mReceiveFd(-1){    mReceiveFd = dup(data.readFileDescriptor());    if (mReceiveFd < 0) {        mReceiveFd = -errno;        ALOGE("BitTube(Parcel): can't dup filedescriptor (%s)",                strerror(-mReceiveFd));    }}

native层的NativeDisplayEventReceiver对象已经创建结束,这时候客户端进程已经有了一个和SurfaceFlinger服务端相连的socket接收端描述符

3.3 NativeDisplayEventReceiver->initialize()

/frameworks/base/libs/androidfw/DisplayEventDispatcher.cpp
[DisplayEventDispatcher.cpp–>DisplayEventDispatcher::initialize()]

status_t DisplayEventDispatcher::initialize() {    status_t result = mReceiver.initCheck();    if (result) {        ALOGW("Failed to initialize display event receiver, status=%d", result);        return result;    }    /**       参数mReceiver.getFd()返回的是在创建NativeDisplayEventReceiver时从SurfaceFlinger服务端接收回来的socket接收端描述符     */    int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,            this, NULL);    if (rc < 0) {        return UNKNOWN_ERROR;    }    return OK;}

/system/core/libutils/Looper.cpp

[Looper.cpp–>Looper::addFd()]

int Looper::addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data) {   /**      将上面传进来的NativeDisplayEventReceiver对象封装成一个SimpleLooperCallback对象    */    return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : NULL, data);}int Looper::addFd(int fd, int ident, int events, const sp& callback, void* data) {#if DEBUG_CALLBACKS    ALOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident,            events, callback.get(), data);#endif    if (!callback.get()) {        if (! mAllowNonCallbacks) {            ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");            return -1;        }        if (ident < 0) {            ALOGE("Invalid attempt to set NULL callback with ident < 0.");            return -1;        }    } else {        ident = POLL_CALLBACK;    }    { // acquire lock        AutoMutex _l(mLock);        Request request;        request.fd = fd;        request.ident = ident;        request.events = events;        request.seq = mNextRequestSeq++;        request.callback = callback;        request.data = data;        if (mNextRequestSeq == -1) mNextRequestSeq = 0; // reserve sequence number -1        /**           1. 创建一个struct epoll_event结构体对象,将对应的内存全部用清0,并作对应的初始化         */        struct epoll_event eventItem;        request.initEventItem(&eventItem);        /**           2. 查询通过addFd方法已经添加到epoll中监听的文件描述符         */        ssize_t requestIndex = mRequests.indexOfKey(fd);        if (requestIndex < 0) {            /**                查询不到的话,则调用epoll_ctl方法设置EPOLL_CTL_ADD属性将对应的文件描述符添加到epoll监听的描述符中             */            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);            if (epollResult < 0) {                ALOGE("Error adding epoll events for fd %d: %s", fd, strerror(errno));                return -1;            }            mRequests.add(fd, request);        } else {            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);            if (epollResult < 0) {                if (errno == ENOENT) {                    // Tolerate ENOENT because it means that an older file descriptor was                    // closed before its callback was unregistered and meanwhile a new                    // file descriptor with the same number has been created and is now                    // being registered for the first time.  This error may occur naturally                    // when a callback has the side-effect of closing the file descriptor                    // before returning and unregistering itself.  Callback sequence number                    // checks further ensure that the race is benign.                    //                    // Unfortunately due to kernel limitations we need to rebuild the epoll                    // set from scratch because it may contain an old file handle that we are                    // now unable to remove since its file descriptor is no longer valid.                    // No such problem would have occurred if we were using the poll system                    // call instead, but that approach carries others disadvantages.#if DEBUG_CALLBACKS                    ALOGD("%p ~ addFd - EPOLL_CTL_MOD failed due to file descriptor "                            "being recycled, falling back on EPOLL_CTL_ADD: %s",                            this, strerror(errno));#endif                    epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);                    if (epollResult < 0) {                        ALOGE("Error modifying or adding epoll events for fd %d: %s",                                fd, strerror(errno));                        return -1;                    }                    scheduleEpollRebuildLocked();                } else {                    ALOGE("Error modifying epoll events for fd %d: %s", fd, strerror(errno));                    return -1;                }            }            mRequests.replaceValueAt(requestIndex, request);        }    } // release lock    return 1;}

addFd传入的参数EVENT_INPUT,说明当前应用线程的native层的Looper对象中的epoll机制已经开始监听来自于SurfaceFlinger服务端socket端的写入事件

4.mCallbackQueues

/frameworks/base/core/java/android/view/Choreographer.java
[Choreographer.java]

    /**     * Callback type: Input callback.  Runs first.     * @hide     */    public static final int CALLBACK_INPUT = 0;    /**     * Callback type: Animation callback.  Runs before traversals.     * @hide     */    public static final int CALLBACK_ANIMATION = 1;    /**     * Callback type: Traversal callback.  Handles layout and draw.  Runs     * after all other asynchronous messages have been handled.     * @hide     */    public static final int CALLBACK_TRAVERSAL = 2;    /**     * Callback type: Commit callback.  Handles post-draw operations for the frame.     * Runs after traversal completes.  The {@link #getFrameTime() frame time} reported     * during this callback may be updated to reflect delays that occurred while     * traversals were in progress in case heavy layout operations caused some frames     * to be skipped.  The frame time reported during this callback provides a better     * estimate of the start time of the frame in which animations (and other updates     * to the view hierarchy state) actually took effect.     * @hide     */    public static final int CALLBACK_COMMIT = 3;    private static final int CALLBACK_LAST = CALLBACK_COMMIT;
           mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];           for (int i = 0; i <= CALLBACK_LAST; i++) {               mCallbackQueues[i] = new CallbackQueue();           }

[Choreographer.java–>CallbackQueue]

private final class CallbackQueue {        private CallbackRecord mHead;        public boolean hasDueCallbacksLocked(long now) {            return mHead != null && mHead.dueTime <= now;        }        public CallbackRecord extractDueCallbacksLocked(long now) {            CallbackRecord callbacks = mHead;            if (callbacks == null || callbacks.dueTime > now) {                return null;            }            CallbackRecord last = callbacks;            CallbackRecord next = last.next;            while (next != null) {                if (next.dueTime > now) {                    last.next = null;                    break;                }                last = next;                next = next.next;            }            mHead = next;            return callbacks;        }        public void addCallbackLocked(long dueTime, Object action, Object token) {            CallbackRecord callback = obtainCallbackLocked(dueTime, action, token);            CallbackRecord entry = mHead;            if (entry == null) {                mHead = callback;                return;            }            if (dueTime < entry.dueTime) {                callback.next = entry;                mHead = callback;                return;            }            while (entry.next != null) {                if (dueTime < entry.next.dueTime) {                    callback.next = entry.next;                    break;                }                entry = entry.next;            }            entry.next = callback;        }        public void removeCallbacksLocked(Object action, Object token) {            CallbackRecord predecessor = null;            for (CallbackRecord callback = mHead; callback != null;) {                final CallbackRecord next = callback.next;                if ((action == null || callback.action == action)                        && (token == null || callback.token == token)) {                    if (predecessor != null) {                        predecessor.next = next;                    } else {                        mHead = next;                    }                    recycleCallbackLocked(callback);                } else {                    predecessor = callback;                }                callback = next;            }        }    }

[Choreographer.java–>CallbackRecord]

    private static final class CallbackRecord {        public CallbackRecord next;        public long dueTime;        public Object action; // Runnable or FrameCallback        public Object token;        public void run(long frameTimeNanos) {            if (token == FRAME_CALLBACK_TOKEN) {                ((FrameCallback)action).doFrame(frameTimeNanos);            } else {                ((Runnable)action).run();            }        }    }

UML图


Choreographer Init UML

更多相关文章

  1. AndroidAndroid程序提示和消息button响应事件
  2. Android基础笔记(四)-数据存储和界面展现
  3. android:layout_gravity和android:gravity的区别
  4. android:layout_gravity 和 android:gravity 的区别
  5. android:layout_gravity和android:gravity的区别
  6. android:layout_gravity和android:gravity的区别
  7. Android应用程序进程启动过程(后篇)
  8. Android开发实战-项目学习笔记(2)
  9. Android(安卓)对象序列化之 Parcelable 取代 Serializable ?

随机推荐

  1. Sql Server如何查看被锁的表及解锁的方法
  2. SQL2000安装后,SQL Server组无项目解决方
  3. sql server 编译与重编译详解
  4. SQL Server通过重建方式还原master数据库
  5. SQL查询数据库中符合条件的记录的总数
  6. Sql Server2016 正式版安装程序图解教程
  7. Windows Server2008 R2 MVC 环境安装配置
  8. sql server 2012安装程序图集
  9. SqlServer编写数据库表的操作方式(建库、
  10. SQL Server纵表与横表相互转换的方法