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 static android.app.ActivityTaskManager.INVALID_TASK_ID; 20 21 import android.annotation.AnimRes; 22 import android.annotation.ColorInt; 23 import android.annotation.IntDef; 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.annotation.TestApi; 27 import android.graphics.Color; 28 import android.graphics.Rect; 29 import android.os.Bundle; 30 import android.os.Parcel; 31 import android.os.Parcelable; 32 import android.os.RemoteCallback; 33 34 import java.lang.annotation.Retention; 35 import java.lang.annotation.RetentionPolicy; 36 37 /** 38 * Information to be sent to SysUI about a back event. 39 * 40 * @hide 41 */ 42 @TestApi 43 public final class BackNavigationInfo implements Parcelable { 44 45 /** 46 * The target of the back navigation is undefined. 47 */ 48 public static final int TYPE_UNDEFINED = -1; 49 50 /** 51 * Navigating back will close the currently visible dialog 52 */ 53 public static final int TYPE_DIALOG_CLOSE = 0; 54 55 /** 56 * Navigating back will bring the user back to the home screen 57 */ 58 public static final int TYPE_RETURN_TO_HOME = 1; 59 60 /** 61 * Navigating back will bring the user to the previous activity in the same Task 62 */ 63 public static final int TYPE_CROSS_ACTIVITY = 2; 64 65 /** 66 * Navigating back will bring the user to the previous activity in the previous Task 67 */ 68 public static final int TYPE_CROSS_TASK = 3; 69 70 /** 71 * A {@link OnBackInvokedCallback} is available and needs to be called. 72 * <p> 73 */ 74 public static final int TYPE_CALLBACK = 4; 75 76 /** 77 * Key to access the boolean value passed in {#mOnBackNavigationDone} result bundle 78 * that represents if back navigation has been triggered. 79 * @hide 80 */ 81 public static final String KEY_NAVIGATION_FINISHED = "NavigationFinished"; 82 83 /** 84 * Key to access the boolean value passed in {#mOnBackNavigationDone} result bundle 85 * that represents if back gesture has been triggered. 86 * @hide 87 */ 88 public static final String KEY_GESTURE_FINISHED = "GestureFinished"; 89 90 /** 91 * Touch gestured has transferred to embedded window, Shell should pilfer pointers so the 92 * embedded won't receive motion events. 93 * @hide 94 */ 95 public static final String KEY_TOUCH_GESTURE_TRANSFERRED = "TouchGestureTransferred"; 96 97 98 /** 99 * Defines the type of back destinations a back even can lead to. This is used to define the 100 * type of animation that need to be run on SystemUI. 101 * @hide 102 */ 103 @IntDef(prefix = "TYPE_", value = { 104 TYPE_UNDEFINED, 105 TYPE_DIALOG_CLOSE, 106 TYPE_RETURN_TO_HOME, 107 TYPE_CROSS_ACTIVITY, 108 TYPE_CROSS_TASK, 109 TYPE_CALLBACK 110 }) 111 @Retention(RetentionPolicy.SOURCE) 112 public @interface BackTargetType { 113 } 114 115 private final int mType; 116 @Nullable 117 private final RemoteCallback mOnBackNavigationDone; 118 @Nullable 119 private final IOnBackInvokedCallback mOnBackInvokedCallback; 120 private final boolean mPrepareRemoteAnimation; 121 private final boolean mAnimationCallback; 122 @Nullable 123 private final CustomAnimationInfo mCustomAnimationInfo; 124 125 private final int mLetterboxColor; 126 @NonNull 127 private final Rect mTouchableRegion; 128 129 private boolean mAppProgressGenerationAllowed; 130 private final int mFocusedTaskId; 131 132 /** 133 * Create a new {@link BackNavigationInfo} instance. 134 * 135 * @param type The {@link BackTargetType} of the destination (what will be 136 * @param onBackNavigationDone The callback to be called once the client is done with the 137 * back preview. 138 * @param onBackInvokedCallback The back callback registered by the current top level window. 139 */ BackNavigationInfo(@ackTargetType int type, @Nullable RemoteCallback onBackNavigationDone, @Nullable IOnBackInvokedCallback onBackInvokedCallback, boolean isPrepareRemoteAnimation, boolean isAnimationCallback, @Nullable CustomAnimationInfo customAnimationInfo, int letterboxColor, @Nullable Rect touchableRegion, boolean appProgressGenerationAllowed, int focusedTaskId)140 private BackNavigationInfo(@BackTargetType int type, 141 @Nullable RemoteCallback onBackNavigationDone, 142 @Nullable IOnBackInvokedCallback onBackInvokedCallback, 143 boolean isPrepareRemoteAnimation, 144 boolean isAnimationCallback, 145 @Nullable CustomAnimationInfo customAnimationInfo, 146 int letterboxColor, 147 @Nullable Rect touchableRegion, 148 boolean appProgressGenerationAllowed, 149 int focusedTaskId) { 150 mType = type; 151 mOnBackNavigationDone = onBackNavigationDone; 152 mOnBackInvokedCallback = onBackInvokedCallback; 153 mPrepareRemoteAnimation = isPrepareRemoteAnimation; 154 mAnimationCallback = isAnimationCallback; 155 mCustomAnimationInfo = customAnimationInfo; 156 mLetterboxColor = letterboxColor; 157 mTouchableRegion = new Rect(touchableRegion); 158 mAppProgressGenerationAllowed = appProgressGenerationAllowed; 159 mFocusedTaskId = focusedTaskId; 160 } 161 BackNavigationInfo(@onNull Parcel in)162 private BackNavigationInfo(@NonNull Parcel in) { 163 mType = in.readInt(); 164 mOnBackNavigationDone = in.readTypedObject(RemoteCallback.CREATOR); 165 mOnBackInvokedCallback = IOnBackInvokedCallback.Stub.asInterface(in.readStrongBinder()); 166 mPrepareRemoteAnimation = in.readBoolean(); 167 mAnimationCallback = in.readBoolean(); 168 mCustomAnimationInfo = in.readTypedObject(CustomAnimationInfo.CREATOR); 169 mLetterboxColor = in.readInt(); 170 mTouchableRegion = in.readTypedObject(Rect.CREATOR); 171 mAppProgressGenerationAllowed = in.readBoolean(); 172 mFocusedTaskId = in.readInt(); 173 } 174 175 /** @hide */ 176 @Override writeToParcel(@onNull Parcel dest, int flags)177 public void writeToParcel(@NonNull Parcel dest, int flags) { 178 dest.writeInt(mType); 179 dest.writeTypedObject(mOnBackNavigationDone, flags); 180 dest.writeStrongInterface(mOnBackInvokedCallback); 181 dest.writeBoolean(mPrepareRemoteAnimation); 182 dest.writeBoolean(mAnimationCallback); 183 dest.writeTypedObject(mCustomAnimationInfo, flags); 184 dest.writeInt(mLetterboxColor); 185 dest.writeTypedObject(mTouchableRegion, flags); 186 dest.writeBoolean(mAppProgressGenerationAllowed); 187 dest.writeInt(mFocusedTaskId); 188 } 189 190 /** 191 * Returns the type of back navigation that is about to happen. 192 * @hide 193 * @see BackTargetType 194 */ getType()195 public @BackTargetType int getType() { 196 return mType; 197 } 198 199 /** 200 * Returns the {@link OnBackInvokedCallback} of the top level window or null if 201 * the client didn't register a callback. 202 * <p> 203 * This is never null when {@link #getType} returns {@link #TYPE_CALLBACK}. 204 * @hide 205 * @see OnBackInvokedCallback 206 * @see OnBackInvokedDispatcher 207 */ 208 @Nullable getOnBackInvokedCallback()209 public IOnBackInvokedCallback getOnBackInvokedCallback() { 210 return mOnBackInvokedCallback; 211 } 212 213 /** 214 * Return true if the core is preparing a back gesture animation. 215 * @hide 216 */ isPrepareRemoteAnimation()217 public boolean isPrepareRemoteAnimation() { 218 return mPrepareRemoteAnimation; 219 } 220 221 /** 222 * Return true if the callback is {@link OnBackAnimationCallback}. 223 * @hide 224 */ isAnimationCallback()225 public boolean isAnimationCallback() { 226 return mAnimationCallback; 227 } 228 229 /** 230 * @return Letterbox color 231 * @hide 232 */ getLetterboxColor()233 public int getLetterboxColor() { 234 return mLetterboxColor; 235 } 236 237 /** 238 * @return The app window region where the client can handle touch event. 239 * @hide 240 */ 241 @NonNull getTouchableRegion()242 public Rect getTouchableRegion() { 243 return mTouchableRegion; 244 } 245 246 /** 247 * @return The client side view is able to intercept back progress event. 248 * @hide 249 */ isAppProgressGenerationAllowed()250 public boolean isAppProgressGenerationAllowed() { 251 return mAppProgressGenerationAllowed; 252 } 253 254 /** 255 * @return The focused task id when back gesture start. 256 * @hide 257 */ getFocusedTaskId()258 public int getFocusedTaskId() { 259 return mFocusedTaskId; 260 } 261 262 /** 263 * Force disable app to intercept back progress event. 264 * @hide 265 */ disableAppProgressGenerationAllowed()266 public void disableAppProgressGenerationAllowed() { 267 mAppProgressGenerationAllowed = false; 268 } 269 270 /** 271 * Callback to be called when the back preview is finished in order to notify the server that 272 * it can clean up the resources created for the animation. 273 * @hide 274 * @param triggerBack Boolean indicating if back navigation has been triggered. 275 */ onBackNavigationFinished(boolean triggerBack)276 public void onBackNavigationFinished(boolean triggerBack) { 277 if (mOnBackNavigationDone != null) { 278 Bundle result = new Bundle(); 279 result.putBoolean(KEY_NAVIGATION_FINISHED, triggerBack); 280 mOnBackNavigationDone.sendResult(result); 281 } 282 } 283 284 /** 285 * Get customize animation info. 286 * @hide 287 */ 288 @Nullable getCustomAnimationInfo()289 public CustomAnimationInfo getCustomAnimationInfo() { 290 return mCustomAnimationInfo; 291 } 292 293 /** @hide */ 294 @Override describeContents()295 public int describeContents() { 296 return 0; 297 } 298 299 @NonNull 300 public static final Creator<BackNavigationInfo> CREATOR = new Creator<BackNavigationInfo>() { 301 @Override 302 public BackNavigationInfo createFromParcel(Parcel in) { 303 return new BackNavigationInfo(in); 304 } 305 306 @Override 307 public BackNavigationInfo[] newArray(int size) { 308 return new BackNavigationInfo[size]; 309 } 310 }; 311 312 @Override toString()313 public String toString() { 314 return "BackNavigationInfo{" 315 + "mType=" + typeToString(mType) + " (" + mType + ")" 316 + ", mOnBackNavigationDone=" + mOnBackNavigationDone 317 + ", mOnBackInvokedCallback=" + mOnBackInvokedCallback 318 + ", mPrepareRemoteAnimation=" + mPrepareRemoteAnimation 319 + ", mAnimationCallback=" + mAnimationCallback 320 + ", mCustomizeAnimationInfo=" + mCustomAnimationInfo 321 + '}'; 322 } 323 324 /** 325 * Translates the {@link BackNavigationInfo} integer type to its String representation 326 */ 327 @NonNull typeToString(@ackTargetType int type)328 public static String typeToString(@BackTargetType int type) { 329 switch (type) { 330 case TYPE_UNDEFINED: 331 return "TYPE_UNDEFINED"; 332 case TYPE_DIALOG_CLOSE: 333 return "TYPE_DIALOG_CLOSE"; 334 case TYPE_RETURN_TO_HOME: 335 return "TYPE_RETURN_TO_HOME"; 336 case TYPE_CROSS_ACTIVITY: 337 return "TYPE_CROSS_ACTIVITY"; 338 case TYPE_CROSS_TASK: 339 return "TYPE_CROSS_TASK"; 340 case TYPE_CALLBACK: 341 return "TYPE_CALLBACK"; 342 } 343 return String.valueOf(type); 344 } 345 346 /** 347 * Information for customize back animation. 348 * @hide 349 */ 350 public static final class CustomAnimationInfo implements Parcelable { 351 private final String mPackageName; 352 private int mWindowAnimations; 353 @AnimRes private int mCustomExitAnim; 354 @AnimRes private int mCustomEnterAnim; 355 @ColorInt private int mCustomBackground; 356 357 /** 358 * The package name of the windowAnimations. 359 */ 360 @NonNull getPackageName()361 public String getPackageName() { 362 return mPackageName; 363 } 364 365 /** 366 * The resource Id of window animations. 367 */ getWindowAnimations()368 public int getWindowAnimations() { 369 return mWindowAnimations; 370 } 371 372 /** 373 * The exit animation resource Id of customize activity transition. 374 */ getCustomExitAnim()375 public int getCustomExitAnim() { 376 return mCustomExitAnim; 377 } 378 379 /** 380 * The entering animation resource Id of customize activity transition. 381 */ getCustomEnterAnim()382 public int getCustomEnterAnim() { 383 return mCustomEnterAnim; 384 } 385 386 /** 387 * The background color of customize activity transition. 388 */ getCustomBackground()389 public int getCustomBackground() { 390 return mCustomBackground; 391 } 392 CustomAnimationInfo(@onNull String packageName)393 public CustomAnimationInfo(@NonNull String packageName) { 394 this.mPackageName = packageName; 395 } 396 397 @Override describeContents()398 public int describeContents() { 399 return 0; 400 } 401 402 @Override writeToParcel(@onNull Parcel dest, int flags)403 public void writeToParcel(@NonNull Parcel dest, int flags) { 404 dest.writeString8(mPackageName); 405 dest.writeInt(mWindowAnimations); 406 dest.writeInt(mCustomEnterAnim); 407 dest.writeInt(mCustomExitAnim); 408 dest.writeInt(mCustomBackground); 409 } 410 CustomAnimationInfo(@onNull Parcel in)411 private CustomAnimationInfo(@NonNull Parcel in) { 412 mPackageName = in.readString8(); 413 mWindowAnimations = in.readInt(); 414 mCustomEnterAnim = in.readInt(); 415 mCustomExitAnim = in.readInt(); 416 mCustomBackground = in.readInt(); 417 } 418 419 @Override toString()420 public String toString() { 421 return "CustomAnimationInfo, package name= " + mPackageName; 422 } 423 424 @NonNull 425 public static final Creator<CustomAnimationInfo> CREATOR = new Creator<>() { 426 @Override 427 public CustomAnimationInfo createFromParcel(Parcel in) { 428 return new CustomAnimationInfo(in); 429 } 430 431 @Override 432 public CustomAnimationInfo[] newArray(int size) { 433 return new CustomAnimationInfo[size]; 434 } 435 }; 436 } 437 /** 438 * @hide 439 */ 440 @SuppressWarnings("UnusedReturnValue") // Builder pattern 441 public static class Builder { 442 private int mType = TYPE_UNDEFINED; 443 @Nullable 444 private RemoteCallback mOnBackNavigationDone = null; 445 @Nullable 446 private IOnBackInvokedCallback mOnBackInvokedCallback = null; 447 private boolean mPrepareRemoteAnimation; 448 private CustomAnimationInfo mCustomAnimationInfo; 449 private boolean mAnimationCallback = false; 450 451 private int mLetterboxColor = Color.TRANSPARENT; 452 private Rect mTouchableRegion; 453 private boolean mAppProgressGenerationAllowed; 454 private int mFocusedTaskId = INVALID_TASK_ID; 455 456 /** 457 * @see BackNavigationInfo#getType() 458 */ setType(@ackTargetType int type)459 public Builder setType(@BackTargetType int type) { 460 mType = type; 461 return this; 462 } 463 464 /** 465 * @see BackNavigationInfo#onBackNavigationFinished(boolean) 466 */ setOnBackNavigationDone(@ullable RemoteCallback onBackNavigationDone)467 public Builder setOnBackNavigationDone(@Nullable RemoteCallback onBackNavigationDone) { 468 mOnBackNavigationDone = onBackNavigationDone; 469 return this; 470 } 471 472 /** 473 * @see BackNavigationInfo#getOnBackInvokedCallback 474 */ setOnBackInvokedCallback( @ullable IOnBackInvokedCallback onBackInvokedCallback)475 public Builder setOnBackInvokedCallback( 476 @Nullable IOnBackInvokedCallback onBackInvokedCallback) { 477 mOnBackInvokedCallback = onBackInvokedCallback; 478 return this; 479 } 480 481 /** 482 * @param prepareRemoteAnimation Whether core prepare animation for shell. 483 */ setPrepareRemoteAnimation(boolean prepareRemoteAnimation)484 public Builder setPrepareRemoteAnimation(boolean prepareRemoteAnimation) { 485 mPrepareRemoteAnimation = prepareRemoteAnimation; 486 return this; 487 } 488 489 /** 490 * Set windowAnimations for customize animation. 491 */ setWindowAnimations(String packageName, int windowAnimations)492 public Builder setWindowAnimations(String packageName, int windowAnimations) { 493 if (mCustomAnimationInfo == null) { 494 mCustomAnimationInfo = new CustomAnimationInfo(packageName); 495 } 496 mCustomAnimationInfo.mWindowAnimations = windowAnimations; 497 return this; 498 } 499 500 /** 501 * Set resources ids for customize activity animation. 502 */ setCustomAnimation(String packageName, @AnimRes int enterResId, @AnimRes int exitResId, @ColorInt int backgroundColor)503 public Builder setCustomAnimation(String packageName, @AnimRes int enterResId, 504 @AnimRes int exitResId, @ColorInt int backgroundColor) { 505 if (mCustomAnimationInfo == null) { 506 mCustomAnimationInfo = new CustomAnimationInfo(packageName); 507 } 508 mCustomAnimationInfo.mCustomExitAnim = exitResId; 509 mCustomAnimationInfo.mCustomEnterAnim = enterResId; 510 mCustomAnimationInfo.mCustomBackground = backgroundColor; 511 return this; 512 } 513 514 /** 515 * @param isAnimationCallback whether the callback is {@link OnBackAnimationCallback} 516 */ setAnimationCallback(boolean isAnimationCallback)517 public Builder setAnimationCallback(boolean isAnimationCallback) { 518 mAnimationCallback = isAnimationCallback; 519 return this; 520 } 521 522 /** 523 * @param color Non-transparent if there contain letterbox color. 524 */ setLetterboxColor(int color)525 public Builder setLetterboxColor(int color) { 526 mLetterboxColor = color; 527 return this; 528 } 529 530 /** 531 * @param rect Non-empty for frame of current focus window. 532 */ setTouchableRegion(Rect rect)533 public Builder setTouchableRegion(Rect rect) { 534 mTouchableRegion = new Rect(rect); 535 return this; 536 } 537 538 /** 539 * @param allowed Whether client side view able to intercept back progress event. 540 */ setAppProgressAllowed(boolean allowed)541 public Builder setAppProgressAllowed(boolean allowed) { 542 mAppProgressGenerationAllowed = allowed; 543 return this; 544 } 545 546 /** 547 * @param focusedTaskId The current focused taskId when back gesture start. 548 */ setFocusedTaskId(int focusedTaskId)549 public Builder setFocusedTaskId(int focusedTaskId) { 550 mFocusedTaskId = focusedTaskId; 551 return this; 552 } 553 554 /** 555 * Builds and returns an instance of {@link BackNavigationInfo} 556 */ build()557 public BackNavigationInfo build() { 558 return new BackNavigationInfo(mType, mOnBackNavigationDone, 559 mOnBackInvokedCallback, 560 mPrepareRemoteAnimation, 561 mAnimationCallback, 562 mCustomAnimationInfo, 563 mLetterboxColor, 564 mTouchableRegion, 565 mAppProgressGenerationAllowed, 566 mFocusedTaskId); 567 } 568 } 569 } 570