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