diff options
2 files changed, 488 insertions, 0 deletions
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java new file mode 100644 index 000000000000..30c062b66da9 --- /dev/null +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.shared.system; + +import android.graphics.HardwareRenderer; +import android.graphics.Matrix; +import android.graphics.Rect; +import android.os.Handler; +import android.os.Handler.Callback; +import android.os.Message; +import android.os.Trace; +import android.view.SurfaceControl; +import android.view.SurfaceControl.Transaction; +import android.view.View; +import android.view.ViewRootImpl; + +import java.util.function.Consumer; + +/** + * Helper class to apply surface transactions in sync with RenderThread. + * + * NOTE: This is a modification of {@link android.view.SyncRtSurfaceTransactionApplier}, we can't + * currently reference that class from the shared lib as it is hidden. + */ +public class SyncRtSurfaceTransactionApplierCompat { + + public static final int FLAG_ALL = 0xffffffff; + public static final int FLAG_ALPHA = 1; + public static final int FLAG_MATRIX = 1 << 1; + public static final int FLAG_WINDOW_CROP = 1 << 2; + public static final int FLAG_LAYER = 1 << 3; + public static final int FLAG_CORNER_RADIUS = 1 << 4; + public static final int FLAG_BACKGROUND_BLUR_RADIUS = 1 << 5; + public static final int FLAG_VISIBILITY = 1 << 6; + public static final int FLAG_RELATIVE_LAYER = 1 << 7; + public static final int FLAG_SHADOW_RADIUS = 1 << 8; + + private static final int MSG_UPDATE_SEQUENCE_NUMBER = 0; + + private final SurfaceControl mBarrierSurfaceControl; + private final ViewRootImpl mTargetViewRootImpl; + private final Handler mApplyHandler; + + private int mSequenceNumber = 0; + private int mPendingSequenceNumber = 0; + private Runnable mAfterApplyCallback; + + /** + * @param targetView The view in the surface that acts as synchronization anchor. + */ + public SyncRtSurfaceTransactionApplierCompat(View targetView) { + mTargetViewRootImpl = targetView != null ? targetView.getViewRootImpl() : null; + mBarrierSurfaceControl = mTargetViewRootImpl != null + ? mTargetViewRootImpl.getSurfaceControl() : null; + + mApplyHandler = new Handler(new Callback() { + @Override + public boolean handleMessage(Message msg) { + if (msg.what == MSG_UPDATE_SEQUENCE_NUMBER) { + onApplyMessage(msg.arg1); + return true; + } + return false; + } + }); + } + + private void onApplyMessage(int seqNo) { + mSequenceNumber = seqNo; + if (mSequenceNumber == mPendingSequenceNumber && mAfterApplyCallback != null) { + Runnable r = mAfterApplyCallback; + mAfterApplyCallback = null; + r.run(); + } + } + + /** + * Schedules applying surface parameters on the next frame. + * + * @param params The surface parameters to apply. DO NOT MODIFY the list after passing into + * this method to avoid synchronization issues. + */ + public void scheduleApply(final SyncRtSurfaceTransactionApplierCompat.SurfaceParams... params) { + if (mTargetViewRootImpl == null || mTargetViewRootImpl.getView() == null) { + return; + } + + mPendingSequenceNumber++; + final int toApplySeqNo = mPendingSequenceNumber; + mTargetViewRootImpl.registerRtFrameCallback(new HardwareRenderer.FrameDrawingCallback() { + @Override + public void onFrameDraw(long frame) { + if (mBarrierSurfaceControl == null || !mBarrierSurfaceControl.isValid()) { + Message.obtain(mApplyHandler, MSG_UPDATE_SEQUENCE_NUMBER, toApplySeqNo, 0) + .sendToTarget(); + return; + } + Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Sync transaction frameNumber=" + frame); + Transaction t = new Transaction(); + for (int i = params.length - 1; i >= 0; i--) { + SyncRtSurfaceTransactionApplierCompat.SurfaceParams surfaceParams = + params[i]; + surfaceParams.applyTo(t); + } + if (mTargetViewRootImpl != null) { + mTargetViewRootImpl.mergeWithNextTransaction(t, frame); + } else { + t.apply(); + } + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + Message.obtain(mApplyHandler, MSG_UPDATE_SEQUENCE_NUMBER, toApplySeqNo, 0) + .sendToTarget(); + } + }); + + // Make sure a frame gets scheduled. + mTargetViewRootImpl.getView().invalidate(); + } + + /** + * Calls the runnable when any pending apply calls have completed + */ + public void addAfterApplyCallback(final Runnable afterApplyCallback) { + if (mSequenceNumber == mPendingSequenceNumber) { + afterApplyCallback.run(); + } else { + if (mAfterApplyCallback == null) { + mAfterApplyCallback = afterApplyCallback; + } else { + final Runnable oldCallback = mAfterApplyCallback; + mAfterApplyCallback = new Runnable() { + @Override + public void run() { + afterApplyCallback.run(); + oldCallback.run(); + } + }; + } + } + } + + public static void applyParams(TransactionCompat t, + SyncRtSurfaceTransactionApplierCompat.SurfaceParams params) { + params.applyTo(t.mTransaction); + } + + /** + * Creates an instance of SyncRtSurfaceTransactionApplier, deferring until the target view is + * attached if necessary. + */ + public static void create(final View targetView, + final Consumer<SyncRtSurfaceTransactionApplierCompat> callback) { + if (targetView == null) { + // No target view, no applier + callback.accept(null); + } else if (targetView.getViewRootImpl() != null) { + // Already attached, we're good to go + callback.accept(new SyncRtSurfaceTransactionApplierCompat(targetView)); + } else { + // Haven't been attached before we can get the view root + targetView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View v) { + targetView.removeOnAttachStateChangeListener(this); + callback.accept(new SyncRtSurfaceTransactionApplierCompat(targetView)); + } + + @Override + public void onViewDetachedFromWindow(View v) { + // Do nothing + } + }); + } + } + + public static class SurfaceParams { + public static class Builder { + final SurfaceControl surface; + int flags; + float alpha; + float cornerRadius; + int backgroundBlurRadius; + Matrix matrix; + Rect windowCrop; + int layer; + SurfaceControl relativeTo; + int relativeLayer; + boolean visible; + float shadowRadius; + + /** + * @param surface The surface to modify. + */ + public Builder(SurfaceControl surface) { + this.surface = surface; + } + + /** + * @param alpha The alpha value to apply to the surface. + * @return this Builder + */ + public Builder withAlpha(float alpha) { + this.alpha = alpha; + flags |= FLAG_ALPHA; + return this; + } + + /** + * @param matrix The matrix to apply to the surface. + * @return this Builder + */ + public Builder withMatrix(Matrix matrix) { + this.matrix = new Matrix(matrix); + flags |= FLAG_MATRIX; + return this; + } + + /** + * @param windowCrop The window crop to apply to the surface. + * @return this Builder + */ + public Builder withWindowCrop(Rect windowCrop) { + this.windowCrop = new Rect(windowCrop); + flags |= FLAG_WINDOW_CROP; + return this; + } + + /** + * @param layer The layer to assign the surface. + * @return this Builder + */ + public Builder withLayer(int layer) { + this.layer = layer; + flags |= FLAG_LAYER; + return this; + } + + /** + * @param relativeTo The surface that's set relative layer to. + * @param relativeLayer The relative layer. + * @return this Builder + */ + public Builder withRelativeLayerTo(SurfaceControl relativeTo, int relativeLayer) { + this.relativeTo = relativeTo; + this.relativeLayer = relativeLayer; + flags |= FLAG_RELATIVE_LAYER; + return this; + } + + /** + * @param radius the Radius for rounded corners to apply to the surface. + * @return this Builder + */ + public Builder withCornerRadius(float radius) { + this.cornerRadius = radius; + flags |= FLAG_CORNER_RADIUS; + return this; + } + + /** + * @param radius the Radius for the shadows to apply to the surface. + * @return this Builder + */ + public Builder withShadowRadius(float radius) { + this.shadowRadius = radius; + flags |= FLAG_SHADOW_RADIUS; + return this; + } + + /** + * @param radius the Radius for blur to apply to the background surfaces. + * @return this Builder + */ + public Builder withBackgroundBlur(int radius) { + this.backgroundBlurRadius = radius; + flags |= FLAG_BACKGROUND_BLUR_RADIUS; + return this; + } + + /** + * @param visible The visibility to apply to the surface. + * @return this Builder + */ + public Builder withVisibility(boolean visible) { + this.visible = visible; + flags |= FLAG_VISIBILITY; + return this; + } + + /** + * @return a new SurfaceParams instance + */ + public SurfaceParams build() { + return new SurfaceParams(surface, flags, alpha, matrix, windowCrop, layer, + relativeTo, relativeLayer, cornerRadius, backgroundBlurRadius, visible, + shadowRadius); + } + } + + private SurfaceParams(SurfaceControl surface, int flags, float alpha, Matrix matrix, + Rect windowCrop, int layer, SurfaceControl relativeTo, int relativeLayer, + float cornerRadius, int backgroundBlurRadius, boolean visible, float shadowRadius) { + this.flags = flags; + this.surface = surface; + this.alpha = alpha; + this.matrix = matrix; + this.windowCrop = windowCrop; + this.layer = layer; + this.relativeTo = relativeTo; + this.relativeLayer = relativeLayer; + this.cornerRadius = cornerRadius; + this.backgroundBlurRadius = backgroundBlurRadius; + this.visible = visible; + this.shadowRadius = shadowRadius; + } + + private final int flags; + private final float[] mTmpValues = new float[9]; + + public final SurfaceControl surface; + public final float alpha; + public final float cornerRadius; + public final int backgroundBlurRadius; + public final Matrix matrix; + public final Rect windowCrop; + public final int layer; + public final SurfaceControl relativeTo; + public final int relativeLayer; + public final boolean visible; + public final float shadowRadius; + + public void applyTo(SurfaceControl.Transaction t) { + if ((flags & FLAG_MATRIX) != 0) { + t.setMatrix(surface, matrix, mTmpValues); + } + if ((flags & FLAG_WINDOW_CROP) != 0) { + t.setWindowCrop(surface, windowCrop); + } + if ((flags & FLAG_ALPHA) != 0) { + t.setAlpha(surface, alpha); + } + if ((flags & FLAG_LAYER) != 0) { + t.setLayer(surface, layer); + } + if ((flags & FLAG_CORNER_RADIUS) != 0) { + t.setCornerRadius(surface, cornerRadius); + } + if ((flags & FLAG_BACKGROUND_BLUR_RADIUS) != 0) { + t.setBackgroundBlurRadius(surface, backgroundBlurRadius); + } + if ((flags & FLAG_VISIBILITY) != 0) { + if (visible) { + t.show(surface); + } else { + t.hide(surface); + } + } + if ((flags & FLAG_RELATIVE_LAYER) != 0) { + t.setRelativeLayer(surface, relativeTo, relativeLayer); + } + if ((flags & FLAG_SHADOW_RADIUS) != 0) { + t.setShadowRadius(surface, shadowRadius); + } + } + } +} diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java new file mode 100644 index 000000000000..43a882a5f6be --- /dev/null +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.shared.system; + +import android.graphics.Matrix; +import android.graphics.Rect; +import android.view.SurfaceControl; +import android.view.SurfaceControl.Transaction; + +public class TransactionCompat { + + final Transaction mTransaction; + + final float[] mTmpValues = new float[9]; + + public TransactionCompat() { + mTransaction = new Transaction(); + } + + public void apply() { + mTransaction.apply(); + } + + public TransactionCompat show(SurfaceControl surfaceControl) { + mTransaction.show(surfaceControl); + return this; + } + + public TransactionCompat hide(SurfaceControl surfaceControl) { + mTransaction.hide(surfaceControl); + return this; + } + + public TransactionCompat setPosition(SurfaceControl surfaceControl, float x, float y) { + mTransaction.setPosition(surfaceControl, x, y); + return this; + } + + public TransactionCompat setSize(SurfaceControl surfaceControl, int w, int h) { + mTransaction.setBufferSize(surfaceControl, w, h); + return this; + } + + public TransactionCompat setLayer(SurfaceControl surfaceControl, int z) { + mTransaction.setLayer(surfaceControl, z); + return this; + } + + public TransactionCompat setAlpha(SurfaceControl surfaceControl, float alpha) { + mTransaction.setAlpha(surfaceControl, alpha); + return this; + } + + public TransactionCompat setOpaque(SurfaceControl surfaceControl, boolean opaque) { + mTransaction.setOpaque(surfaceControl, opaque); + return this; + } + + public TransactionCompat setMatrix(SurfaceControl surfaceControl, float dsdx, float dtdx, + float dtdy, float dsdy) { + mTransaction.setMatrix(surfaceControl, dsdx, dtdx, dtdy, dsdy); + return this; + } + + public TransactionCompat setMatrix(SurfaceControl surfaceControl, Matrix matrix) { + mTransaction.setMatrix(surfaceControl, matrix, mTmpValues); + return this; + } + + public TransactionCompat setWindowCrop(SurfaceControl surfaceControl, Rect crop) { + mTransaction.setWindowCrop(surfaceControl, crop); + return this; + } + + public TransactionCompat setCornerRadius(SurfaceControl surfaceControl, float radius) { + mTransaction.setCornerRadius(surfaceControl, radius); + return this; + } + + public TransactionCompat setBackgroundBlurRadius(SurfaceControl surfaceControl, int radius) { + mTransaction.setBackgroundBlurRadius(surfaceControl, radius); + return this; + } + + public TransactionCompat setColor(SurfaceControl surfaceControl, float[] color) { + mTransaction.setColor(surfaceControl, color); + return this; + } + + public static void setRelativeLayer(Transaction t, SurfaceControl surfaceControl, + SurfaceControl relativeTo, int z) { + t.setRelativeLayer(surfaceControl, relativeTo, z); + } +} |