Android13 DisplayEventDispatcher handleEvent流程分析

SurfaceFlinger 进程中请求到 VSync 信号,并且封装成 Event 事件后回调给 EventThread 进行分发,EventThread 将数据通过文件描述符 mSendFd 关联的 socket 管道发送到一段指定大小的缓冲区中,现在应用进程端需要通过文件描述符 mReceiveFd 关联的 socket 管道从指定的缓冲区中读取出数据。

当 socket 管道的 mSendFd 端有数据写入时,就会把与之对应的 mReceiveFd 有关的 Request 取出并收集起来,待 Native 层的 Message 处理完后,循环遍历收集起来的 Request,取出每个 Request 并调用其 callback 回调的 handleEvent() 方法。该回调就是向 Looper 中添加 fd 时作为 LooperCallback 回调一并传入的 DisplayEventDispatcher 实现类,查看实现类的 handleEvent() 方法,代码如下:

//frameworks/native/libs/gui/DisplayEventDispatcher.cpp
int DisplayEventDispatcher::handleEvent(int, int events, void*) {
    if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
        ALOGE("Display event receiver pipe was closed or an error occurred.  "
              "events=0x%x",
              events);
 // 管道关闭或者出现了错误,则移除回调
        return 0; // remove the callback
    }


    if (!(events & Looper::EVENT_INPUT)) {
        ALOGW("Received spurious callback for unhandled poll event.  "
              "events=0x%x",
              events);
 // 收到未处理轮询事件的伪造事件 Event(前面分析过为了防止驱动程序停止),则保留回调
        return 1; // keep the callback
    }


    // Drain all pending events, keep the last vsync.
    // 清空所有挂起的事件,只保留最近一次 VSync 事件
    nsecs_t vsyncTimestamp;
    PhysicalDisplayId vsyncDisplayId;
    uint32_t vsyncCount;
    VsyncEventData vsyncEventData;
    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) {
        ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64
              ", displayId=%s, count=%d, vsyncId=%" PRId64,
              this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount,
              vsyncEventData.preferredVsyncId());
        // 获取到最近的 VSync 信息,将正在等待 VSync 标志位置为 false
        mWaitingForVsync = false;
        mLastVsyncCount = vsyncCount;


 // 由于 DisplayEventDispatcher 类没有复写 dispatchVsync 方法,在其子类NativeDisplayEventReceiver 中复写了该方法
        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
    }


    if (mWaitingForVsync) {
        const nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
        const nsecs_t vsyncScheduleDelay = currentTime - mLastScheduleVsyncTime;
        if (vsyncScheduleDelay > WAITING_FOR_VSYNC_TIMEOUT) {
            ALOGW("Vsync time out! vsyncScheduleDelay=%" PRId64 "ms", ns2ms(vsyncScheduleDelay));
            mWaitingForVsync = false;
            dispatchVsync(currentTime, vsyncDisplayId /* displayId is not used */,
                          ++mLastVsyncCount, vsyncEventData /* empty data */);
        }
    }


    return 1; // keep the callback
}

调用NativeDisplayEventReceiver的dispatchVsync方法:

//frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId,
                                               uint32_t count, VsyncEventData vsyncEventData) {
    // 获取 JNI 上下文环境
    JNIEnv* env = AndroidRuntime::getJNIEnv();


    ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
    if (receiverObj.get()) {
        ALOGV("receiver %p ~ Invoking vsync handler.", this);


        jobject javaVsyncEventData = createJavaVsyncEventData(env, vsyncEventData);
 // 通过 JNI 方法调用,调用 Java 层 DisplayEventReceiver 的 dispatchVsync() 方法,参数传入对应的时间戳、显示屏 Id、VSync 个数、帧间隔等信息
        env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchVsync,
                            timestamp, displayId.value, count, javaVsyncEventData);
        ALOGV("receiver %p ~ Returned from vsync handler.", this);
    }


    mMessageQueue->raiseAndClearException(env, "dispatchVsync");
}

DisplayEventReceiver dispatchVsync

调用DisplayEventReceiver的dispatchVsync方法:

//frameworks/base/core/java/android/view/DisplayEventReceiver.java
public abstract class DisplayEventReceiver {
    private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame,
            VsyncEventData vsyncEventData) {
        onVsync(timestampNanos, physicalDisplayId, frame, vsyncEventData);
    }
}

调用onVsync方法,DisplayEventReceiver 是一个抽象类,onVsync() 方法是一个空方法,因此需要进入其实现类 FrameDisplayEventReceiver 中查看:

