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 private final Rect mWindowCrop; 51 PictureInPictureSurfaceTransaction(Parcel in)52 private PictureInPictureSurfaceTransaction(Parcel in) { 53 mAlpha = in.readFloat(); 54 mPosition = in.readTypedObject(PointF.CREATOR); 55 mFloat9 = new float[9]; 56 in.readFloatArray(mFloat9); 57 mRotation = in.readFloat(); 58 mCornerRadius = in.readFloat(); 59 mWindowCrop = in.readTypedObject(Rect.CREATOR); 60 } 61 PictureInPictureSurfaceTransaction(float alpha, @Nullable PointF position, @Nullable float[] float9, float rotation, float cornerRadius, @Nullable Rect windowCrop)62 private PictureInPictureSurfaceTransaction(float alpha, @Nullable PointF position, 63 @Nullable float[] float9, float rotation, float cornerRadius, 64 @Nullable Rect windowCrop) { 65 mAlpha = alpha; 66 mPosition = position; 67 if (float9 == null) { 68 mFloat9 = new float[9]; 69 Matrix.IDENTITY_MATRIX.getValues(mFloat9); 70 mRotation = 0; 71 } else { 72 mFloat9 = Arrays.copyOf(float9, 9); 73 mRotation = rotation; 74 } 75 mCornerRadius = cornerRadius; 76 mWindowCrop = (windowCrop == null) ? null : new Rect(windowCrop); 77 } 78 PictureInPictureSurfaceTransaction(PictureInPictureSurfaceTransaction other)79 public PictureInPictureSurfaceTransaction(PictureInPictureSurfaceTransaction other) { 80 this(other.mAlpha, other.mPosition, 81 other.mFloat9, other.mRotation, other.mCornerRadius, other.mWindowCrop); 82 } 83 84 /** @return {@link Matrix} from {@link #mFloat9} */ getMatrix()85 public Matrix getMatrix() { 86 final Matrix matrix = new Matrix(); 87 matrix.setValues(mFloat9); 88 return matrix; 89 } 90 91 /** @return {@code true} if this transaction contains setting corner radius. */ hasCornerRadiusSet()92 public boolean hasCornerRadiusSet() { 93 return mCornerRadius > 0; 94 } 95 96 @Override equals(Object o)97 public boolean equals(Object o) { 98 if (this == o) return true; 99 if (!(o instanceof PictureInPictureSurfaceTransaction)) return false; 100 PictureInPictureSurfaceTransaction that = (PictureInPictureSurfaceTransaction) o; 101 return Objects.equals(mAlpha, that.mAlpha) 102 && Objects.equals(mPosition, that.mPosition) 103 && Arrays.equals(mFloat9, that.mFloat9) 104 && Objects.equals(mRotation, that.mRotation) 105 && Objects.equals(mCornerRadius, that.mCornerRadius) 106 && Objects.equals(mWindowCrop, that.mWindowCrop); 107 } 108 109 @Override hashCode()110 public int hashCode() { 111 return Objects.hash(mAlpha, mPosition, Arrays.hashCode(mFloat9), 112 mRotation, mCornerRadius, mWindowCrop); 113 } 114 115 @Override describeContents()116 public int describeContents() { 117 return 0; 118 } 119 120 @Override writeToParcel(Parcel out, int flags)121 public void writeToParcel(Parcel out, int flags) { 122 out.writeFloat(mAlpha); 123 out.writeTypedObject(mPosition, 0 /* flags */); 124 out.writeFloatArray(mFloat9); 125 out.writeFloat(mRotation); 126 out.writeFloat(mCornerRadius); 127 out.writeTypedObject(mWindowCrop, 0 /* flags */); 128 } 129 130 @Override toString()131 public String toString() { 132 final Matrix matrix = getMatrix(); 133 return "PictureInPictureSurfaceTransaction(" 134 + " alpha=" + mAlpha 135 + " position=" + mPosition 136 + " matrix=" + matrix.toShortString() 137 + " rotation=" + mRotation 138 + " cornerRadius=" + mCornerRadius 139 + " crop=" + mWindowCrop 140 + ")"; 141 } 142 143 /** Applies {@link PictureInPictureSurfaceTransaction} to a given leash. */ apply(@onNull PictureInPictureSurfaceTransaction surfaceTransaction, @NonNull SurfaceControl surfaceControl, @NonNull SurfaceControl.Transaction tx)144 public static void apply(@NonNull PictureInPictureSurfaceTransaction surfaceTransaction, 145 @NonNull SurfaceControl surfaceControl, 146 @NonNull SurfaceControl.Transaction tx) { 147 final Matrix matrix = surfaceTransaction.getMatrix(); 148 tx.setMatrix(surfaceControl, matrix, new float[9]); 149 if (surfaceTransaction.mPosition != null) { 150 tx.setPosition(surfaceControl, 151 surfaceTransaction.mPosition.x, surfaceTransaction.mPosition.y); 152 } 153 if (surfaceTransaction.mWindowCrop != null) { 154 tx.setWindowCrop(surfaceControl, surfaceTransaction.mWindowCrop); 155 } 156 if (surfaceTransaction.hasCornerRadiusSet()) { 157 tx.setCornerRadius(surfaceControl, surfaceTransaction.mCornerRadius); 158 } 159 if (surfaceTransaction.mAlpha != NOT_SET) { 160 tx.setAlpha(surfaceControl, surfaceTransaction.mAlpha); 161 } 162 } 163 164 public static final @android.annotation.NonNull Creator<PictureInPictureSurfaceTransaction> 165 CREATOR = 166 new Creator<PictureInPictureSurfaceTransaction>() { 167 public PictureInPictureSurfaceTransaction createFromParcel(Parcel in) { 168 return new PictureInPictureSurfaceTransaction(in); 169 } 170 public PictureInPictureSurfaceTransaction[] newArray(int size) { 171 return new PictureInPictureSurfaceTransaction[size]; 172 } 173 }; 174 175 public static class Builder { 176 private float mAlpha = NOT_SET; 177 private PointF mPosition; 178 private float[] mFloat9; 179 private float mRotation; 180 private float mCornerRadius = NOT_SET; 181 private Rect mWindowCrop; 182 setAlpha(float alpha)183 public Builder setAlpha(float alpha) { 184 mAlpha = alpha; 185 return this; 186 } 187 setPosition(float x, float y)188 public Builder setPosition(float x, float y) { 189 mPosition = new PointF(x, y); 190 return this; 191 } 192 setTransform(@onNull float[] float9, float rotation)193 public Builder setTransform(@NonNull float[] float9, float rotation) { 194 mFloat9 = Arrays.copyOf(float9, 9); 195 mRotation = rotation; 196 return this; 197 } 198 setCornerRadius(float cornerRadius)199 public Builder setCornerRadius(float cornerRadius) { 200 mCornerRadius = cornerRadius; 201 return this; 202 } 203 setWindowCrop(@onNull Rect windowCrop)204 public Builder setWindowCrop(@NonNull Rect windowCrop) { 205 mWindowCrop = new Rect(windowCrop); 206 return this; 207 } 208 build()209 public PictureInPictureSurfaceTransaction build() { 210 return new PictureInPictureSurfaceTransaction(mAlpha, mPosition, 211 mFloat9, mRotation, mCornerRadius, mWindowCrop); 212 } 213 } 214 } 215