1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.systemui.shared.system;
18 
19 import android.graphics.Matrix;
20 import android.graphics.Rect;
21 import android.view.Surface;
22 import android.view.SurfaceControl;
23 import android.view.SurfaceControl.Transaction;
24 import android.view.View;
25 import android.view.ViewRootImpl;
26 
27 /**
28  * Helper class to apply surface transactions in sync with RenderThread.
29  */
30 public class SyncRtSurfaceTransactionApplier {
31 
32     private final Surface mTargetSurface;
33     private final ViewRootImpl mTargetViewRootImpl;
34     private final float[] mTmpFloat9 = new float[9];
35 
36     /**
37      * @param targetView The view in the surface that acts as synchronization anchor.
38      */
SyncRtSurfaceTransactionApplier(View targetView)39     public SyncRtSurfaceTransactionApplier(View targetView) {
40         mTargetViewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
41         mTargetSurface = mTargetViewRootImpl != null ? mTargetViewRootImpl.mSurface : null;
42     }
43 
44     /**
45      * Schedules applying surface parameters on the next frame.
46      *
47      * @param params The surface parameters to apply. DO NOT MODIFY the list after passing into
48      *               this method to avoid synchronization issues.
49      */
scheduleApply(SurfaceParams... params)50     public void scheduleApply(SurfaceParams... params) {
51         if (mTargetViewRootImpl == null) {
52             return;
53         }
54         mTargetViewRootImpl.registerRtFrameCallback(frame -> {
55                 if (mTargetSurface == null || !mTargetSurface.isValid()) {
56                     return;
57                 }
58                 Transaction t = new Transaction();
59                 for (int i = params.length - 1; i >= 0; i--) {
60                     SurfaceParams surfaceParams = params[i];
61                     SurfaceControl surface = surfaceParams.surface;
62                     t.deferTransactionUntilSurface(surface, mTargetSurface, frame);
63                     applyParams(t, surfaceParams, mTmpFloat9);
64                 }
65                 t.setEarlyWakeup();
66                 t.apply();
67         });
68 
69         // Make sure a frame gets scheduled.
70         mTargetViewRootImpl.getView().invalidate();
71     }
72 
applyParams(TransactionCompat t, SurfaceParams params)73     public static void applyParams(TransactionCompat t, SurfaceParams params) {
74         applyParams(t.mTransaction, params, t.mTmpValues);
75     }
76 
applyParams(Transaction t, SurfaceParams params, float[] tmpFloat9)77     private static void applyParams(Transaction t, SurfaceParams params, float[] tmpFloat9) {
78         t.setMatrix(params.surface, params.matrix, tmpFloat9);
79         t.setWindowCrop(params.surface, params.windowCrop);
80         t.setAlpha(params.surface, params.alpha);
81         t.setLayer(params.surface, params.layer);
82         t.show(params.surface);
83     }
84 
85     public static class SurfaceParams {
86 
87         /**
88          * Constructs surface parameters to be applied when the current view state gets pushed to
89          * RenderThread.
90          *
91          * @param surface The surface to modify.
92          * @param alpha Alpha to apply.
93          * @param matrix Matrix to apply.
94          * @param windowCrop Crop to apply.
95          */
SurfaceParams(SurfaceControlCompat surface, float alpha, Matrix matrix, Rect windowCrop, int layer)96         public SurfaceParams(SurfaceControlCompat surface, float alpha, Matrix matrix,
97                 Rect windowCrop, int layer) {
98             this.surface = surface.mSurfaceControl;
99             this.alpha = alpha;
100             this.matrix = new Matrix(matrix);
101             this.windowCrop = new Rect(windowCrop);
102             this.layer = layer;
103         }
104 
105         final SurfaceControl surface;
106         final float alpha;
107         final Matrix matrix;
108         final Rect windowCrop;
109         final int layer;
110     }
111 }
112