//frameworks/base/core/java/android/view/Choreographer.java
public final class Choreographer {
    private final class FrameDisplayEventReceiver extends DisplayEventReceiver
            implements Runnable {
        @Override
        public void onVsync(long timestampNanos, long physicalDisplayId, int frame,
                VsyncEventData vsyncEventData) {
            try {
                if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
                    Trace.traceBegin(Trace.TRACE_TAG_VIEW,
                            "Choreographer#onVsync "
                                    + vsyncEventData.preferredFrameTimeline().vsyncId);
                }
                // Post the vsync event to the Handler.
                // The idea is to prevent incoming vsync events from completely starving
                // the message queue.  If there are no messages in the queue with timestamps
                // earlier than the frame time, then the vsync event will be processed immediately.
                // Otherwise, messages that predate the vsync event will be handled first.
                long now = System.nanoTime();
                if (timestampNanos > now) {
                    Log.w(TAG, "Frame time is " + ((timestampNanos - now) * 0.000001f)
                            + " ms in the future!  Check that graphics HAL is generating vsync "
                            + "timestamps using the correct timebase.");
                    timestampNanos = now;
                }


                if (mHavePendingVsync) {
                    Log.w(TAG, "Already have a pending vsync event.  There should only be "
                            + "one at a time.");
                } else {
                    mHavePendingVsync = true;
                }


                mTimestampNanos = timestampNanos;
                mFrame = frame;
                mLastVsyncEventData = vsyncEventData;
                Message msg = Message.obtain(mHandler, this);
                msg.setAsynchronous(true);
                mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
            }
        }
    }
}

在该方法中通过 Message的obtain() 方法获取到 Message,由 FrameHandler 发送消息并执行获取消息时传入的回调。由于获取消息时传入的回调是 FrameDisplayEventReceiver 本身,并且实现了 Runnable 接口,因此会回调 FrameDisplayEventReceiver的run() 方法:

//frameworks/base/core/java/android/view/Choreographer.java
public final class Choreographer {
    private final class FrameDisplayEventReceiver extends DisplayEventReceiver
            implements Runnable {
        public void run() {
            mHavePendingVsync = false;
            doFrame(mTimestampNanos, mFrame, mLastVsyncEventData);
        }
    }
}

Choreographer doFrame

调用Choreographer的doFrame方法:

//frameworks/base/core/java/android/view/Choreographer.java
public final class Choreographer {
    void doFrame(long frameTimeNanos, int frame,
            DisplayEventReceiver.VsyncEventData vsyncEventData) {
        final long startNanos;
        final long frameIntervalNanos = vsyncEventData.frameInterval;
        try {
            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
                        "Choreographer#doFrame " + vsyncEventData.preferredFrameTimeline().vsyncId);
            }
            FrameData frameData = new FrameData(frameTimeNanos, vsyncEventData);
            synchronized (mLock) {
                if (!mFrameScheduled) {
                    traceMessage("Frame not scheduled");
                    return; // no work to do
                }


                if (DEBUG_JANK && mDebugPrintNextFrameTimeDelta) {
                    mDebugPrintNextFrameTimeDelta = false;
                    Log.d(TAG, "Frame time delta: "
                            + ((frameTimeNanos - mLastFrameTimeNanos) * 0.000001f) + " ms");
                }


  // 设置将要处理的当前帧的时间戳
                long intendedFrameTimeNanos = frameTimeNanos;
                startNanos = System.nanoTime(); 	// 记录实际开始执行当前 frame 的时间
                final long jitterNanos = startNanos - frameTimeNanos; // 计算时间差值
                if (jitterNanos >= frameIntervalNanos) { // 时间差值大于等于帧间隔,即发生了跳帧
                    long lastFrameOffset = 0; 
                    if (frameIntervalNanos == 0) {
                        Log.i(TAG, "Vsync data empty due to timeout");
                    } else {
          // 计算实际开始当前 frame 的时间戳与帧间隔的偏移值
                        lastFrameOffset = jitterNanos % frameIntervalNanos;
                        final long skippedFrames = jitterNanos / frameIntervalNanos; // 计算跳帧数
                        if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
                            Log.i(TAG, "Skipped " + skippedFrames + " frames!  "
                                    + "The application may be doing too much work on its main "
                                    + "thread.");
                        }
                        if (DEBUG_JANK) {
                            Log.d(TAG, "Missed vsync by " + (jitterNanos * 0.000001f) + " ms "
                                    + "which is more than the frame interval of "
                                    + (frameIntervalNanos * 0.000001f) + " ms!  "
                                    + "Skipping " + skippedFrames + " frames and setting frame "
                                    + "time to " + (lastFrameOffset * 0.000001f)
                                    + " ms in the past.");
                        }
                    }
      // 修正偏移值,下一帧的时间戳开始值要减去计算得出的偏移值
                    frameTimeNanos = startNanos - lastFrameOffset;
                    frameData.updateFrameData(frameTimeNanos);
                }


