1 /* 2 * Copyright (C) 2024 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.animation; 18 19 import android.graphics.Matrix; 20 import android.graphics.Rect; 21 import android.graphics.RectF; 22 import android.view.SurfaceControl; 23 24 import java.util.ArrayList; 25 import java.util.Arrays; 26 import java.util.Collection; 27 import java.util.concurrent.Executor; 28 29 /** 30 * A {@link UIComponent} representing a {@link SurfaceControl}. 31 * @hide 32 */ 33 public class SurfaceUIComponent implements UIComponent { 34 private final Collection<SurfaceControl> mSurfaces; 35 private final Rect mBaseBounds; 36 private final float[] mFloat9 = new float[9]; 37 38 private float mAlpha; 39 private boolean mVisible; 40 private Rect mBounds; 41 SurfaceUIComponent( SurfaceControl sc, float alpha, boolean visible, Rect bounds, Rect baseBounds)42 public SurfaceUIComponent( 43 SurfaceControl sc, float alpha, boolean visible, Rect bounds, Rect baseBounds) { 44 this(Arrays.asList(sc), alpha, visible, bounds, baseBounds); 45 } 46 SurfaceUIComponent( Collection<SurfaceControl> surfaces, float alpha, boolean visible, Rect bounds, Rect baseBounds)47 public SurfaceUIComponent( 48 Collection<SurfaceControl> surfaces, 49 float alpha, 50 boolean visible, 51 Rect bounds, 52 Rect baseBounds) { 53 mSurfaces = surfaces; 54 mAlpha = alpha; 55 mVisible = visible; 56 mBounds = bounds; 57 mBaseBounds = baseBounds; 58 } 59 60 @Override getAlpha()61 public float getAlpha() { 62 return mAlpha; 63 } 64 65 @Override isVisible()66 public boolean isVisible() { 67 return mVisible; 68 } 69 70 @Override getBounds()71 public Rect getBounds() { 72 return mBounds; 73 } 74 75 @Override newTransaction()76 public Transaction newTransaction() { 77 return new Transaction(new SurfaceControl.Transaction()); 78 } 79 80 @Override toString()81 public String toString() { 82 return "SurfaceUIComponent{mSurfaces=" 83 + mSurfaces 84 + ", mAlpha=" 85 + mAlpha 86 + ", mVisible=" 87 + mVisible 88 + ", mBounds=" 89 + mBounds 90 + ", mBaseBounds=" 91 + mBaseBounds 92 + "}"; 93 } 94 95 /** 96 * A {@link Transaction} wrapping a {@link SurfaceControl.Transaction}. 97 * @hide 98 */ 99 public static class Transaction implements UIComponent.Transaction<SurfaceUIComponent> { 100 private final SurfaceControl.Transaction mTransaction; 101 private final ArrayList<Runnable> mChanges = new ArrayList<>(); 102 Transaction(SurfaceControl.Transaction transaction)103 public Transaction(SurfaceControl.Transaction transaction) { 104 mTransaction = transaction; 105 } 106 107 @Override setAlpha(SurfaceUIComponent ui, float alpha)108 public Transaction setAlpha(SurfaceUIComponent ui, float alpha) { 109 mChanges.add( 110 () -> { 111 ui.mAlpha = alpha; 112 ui.mSurfaces.forEach(s -> mTransaction.setAlpha(s, alpha)); 113 }); 114 return this; 115 } 116 117 @Override setVisible(SurfaceUIComponent ui, boolean visible)118 public Transaction setVisible(SurfaceUIComponent ui, boolean visible) { 119 mChanges.add( 120 () -> { 121 ui.mVisible = visible; 122 if (visible) { 123 ui.mSurfaces.forEach(s -> mTransaction.show(s)); 124 } else { 125 ui.mSurfaces.forEach(s -> mTransaction.hide(s)); 126 } 127 }); 128 return this; 129 } 130 131 @Override setBounds(SurfaceUIComponent ui, Rect bounds)132 public Transaction setBounds(SurfaceUIComponent ui, Rect bounds) { 133 mChanges.add( 134 () -> { 135 if (ui.mBounds.equals(bounds)) { 136 return; 137 } 138 ui.mBounds = bounds; 139 Matrix matrix = new Matrix(); 140 matrix.setRectToRect( 141 new RectF(ui.mBaseBounds), 142 new RectF(ui.mBounds), 143 Matrix.ScaleToFit.FILL); 144 ui.mSurfaces.forEach(s -> mTransaction.setMatrix(s, matrix, ui.mFloat9)); 145 }); 146 return this; 147 } 148 149 @Override attachToTransitionLeash( SurfaceUIComponent ui, SurfaceControl transitionLeash, int w, int h)150 public Transaction attachToTransitionLeash( 151 SurfaceUIComponent ui, SurfaceControl transitionLeash, int w, int h) { 152 mChanges.add( 153 () -> ui.mSurfaces.forEach(s -> mTransaction.reparent(s, transitionLeash))); 154 return this; 155 } 156 157 @Override detachFromTransitionLeash( SurfaceUIComponent ui, Executor executor, Runnable onDone)158 public Transaction detachFromTransitionLeash( 159 SurfaceUIComponent ui, Executor executor, Runnable onDone) { 160 mChanges.add( 161 () -> { 162 ui.mSurfaces.forEach(s -> mTransaction.reparent(s, null)); 163 mTransaction.addTransactionCommittedListener(executor, onDone::run); 164 }); 165 return this; 166 } 167 168 @Override commit()169 public void commit() { 170 mChanges.forEach(Runnable::run); 171 mChanges.clear(); 172 mTransaction.apply(); 173 } 174 } 175 } 176