Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d8c4603 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Revert "Removing unused surface transaction wrappers"" into tm-qpr-dev

parents f5004fc3 2460910c
Loading
Loading
Loading
Loading
+380 −0
Original line number Diff line number Diff line
/*
 * 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);
            }
        }
    }
}
+108 −0
Original line number Diff line number Diff line
/*
 * 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);
    }
}