1 /* 2 * Copyright (C) 2022 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.view; 18 19 import static android.view.Display.INVALID_DISPLAY; 20 21 import android.annotation.IntDef; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.os.IBinder; 25 import android.os.Parcel; 26 import android.os.Parcelable; 27 28 import com.android.internal.util.DataClass; 29 30 import java.lang.annotation.Retention; 31 import java.lang.annotation.RetentionPolicy; 32 33 /** 34 * Description of a content recording session. 35 * 36 * @hide 37 */ 38 @DataClass( 39 genConstructor = false, 40 genToString = true, 41 genSetters = true, 42 genEqualsHashCode = true 43 ) 44 public final class ContentRecordingSession implements Parcelable { 45 46 /** 47 * An entire DisplayContent is being recorded. Recording may also be paused. 48 */ 49 public static final int RECORD_CONTENT_DISPLAY = 0; 50 /** 51 * A single Task is being recorded. Recording may also be paused. 52 */ 53 public static final int RECORD_CONTENT_TASK = 1; 54 55 /** 56 * Unique logical identifier of the {@link android.hardware.display.VirtualDisplay} that has 57 * recorded content rendered to its surface. 58 */ 59 private int mVirtualDisplayId = INVALID_DISPLAY; 60 61 /** 62 * The content to record. 63 */ 64 @RecordContent 65 private int mContentToRecord = RECORD_CONTENT_DISPLAY; 66 67 /** 68 * Unique logical identifier of the {@link android.view.Display} to record. 69 * 70 * <p>If {@link #getContentToRecord()} is {@link RecordContent#RECORD_CONTENT_DISPLAY}, then is 71 * a valid display id. 72 */ 73 private int mDisplayToRecord = INVALID_DISPLAY; 74 75 /** 76 * The token of the layer of the hierarchy to record. 77 * 78 * <p>If {@link #getContentToRecord()} is {@link RecordContent#RECORD_CONTENT_TASK}, then 79 * represents the {@link android.window.WindowContainerToken} of the Task to record. 80 */ 81 @Nullable 82 private IBinder mTokenToRecord = null; 83 84 /** 85 * When {@code true}, no mirroring should take place until the user has re-granted access to 86 * the consent token. When {@code false}, recording can begin immediately. 87 * 88 * <p>Only set on the server side to sanitize any input from the client process. 89 */ 90 private boolean mWaitingForConsent = false; 91 92 /** 93 * Default instance, with recording the display. 94 */ ContentRecordingSession()95 private ContentRecordingSession() { 96 } 97 98 /** 99 * Returns an instance initialized for recording the indicated display. 100 */ createDisplaySession(int displayToMirror)101 public static ContentRecordingSession createDisplaySession(int displayToMirror) { 102 return new ContentRecordingSession().setDisplayToRecord(displayToMirror) 103 .setContentToRecord(RECORD_CONTENT_DISPLAY); 104 } 105 106 /** 107 * Returns an instance initialized for task recording. 108 */ createTaskSession( @onNull IBinder taskWindowContainerToken)109 public static ContentRecordingSession createTaskSession( 110 @NonNull IBinder taskWindowContainerToken) { 111 return new ContentRecordingSession().setContentToRecord(RECORD_CONTENT_TASK) 112 .setTokenToRecord(taskWindowContainerToken); 113 } 114 115 /** 116 * Returns {@code true} if this is a valid session. 117 * 118 * <p>A valid session has a non-null token for task recording, or a valid id for the display to 119 * record. 120 */ isValid(ContentRecordingSession session)121 public static boolean isValid(ContentRecordingSession session) { 122 if (session == null) { 123 return false; 124 } 125 final boolean isValidTaskSession = session.getContentToRecord() == RECORD_CONTENT_TASK 126 && session.getTokenToRecord() != null; 127 final boolean isValidDisplaySession = session.getContentToRecord() == RECORD_CONTENT_DISPLAY 128 && session.getDisplayToRecord() > INVALID_DISPLAY; 129 return session.getVirtualDisplayId() > INVALID_DISPLAY 130 && (isValidTaskSession || isValidDisplaySession); 131 } 132 133 /** 134 * Returns {@code true} when both sessions are on the same 135 * {@link android.hardware.display.VirtualDisplay}. 136 */ isProjectionOnSameDisplay(ContentRecordingSession session, ContentRecordingSession incomingSession)137 public static boolean isProjectionOnSameDisplay(ContentRecordingSession session, 138 ContentRecordingSession incomingSession) { 139 return session != null && incomingSession != null 140 && session.getVirtualDisplayId() == incomingSession.getVirtualDisplayId(); 141 } 142 143 144 145 146 // Code below generated by codegen v1.0.23. 147 // 148 // DO NOT MODIFY! 149 // CHECKSTYLE:OFF Generated code 150 // 151 // To regenerate run: 152 // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/ContentRecordingSession.java 153 // 154 // To exclude the generated code from IntelliJ auto-formatting enable (one-time): 155 // Settings > Editor > Code Style > Formatter Control 156 //@formatter:off 157 158 159 @IntDef(prefix = "RECORD_CONTENT_", value = { 160 RECORD_CONTENT_DISPLAY, 161 RECORD_CONTENT_TASK 162 }) 163 @Retention(RetentionPolicy.SOURCE) 164 @DataClass.Generated.Member 165 public @interface RecordContent {} 166 167 @DataClass.Generated.Member recordContentToString(@ecordContent int value)168 public static String recordContentToString(@RecordContent int value) { 169 switch (value) { 170 case RECORD_CONTENT_DISPLAY: 171 return "RECORD_CONTENT_DISPLAY"; 172 case RECORD_CONTENT_TASK: 173 return "RECORD_CONTENT_TASK"; 174 default: return Integer.toHexString(value); 175 } 176 } 177 178 @DataClass.Generated.Member ContentRecordingSession( int virtualDisplayId, @RecordContent int contentToRecord, int displayToRecord, @Nullable IBinder tokenToRecord, boolean waitingForConsent)179 /* package-private */ ContentRecordingSession( 180 int virtualDisplayId, 181 @RecordContent int contentToRecord, 182 int displayToRecord, 183 @Nullable IBinder tokenToRecord, 184 boolean waitingForConsent) { 185 this.mVirtualDisplayId = virtualDisplayId; 186 this.mContentToRecord = contentToRecord; 187 188 if (!(mContentToRecord == RECORD_CONTENT_DISPLAY) 189 && !(mContentToRecord == RECORD_CONTENT_TASK)) { 190 throw new java.lang.IllegalArgumentException( 191 "contentToRecord was " + mContentToRecord + " but must be one of: " 192 + "RECORD_CONTENT_DISPLAY(" + RECORD_CONTENT_DISPLAY + "), " 193 + "RECORD_CONTENT_TASK(" + RECORD_CONTENT_TASK + ")"); 194 } 195 196 this.mDisplayToRecord = displayToRecord; 197 this.mTokenToRecord = tokenToRecord; 198 this.mWaitingForConsent = waitingForConsent; 199 200 // onConstructed(); // You can define this method to get a callback 201 } 202 203 /** 204 * Unique logical identifier of the {@link android.hardware.display.VirtualDisplay} that has 205 * recorded content rendered to its surface. 206 */ 207 @DataClass.Generated.Member getVirtualDisplayId()208 public int getVirtualDisplayId() { 209 return mVirtualDisplayId; 210 } 211 212 /** 213 * The content to record. 214 */ 215 @DataClass.Generated.Member getContentToRecord()216 public @RecordContent int getContentToRecord() { 217 return mContentToRecord; 218 } 219 220 /** 221 * Unique logical identifier of the {@link android.view.Display} to record. 222 * 223 * <p>If {@link #getContentToRecord()} is {@link RecordContent#RECORD_CONTENT_DISPLAY}, then is 224 * a valid display id. 225 */ 226 @DataClass.Generated.Member getDisplayToRecord()227 public int getDisplayToRecord() { 228 return mDisplayToRecord; 229 } 230 231 /** 232 * The token of the layer of the hierarchy to record. 233 * 234 * <p>If {@link #getContentToRecord()} is {@link RecordContent#RECORD_CONTENT_TASK}, then 235 * represents the {@link android.window.WindowContainerToken} of the Task to record. 236 */ 237 @DataClass.Generated.Member getTokenToRecord()238 public @Nullable IBinder getTokenToRecord() { 239 return mTokenToRecord; 240 } 241 242 /** 243 * When {@code true}, no mirroring should take place until the user has re-granted access to 244 * the consent token. When {@code false}, recording can begin immediately. 245 * 246 * <p>Only set on the server side to sanitize any input from the client process. 247 */ 248 @DataClass.Generated.Member isWaitingForConsent()249 public boolean isWaitingForConsent() { 250 return mWaitingForConsent; 251 } 252 253 /** 254 * Unique logical identifier of the {@link android.hardware.display.VirtualDisplay} that has 255 * recorded content rendered to its surface. 256 */ 257 @DataClass.Generated.Member setVirtualDisplayId( int value)258 public @NonNull ContentRecordingSession setVirtualDisplayId( int value) { 259 mVirtualDisplayId = value; 260 return this; 261 } 262 263 /** 264 * The content to record. 265 */ 266 @DataClass.Generated.Member setContentToRecord(@ecordContent int value)267 public @NonNull ContentRecordingSession setContentToRecord(@RecordContent int value) { 268 mContentToRecord = value; 269 270 if (!(mContentToRecord == RECORD_CONTENT_DISPLAY) 271 && !(mContentToRecord == RECORD_CONTENT_TASK)) { 272 throw new java.lang.IllegalArgumentException( 273 "contentToRecord was " + mContentToRecord + " but must be one of: " 274 + "RECORD_CONTENT_DISPLAY(" + RECORD_CONTENT_DISPLAY + "), " 275 + "RECORD_CONTENT_TASK(" + RECORD_CONTENT_TASK + ")"); 276 } 277 278 return this; 279 } 280 281 /** 282 * Unique logical identifier of the {@link android.view.Display} to record. 283 * 284 * <p>If {@link #getContentToRecord()} is {@link RecordContent#RECORD_CONTENT_DISPLAY}, then is 285 * a valid display id. 286 */ 287 @DataClass.Generated.Member setDisplayToRecord( int value)288 public @NonNull ContentRecordingSession setDisplayToRecord( int value) { 289 mDisplayToRecord = value; 290 return this; 291 } 292 293 /** 294 * The token of the layer of the hierarchy to record. 295 * 296 * <p>If {@link #getContentToRecord()} is {@link RecordContent#RECORD_CONTENT_TASK}, then 297 * represents the {@link android.window.WindowContainerToken} of the Task to record. 298 */ 299 @DataClass.Generated.Member setTokenToRecord(@onNull IBinder value)300 public @NonNull ContentRecordingSession setTokenToRecord(@NonNull IBinder value) { 301 mTokenToRecord = value; 302 return this; 303 } 304 305 /** 306 * When {@code true}, no mirroring should take place until the user has re-granted access to 307 * the consent token. When {@code false}, recording can begin immediately. 308 * 309 * <p>Only set on the server side to sanitize any input from the client process. 310 */ 311 @DataClass.Generated.Member setWaitingForConsent( boolean value)312 public @NonNull ContentRecordingSession setWaitingForConsent( boolean value) { 313 mWaitingForConsent = value; 314 return this; 315 } 316 317 @Override 318 @DataClass.Generated.Member toString()319 public String toString() { 320 // You can override field toString logic by defining methods like: 321 // String fieldNameToString() { ... } 322 323 return "ContentRecordingSession { " + 324 "virtualDisplayId = " + mVirtualDisplayId + ", " + 325 "contentToRecord = " + recordContentToString(mContentToRecord) + ", " + 326 "displayToRecord = " + mDisplayToRecord + ", " + 327 "tokenToRecord = " + mTokenToRecord + ", " + 328 "waitingForConsent = " + mWaitingForConsent + 329 " }"; 330 } 331 332 @Override 333 @DataClass.Generated.Member equals(@ullable Object o)334 public boolean equals(@Nullable Object o) { 335 // You can override field equality logic by defining either of the methods like: 336 // boolean fieldNameEquals(ContentRecordingSession other) { ... } 337 // boolean fieldNameEquals(FieldType otherValue) { ... } 338 339 if (this == o) return true; 340 if (o == null || getClass() != o.getClass()) return false; 341 @SuppressWarnings("unchecked") 342 ContentRecordingSession that = (ContentRecordingSession) o; 343 //noinspection PointlessBooleanExpression 344 return true 345 && mVirtualDisplayId == that.mVirtualDisplayId 346 && mContentToRecord == that.mContentToRecord 347 && mDisplayToRecord == that.mDisplayToRecord 348 && java.util.Objects.equals(mTokenToRecord, that.mTokenToRecord) 349 && mWaitingForConsent == that.mWaitingForConsent; 350 } 351 352 @Override 353 @DataClass.Generated.Member hashCode()354 public int hashCode() { 355 // You can override field hashCode logic by defining methods like: 356 // int fieldNameHashCode() { ... } 357 358 int _hash = 1; 359 _hash = 31 * _hash + mVirtualDisplayId; 360 _hash = 31 * _hash + mContentToRecord; 361 _hash = 31 * _hash + mDisplayToRecord; 362 _hash = 31 * _hash + java.util.Objects.hashCode(mTokenToRecord); 363 _hash = 31 * _hash + Boolean.hashCode(mWaitingForConsent); 364 return _hash; 365 } 366 367 @Override 368 @DataClass.Generated.Member writeToParcel(@onNull Parcel dest, int flags)369 public void writeToParcel(@NonNull Parcel dest, int flags) { 370 // You can override field parcelling by defining methods like: 371 // void parcelFieldName(Parcel dest, int flags) { ... } 372 373 byte flg = 0; 374 if (mWaitingForConsent) flg |= 0x10; 375 if (mTokenToRecord != null) flg |= 0x8; 376 dest.writeByte(flg); 377 dest.writeInt(mVirtualDisplayId); 378 dest.writeInt(mContentToRecord); 379 dest.writeInt(mDisplayToRecord); 380 if (mTokenToRecord != null) dest.writeStrongBinder(mTokenToRecord); 381 } 382 383 @Override 384 @DataClass.Generated.Member describeContents()385 public int describeContents() { return 0; } 386 387 /** @hide */ 388 @SuppressWarnings({"unchecked", "RedundantCast"}) 389 @DataClass.Generated.Member ContentRecordingSession(@onNull Parcel in)390 /* package-private */ ContentRecordingSession(@NonNull Parcel in) { 391 // You can override field unparcelling by defining methods like: 392 // static FieldType unparcelFieldName(Parcel in) { ... } 393 394 byte flg = in.readByte(); 395 boolean waitingForConsent = (flg & 0x10) != 0; 396 int virtualDisplayId = in.readInt(); 397 int contentToRecord = in.readInt(); 398 int displayToRecord = in.readInt(); 399 IBinder tokenToRecord = (flg & 0x8) == 0 ? null : (IBinder) in.readStrongBinder(); 400 401 this.mVirtualDisplayId = virtualDisplayId; 402 this.mContentToRecord = contentToRecord; 403 404 if (!(mContentToRecord == RECORD_CONTENT_DISPLAY) 405 && !(mContentToRecord == RECORD_CONTENT_TASK)) { 406 throw new java.lang.IllegalArgumentException( 407 "contentToRecord was " + mContentToRecord + " but must be one of: " 408 + "RECORD_CONTENT_DISPLAY(" + RECORD_CONTENT_DISPLAY + "), " 409 + "RECORD_CONTENT_TASK(" + RECORD_CONTENT_TASK + ")"); 410 } 411 412 this.mDisplayToRecord = displayToRecord; 413 this.mTokenToRecord = tokenToRecord; 414 this.mWaitingForConsent = waitingForConsent; 415 416 // onConstructed(); // You can define this method to get a callback 417 } 418 419 @DataClass.Generated.Member 420 public static final @NonNull Parcelable.Creator<ContentRecordingSession> CREATOR 421 = new Parcelable.Creator<ContentRecordingSession>() { 422 @Override 423 public ContentRecordingSession[] newArray(int size) { 424 return new ContentRecordingSession[size]; 425 } 426 427 @Override 428 public ContentRecordingSession createFromParcel(@NonNull Parcel in) { 429 return new ContentRecordingSession(in); 430 } 431 }; 432 433 /** 434 * A builder for {@link ContentRecordingSession} 435 */ 436 @SuppressWarnings("WeakerAccess") 437 @DataClass.Generated.Member 438 public static final class Builder { 439 440 private int mVirtualDisplayId; 441 private @RecordContent int mContentToRecord; 442 private int mDisplayToRecord; 443 private @Nullable IBinder mTokenToRecord; 444 private boolean mWaitingForConsent; 445 446 private long mBuilderFieldsSet = 0L; 447 Builder()448 public Builder() { 449 } 450 451 /** 452 * Unique logical identifier of the {@link android.hardware.display.VirtualDisplay} that has 453 * recorded content rendered to its surface. 454 */ 455 @DataClass.Generated.Member setVirtualDisplayId(int value)456 public @NonNull Builder setVirtualDisplayId(int value) { 457 checkNotUsed(); 458 mBuilderFieldsSet |= 0x1; 459 mVirtualDisplayId = value; 460 return this; 461 } 462 463 /** 464 * The content to record. 465 */ 466 @DataClass.Generated.Member setContentToRecord(@ecordContent int value)467 public @NonNull Builder setContentToRecord(@RecordContent int value) { 468 checkNotUsed(); 469 mBuilderFieldsSet |= 0x2; 470 mContentToRecord = value; 471 return this; 472 } 473 474 /** 475 * Unique logical identifier of the {@link android.view.Display} to record. 476 * 477 * <p>If {@link #getContentToRecord()} is {@link RecordContent#RECORD_CONTENT_DISPLAY}, then is 478 * a valid display id. 479 */ 480 @DataClass.Generated.Member setDisplayToRecord(int value)481 public @NonNull Builder setDisplayToRecord(int value) { 482 checkNotUsed(); 483 mBuilderFieldsSet |= 0x4; 484 mDisplayToRecord = value; 485 return this; 486 } 487 488 /** 489 * The token of the layer of the hierarchy to record. 490 * 491 * <p>If {@link #getContentToRecord()} is {@link RecordContent#RECORD_CONTENT_TASK}, then 492 * represents the {@link android.window.WindowContainerToken} of the Task to record. 493 */ 494 @DataClass.Generated.Member setTokenToRecord(@onNull IBinder value)495 public @NonNull Builder setTokenToRecord(@NonNull IBinder value) { 496 checkNotUsed(); 497 mBuilderFieldsSet |= 0x8; 498 mTokenToRecord = value; 499 return this; 500 } 501 502 /** 503 * When {@code true}, no mirroring should take place until the user has re-granted access to 504 * the consent token. When {@code false}, recording can begin immediately. 505 * 506 * <p>Only set on the server side to sanitize any input from the client process. 507 */ 508 @DataClass.Generated.Member setWaitingForConsent(boolean value)509 public @NonNull Builder setWaitingForConsent(boolean value) { 510 checkNotUsed(); 511 mBuilderFieldsSet |= 0x10; 512 mWaitingForConsent = value; 513 return this; 514 } 515 516 /** Builds the instance. This builder should not be touched after calling this! */ build()517 public @NonNull ContentRecordingSession build() { 518 checkNotUsed(); 519 mBuilderFieldsSet |= 0x20; // Mark builder used 520 521 if ((mBuilderFieldsSet & 0x1) == 0) { 522 mVirtualDisplayId = INVALID_DISPLAY; 523 } 524 if ((mBuilderFieldsSet & 0x2) == 0) { 525 mContentToRecord = RECORD_CONTENT_DISPLAY; 526 } 527 if ((mBuilderFieldsSet & 0x4) == 0) { 528 mDisplayToRecord = INVALID_DISPLAY; 529 } 530 if ((mBuilderFieldsSet & 0x8) == 0) { 531 mTokenToRecord = null; 532 } 533 if ((mBuilderFieldsSet & 0x10) == 0) { 534 mWaitingForConsent = false; 535 } 536 ContentRecordingSession o = new ContentRecordingSession( 537 mVirtualDisplayId, 538 mContentToRecord, 539 mDisplayToRecord, 540 mTokenToRecord, 541 mWaitingForConsent); 542 return o; 543 } 544 checkNotUsed()545 private void checkNotUsed() { 546 if ((mBuilderFieldsSet & 0x20) != 0) { 547 throw new IllegalStateException( 548 "This Builder should not be reused. Use a new Builder instance instead"); 549 } 550 } 551 } 552 553 @DataClass.Generated( 554 time = 1683628463074L, 555 codegenVersion = "1.0.23", 556 sourceFile = "frameworks/base/core/java/android/view/ContentRecordingSession.java", 557 inputSignatures = "public static final int RECORD_CONTENT_DISPLAY\npublic static final int RECORD_CONTENT_TASK\nprivate int mVirtualDisplayId\nprivate @android.view.ContentRecordingSession.RecordContent int mContentToRecord\nprivate int mDisplayToRecord\nprivate @android.annotation.Nullable android.os.IBinder mTokenToRecord\nprivate boolean mWaitingForConsent\npublic static android.view.ContentRecordingSession createDisplaySession(int)\npublic static android.view.ContentRecordingSession createTaskSession(android.os.IBinder)\npublic static boolean isValid(android.view.ContentRecordingSession)\npublic static boolean isProjectionOnSameDisplay(android.view.ContentRecordingSession,android.view.ContentRecordingSession)\nclass ContentRecordingSession extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genToString=true, genSetters=true, genEqualsHashCode=true)") 558 @Deprecated __metadata()559 private void __metadata() {} 560 561 562 //@formatter:on 563 // End of generated code 564 565 } 566