                if (frameTimeNanos < mLastFrameTimeNanos) {
                    if (DEBUG_JANK) {
                        Log.d(TAG, "Frame time appears to be going backwards.  May be due to a "
                                + "previously skipped frame.  Waiting for next vsync.");
                    }
                    traceMessage("Frame time goes backward");
      // 当前帧的时间小于上一个帧的时间,可能是由于先前跳帧的缘故,申请并等待下一次 VSync 信号到来
                    scheduleVsyncLocked();
                    return;
                }


                if (mFPSDivisor > 1) {
                    long timeSinceVsync = frameTimeNanos - mLastFrameTimeNanos;
                    if (timeSinceVsync < (frameIntervalNanos * mFPSDivisor) && timeSinceVsync > 0) {
                        traceMessage("Frame skipped due to FPSDivisor");
   // 由于 FPSDivisor 导致跳帧,继续申请并等待下一次 VSync 信号到来
                        scheduleVsyncLocked();
                        return;
                    }
                }


  // 记录当前 Frame 信息
                mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos,
                        vsyncEventData.preferredFrameTimeline().vsyncId,
                        vsyncEventData.preferredFrameTimeline().deadline, startNanos,
                        vsyncEventData.frameInterval);
  // 收到 VSync 信号当前帧调度完,mFrameScheduled 标志位重置为 false,以便下一轮请求使用
                mFrameScheduled = false;
                mLastFrameTimeNanos = frameTimeNanos; // 记录上一次 Frame 渲染的时间
                mLastFrameIntervalNanos = frameIntervalNanos; // 记录上一次 Frame 渲染的帧间隔
                mLastVsyncEventData = vsyncEventData; // 记录上一次 VSync 事件信息
            }
     // 动画锁定为当前线程的固定值
            AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);
     // 按照事件类型的优先级执行 CallBack
            mFrameInfo.markInputHandlingStart();
     // 输入事件,首先执行
            doCallbacks(Choreographer.CALLBACK_INPUT, frameData, frameIntervalNanos);


            mFrameInfo.markAnimationsStart();
     // 动画事件,在 CALLBACK_INSETS_ANIMATION 之前执行
            doCallbacks(Choreographer.CALLBACK_ANIMATION, frameData, frameIntervalNanos);
     // 插入更新动画事件,INPUT 和 ANIMATION 后面执行,TRAVERSAL 之前执行
            doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameData,
                    frameIntervalNanos);


     // 处理布局和绘制事件,在处理完上述异步消息之后运行
            mFrameInfo.markPerformTraversalsStart();
            doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameData, frameIntervalNanos);


            doCallbacks(Choreographer.CALLBACK_COMMIT, frameData, frameIntervalNanos);
        } finally {
            AnimationUtils.unlockAnimationClock();
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }


        if (DEBUG_FRAMES) {
            final long endNanos = System.nanoTime();
            Log.d(TAG, "Frame " + frame + ": Finished, took "
                    + (endNanos - startNanos) * 0.000001f + " ms, latency "
                    + (startNanos - frameTimeNanos) * 0.000001f + " ms.");
        }
    }
}

调用Choreographer的doCallbacks方法:

