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