1 /* 2 * Copyright (C) 2021 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 android.window; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.graphics.Matrix; 22 import android.graphics.PointF; 23 import android.graphics.Rect; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 import android.view.SurfaceControl; 27 28 import java.util.Arrays; 29 import java.util.Objects; 30 31 /** 32 * Represents a set of {@link android.view.SurfaceControl.Transaction} operations used to 33 * operate on the {@link android.view.SurfaceControl} for picture-in-picture. 34 * 35 * @hide 36 */ 37 public final class PictureInPictureSurfaceTransaction implements Parcelable { 38 private static final float NOT_SET = -1f; 39 40 public final float mAlpha; 41 public final PointF mPosition; 42 43 public final float[] mFloat9; 44 45 // Though this can be determined by mFloat9, it's easier to set the value directly 46 public final float mRotation; 47 48 public final float mCornerRadius; 49 50 public final float mShadowRadius; 51 52 private final Rect mWindowCrop; 53 54 private boolean mShouldDisableCanAffectSystemUiFlags; 55 PictureInPictureSurfaceTransaction(Parcel in)56 private PictureInPictureSurfaceTransaction(Parcel in) { 57 mAlpha = in.readFloat(); 58 mPosition = in.readTypedObject(PointF.CREATOR); 59 mFloat9 = new float[9]; 60 in.readFloatArray(mFloat9); 61 mRotation = in.readFloat(); 62 mCornerRadius = in.readFloat(); 63 mShadowRadius = in.readFloat(); 64 mWindowCrop = in.readTypedObject(Rect.CREATOR); 65 mShouldDisableCanAffectSystemUiFlags = in.readBoolean(); 66 } 67 PictureInPictureSurfaceTransaction(float alpha, @Nullable PointF position, @Nullable float[] float9, float rotation, float cornerRadius, float shadowRadius, @Nullable Rect windowCrop)68 private PictureInPictureSurfaceTransaction(float alpha, @Nullable PointF position, 69 @Nullable float[] float9, float rotation, float cornerRadius, float shadowRadius, 70 @Nullable Rect windowCrop) { 71 mAlpha = alpha; 72 mPosition = position; 73 if (float9 == null) { 74 mFloat9 = new float[9]; 75 Matrix.IDENTITY_MATRIX.getValues(mFloat9); 76 mRotation = 0; 77 } else { 78 mFloat9 = Arrays.copyOf(float9, 9); 79 mRotation = rotation; 80 } 81 mCornerRadius = cornerRadius; 82 mShadowRadius = shadowRadius; 83 mWindowCrop = (windowCrop == null) ? null : new Rect(windowCrop); 84 } 85 PictureInPictureSurfaceTransaction(PictureInPictureSurfaceTransaction other)86 public PictureInPictureSurfaceTransaction(PictureInPictureSurfaceTransaction other) { 87 this(other.mAlpha, other.mPosition, 88 other.mFloat9, other.mRotation, other.mCornerRadius, other.mShadowRadius, 89 other.mWindowCrop); 90 mShouldDisableCanAffectSystemUiFlags = other.mShouldDisableCanAffectSystemUiFlags; 91 } 92 93 /** @return {@link Matrix} from {@link #mFloat9} */ getMatrix()94 public Matrix getMatrix() { 95 final Matrix matrix = new Matrix(); 96 matrix.setValues(mFloat9); 97 return matrix; 98 } 99 100 /** @return {@code true} if this transaction contains setting corner radius. */ hasCornerRadiusSet()101 public boolean hasCornerRadiusSet() { 102 return mCornerRadius > 0; 103 } 104 105 /** @return {@code true} if this transaction contains setting shadow radius. */ hasShadowRadiusSet()106 public boolean hasShadowRadiusSet() { 107 return mShadowRadius > 0; 108 } 109 110 /** Sets the internal {@link #mShouldDisableCanAffectSystemUiFlags}. */ setShouldDisableCanAffectSystemUiFlags(boolean shouldDisable)111 public void setShouldDisableCanAffectSystemUiFlags(boolean shouldDisable) { 112 mShouldDisableCanAffectSystemUiFlags = shouldDisable; 113 } 114 115 /** @return {@code true} if we should disable Task#setCanAffectSystemUiFlags. */ getShouldDisableCanAffectSystemUiFlags()116 public boolean getShouldDisableCanAffectSystemUiFlags() { 117 return mShouldDisableCanAffectSystemUiFlags; 118 } 119 120 @Override equals(Object o)121 public boolean equals(Object o) { 122 if (this == o) return true; 123 if (!(o instanceof PictureInPictureSurfaceTransaction)) return false; 124 PictureInPictureSurfaceTransaction that = (PictureInPictureSurfaceTransaction) o; 125 return Objects.equals(mAlpha, that.mAlpha) 126 && Objects.equals(mPosition, that.mPosition) 127 && Arrays.equals(mFloat9, that.mFloat9) 128 && Objects.equals(mRotation, that.mRotation) 129 && Objects.equals(mCornerRadius, that.mCornerRadius) 130 && Objects.equals(mShadowRadius, that.mShadowRadius) 131 && Objects.equals(mWindowCrop, that.mWindowCrop) 132 && mShouldDisableCanAffectSystemUiFlags 133 == that.mShouldDisableCanAffectSystemUiFlags; 134 } 135 136 @Override hashCode()137 public int hashCode() { 138 return Objects.hash(mAlpha, mPosition, Arrays.hashCode(mFloat9), 139 mRotation, mCornerRadius, mShadowRadius, mWindowCrop, 140 mShouldDisableCanAffectSystemUiFlags); 141 } 142 143 @Override describeContents()144 public int describeContents() { 145 return 0; 146 } 147 148 @Override writeToParcel(Parcel out, int flags)149 public void writeToParcel(Parcel out, int flags) { 150 out.writeFloat(mAlpha); 151 out.writeTypedObject(mPosition, 0 /* flags */); 152 out.writeFloatArray(mFloat9); 153 out.writeFloat(mRotation); 154 out.writeFloat(mCornerRadius); 155 out.writeFloat(mShadowRadius); 156 out.writeTypedObject(mWindowCrop, 0 /* flags */); 157 out.writeBoolean(mShouldDisableCanAffectSystemUiFlags); 158 } 159 160 @Override toString()161 public String toString() { 162 final Matrix matrix = getMatrix(); 163 return "PictureInPictureSurfaceTransaction(" 164 + " alpha=" + mAlpha 165 + " position=" + mPosition 166 + " matrix=" + matrix.toShortString() 167 + " rotation=" + mRotation 168 + " cornerRadius=" + mCornerRadius 169 + " shadowRadius=" + mShadowRadius 170 + " crop=" + mWindowCrop 171 + " shouldDisableCanAffectSystemUiFlags" + mShouldDisableCanAffectSystemUiFlags 172 + ")"; 173 } 174 175 /** Applies {@link PictureInPictureSurfaceTransaction} to a given leash. */ apply(@onNull PictureInPictureSurfaceTransaction surfaceTransaction, @NonNull SurfaceControl surfaceControl, @NonNull SurfaceControl.Transaction tx)176 public static void apply(@NonNull PictureInPictureSurfaceTransaction surfaceTransaction, 177 @NonNull SurfaceControl surfaceControl, 178 @NonNull SurfaceControl.Transaction tx) { 179 final Matrix matrix = surfaceTransaction.getMatrix(); 180 tx.setMatrix(surfaceControl, matrix, new float[9]); 181 if (surfaceTransaction.mPosition != null) { 182 tx.setPosition(surfaceControl, 183 surfaceTransaction.mPosition.x, surfaceTransaction.mPosition.y); 184 } 185 if (surfaceTransaction.mWindowCrop != null) { 186 tx.setWindowCrop(surfaceControl, surfaceTransaction.mWindowCrop); 187 } 188 if (surfaceTransaction.hasCornerRadiusSet()) { 189 tx.setCornerRadius(surfaceControl, surfaceTransaction.mCornerRadius); 190 } 191 if (surfaceTransaction.hasShadowRadiusSet()) { 192 tx.setShadowRadius(surfaceControl, surfaceTransaction.mShadowRadius); 193 } 194 if (surfaceTransaction.mAlpha != NOT_SET) { 195 tx.setAlpha(surfaceControl, surfaceTransaction.mAlpha); 196 } 197 } 198 199 public static final @android.annotation.NonNull Creator<PictureInPictureSurfaceTransaction> 200 CREATOR = 201 new Creator<PictureInPictureSurfaceTransaction>() { 202 public PictureInPictureSurfaceTransaction createFromParcel(Parcel in) { 203 return new PictureInPictureSurfaceTransaction(in); 204 } 205 public PictureInPictureSurfaceTransaction[] newArray(int size) { 206 return new PictureInPictureSurfaceTransaction[size]; 207 } 208 }; 209 210 public static class Builder { 211 private float mAlpha = NOT_SET; 212 private PointF mPosition; 213 private float[] mFloat9; 214 private float mRotation; 215 private float mCornerRadius = NOT_SET; 216 private float mShadowRadius = NOT_SET; 217 private Rect mWindowCrop; 218 setAlpha(float alpha)219 public Builder setAlpha(float alpha) { 220 mAlpha = alpha; 221 return this; 222 } 223 setPosition(float x, float y)224 public Builder setPosition(float x, float y) { 225 mPosition = new PointF(x, y); 226 return this; 227 } 228 setTransform(@onNull float[] float9, float rotation)229 public Builder setTransform(@NonNull float[] float9, float rotation) { 230 mFloat9 = Arrays.copyOf(float9, 9); 231 mRotation = rotation; 232 return this; 233 } 234 setCornerRadius(float cornerRadius)235 public Builder setCornerRadius(float cornerRadius) { 236 mCornerRadius = cornerRadius; 237 return this; 238 } 239 setShadowRadius(float shadowRadius)240 public Builder setShadowRadius(float shadowRadius) { 241 mShadowRadius = shadowRadius; 242 return this; 243 } 244 setWindowCrop(@onNull Rect windowCrop)245 public Builder setWindowCrop(@NonNull Rect windowCrop) { 246 mWindowCrop = new Rect(windowCrop); 247 return this; 248 } 249 build()250 public PictureInPictureSurfaceTransaction build() { 251 return new PictureInPictureSurfaceTransaction(mAlpha, mPosition, 252 mFloat9, mRotation, mCornerRadius, mShadowRadius, mWindowCrop); 253 } 254 } 255 } 256