//frameworks/base/core/java/android/view/Choreographer.java
public final class Choreographer {
    void doCallbacks(int callbackType, FrameData frameData, long frameIntervalNanos) {
        CallbackRecord callbacks;
        long frameTimeNanos = frameData.mFrameTimeNanos;
        synchronized (mLock) {
            // We use "now" to determine when callbacks become due because it's possible
            // for earlier processing phases in a frame to post callbacks that should run
            // in a following phase, such as an input event that causes an animation to start.
     // 获取正在运行的 Java 虚拟机的当前时间,单位为纳秒,以此来确定回调何时执行,因为帧中的前期处理阶段可能会发布应在下一阶段运行的回调,例如导致动画启动的输入事件
            final long now = System.nanoTime();
     // 从数组链表 mCallbackQueues 中获取指定类型的链表
            callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(
                    now / TimeUtils.NANOS_PER_MS);
            if (callbacks == null) {
                return;
            }
            mCallbacksRunning = true;


            // Update the frame time if necessary when committing the frame.
            // We only update the frame time if we are more than 2 frames late reaching
            // the commit phase.  This ensures that the frame time which is observed by the
            // callbacks will always increase from one frame to the next and never repeat.
            // We never want the next frame's starting frame time to end up being less than
            // or equal to the previous frame's commit frame time.  Keep in mind that the
            // next frame has most likely already been scheduled by now so we play it
            // safe by ensuring the commit time is always at least one frame behind.
            if (callbackType == Choreographer.CALLBACK_COMMIT) {
                final long jitterNanos = now - frameTimeNanos;
                Trace.traceCounter(Trace.TRACE_TAG_VIEW, "jitterNanos", (int) jitterNanos);
                if (jitterNanos >= 2 * frameIntervalNanos) {
                    final long lastFrameOffset = jitterNanos % frameIntervalNanos
                            + frameIntervalNanos;
                    if (DEBUG_JANK) {
                        Log.d(TAG, "Commit callback delayed by " + (jitterNanos * 0.000001f)
                                + " ms which is more than twice the frame interval of "
                                + (frameIntervalNanos * 0.000001f) + " ms!  "
                                + "Setting frame time to " + (lastFrameOffset * 0.000001f)
                                + " ms in the past.");
                        mDebugPrintNextFrameTimeDelta = true;
                    }
                    frameTimeNanos = now - lastFrameOffset;
                    mLastFrameTimeNanos = frameTimeNanos;
                    frameData.updateFrameData(frameTimeNanos);
                }
            }
        }
        try {
            Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]);
     // 遍历 callbacks 链表获取 CallbackRecord 对象
            for (CallbackRecord c = callbacks; c != null; c = c.next) {
                if (DEBUG_FRAMES) {
                    Log.d(TAG, "RunCallback: type=" + callbackType
                            + ", action=" + c.action + ", token=" + c.token
                            + ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime));
                }
  // 执行 CallbackRecord 对象的 run() 方法
                c.run(frameData);
            }
        } finally {
            synchronized (mLock) {
                mCallbacksRunning = false;
  // 回收 callbacks,置空其内部 CallbackRecord 保存的信息,重组并赋值给 mCallbackPool 链表
                do {
                    final CallbackRecord next = callbacks.next;
                    recycleCallbackLocked(callbacks);
                    callbacks = next;
                } while (callbacks != null);
            }
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
    }
}

调用c(CallbackRecord)的run方法:

//frameworks/base/core/java/android/view/Choreographer.java
public final class Choreographer {
    private static final class CallbackRecord {
        void run(FrameData frameData) {
     // 根据 token 判断当前回调类型
            if (token == VSYNC_CALLBACK_TOKEN) {
                ((VsyncCallback) action).onVsync(frameData);
            } else {
                run(frameData.getFrameTimeNanos());
            }
        }
    }
}

调用run方法:

//frameworks/base/core/java/android/view/Choreographer.java
public final class Choreographer {
    private static final class CallbackRecord {
        public void run(long frameTimeNanos) {
            if (token == FRAME_CALLBACK_TOKEN) {
  // 通过 postFrameCallback() 或 postFrameCallbackDelayed() 会执行这里
                ((FrameCallback)action).doFrame(frameTimeNanos);
            } else {
  // 取出 Runnable 并执行其 run() 方法
                ((Runnable)action).run();
            }
        }
    }
}

在Choreographer的postCallback方法中,提交一个任务 TraversalRunnable,将任务 TraversalRunnable 和执行时间一起被封装成 CallbackRecord,因此这里执行的就是 TraversalRunnable 的 run() 方法。

//frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }
}

ViewRootImpl doTraversal

调用ViewRootImpl的doTraversal方法:

//frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    void doTraversal() {
        if (mTraversalScheduled) {
     // mTraversalScheduled 标志位重新置为 false
            mTraversalScheduled = false;
     // 通过调用 removeSyncBarrier 方法移除同步屏障消息,传入 postSyncBarrier() 方法的返回值作为参数
     // 标识需要移除哪个屏障,然后将该屏障消息会从队列中移除,以确保消息队列恢复正常操作,否则应用程序可能会挂起
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);


            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }


     // 执行 View 的绘制流程开始渲染新页面
            performTraversals();


            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }
}
ViewRootImpl performTraversals

调用ViewRootImpl的performTraversals方法,开始View的三大流程(measure、layout、draw):

Android13 ViewRootImpl performTraversals流程分析-CSDN博客

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值