You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
9.8 KiB
9.8 KiB
说说 Android 的 UI 刷新机制
- 丢帧一般是什么原因引起的?
- Android 刷新频率 60 帧/秒,每隔 16 ms 调 onDraw 绘制一次?
- onDraw 完之后屏幕会马上刷新吗?
- 如果界面没有重绘,还会每隔 16ms 刷新屏幕吗?
- 如果在屏幕快要刷新的时候才去 onDraw 绘制会丢帧吗?
public void requestLayout(){
scheduleTraversals();
}
void scheduleTraversals(){
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
if(!mTraversalScheduled){
mTraversalScheduled = true;
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
}
}
// mTraversalRunnable
void doTraversal(){
if(mTraversalScheduled){
mTraversalScheduled = false;
performTraversals();
}
}
private void postCallbackDelayedInternal(int callbackType, ){
mCallbackQueues[callbackType].addCallbackLocked(dueTime, ...);
scheduleFrameLocked(now);
}
private void scheduleFrameLocked(long now){
if(isRunningOnLooperThreadLocked()){
scheduleVsyncLocked();
}else{
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
msg.setAsynchronous(true);
mHandler.sendMEssageAtFrontOfQueue(msg);
}
}
class FrameDisplayEventReceiver extends DisplayEventReceiver{
public void onVsync(long timestampNanos, int builtInDisplayId, int frame){
mTimestampNanos = timestampNanos;
mFrame = frame;
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos/TimeUtils.NANOS_PER_MS);
}
public void run(){
doFrame(mTimestampNanos, mFrame);
}
}
// Choreographer#doFrame
void doFrame(long frameTimeNanos, int frame){
long intendedFrameTimeNanos = frameTimeNanos;
startNanos = System.nanoTime();
final long jitterNanos = startNanos - frameTimeNanos;
if (jitterNanos >= mFrameIntervalNanos) {
final long skippedFrames = jitterNanos / mFrameIntervalNanos;
if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
Log.i(TAG, "Skipped " + skippedFrames + " frames! " + "The application may be doing too much work on its main thread.");
}
final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
frameTimeNanos = startNanos - lastFrameOffset;
}
// 处理 Callback
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
}
void doCallback(int callbackType, long frameTimeNanos){
CallbackRecord callbacks;
callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(...);
for (CallbackRecord c = callbacks; c != null; c = c.next) {
c.run(frameTimeNanos);
}
}
private void scheduleVsyncLocked(){
mDisplayEventReceiver.scheduleVsync();
}
status_t NativeDisplayEventReceiver::scheduleVsync(){
status_t status = mReceiver.requestNextVsync();
}
status_t DisplayEventReceiver::requestNextVsync(){
mEventConnection->requestNextVsync();
}
DisplayEventReceiver::DisplayEventReceiver(){
sp<ISurfaceComposer> sf(ComposerService::slef());
if(sf!=null){
mEventConnection = sf->createDisplayEventConnection();
mDataChannel = mEventConnection->getDataChannel();
}
}
sp<BitTube> EventThread::Connection::getDataChannel() const{
return mChannel;
}
创建 Connection,实现是在 SurfaceFlinger 里:
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(){
return mEventThread->createEventConnection();
}
sp<EventThread::Connection> EventThread::createEventConnection() const {
return new Connection(const_cast<EventThread*>(this));
}
EventThread::Connection::Connection(const sp<EventThread>&eventThread):count(-1), mEventThread(eventThread), mChannel(new BitTubr()) {
}
void EventThread::Connection::onFirstRef(){
mEventThread->registerDisplayEventConnection(this);
}
status_t EventThread::registerDisplayEventConnection(const sp<EventThread::Connection>&connection){
mDisplayEventConnections.add(connection);
mCondition.broadcast();
}
创建 EventThread:
void SurfaceFlinger::init(){
sp<VSYNCSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, ...);
mEventThread = new EventThread(vsyncSrc);
}
bool EventThread::threadLoop(){
DisplayEventReceiver::Event event;
Vector<sp<EventThread::Connection>> signalConnections;
signalConnections = waitForEvent(&event);
const size_t count = signalConnection,size();
for(size_t i = 0;i<count:i++){
const sp<Connection>&conn(signalConnections[i]);
conn->postEvent(event);
}
return true;
}
Vector<sp<EventThread::Connection>> EventThread::waitForEvent(...){
Vector<sp<EventThread::Connectiob>> signalConnections;
do{
// 看是否已经有 vsync 信号来了
// 如果有的话,就准备 connection 列表返回
// 如果没有的话,就等待 vsync 信号
}while(signalConnections.isEmpty());
return signalConnections;
}
void EventThread::requestNextVsync(const sp<EventThread::Connection>&connection){
if(connection->count<0){
connection->count=0;
mCondition.broadcast();
}
}
status_t EventThread::Connection::postEvent(const DisplayEventReceiver::Event& event){
ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);
return size<0?status_t(size):status_t(NO_ERROR);
}
ssize_t size DisplayEventReceiver::sendEvents(const sp<BitTube> &dataChannel, Event const* events, size_t count) {
return BitTube:sendObjects(dataChannel, events, count);
}
ssize_t BitTube::sendObjects(const sp<BitTube> &tube, ...){
const char* vaddr = reinterpret_cast<const char*>(events);
sszie_t size = tube->write(vaddr, count*objSize);
return size<0?size:size/static_cast<sszie_t>(objSize);
}
BitTube 是在 SurfaceFlinger 创建的,读的一端是如何传递给应用进程呢?
DisplayEventReceiver::DisplayEventReceiver(){
sp<ISrufaceComposer> sf(ComposerService::getComposerService());
mEventConnection = sf->createDisplayEventConnection();
mDataChannel = mEventConnection->getDataChannel();
}
virtual sp<BitTube> getDataChannel() const{
Parcel data, reply;
data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
remote()->transact(GET_DATA_CHANNEL, data, &reply);
return new BitTube(reply);
}
sp<BitTube> EventThread::Connection::getDataChannel() const{
return mChannel;
}
应用进程如何监听读的描述符呢?
private Choreographer(Looper looper){
mDisplayEventReceiver = new FrameDisplayEventReceiver(looper);
}
public DisplayEventReceiver(Looper looper){
mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), ...);
}
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, ...){
sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(...);
status_t status = receiver->initialize();
return reinterpret_cast<jlong>(receiver.get());
}
status_t NativeDisplayEventReceiver::initialize(){
mMessageQueue->getLooper()->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);
rwturn OK;
}
DisplayEventReceiver::DisplayEventReceiver(){
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
mEventConnection = sf->createisplayEventConnection();
mDataChannel = mEventConnection->getDataChannel();
}
int DisplayEventReceiver::getFd() const{
return mDataChannel->getFd();
}
int BitTube::getFd() const{
return mReceiverFd;
}
int Looper::addFd(int fd, int ident, int events, ...){
Request request:
request.fd = fd;
struct epoll_event eventItem:
request.initEventItem(&eventItem);
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem);
mRequests.add(fd, request);
}
Looper 检测 fd 的读事件:
int Looper::pollInner(int timeoutMillis){
int eventCount = epoll_wait(mEpollFd, eventItems, ...);
for(int i = 0;i<eventCount;i++){
int fd = eventItems[i].data.fd;
uint32_t epollEvents = eventItem[i].events;
if(fd == mWakeEventFd){
}else{
if(epollEvent&EPOLLIN)events|=EVENT_INPUT;
pustResponse(events, mRequest.valueAt(requestIndex));
}
}
// 统一处理 Response
for(size_t i=0;i<mResponse.size();i++){
Response& response = mResponse.editItemAt(i);
int fd = response.request.fd;
int events = response.events;
void* data = response.request.data;
int callbackResult = response.request.callback->handleEvent(fd, events, data);
if(callbackResult==0){
removeFd(fd, response.request.seq);
}
response.request.callback.clear();
result = POLL_CALLBACK;
}
return result;
}
int NativeDisplayEventReceiver::handleEvent(int receiveFd, int events, ...){
if(processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, ...)){
mWaitingForVsync = false;
dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
}
return 1;
}
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, ...){
env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, ...);
}
void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame){
onVsync(timestampNanos, buildInDisplayId, frame);
}
总结
- Vsync 的原理是怎样的?
- Choreographer 的原理是怎样的?
- UI 刷新的大致流程,应用和 SurfaceFlinger 的通信过程?