0.前言
之前遇到了因Surface同步迟迟未完成导致发生无焦点窗口类型anr的情况,现在抽空对android13中的Surface同步机制进行梳理与总结。
1.简介
Surface同步机制为android13新增,相关核心代码为SurfaceSyncer.java,主要作用为提供ViewRootImpl与SurfaceView(假如窗口存在SurfaceView的情况下)同步服务,实现在主Surface与SurfaceView均完成绘制时再去上报至WMS进行窗口状态的切换,避免主Surface绘制完成上报至WMS后、同时SurfaceView迟迟没有绘制完成使得startingWindow过早移除从而产生黑屏的现象。Android14上保留了Surface同步机制,但是相关代码位置发生变化,不再有SurfaceSyncer.java,而是移动至SurfaceSyncGroup.java。相关核心方法为createSyncIfNeeded、checkIfSyncIsComplete等。
2.Surface同步流程
2.1 ViewRootImpl发起同步
ViewRootImpl中会在绘制流程中发起sync流程,依次完成callback注册、seqId返回、添加syncTarget、通知SurfaceView发起merge等流程。
/frameworks/base/core/java/android/view/ViewRootImpl.java
2685 private void performTraversals() { ... >>回调各个listener的onPreDraw方法,同时通知SurfaceView发起sync流程 3491 boolean cancelAndRedraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw(); 3492 if (!cancelAndRedraw) { >>ViewRootImpl发起sync流程 3493 createSyncIfNeeded(); 3494 } ... 3529 if (!cancelAndRedraw) { 3530 mReportNextDraw = false; 3531 mSyncBufferCallback = null; >>置mSyncBuffer=false 3532 mSyncBuffer = false; 3533 if (isInLocalSync()) { 3534 mSurfaceSyncer.markSyncReady(mSyncId); >>重置mSyncId为UNSET_SYNC_ID 3535 mSyncId = UNSET_SYNC_ID; 3536 } 3537 }
4201 /** 4202 * This VRI is currently in the middle of a sync request, but specifically one initiated from 4203 * within VRI. 4204 */ >>VRI发起sync后会把mSyncId重置为UNSET_SYNC_ID >>如果返回true,说明VRI正处于sync中,尚未完成sync流程 4205 public boolean isInLocalSync() { 4206 return mSyncId != UNSET_SYNC_ID; 4207 }
3540 private void createSyncIfNeeded() { 3541 // Started a sync already or there's nothing needing to sync >>假如VRI正在Sync,或者mReportNextDraw为false,那么立即return 3542 if (isInLocalSync() || !mReportNextDraw) { 3543 return; 3544 } 3545 >>这里的mSyncSeqId为relayoutWindow后由WMS返回的id,赋值给seqId是为了后面执行>>reportDrawFinished流程时再回传至WMS 3546 final int seqId = mSyncSeqId; >>正式发起sync流程,返回syncId >>传入的callback会在完成同步后被回调 3547 mSyncId = mSurfaceSyncer.setupSync(transaction -> { 3548 // Callback will be invoked on executor thread so post to main thread. 3549 mHandler.postAtFrontOfQueue(() -> { 3550 mSurfaceChangedTransaction.merge(transaction); 3551 reportDrawFinished(seqId); 3552 }); 3553 }); 3554 if (DEBUG_BLAST) { 3555 Log.d(mTag, "Setup new sync id=" + mSyncId); 3556 } >>将VRI对应的syncTarget添加至SurfaceSyncer 3557 mSurfaceSyncer.addToSync(mSyncId, mSyncTarget); >>通知SurfaceView发起merge流程 3558 notifySurfaceSyncStarted(); 3559 }
2.2 SurfaceView发起同步
SurfaceView会在ViewRootImpl回调OnPreDrawListener.onPreDraw方法时执行updateSurface方法,原因是SurfaceView实现了OnPreDrawListener并进行了注册。然后SurfaceView会在handleSyncNoBuffer方法发起sync流程,也会依次完成callback注册、seqId返回、添加syncTarget等操作。
frameworks/base/core/java/android/view/SurfaceView.java
>>SurfaceView实现OnPreDrawListener,回调onPreDraw时会执行updateSurface方法 157 private final ViewTreeObserver.OnPreDrawListener mDrawListener = () -> { 158 // reposition ourselves where the surface is 159 mHaveFrame = getWidth() > 0 && getHeight() > 0; 160 updateSurface(); 161 return true; 162 };
284 protected void onAttachedToWindow() { 285 super.onAttachedToWindow(); ... 295 if (!mGlobalListenersAdded) { 296 ViewTreeObserver observer = getViewTreeObserver(); 297 observer.addOnScrollChangedListener(mScrollChangedListener); >>在attachedToWindow时注册OnPreDrawListener 298 observer.addOnPreDrawListener(mDrawListener); 299 mGlobalListenersAdded = true; 300 }
875 protected void updateSurface() { ... 1023 if (shouldSyncBuffer) { 1024 handleSyncBufferCallback(callbacks, syncBufferTransactionCallback); 1025 } else { >>当onPreDraw被回调时,如果shouldSyncBuffer=false,将执行handleSyncNoBuffer方法 1026 handleSyncNoBuffer(callbacks); 1027 }
1071 private void handleSyncNoBuffer(SurfaceHolder.Callback[] callbacks) { >>SurfaceView发起sync流程 1072 final int syncId = mSurfaceSyncer.setupSync(this::onDrawFinished); 1073 >>SurfaceView添加对应的syncTarget 1074 mSurfaceSyncer.addToSync(syncId, syncBufferCallback -> redrawNeededAsync(callbacks, 1075 () -> { 1076 syncBufferCallback.onBufferReady(null); 1077 synchronized (mSyncIds) { 1078 mSyncIds.remove(syncId); 1079 } 1080 })); 1081 >>回调markSyncReady方法,会将对应SurfaceSyncer中的mSyncReady置为true 1082 mSurfaceSyncer.markSyncReady(syncId); 1083 synchronized (mSyncIds) { 1084 mSyncIds.add(syncId); 1085 } 1086 }
2.3 合并同步
sync流程中的merge操作由VRI发起,发起的时机是由VRI决定的,时机为VRI添加syncTarget后会调用notifySurfaceSyncStarted方法,该方法会通知到SurfaceView中。merge操作的本质就是,将VRI与SurfaceView各自对应的syncSet给merge到一起。
/frameworks/base/core/java/android/view/ViewRootImpl.java
3540 private void createSyncIfNeeded() { ... >>VRI向SurfaceSyncer中添加syncTarget 3557 mSurfaceSyncer.addToSync(mSyncId, mSyncTarget); >>回调callback通知SurfaceView 3558 notifySurfaceSyncStarted();
2085 private void notifySurfaceSyncStarted() { 2086 for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) { >>回调surfaceSyncStarted方法 2087 mSurfaceChangedCallbacks.get(i).surfaceSyncStarted(); 2088 } 2089 }
2054 public void addSurfaceChangedCallback(SurfaceChangedCallback c) { >>通过addSurfaceChangedCallback方法将callback添加到mSurfaceChangedCallbacks 2055 mSurfaceChangedCallbacks.add(c); 2056 }
/frameworks/base/core/java/android/view/SurfaceView.java
284 protected void onAttachedToWindow() { 285 super.onAttachedToWindow(); ... 286 >>SurfaceView调用VRI的接口去添加callback,用于接收surface变化通知 287 getViewRootImpl().addSurfaceChangedCallback(this); 288 mWindowStopped = false;
1098 public void surfaceSyncStarted() { 1099 ViewRootImpl viewRoot = getViewRootImpl(); 1100 if (viewRoot != null) { 1101 synchronized (mSyncIds) { 1102 for (int syncId : mSyncIds) { >>接到VRI通知后,SurfaceView发起merge操作 >>将SurafaceView对应的syncId以及SurfaceSyncer传入VRI 1103 viewRoot.mergeSync(syncId, mSurfaceSyncer); 1104 } 1105 } 1106 } 1107 }
frameworks/base/core/java/android/view/ViewRootImpl.java 10977 void mergeSync(int syncId, SurfaceSyncer otherSyncer) { 10978 if (!isInLocalSync()) { 10979 return; 10980 } >>最终由VRI对应的SurfaceSyncer发起merge操作 >>mSyncId为VRI发起sync的序列号 10981 mSurfaceSyncer.merge(mSyncId, syncId, otherSyncer); 10982 }
frameworks/base/core/java/android/window/SurfaceSyncer.java
160 public void merge(int syncId, int otherSyncId, SurfaceSyncer otherSurfaceSyncer) { 161 SyncSet syncSet; 162 synchronized (mSyncSetLock) { >>获取VRI对应的syncSet 163 syncSet = mSyncSets.get(syncId); 164 } 165 >>获取SurfaceView对应的syncSet 166 SyncSet otherSyncSet = otherSurfaceSyncer.getAndValidateSyncSet(otherSyncId); 167 if (otherSyncSet == null) { 168 return; 169 } 170 >>打印merge相关log 171 if (DEBUG) { 172 Log.d(TAG, 173 "merge id=" + otherSyncId + " from=" + otherSurfaceSyncer + " into id=" + syncId 174 + " from" + this); 175 } >>最终最终把VRI和SurfaceView各自的syncSet给merge 176 syncSet.merge(otherSyncSet); 177 }
427 public void merge(SyncSet otherSyncSet) { 428 synchronized (mLock) { >>把SurfaceView对应的syncSet添加到VRI对应syncSet中的一个列表中 429 mMergedSyncSets.add(otherSyncSet); 430 } >>同时更新callback >>注意这里更新的是SurfaceView对应SurfaceSyncer中的callback >>即该callback调用时机由SurfaceView控制,但callback中的操作是针对VRI所对应的syncSet 431 otherSyncSet.updateCallback(transaction -> { 432 synchronized (mLock) { >>callback回调时会将VRI对应syncSet中的列表中元素移除 433 mMergedSyncSets.remove(otherSyncSet); 434 mTransaction.merge(transaction); >>同时检查VRI对应sync流程是否完成 435 checkIfSyncIsComplete(); 436 } 437 }); 438 }
2.4 检查同步完成情况
checkIfSyncIsComplete方法是检查sync流程是否完成的核心逻辑所在,VRI与SurfaceView均是通过此方法来判断各自的sync流程是否完成。其中,SurfaceView判断自己的sync流程是否完成不受VRI的影响,而VRI判断自己的sync流程是否完成则会受到SurfaceView(前提是SurfaceView发起了sync流程)影响,原因是SurfaceView对应的syncSet会merge到VRI对应的syncSet中,因此VRI完成sync流程前需要SurfaceView先完成sync流程。
在checkIfSyncIsComplete方法中,判断完成sync流程需要同时满足三个条件,而调用此方法检查是否完成sync流程的时机就是其中每个条件在得到满足时,即第一个条件满足时回去调用checkIfSyncIsComplete方法去检查,第二个条件满足时又会调用此方法去检查sync流程完成情况,依次类推。
frameworks/base/core/java/android/window/SurfaceSyncer.java
364 private void checkIfSyncIsComplete() { >>判断完成sync流程需要同时满足:1.mSyncReady=true;2.mPendingSyncs.size()=0; >>3.mMergedSyncSets.size()=0.只要有一个条件没有满足,便会拦截、判断为当前sync流程未完成。 >>其中,前面两个条件均在特定时机才满足,而mMergedSyncSets条件对于SurfaceView始终是满足的, >>因为不会有其他Surface的syncSet会merge到SurfaceView对应的syncSet中。 365 if (!mSyncReady || !mPendingSyncs.isEmpty() || !mMergedSyncSets.isEmpty()) { 366 if (DEBUG) { 367 Log.d(TAG, "Syncable is not complete. mSyncReady=" + mSyncReady 368 + " mPendingSyncs=" + mPendingSyncs.size() + " mergedSyncs=" 369 + mMergedSyncSets.size()); 370 } 371 return; 372 } 373 >>执行到这里,说明当前SurfaceSyncer完成了sync流程 374 if (DEBUG) { 375 Log.d(TAG, "Successfully finished sync id=" + mSyncId); 376 } 377 >>执行对应syncTarget的onSyncComplete方法 378 for (SyncTarget syncTarget : mSyncTargets) { 379 syncTarget.onSyncComplete(); 380 } 381 mSyncTargets.clear(); >>执行前面设置的callback:mSYncRequestCompleteCallback 382 mSyncRequestCompleteCallback.accept(mTransaction); >>置mFinished为true 383 mFinished = true; 384 }
2.4.1 设置mSyncReady为true
调用markSyncReady会把mSyncReady置为true,同时调用checkIfSyncIsComplete方法检查当前sync流程是否完成。
frameworks/base/core/java/android/window/SurfaceSyncer.java
142 public void markSyncReady(int syncId) { 143 SyncSet syncSet; 144 synchronized (mSyncSetLock) { 145 syncSet = mSyncSets.get(syncId); 146 } 147 if (syncSet == null) { 148 Log.e(TAG, "Failed to find syncSet for syncId=" + syncId); 149 return; 150 } 151 syncSet.markSyncReady(); 152 }
2.4.2 移除mPendingSyncs中元素
mPendingSyncs中的元素是发起sync流程初期通过addToSync方法向mPendingSyncs中添加的,在完成sync流程前需要把mPendingSyncs中的元素给移除掉。
>>向SurfaceSyncer中通过syncId添加syncTraget 223 public boolean addToSync(int syncId, @NonNull SyncTarget syncTarget) { 224 SyncSet syncSet = getAndValidateSyncSet(syncId); 225 if (syncSet == null) { 226 return false; 227 } 228 if (DEBUG) { 229 Log.d(TAG, "addToSync id=" + syncId); 230 } >>调用对应的syncSet的addSyncableSurface方法 231 return syncSet.addSyncableSurface(syncTarget); 232 }
329 boolean addSyncableSurface(SyncTarget syncTarget) { >>实现syncBufferCallback 330 SyncBufferCallback syncBufferCallback = new SyncBufferCallback() { 331 @Override 332 public void onBufferReady(Transaction t) { 333 synchronized (mLock) { 334 if (t != null) { 335 mTransaction.merge(t); 336 } >>回调callback时会将mPendingSyncs中的元素移除 337 mPendingSyncs.remove(hashCode()); 338 checkIfSyncIsComplete(); 339 } 340 } 341 }; 342 343 synchronized (mLock) { 344 if (mSyncReady) { 345 Log.e(TAG, "Sync " + mSyncId + " was already marked as ready. No more " 346 + "SyncTargets can be added."); 347 return false; 348 } >>向pendingSyncs中添加syncBufferCallback 349 mPendingSyncs.add(syncBufferCallback.hashCode()); 350 mSyncTargets.add(syncTarget); 351 } >>将syncBufferCallback添加到syncTaret中,说明callback触发时机由syncTarget决定 352 syncTarget.onReadyToSync(syncBufferCallback); 353 return true; 354 }
2.4.3 移除mMergedSyncSets中元素
mMergedSyncSets中的元素是SurfaceView发起merge流程、将自己对应的syncSet给添加到了mMergedSyncSets中的。在完成sync流程前需要将mMergedSyncSets中的元素给移除掉。
>>由SurfaceView发起调用,传入参数分别为VRI对应的syncId、SurafceView对应的syncId、 >>以及SurafceView对应的SurfaceSyncer 160 public void merge(int syncId, int otherSyncId, SurfaceSyncer otherSurfaceSyncer) { 161 SyncSet syncSet; 162 synchronized (mSyncSetLock) { >>通过syncId获取VRI对应的syncSet 163 syncSet = mSyncSets.get(syncId); 164 } 165 >>通过syncId获取SurfaceView对应的syncSet 166 SyncSet otherSyncSet = otherSurfaceSyncer.getAndValidateSyncSet(otherSyncId); 167 if (otherSyncSet == null) { 168 return; 169 } 170 171 if (DEBUG) { 172 Log.d(TAG, 173 "merge id=" + otherSyncId + " from=" + otherSurfaceSyncer + " into id=" + syncId 174 + " from" + this); 175 } >>将SurfaceView对应的syncSet合并到VRI对应的syncSet中 176 syncSet.merge(otherSyncSet); 177 }
427 public void merge(SyncSet otherSyncSet) { 428 synchronized (mLock) { >>向mMergedSyncSets中添加元素,元素类型为SyncSet。 429 mMergedSyncSets.add(otherSyncSet); 430 } 431 otherSyncSet.updateCallback(transaction -> { 432 synchronized (mLock) { >>当callback回调时会将元素从mMergedSyncSets中移除 >>移除的时机则由otherSyncSet决定 433 mMergedSyncSets.remove(otherSyncSet); 434 mTransaction.merge(transaction); 435 checkIfSyncIsComplete(); 436 } 437 }); 438 }
2.5 同步完成并报告
一般流程为SurfaceView先完成sync流程、然后VRI完成sync流程,最后VRI向WMS报告当前窗口绘制完毕。
2.5.1 SurfaceView同步完成
SurfaceView中的sync流程相对VRI要简单一些,其不需要检查merge条件(准确的说是因为其对应SurfaceSyncer中的mMergedSyncSets一直为空,始终是满足条件的),当SurfaceView绘制完成时基本就算是完成sync流程了,此时对应的三个条件均已满足。
frameworks/base/core/java/android/view/SurfaceView.java 1071 private void handleSyncNoBuffer(SurfaceHolder.Callback[] callbacks) { 1072 final int syncId = mSurfaceSyncer.setupSync(this::onDrawFinished); 1073 >>向SurfaceSyncer中添加syncTarget >>其中第二个参数为syncTarget,重写了SyncTarget的onReadyToSync方法 >>在重写的onReadyToSync方法中,会执行redrawNeededAsync方法,而syncBufferCallback的 >>执行时机则由redrawNeededAsync方法决定,一般认为是SurfaceView绘制完成后执行 1074 mSurfaceSyncer.addToSync(syncId, syncBufferCallback -> redrawNeededAsync(callbacks, 1075 () -> { 1076 syncBufferCallback.onBufferReady(null); 1077 synchronized (mSyncIds) { 1078 mSyncIds.remove(syncId); 1079 } 1080 })); 1081 >>在向SurfaceSyncer中添加完syncTarget后,就会立马调用markSyncReady方法将mSyncRead置为true 1082 mSurfaceSyncer.markSyncReady(syncId); 1083 synchronized (mSyncIds) { 1084 mSyncIds.add(syncId); 1085 } 1086 }
2.5.2 ViewRootImpl同步完成
VRI在绘制完成后、底层回调FrameCallBack时,会执行syncBufferCallback.onBufferReady方法,移除对应SurfaceSyncer中的mPendingSyncs中的元素。这里syncBufferCallback是VRI向SurfaceSyncer添加syncTarget时由SurafaceSyncer传入。
2.5.2.1 VRI设置mSyncReady为true
VRI会在performTraversal流程结束时将对应SurfaceSyncer中的mSyncReady置为true,应该是三个条件中最先满足的一个。
2685 private void performTraversals() { ... 3529 if (!cancelAndRedraw) { 3530 mReportNextDraw = false; 3531 mSyncBufferCallback = null; 3532 mSyncBuffer = false; 3533 if (isInLocalSync()) { >>VRI调用markSyncReady方法将mSyncReady置为true 3534 mSurfaceSyncer.markSyncReady(mSyncId); 3535 mSyncId = UNSET_SYNC_ID; 3536 } 3537 }
2.5.2.2 VRI移除mPendingSyncs中元素
VRI在绘制完成后、底层回调FrameCommitCallback时,会执行syncBufferCallback.onBufferReady 方法,移除对应SurfaceSyncer中对应mPendingSyncs中的元素。这里的syncBufferCallback是VRI向SurfaceSyncer添加syncTarget时从SurfaceSyncer传入。
10938 public final SurfaceSyncer.SyncTarget mSyncTarget = new SurfaceSyncer.SyncTarget() { 10939 @Override 10940 public void onReadyToSync(SurfaceSyncer.SyncBufferCallback syncBufferCallback) { >>SurfaceSyncer侧回调syncTarget的onReadyToSync方法时,会执行VRI的readyToSync方法 10941 readyToSync(syncBufferCallback); 10942 }
10954 private void readyToSync(SurfaceSyncer.SyncBufferCallback syncBufferCallback) { ... 10968 if (DEBUG_BLAST) { 10969 Log.d(mTag, "Setting syncFrameCallback"); 10970 } >>将由SurfaceSyncer传入的syncBufferCallback赋值给mSyncBufferCallback 10971 mSyncBufferCallback = syncBufferCallback;
4263 private boolean performDraw() { ... 4276 addFrameCommitCallbackIfNeeded(); 4277 4278 boolean usingAsyncReport = isHardwareEnabled() && mSyncBufferCallback != null; 4279 if (usingAsyncReport) { >>注册calback时将mSyncBufferCallback传入 4280 registerCallbacksForSync(mSyncBuffer, mSyncBufferCallback); 4281 } else if (mHasPendingTransactions) {
10864 private void registerCallbacksForSync(boolean syncBuffer, 10865 final SurfaceSyncer.SyncBufferCallback syncBufferCallback) { ... 10870 if (DEBUG_BLAST) { 10871 Log.d(mTag, "registerCallbacksForSync syncBuffer=" + syncBuffer); 10872 } 10873 mAttachInfo.mThreadedRenderer.registerRtFrameCallback(new FrameDrawingCallback() { 10874 @Override 10875 public void onFrameDraw(long frame) { 10876 } 10877 10878 @Override 10879 public HardwareRenderer.FrameCommitCallback onFrameDraw(int syncResult, long frame) { 10880 if (DEBUG_BLAST) { 10881 Log.d(mTag, 10882 "Received frameDrawingCallback syncResult=" + syncResult + " frameNum=" 10883 + frame + "."); 10884 } ... >>如果syncBuffer=true,会向BlastBufferQueue中传入一个callback >>该callback会在底层绘制完成后回调,并将包含buffer的transaction作为参数传入callback 10901 if (syncBuffer) { 10902 mBlastBufferQueue.syncNextTransaction(syncBufferCallback::onBufferReady); 10903 } 10904 >>返回FrameCommitCallback类型的callback 10905 return didProduceBuffer -> { 10906 if (DEBUG_BLAST) { 10907 Log.d(mTag, "Received frameCommittedCallback" 10908 + " lastAttemptedDrawFrameNum=" + frame 10909 + " didProduceBuffer=" + didProduceBuffer); 10910 } ... 10927 // If we didn't request to sync a buffer, then we won't get the 10928 // syncNextTransaction callback. Instead, just report back to the Syncer so it 10929 // knows that this sync request is complete. 10930 if (!syncBuffer) { >>当绘制完成时,底层回调FrameCommitCallback时会执行syncBufferCallback,将VRI对应的 >>SurfaceSyncer中的mPendingSyncs中元素移除掉 10931 syncBufferCallback.onBufferReady(null); 10932 }
2.5.2.3 VRI移除mMergedSyncSets中元素
如前面所述,当SurfaceView通知VRI发起merge流程后,会执行SurfaceView对应syncSet的updateCallback流程,去更新SurfaceView中的callback。当这个callback被回调时会将VRI对应SurfaceSyncer中mMergedSyncSets中的元素移除,从而使得VRI完成sync流程所需的三个条件之一得到满足。一般情况下,这个条件是VRI完成sync流程的最后一个条件。
427 public void merge(SyncSet otherSyncSet) { 428 synchronized (mLock) { >>VRI发起merge时会将SurfaceView对应的syncSets添加到自身的mMergedSyncSets中 429 mMergedSyncSets.add(otherSyncSet); 430 } >>更新SurfaceView对应syncSet的callback,实际上updateCallback中的参数为一个consumer 431 otherSyncSet.updateCallback(transaction -> { 432 synchronized (mLock) { >>该callback被SurfaceView回调时会把VRI对应mMergedSyncSets中的元素移除 433 mMergedSyncSets.remove(otherSyncSet); 434 mTransaction.merge(transaction); 435 checkIfSyncIsComplete(); 436 } 437 }); 438 }
可以看的,实际上updateCallback方法传入的是一个consumer类型的参数,该consumer放在了mSyncRequestCompleteCallback中,即该consumer的执行时机取决于mSyncRequestCompleteCallback的执行时机。
396 public void updateCallback(Consumer<Transaction> transactionConsumer) { 397 synchronized (mLock) { 398 if (mFinished) { 399 Log.e(TAG, "Attempting to merge SyncSet " + mSyncId + " when sync is" 400 + " already complete"); 401 transactionConsumer.accept(new Transaction()); 402 } 403 404 final Consumer<Transaction> oldCallback = mSyncRequestCompleteCallback; 405 mSyncRequestCompleteCallback = transaction -> { 406 oldCallback.accept(new Transaction()); >>执行传入的consumer,执行的时机为mSyncRequestCompleteCallback的执行时机 407 transactionConsumer.accept(transaction); 408 }; 409 } 410 }
mSyncRequestCompleteCallback的执行时机为完成sync流程时,具体来说就是当checkIfSyncIsComplete方法检查SurfaceView对应SurfaceSyncer的三项条件都通过时会执行mSyncRequestCompleteCallback,从而执行callback中的consumer去把VRI对应的SurfaceSyncer中的mMergedSyncSets中的元素移除,从而使得VRI满足完成sync的条件。
364 private void checkIfSyncIsComplete() { 365 if (!mSyncReady || !mPendingSyncs.isEmpty() || !mMergedSyncSets.isEmpty()) { 366 if (DEBUG) { 367 Log.d(TAG, "Syncable is not complete. mSyncReady=" + mSyncReady 368 + " mPendingSyncs=" + mPendingSyncs.size() + " mergedSyncs=" 369 + mMergedSyncSets.size()); 370 } 371 return; 372 } ... 374 if (DEBUG) { 375 Log.d(TAG, "Successfully finished sync id=" + mSyncId); 376 } ... >>sync完成后,执行 mSyncRequestCompleteCallback 382 mSyncRequestCompleteCallback.accept(mTransaction); 383 mFinished = true;
2.5.3 报告WMS
在VRI发起ync流程时,会向SurfaceSyncer中传入一个consumer,而reportDrawFinished方法就是在此consumer中调用执行。
3540 private void createSyncIfNeeded() { ... 3546 final int seqId = mSyncSeqId; 3547 mSyncId = mSurfaceSyncer.setupSync(transaction -> { 3548 // Callback will be invoked on executor thread so post to main thread. 3549 mHandler.postAtFrontOfQueue(() -> { 3550 mSurfaceChangedTransaction.merge(transaction); >>setupSync方法中的参数为consumer类型 >>reportDrawFinished方法的执行时机就是该consumer的执行时机 3551 reportDrawFinished(seqId); 3552 }); 3553 });
从VRI传过来的consumer会继续传入对应的yncSet中,即该consumer的执行时机由syncSet决定。
118 public int setupSync(@NonNull Consumer<Transaction> syncRequestComplete) { 119 synchronized (mSyncSetLock) { 120 final int syncId = mIdCounter++; 121 if (DEBUG) { 122 Log.d(TAG, "setupSync " + syncId); 123 } 124 SyncSet syncSet = new SyncSet(syncId, transaction -> { 125 synchronized (mSyncSetLock) { 126 mSyncSets.remove(syncId); 127 } >>consumer传入syncSet中 128 syncRequestComplete.accept(transaction); 129 });
对应consumer传入syncSet中时,会赋值给mSyncRequestCompleteCallback。因此,该callback的执行时机就是consumer的执行时机,也就是reportDrawFinished方法的执行时机。
324 private SyncSet(int syncId, Consumer<Transaction> syncRequestComplete) { 325 mSyncId = syncId; 326 mSyncRequestCompleteCallback = syncRequestComplete; 327 }
根据前面2.5.2.3得知,mSyncRequestCompleteCallback的执行时机为VRI完成sync流程之时。因此,reporDrawFinished方法的执行时机也正是VRI完成sync流程的时候。该方法调用后,WMS得知应用绘制完成,开始更新对应窗口状态。
2.6 整体流程
整体流程如下:
VRI发起performTraversal -> SurfaceView发起sync -> VRI发起sync -> SurfaceView通知VRI发起merge ->SurfaceView绘制完成 -> SurfaceView完成sync -> VRI完成sync -> VRI发起reportDrawFinished流程