/** * Test app that allows the user to resize the SurfaceView and have the new buffer sync with the * main window. This tests that {@link SurfaceSyncer} is working correctly. */ publicclassSurfaceViewSyncActivityextendsActivityimplementsSurfaceHolder.Callback { privatestaticfinalStringTAG="SurfaceViewSyncActivity";
/** * Starts a sync and will automatically apply the final, merged transaction. * * @param onComplete The runnable that is invoked when the sync has completed. This will run on * the same thread that the sync was started on. * @return The syncId for the newly created sync. * @see #setupSync(Consumer) */ publicintsetupSync(@Nullable Runnable onComplete) { Handlerhandler=newHandler(Looper.myLooper()); return setupSync(transaction -> { transaction.apply(); if (onComplete != null) { handler.post(onComplete); } }); }
/** * Starts a sync. * * @param syncRequestComplete The complete callback that contains the syncId and transaction * with all the sync data merged. * @return The syncId for the newly created sync. * @hide * @see #setupSync(Runnable) */ publicintsetupSync(@NonNull Consumer<Transaction> syncRequestComplete) { synchronized (mSyncSetLock) { finalintsyncId= mIdCounter++; if (DEBUG) { Log.d(TAG, "setupSync " + syncId); } SyncSetsyncSet=newSyncSet(syncId, transaction -> { synchronized (mSyncSetLock) { mSyncSets.remove(syncId); } syncRequestComplete.accept(transaction); }); mSyncSets.put(syncId, syncSet); return syncId; } }
/** * Add a SurfaceView to a sync set. This is different than {@link #addToSync(int, View)} because * it requires the caller to notify the start and finish drawing in order to sync. * * @param syncId The syncId to add an entry to. * @param surfaceView The SurfaceView to add to the sync. * @param frameCallbackConsumer The callback that's invoked to allow the caller to notify the * Syncer when the SurfaceView has started drawing and finished. * * @return true if the SurfaceView was successfully added to the SyncSet, false otherwise. */ @UiThread publicbooleanaddToSync(int syncId, SurfaceView surfaceView, Consumer<SurfaceViewFrameCallback> frameCallbackConsumer) { return addToSync(syncId, newSurfaceViewSyncTarget(surfaceView, frameCallbackConsumer)); }
/** * Add a View's rootView to a sync set. * * @param syncId The syncId to add an entry to. * @param view The view where the root will be add to the sync set * * @return true if the View was successfully added to the SyncSet, false otherwise. */ @UiThread publicbooleanaddToSync(int syncId, @NonNull View view) { ViewRootImplviewRoot= view.getViewRootImpl(); if (viewRoot == null) { returnfalse; } return addToSync(syncId, viewRoot.mSyncTarget); }
/** * Add a {@link SyncTarget} to a sync set. The sync set will wait for all * SyncableSurfaces to complete before notifying. * * @param syncId The syncId to add an entry to. * @param syncTarget A SyncableSurface that implements how to handle syncing * buffers. * * @return true if the SyncTarget was successfully added to the SyncSet, false otherwise. */ publicbooleanaddToSync(int syncId, @NonNull SyncTarget syncTarget) { SyncSetsyncSet= getAndValidateSyncSet(syncId); if (syncSet == null) { returnfalse; } if (DEBUG) { Log.d(TAG, "addToSync id=" + syncId); } return syncSet.addSyncableSurface(syncTarget); }
/** * Merge another SyncSet into the specified syncId. * @param syncId The current syncId to merge into * @param otherSyncId The other syncId to be merged * @param otherSurfaceSyncer The other SurfaceSyncer where the otherSyncId is from */ publicvoidmerge(int syncId, int otherSyncId, SurfaceSyncer otherSurfaceSyncer) { SyncSet syncSet; synchronized (mSyncSetLock) { syncSet = mSyncSets.get(syncId); }
SyncSetotherSyncSet= otherSurfaceSyncer.getAndValidateSyncSet(otherSyncId); if (otherSyncSet == null) { return; }
/** * Merge a SyncSet into this SyncSet. Since SyncSets could still have pending SyncTargets, * we need to make sure those can still complete before the mergeTo syncSet is considered * complete. * * We keep track of all the merged SyncSets until they are marked as done, and then they * are removed from the set. This SyncSet is not considered done until all the merged * SyncSets are done. * * When the merged SyncSet is complete, it will invoke the original syncRequestComplete * callback but send an empty transaction to ensure the changes are applied early. This * is needed in case the original sync is relying on the callback to continue processing. * * @param otherSyncSet The other SyncSet to merge into this one. */ publicvoidmerge(SyncSet otherSyncSet) { synchronized (mLock) { mMergedSyncSets.add(otherSyncSet); } otherSyncSet.updateCallback(transaction -> { synchronized (mLock) { mMergedSyncSets.remove(otherSyncSet); mTransaction.merge(transaction); checkIfSyncIsComplete(); } }); }
更新callback
将oldCallback做了替换。
其实本质上就了如下操作
1.包装oldCallback通过空Transaction回调
2.实际的Transition回调给
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
publicvoidupdateCallback(Consumer<Transaction> transactionConsumer) { synchronized (mLock) { if (mFinished) { Log.e(TAG, "Attempting to merge SyncSet " + mSyncId + " when sync is" + " already complete"); transactionConsumer.accept(newTransaction()); }