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.window; 18 19 import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_SWIPE_EDGE_NONE_API; 20 import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_TIMESTAMP_API; 21 import static com.android.window.flags.Flags.predictiveBackTimestampApi; 22 23 import android.annotation.FlaggedApi; 24 import android.annotation.FloatRange; 25 import android.annotation.IntDef; 26 27 import java.lang.annotation.Retention; 28 import java.lang.annotation.RetentionPolicy; 29 30 /** 31 * Object used to report back gesture progress. 32 * Holds information about the touch event, swipe direction and the animation progress that 33 * predictive back animations should seek to. 34 */ 35 public final class BackEvent { 36 /** Indicates that the edge swipe starts from the left edge of the screen */ 37 public static final int EDGE_LEFT = 0; 38 /** Indicates that the edge swipe starts from the right edge of the screen */ 39 public static final int EDGE_RIGHT = 1; 40 /** 41 * Indicates that the back event was not triggered by an edge swipe back gesture. This applies 42 * to cases like using the back button in 3-button navigation or pressing a hardware back 43 * button. 44 */ 45 @FlaggedApi(FLAG_PREDICTIVE_BACK_SWIPE_EDGE_NONE_API) 46 public static final int EDGE_NONE = 2; 47 48 /** @hide */ 49 @IntDef({ 50 EDGE_LEFT, 51 EDGE_RIGHT, 52 EDGE_NONE, 53 }) 54 @Retention(RetentionPolicy.SOURCE) 55 public @interface SwipeEdge{} 56 57 private final float mTouchX; 58 private final float mTouchY; 59 private final float mProgress; 60 private final long mFrameTimeMillis; 61 62 @SwipeEdge 63 private final int mSwipeEdge; 64 65 /** @hide */ fromBackMotionEvent(BackMotionEvent backMotionEvent)66 public static BackEvent fromBackMotionEvent(BackMotionEvent backMotionEvent) { 67 if (predictiveBackTimestampApi()) { 68 return new BackEvent(backMotionEvent.getTouchX(), backMotionEvent.getTouchY(), 69 backMotionEvent.getProgress(), backMotionEvent.getSwipeEdge(), 70 backMotionEvent.getFrameTimeMillis()); 71 } else { 72 return new BackEvent(backMotionEvent.getTouchX(), backMotionEvent.getTouchY(), 73 backMotionEvent.getProgress(), backMotionEvent.getSwipeEdge()); 74 } 75 } 76 77 /** 78 * Creates a new {@link BackEvent} instance with a frame time of 0. 79 * 80 * @param touchX Absolute X location of the touch point of this event. 81 * @param touchY Absolute Y location of the touch point of this event. 82 * @param progress Value between 0 and 1 on how far along the back gesture is. 83 * @param swipeEdge Indicates which edge the swipe starts from. 84 */ BackEvent(float touchX, float touchY, float progress, @SwipeEdge int swipeEdge)85 public BackEvent(float touchX, float touchY, float progress, @SwipeEdge int swipeEdge) { 86 mTouchX = touchX; 87 mTouchY = touchY; 88 mProgress = progress; 89 mSwipeEdge = swipeEdge; 90 mFrameTimeMillis = 0; 91 } 92 93 /** 94 * Creates a new {@link BackEvent} instance. 95 * 96 * @param touchX Absolute X location of the touch point of this event. 97 * @param touchY Absolute Y location of the touch point of this event. 98 * @param progress Value between 0 and 1 on how far along the back gesture is. 99 * @param swipeEdge Indicates which edge the swipe starts from. 100 * @param frameTimeMillis frame time of the back event. 101 */ 102 @FlaggedApi(FLAG_PREDICTIVE_BACK_TIMESTAMP_API) BackEvent(float touchX, float touchY, float progress, @SwipeEdge int swipeEdge, long frameTimeMillis)103 public BackEvent(float touchX, float touchY, float progress, @SwipeEdge int swipeEdge, 104 long frameTimeMillis) { 105 mTouchX = touchX; 106 mTouchY = touchY; 107 mProgress = progress; 108 mSwipeEdge = swipeEdge; 109 mFrameTimeMillis = frameTimeMillis; 110 } 111 112 /** 113 * Returns a value between 0 and 1 on how far along the back gesture is. This value is 114 * driven by the horizontal location of the touch point, and should be used as the fraction to 115 * seek the predictive back animation with. Specifically, 116 * <ol> 117 * <li>The progress is 0 when the touch is at the starting edge of the screen (left or right), 118 * and animation should seek to its start state. 119 * <li>The progress is approximately 1 when the touch is at the opposite side of the screen, 120 * and animation should seek to its end state. Exact end value may vary depending on 121 * screen size. 122 * </ol> 123 * <li> After the gesture finishes in cancel state, this method keeps getting invoked until the 124 * progress value animates back to 0. 125 * </ol> 126 * In-between locations are linearly interpolated based on horizontal distance from the starting 127 * edge and smooth clamped to 1 when the distance exceeds a system-wide threshold. 128 */ 129 @FloatRange(from = 0, to = 1) getProgress()130 public float getProgress() { 131 return mProgress; 132 } 133 134 /** 135 * Returns the absolute X location of the touch point, or NaN if the event is from 136 * a button press. 137 */ getTouchX()138 public float getTouchX() { 139 return mTouchX; 140 } 141 142 /** 143 * Returns the absolute Y location of the touch point, or NaN if the event is from 144 * a button press. 145 */ getTouchY()146 public float getTouchY() { 147 return mTouchY; 148 } 149 150 /** 151 * Returns the screen edge that the swipe starts from. 152 */ 153 @SwipeEdge getSwipeEdge()154 public int getSwipeEdge() { 155 return mSwipeEdge; 156 } 157 158 /** 159 * Returns the frameTime of the BackEvent in milliseconds. Useful for calculating velocity. 160 */ 161 @FlaggedApi(FLAG_PREDICTIVE_BACK_TIMESTAMP_API) getFrameTimeMillis()162 public long getFrameTimeMillis() { 163 return mFrameTimeMillis; 164 } 165 166 @Override equals(Object other)167 public boolean equals(Object other) { 168 if (this == other) { 169 return true; 170 } 171 if (!(other instanceof BackEvent)) { 172 return false; 173 } 174 final BackEvent that = (BackEvent) other; 175 return mTouchX == that.mTouchX 176 && mTouchY == that.mTouchY 177 && mProgress == that.mProgress 178 && mSwipeEdge == that.mSwipeEdge 179 && mFrameTimeMillis == that.mFrameTimeMillis; 180 } 181 182 @Override toString()183 public String toString() { 184 return "BackEvent{" 185 + "mTouchX=" + mTouchX 186 + ", mTouchY=" + mTouchY 187 + ", mProgress=" + mProgress 188 + ", mSwipeEdge=" + mSwipeEdge 189 + ", mFrameTimeMillis=" + mFrameTimeMillis 190 + "}"; 191 } 192 } 193