Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2018 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 | |
Jorim Jaggi | 7f76187 | 2020-01-10 18:24:27 +0100 | [diff] [blame] | 19 | import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE; |
Jorim Jaggi | 9099079 | 2019-01-21 23:00:20 +0100 | [diff] [blame] | 20 | import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; |
Tarandeep Singh | 92d2dd3 | 2019-08-07 14:45:01 -0700 | [diff] [blame] | 21 | import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME; |
Adrian Roos | 11dfd27 | 2019-03-25 19:21:26 +0100 | [diff] [blame] | 22 | import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE; |
Jorim Jaggi | 4e04eb2 | 2020-01-09 16:42:14 +0100 | [diff] [blame] | 23 | import static android.view.ViewRootImpl.sNewInsetsMode; |
Adrian Roos | 11dfd27 | 2019-03-25 19:21:26 +0100 | [diff] [blame] | 24 | import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES; |
Jorim Jaggi | 9099079 | 2019-01-21 23:00:20 +0100 | [diff] [blame] | 25 | import static android.view.WindowInsets.Type.SIZE; |
Adrian Roos | 11dfd27 | 2019-03-25 19:21:26 +0100 | [diff] [blame] | 26 | import static android.view.WindowInsets.Type.SYSTEM_GESTURES; |
Tiger Huang | e16645a | 2020-02-25 22:24:39 +0800 | [diff] [blame] | 27 | import static android.view.WindowInsets.Type.displayCutout; |
Jorim Jaggi | 761a5ab | 2020-01-06 23:16:30 +0100 | [diff] [blame] | 28 | import static android.view.WindowInsets.Type.ime; |
Jorim Jaggi | bcf99ff | 2018-12-03 18:04:26 +0100 | [diff] [blame] | 29 | import static android.view.WindowInsets.Type.indexOf; |
Jorim Jaggi | 4e04eb2 | 2020-01-09 16:42:14 +0100 | [diff] [blame] | 30 | import static android.view.WindowInsets.Type.isVisibleInsetsType; |
Jorim Jaggi | 761a5ab | 2020-01-06 23:16:30 +0100 | [diff] [blame] | 31 | import static android.view.WindowInsets.Type.systemBars; |
| 32 | import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; |
| 33 | import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; |
Jorim Jaggi | bcf99ff | 2018-12-03 18:04:26 +0100 | [diff] [blame] | 34 | |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 35 | import android.annotation.IntDef; |
Jorim Jaggi | 5bb571d | 2018-11-06 14:42:04 +0100 | [diff] [blame] | 36 | import android.annotation.Nullable; |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 37 | import android.graphics.Insets; |
| 38 | import android.graphics.Rect; |
| 39 | import android.os.Parcel; |
| 40 | import android.os.Parcelable; |
| 41 | import android.util.ArrayMap; |
Jorim Jaggi | b603095 | 2018-10-23 18:31:52 +0200 | [diff] [blame] | 42 | import android.util.ArraySet; |
Jorim Jaggi | 5bb571d | 2018-11-06 14:42:04 +0100 | [diff] [blame] | 43 | import android.util.SparseIntArray; |
Jorim Jaggi | b603095 | 2018-10-23 18:31:52 +0200 | [diff] [blame] | 44 | import android.view.WindowInsets.Type; |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 45 | import android.view.WindowInsets.Type.InsetsType; |
Jorim Jaggi | 4e04eb2 | 2020-01-09 16:42:14 +0100 | [diff] [blame] | 46 | import android.view.WindowManager.LayoutParams.SoftInputModeFlags; |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 47 | |
Yunfan Chen | fae0aea | 2020-02-22 20:57:57 +0900 | [diff] [blame] | 48 | import com.android.internal.annotations.VisibleForTesting; |
| 49 | |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 50 | import java.io.PrintWriter; |
| 51 | import java.lang.annotation.Retention; |
| 52 | import java.lang.annotation.RetentionPolicy; |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 53 | import java.util.Arrays; |
Tarandeep Singh | a6f3561 | 2019-01-11 19:50:46 -0800 | [diff] [blame] | 54 | import java.util.Objects; |
Taran Singh | 85661e3 | 2020-05-07 14:45:34 -0700 | [diff] [blame] | 55 | import java.util.StringJoiner; |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 56 | |
| 57 | /** |
| 58 | * Holder for state of system windows that cause window insets for all other windows in the system. |
| 59 | * @hide |
| 60 | */ |
| 61 | public class InsetsState implements Parcelable { |
| 62 | |
| 63 | /** |
| 64 | * Internal representation of inset source types. This is different from the public API in |
| 65 | * {@link WindowInsets.Type} as one type from the public API might indicate multiple windows |
| 66 | * at the same time. |
| 67 | */ |
| 68 | @Retention(RetentionPolicy.SOURCE) |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 69 | @IntDef(prefix = "ITYPE", value = { |
| 70 | ITYPE_STATUS_BAR, |
| 71 | ITYPE_NAVIGATION_BAR, |
| 72 | ITYPE_CAPTION_BAR, |
| 73 | ITYPE_TOP_GESTURES, |
| 74 | ITYPE_BOTTOM_GESTURES, |
| 75 | ITYPE_LEFT_GESTURES, |
| 76 | ITYPE_RIGHT_GESTURES, |
| 77 | ITYPE_TOP_TAPPABLE_ELEMENT, |
| 78 | ITYPE_BOTTOM_TAPPABLE_ELEMENT, |
Tiger Huang | e16645a | 2020-02-25 22:24:39 +0800 | [diff] [blame] | 79 | ITYPE_LEFT_DISPLAY_CUTOUT, |
| 80 | ITYPE_TOP_DISPLAY_CUTOUT, |
| 81 | ITYPE_RIGHT_DISPLAY_CUTOUT, |
| 82 | ITYPE_BOTTOM_DISPLAY_CUTOUT, |
Heemin Seog | d79e4f4 | 2020-05-06 15:32:50 -0700 | [diff] [blame] | 83 | ITYPE_IME, |
| 84 | ITYPE_CLIMATE_BAR, |
| 85 | ITYPE_EXTRA_NAVIGATION_BAR |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 86 | }) |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 87 | public @interface InternalInsetsType {} |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 88 | |
Charles Chen | b8070fb | 2020-02-24 15:42:59 +0800 | [diff] [blame] | 89 | /** |
| 90 | * Special value to be used to by methods returning an {@link InternalInsetsType} to indicate |
| 91 | * that the objects/parameters aren't associated with an {@link InternalInsetsType} |
| 92 | */ |
| 93 | public static final int ITYPE_INVALID = -1; |
| 94 | |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 95 | static final int FIRST_TYPE = 0; |
| 96 | |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 97 | public static final int ITYPE_STATUS_BAR = FIRST_TYPE; |
| 98 | public static final int ITYPE_NAVIGATION_BAR = 1; |
| 99 | public static final int ITYPE_CAPTION_BAR = 2; |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 100 | |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 101 | public static final int ITYPE_TOP_GESTURES = 3; |
| 102 | public static final int ITYPE_BOTTOM_GESTURES = 4; |
| 103 | public static final int ITYPE_LEFT_GESTURES = 5; |
| 104 | public static final int ITYPE_RIGHT_GESTURES = 6; |
| 105 | public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 7; |
| 106 | public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT = 8; |
Adrian Roos | 11dfd27 | 2019-03-25 19:21:26 +0100 | [diff] [blame] | 107 | |
Tiger Huang | e16645a | 2020-02-25 22:24:39 +0800 | [diff] [blame] | 108 | public static final int ITYPE_LEFT_DISPLAY_CUTOUT = 9; |
| 109 | public static final int ITYPE_TOP_DISPLAY_CUTOUT = 10; |
| 110 | public static final int ITYPE_RIGHT_DISPLAY_CUTOUT = 11; |
| 111 | public static final int ITYPE_BOTTOM_DISPLAY_CUTOUT = 12; |
| 112 | |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 113 | /** Input method window. */ |
Tiger Huang | e16645a | 2020-02-25 22:24:39 +0800 | [diff] [blame] | 114 | public static final int ITYPE_IME = 13; |
Adrian Roos | 11dfd27 | 2019-03-25 19:21:26 +0100 | [diff] [blame] | 115 | |
Heemin Seog | d79e4f4 | 2020-05-06 15:32:50 -0700 | [diff] [blame] | 116 | /** Additional system decorations inset type. */ |
| 117 | public static final int ITYPE_CLIMATE_BAR = 14; |
| 118 | public static final int ITYPE_EXTRA_NAVIGATION_BAR = 15; |
| 119 | |
| 120 | static final int LAST_TYPE = ITYPE_EXTRA_NAVIGATION_BAR; |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 121 | public static final int SIZE = LAST_TYPE + 1; |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 122 | |
| 123 | // Derived types |
| 124 | |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 125 | /** A shelf is the same as the navigation bar. */ |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 126 | public static final int ITYPE_SHELF = ITYPE_NAVIGATION_BAR; |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 127 | |
Jorim Jaggi | 5bb571d | 2018-11-06 14:42:04 +0100 | [diff] [blame] | 128 | @Retention(RetentionPolicy.SOURCE) |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 129 | @IntDef(prefix = "IINSETS_SIDE", value = { |
| 130 | ISIDE_LEFT, |
| 131 | ISIDE_TOP, |
| 132 | ISIDE_RIGHT, |
| 133 | ISIDE_BOTTOM, |
| 134 | ISIDE_FLOATING, |
| 135 | ISIDE_UNKNOWN |
Jorim Jaggi | 5bb571d | 2018-11-06 14:42:04 +0100 | [diff] [blame] | 136 | }) |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 137 | public @interface InternalInsetsSide {} |
| 138 | static final int ISIDE_LEFT = 0; |
| 139 | static final int ISIDE_TOP = 1; |
| 140 | static final int ISIDE_RIGHT = 2; |
| 141 | static final int ISIDE_BOTTOM = 3; |
| 142 | static final int ISIDE_FLOATING = 4; |
| 143 | static final int ISIDE_UNKNOWN = 5; |
Jorim Jaggi | 5bb571d | 2018-11-06 14:42:04 +0100 | [diff] [blame] | 144 | |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 145 | private InsetsSource[] mSources = new InsetsSource[SIZE]; |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 146 | |
Tarandeep Singh | a6f3561 | 2019-01-11 19:50:46 -0800 | [diff] [blame] | 147 | /** |
| 148 | * The frame of the display these sources are relative to. |
| 149 | */ |
| 150 | private final Rect mDisplayFrame = new Rect(); |
| 151 | |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 152 | public InsetsState() { |
| 153 | } |
| 154 | |
Jorim Jaggi | 5bb571d | 2018-11-06 14:42:04 +0100 | [diff] [blame] | 155 | public InsetsState(InsetsState copy) { |
| 156 | set(copy); |
| 157 | } |
| 158 | |
Jorim Jaggi | 02a741f | 2018-12-12 17:40:19 -0800 | [diff] [blame] | 159 | public InsetsState(InsetsState copy, boolean copySources) { |
| 160 | set(copy, copySources); |
| 161 | } |
| 162 | |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 163 | /** |
| 164 | * Calculates {@link WindowInsets} based on the current source configuration. |
| 165 | * |
| 166 | * @param frame The frame to calculate the insets relative to. |
Jorim Jaggi | 580aef5 | 2020-02-26 18:28:28 +0100 | [diff] [blame] | 167 | * @param ignoringVisibilityState {@link InsetsState} used to calculate |
| 168 | * {@link WindowInsets#getInsetsIgnoringVisibility(int)} information, or pass |
| 169 | * {@code null} to use this state to calculate that information. |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 170 | * @return The calculated insets. |
| 171 | */ |
Jorim Jaggi | 580aef5 | 2020-02-26 18:28:28 +0100 | [diff] [blame] | 172 | public WindowInsets calculateInsets(Rect frame, @Nullable InsetsState ignoringVisibilityState, |
| 173 | boolean isScreenRound, boolean alwaysConsumeSystemBars, DisplayCutout cutout, |
Jorim Jaggi | 7f76187 | 2020-01-10 18:24:27 +0100 | [diff] [blame] | 174 | int legacySoftInputMode, int legacySystemUiFlags, |
| 175 | @Nullable @InternalInsetsSide SparseIntArray typeSideMap) { |
Jorim Jaggi | bcf99ff | 2018-12-03 18:04:26 +0100 | [diff] [blame] | 176 | Insets[] typeInsetsMap = new Insets[Type.SIZE]; |
| 177 | Insets[] typeMaxInsetsMap = new Insets[Type.SIZE]; |
Jorim Jaggi | 9099079 | 2019-01-21 23:00:20 +0100 | [diff] [blame] | 178 | boolean[] typeVisibilityMap = new boolean[SIZE]; |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 179 | final Rect relativeFrame = new Rect(frame); |
| 180 | final Rect relativeFrameMax = new Rect(frame); |
| 181 | for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) { |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 182 | InsetsSource source = mSources[type]; |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 183 | if (source == null) { |
Jorim Jaggi | 6f2ccea | 2020-04-01 21:59:18 +0200 | [diff] [blame] | 184 | int index = indexOf(toPublicType(type)); |
| 185 | if (typeInsetsMap[index] == null) { |
| 186 | typeInsetsMap[index] = Insets.NONE; |
| 187 | } |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 188 | continue; |
| 189 | } |
Jorim Jaggi | 648e588 | 2019-01-24 13:24:02 +0100 | [diff] [blame] | 190 | |
Tarandeep Singh | 92d2dd3 | 2019-08-07 14:45:01 -0700 | [diff] [blame] | 191 | boolean skipNonImeInImeMode = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_IME |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 192 | && source.getType() != ITYPE_IME; |
Jorim Jaggi | 648e588 | 2019-01-24 13:24:02 +0100 | [diff] [blame] | 193 | boolean skipSystemBars = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 194 | && (type == ITYPE_STATUS_BAR || type == ITYPE_NAVIGATION_BAR); |
Adrian Roos | 11dfd27 | 2019-03-25 19:21:26 +0100 | [diff] [blame] | 195 | boolean skipLegacyTypes = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE |
Jorim Jaggi | 761a5ab | 2020-01-06 23:16:30 +0100 | [diff] [blame] | 196 | && (type == ITYPE_STATUS_BAR || type == ITYPE_NAVIGATION_BAR |
| 197 | || type == ITYPE_IME); |
| 198 | if (skipSystemBars || skipLegacyTypes || skipNonImeInImeMode) { |
Jorim Jaggi | 9099079 | 2019-01-21 23:00:20 +0100 | [diff] [blame] | 199 | typeVisibilityMap[indexOf(toPublicType(type))] = source.isVisible(); |
| 200 | continue; |
| 201 | } |
| 202 | |
Jorim Jaggi | bcf99ff | 2018-12-03 18:04:26 +0100 | [diff] [blame] | 203 | processSource(source, relativeFrame, false /* ignoreVisibility */, typeInsetsMap, |
Jorim Jaggi | 9099079 | 2019-01-21 23:00:20 +0100 | [diff] [blame] | 204 | typeSideMap, typeVisibilityMap); |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 205 | |
| 206 | // IME won't be reported in max insets as the size depends on the EditorInfo of the IME |
| 207 | // target. |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 208 | if (source.getType() != ITYPE_IME) { |
Jorim Jaggi | 580aef5 | 2020-02-26 18:28:28 +0100 | [diff] [blame] | 209 | InsetsSource ignoringVisibilitySource = ignoringVisibilityState != null |
| 210 | ? ignoringVisibilityState.getSource(type) |
| 211 | : source; |
| 212 | if (ignoringVisibilitySource == null) { |
| 213 | continue; |
| 214 | } |
| 215 | processSource(ignoringVisibilitySource, relativeFrameMax, |
| 216 | true /* ignoreVisibility */, typeMaxInsetsMap, null /* typeSideMap */, |
| 217 | null /* typeVisibilityMap */); |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 218 | } |
| 219 | } |
Jorim Jaggi | 761a5ab | 2020-01-06 23:16:30 +0100 | [diff] [blame] | 220 | final int softInputAdjustMode = legacySoftInputMode & SOFT_INPUT_MASK_ADJUST; |
Jorim Jaggi | 9099079 | 2019-01-21 23:00:20 +0100 | [diff] [blame] | 221 | return new WindowInsets(typeInsetsMap, typeMaxInsetsMap, typeVisibilityMap, isScreenRound, |
Jorim Jaggi | 761a5ab | 2020-01-06 23:16:30 +0100 | [diff] [blame] | 222 | alwaysConsumeSystemBars, cutout, softInputAdjustMode == SOFT_INPUT_ADJUST_RESIZE |
Tiger Huang | e16645a | 2020-02-25 22:24:39 +0800 | [diff] [blame] | 223 | ? systemBars() | displayCutout() | ime() |
| 224 | : systemBars() | displayCutout(), |
Jorim Jaggi | 7f76187 | 2020-01-10 18:24:27 +0100 | [diff] [blame] | 225 | sNewInsetsMode == NEW_INSETS_MODE_FULL |
| 226 | && (legacySystemUiFlags & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0); |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 227 | } |
| 228 | |
Jorim Jaggi | 22488d3 | 2020-03-19 01:12:44 +0100 | [diff] [blame] | 229 | public Rect calculateVisibleInsets(Rect frame, @SoftInputModeFlags int softInputMode) { |
Jorim Jaggi | 4e04eb2 | 2020-01-09 16:42:14 +0100 | [diff] [blame] | 230 | Insets insets = Insets.NONE; |
| 231 | for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) { |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 232 | InsetsSource source = mSources[type]; |
Jorim Jaggi | 4e04eb2 | 2020-01-09 16:42:14 +0100 | [diff] [blame] | 233 | if (source == null) { |
| 234 | continue; |
| 235 | } |
| 236 | if (sNewInsetsMode != NEW_INSETS_MODE_FULL && type != ITYPE_IME) { |
| 237 | continue; |
| 238 | } |
| 239 | |
| 240 | // Ignore everything that's not a system bar or IME. |
| 241 | int publicType = InsetsState.toPublicType(type); |
| 242 | if (!isVisibleInsetsType(publicType, softInputMode)) { |
| 243 | continue; |
| 244 | } |
| 245 | insets = Insets.max(source.calculateVisibleInsets(frame), insets); |
| 246 | } |
| 247 | return insets.toRect(); |
| 248 | } |
| 249 | |
Adrian Roos | 8d04bcb | 2020-05-29 18:01:04 +0200 | [diff] [blame] | 250 | /** |
| 251 | * Calculate which insets *cannot* be controlled, because the frame does not cover the |
| 252 | * respective side of the inset. |
| 253 | * |
| 254 | * If the frame of our window doesn't cover the entire inset, the control API makes very |
| 255 | * little sense, as we don't deal with negative insets. |
| 256 | */ |
| 257 | @InsetsType |
| 258 | public int calculateUncontrollableInsetsFromFrame(Rect frame) { |
| 259 | int blocked = 0; |
| 260 | for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) { |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 261 | InsetsSource source = mSources[type]; |
Adrian Roos | 8d04bcb | 2020-05-29 18:01:04 +0200 | [diff] [blame] | 262 | if (source == null) { |
| 263 | continue; |
| 264 | } |
| 265 | if (!canControlSide(frame, getInsetSide( |
| 266 | source.calculateInsets(frame, true /* ignoreVisibility */)))) { |
| 267 | blocked |= toPublicType(type); |
| 268 | } |
| 269 | } |
| 270 | return blocked; |
| 271 | } |
| 272 | |
| 273 | private boolean canControlSide(Rect frame, int side) { |
| 274 | switch (side) { |
| 275 | case ISIDE_LEFT: |
| 276 | case ISIDE_RIGHT: |
| 277 | return frame.left == mDisplayFrame.left && frame.right == mDisplayFrame.right; |
| 278 | case ISIDE_TOP: |
| 279 | case ISIDE_BOTTOM: |
| 280 | return frame.top == mDisplayFrame.top && frame.bottom == mDisplayFrame.bottom; |
| 281 | case ISIDE_FLOATING: |
| 282 | return true; |
| 283 | default: |
| 284 | return false; |
| 285 | } |
| 286 | } |
| 287 | |
Jorim Jaggi | bcf99ff | 2018-12-03 18:04:26 +0100 | [diff] [blame] | 288 | private void processSource(InsetsSource source, Rect relativeFrame, boolean ignoreVisibility, |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 289 | Insets[] typeInsetsMap, @Nullable @InternalInsetsSide SparseIntArray typeSideMap, |
Jorim Jaggi | 9099079 | 2019-01-21 23:00:20 +0100 | [diff] [blame] | 290 | @Nullable boolean[] typeVisibilityMap) { |
Jorim Jaggi | bcf99ff | 2018-12-03 18:04:26 +0100 | [diff] [blame] | 291 | Insets insets = source.calculateInsets(relativeFrame, ignoreVisibility); |
| 292 | |
Adrian Roos | 11dfd27 | 2019-03-25 19:21:26 +0100 | [diff] [blame] | 293 | int type = toPublicType(source.getType()); |
| 294 | processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap, |
| 295 | insets, type); |
| 296 | |
| 297 | if (type == MANDATORY_SYSTEM_GESTURES) { |
| 298 | // Mandatory system gestures are also system gestures. |
| 299 | // TODO: find a way to express this more generally. One option would be to define |
| 300 | // Type.systemGestureInsets() as NORMAL | MANDATORY, but then we lose the |
| 301 | // ability to set systemGestureInsets() independently from |
| 302 | // mandatorySystemGestureInsets() in the Builder. |
| 303 | processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap, |
| 304 | insets, SYSTEM_GESTURES); |
| 305 | } |
| 306 | } |
| 307 | |
| 308 | private void processSourceAsPublicType(InsetsSource source, Insets[] typeInsetsMap, |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 309 | @InternalInsetsSide @Nullable SparseIntArray typeSideMap, |
Adrian Roos | 11dfd27 | 2019-03-25 19:21:26 +0100 | [diff] [blame] | 310 | @Nullable boolean[] typeVisibilityMap, Insets insets, int type) { |
| 311 | int index = indexOf(type); |
Jorim Jaggi | bcf99ff | 2018-12-03 18:04:26 +0100 | [diff] [blame] | 312 | Insets existing = typeInsetsMap[index]; |
| 313 | if (existing == null) { |
| 314 | typeInsetsMap[index] = insets; |
| 315 | } else { |
| 316 | typeInsetsMap[index] = Insets.max(existing, insets); |
| 317 | } |
| 318 | |
Jorim Jaggi | 9099079 | 2019-01-21 23:00:20 +0100 | [diff] [blame] | 319 | if (typeVisibilityMap != null) { |
| 320 | typeVisibilityMap[index] = source.isVisible(); |
| 321 | } |
| 322 | |
Tarandeep Singh | 95a3dbf | 2019-10-22 10:39:24 -0700 | [diff] [blame] | 323 | if (typeSideMap != null) { |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 324 | @InternalInsetsSide int insetSide = getInsetSide(insets); |
| 325 | if (insetSide != ISIDE_UNKNOWN) { |
Tarandeep Singh | 95a3dbf | 2019-10-22 10:39:24 -0700 | [diff] [blame] | 326 | typeSideMap.put(source.getType(), insetSide); |
Jorim Jaggi | 5bb571d | 2018-11-06 14:42:04 +0100 | [diff] [blame] | 327 | } |
| 328 | } |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 329 | } |
| 330 | |
Jorim Jaggi | 5bb571d | 2018-11-06 14:42:04 +0100 | [diff] [blame] | 331 | /** |
| 332 | * Retrieves the side for a certain {@code insets}. It is required that only one field l/t/r/b |
| 333 | * is set in order that this method returns a meaningful result. |
| 334 | */ |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 335 | private @InternalInsetsSide int getInsetSide(Insets insets) { |
Tarandeep Singh | 95a3dbf | 2019-10-22 10:39:24 -0700 | [diff] [blame] | 336 | if (Insets.NONE.equals(insets)) { |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 337 | return ISIDE_FLOATING; |
Tarandeep Singh | 95a3dbf | 2019-10-22 10:39:24 -0700 | [diff] [blame] | 338 | } |
Jorim Jaggi | 5bb571d | 2018-11-06 14:42:04 +0100 | [diff] [blame] | 339 | if (insets.left != 0) { |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 340 | return ISIDE_LEFT; |
Jorim Jaggi | 5bb571d | 2018-11-06 14:42:04 +0100 | [diff] [blame] | 341 | } |
| 342 | if (insets.top != 0) { |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 343 | return ISIDE_TOP; |
Jorim Jaggi | 5bb571d | 2018-11-06 14:42:04 +0100 | [diff] [blame] | 344 | } |
| 345 | if (insets.right != 0) { |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 346 | return ISIDE_RIGHT; |
Jorim Jaggi | 5bb571d | 2018-11-06 14:42:04 +0100 | [diff] [blame] | 347 | } |
| 348 | if (insets.bottom != 0) { |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 349 | return ISIDE_BOTTOM; |
Jorim Jaggi | 5bb571d | 2018-11-06 14:42:04 +0100 | [diff] [blame] | 350 | } |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 351 | return ISIDE_UNKNOWN; |
Jorim Jaggi | 5bb571d | 2018-11-06 14:42:04 +0100 | [diff] [blame] | 352 | } |
| 353 | |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 354 | public InsetsSource getSource(@InternalInsetsType int type) { |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 355 | InsetsSource source = mSources[type]; |
| 356 | if (source != null) { |
| 357 | return source; |
| 358 | } |
| 359 | source = new InsetsSource(type); |
| 360 | mSources[type] = source; |
| 361 | return source; |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 362 | } |
| 363 | |
Jorim Jaggi | 580aef5 | 2020-02-26 18:28:28 +0100 | [diff] [blame] | 364 | public @Nullable InsetsSource peekSource(@InternalInsetsType int type) { |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 365 | return mSources[type]; |
| 366 | } |
| 367 | |
| 368 | public boolean hasSources() { |
| 369 | for (int i = 0; i < SIZE; i++) { |
| 370 | if (mSources[i] != null) { |
| 371 | return true; |
| 372 | } |
| 373 | } |
| 374 | return false; |
Jorim Jaggi | 580aef5 | 2020-02-26 18:28:28 +0100 | [diff] [blame] | 375 | } |
| 376 | |
Tiger Huang | 017d51d | 2020-05-27 17:58:17 +0800 | [diff] [blame] | 377 | /** |
| 378 | * Returns the source visibility or the default visibility if the source doesn't exist. This is |
| 379 | * useful if when treating this object as a request. |
| 380 | * |
| 381 | * @param type The {@link InternalInsetsType} to query. |
| 382 | * @return {@code true} if the source is visible or the type is default visible and the source |
| 383 | * doesn't exist. |
| 384 | */ |
| 385 | public boolean getSourceOrDefaultVisibility(@InternalInsetsType int type) { |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 386 | final InsetsSource source = mSources[type]; |
Tiger Huang | 017d51d | 2020-05-27 17:58:17 +0800 | [diff] [blame] | 387 | return source != null ? source.isVisible() : getDefaultVisibility(type); |
| 388 | } |
| 389 | |
Tarandeep Singh | a6f3561 | 2019-01-11 19:50:46 -0800 | [diff] [blame] | 390 | public void setDisplayFrame(Rect frame) { |
| 391 | mDisplayFrame.set(frame); |
| 392 | } |
| 393 | |
| 394 | public Rect getDisplayFrame() { |
| 395 | return mDisplayFrame; |
| 396 | } |
| 397 | |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 398 | /** |
| 399 | * Modifies the state of this class to exclude a certain type to make it ready for dispatching |
| 400 | * to the client. |
| 401 | * |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 402 | * @param type The {@link InternalInsetsType} of the source to remove |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 403 | */ |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 404 | public void removeSource(@InternalInsetsType int type) { |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 405 | mSources[type] = null; |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 406 | } |
| 407 | |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 408 | /** |
| 409 | * A shortcut for setting the visibility of the source. |
| 410 | * |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 411 | * @param type The {@link InternalInsetsType} of the source to set the visibility |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 412 | * @param visible {@code true} for visible |
| 413 | */ |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 414 | public void setSourceVisible(@InternalInsetsType int type, boolean visible) { |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 415 | InsetsSource source = mSources[type]; |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 416 | if (source != null) { |
| 417 | source.setVisible(visible); |
| 418 | } |
| 419 | } |
| 420 | |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 421 | public void set(InsetsState other) { |
| 422 | set(other, false /* copySources */); |
| 423 | } |
| 424 | |
| 425 | public void set(InsetsState other, boolean copySources) { |
Tarandeep Singh | a6f3561 | 2019-01-11 19:50:46 -0800 | [diff] [blame] | 426 | mDisplayFrame.set(other.mDisplayFrame); |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 427 | if (copySources) { |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 428 | for (int i = 0; i < SIZE; i++) { |
| 429 | InsetsSource source = other.mSources[i]; |
| 430 | if (source == null) continue; |
| 431 | mSources[i] = new InsetsSource(source); |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 432 | } |
| 433 | } else { |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 434 | for (int i = 0; i < SIZE; i++) { |
| 435 | mSources[i] = other.mSources[i]; |
| 436 | } |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 437 | } |
| 438 | } |
| 439 | |
Jorim Jaggi | e35c059 | 2018-11-06 16:21:08 +0100 | [diff] [blame] | 440 | public void addSource(InsetsSource source) { |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 441 | mSources[source.getType()] = source; |
Jorim Jaggi | e35c059 | 2018-11-06 16:21:08 +0100 | [diff] [blame] | 442 | } |
| 443 | |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 444 | public static @InternalInsetsType ArraySet<Integer> toInternalType(@InsetsType int types) { |
Jorim Jaggi | b603095 | 2018-10-23 18:31:52 +0200 | [diff] [blame] | 445 | final ArraySet<Integer> result = new ArraySet<>(); |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 446 | if ((types & Type.STATUS_BARS) != 0) { |
| 447 | result.add(ITYPE_STATUS_BAR); |
Jorim Jaggi | b603095 | 2018-10-23 18:31:52 +0200 | [diff] [blame] | 448 | } |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 449 | if ((types & Type.NAVIGATION_BARS) != 0) { |
| 450 | result.add(ITYPE_NAVIGATION_BAR); |
Jorim Jaggi | b603095 | 2018-10-23 18:31:52 +0200 | [diff] [blame] | 451 | } |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 452 | if ((types & Type.CAPTION_BAR) != 0) { |
| 453 | result.add(ITYPE_CAPTION_BAR); |
| 454 | } |
Tiger Huang | e16645a | 2020-02-25 22:24:39 +0800 | [diff] [blame] | 455 | if ((types & Type.DISPLAY_CUTOUT) != 0) { |
| 456 | result.add(ITYPE_LEFT_DISPLAY_CUTOUT); |
| 457 | result.add(ITYPE_TOP_DISPLAY_CUTOUT); |
| 458 | result.add(ITYPE_RIGHT_DISPLAY_CUTOUT); |
| 459 | result.add(ITYPE_BOTTOM_DISPLAY_CUTOUT); |
| 460 | } |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 461 | if ((types & Type.IME) != 0) { |
| 462 | result.add(ITYPE_IME); |
Jorim Jaggi | b603095 | 2018-10-23 18:31:52 +0200 | [diff] [blame] | 463 | } |
| 464 | return result; |
| 465 | } |
| 466 | |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 467 | /** |
| 468 | * Converting a internal type to the public type. |
| 469 | * @param type internal insets type, {@code InternalInsetsType}. |
| 470 | * @return public insets type, {@code Type.InsetsType}. |
| 471 | */ |
| 472 | public static @Type.InsetsType int toPublicType(@InternalInsetsType int type) { |
Jorim Jaggi | bcf99ff | 2018-12-03 18:04:26 +0100 | [diff] [blame] | 473 | switch (type) { |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 474 | case ITYPE_STATUS_BAR: |
Heemin Seog | d79e4f4 | 2020-05-06 15:32:50 -0700 | [diff] [blame] | 475 | case ITYPE_CLIMATE_BAR: |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 476 | return Type.STATUS_BARS; |
| 477 | case ITYPE_NAVIGATION_BAR: |
Heemin Seog | d79e4f4 | 2020-05-06 15:32:50 -0700 | [diff] [blame] | 478 | case ITYPE_EXTRA_NAVIGATION_BAR: |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 479 | return Type.NAVIGATION_BARS; |
| 480 | case ITYPE_CAPTION_BAR: |
| 481 | return Type.CAPTION_BAR; |
| 482 | case ITYPE_IME: |
Jorim Jaggi | bcf99ff | 2018-12-03 18:04:26 +0100 | [diff] [blame] | 483 | return Type.IME; |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 484 | case ITYPE_TOP_GESTURES: |
| 485 | case ITYPE_BOTTOM_GESTURES: |
Adrian Roos | 11dfd27 | 2019-03-25 19:21:26 +0100 | [diff] [blame] | 486 | return Type.MANDATORY_SYSTEM_GESTURES; |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 487 | case ITYPE_LEFT_GESTURES: |
| 488 | case ITYPE_RIGHT_GESTURES: |
Adrian Roos | 11dfd27 | 2019-03-25 19:21:26 +0100 | [diff] [blame] | 489 | return Type.SYSTEM_GESTURES; |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 490 | case ITYPE_TOP_TAPPABLE_ELEMENT: |
| 491 | case ITYPE_BOTTOM_TAPPABLE_ELEMENT: |
Adrian Roos | 11dfd27 | 2019-03-25 19:21:26 +0100 | [diff] [blame] | 492 | return Type.TAPPABLE_ELEMENT; |
Tiger Huang | e16645a | 2020-02-25 22:24:39 +0800 | [diff] [blame] | 493 | case ITYPE_LEFT_DISPLAY_CUTOUT: |
| 494 | case ITYPE_TOP_DISPLAY_CUTOUT: |
| 495 | case ITYPE_RIGHT_DISPLAY_CUTOUT: |
| 496 | case ITYPE_BOTTOM_DISPLAY_CUTOUT: |
| 497 | return Type.DISPLAY_CUTOUT; |
Jorim Jaggi | bcf99ff | 2018-12-03 18:04:26 +0100 | [diff] [blame] | 498 | default: |
| 499 | throw new IllegalArgumentException("Unknown type: " + type); |
| 500 | } |
| 501 | } |
| 502 | |
Tiger Huang | 017d51d | 2020-05-27 17:58:17 +0800 | [diff] [blame] | 503 | public static boolean getDefaultVisibility(@InternalInsetsType int type) { |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 504 | return type != ITYPE_IME; |
Jorim Jaggi | e35c059 | 2018-11-06 16:21:08 +0100 | [diff] [blame] | 505 | } |
| 506 | |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 507 | public static boolean containsType(@InternalInsetsType int[] types, |
| 508 | @InternalInsetsType int type) { |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 509 | if (types == null) { |
| 510 | return false; |
| 511 | } |
| 512 | for (int t : types) { |
| 513 | if (t == type) { |
| 514 | return true; |
| 515 | } |
| 516 | } |
| 517 | return false; |
| 518 | } |
| 519 | |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 520 | public void dump(String prefix, PrintWriter pw) { |
| 521 | pw.println(prefix + "InsetsState"); |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 522 | for (int i = 0; i < SIZE; i++) { |
| 523 | InsetsSource source = mSources[i]; |
| 524 | if (source == null) continue; |
| 525 | source.dump(prefix + " ", pw); |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 526 | } |
| 527 | } |
| 528 | |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 529 | public static String typeToString(@InternalInsetsType int type) { |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 530 | switch (type) { |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 531 | case ITYPE_STATUS_BAR: |
| 532 | return "ITYPE_STATUS_BAR"; |
| 533 | case ITYPE_NAVIGATION_BAR: |
| 534 | return "ITYPE_NAVIGATION_BAR"; |
| 535 | case ITYPE_CAPTION_BAR: |
| 536 | return "ITYPE_CAPTION_BAR"; |
| 537 | case ITYPE_TOP_GESTURES: |
| 538 | return "ITYPE_TOP_GESTURES"; |
| 539 | case ITYPE_BOTTOM_GESTURES: |
| 540 | return "ITYPE_BOTTOM_GESTURES"; |
| 541 | case ITYPE_LEFT_GESTURES: |
| 542 | return "ITYPE_LEFT_GESTURES"; |
| 543 | case ITYPE_RIGHT_GESTURES: |
| 544 | return "ITYPE_RIGHT_GESTURES"; |
| 545 | case ITYPE_TOP_TAPPABLE_ELEMENT: |
| 546 | return "ITYPE_TOP_TAPPABLE_ELEMENT"; |
| 547 | case ITYPE_BOTTOM_TAPPABLE_ELEMENT: |
| 548 | return "ITYPE_BOTTOM_TAPPABLE_ELEMENT"; |
Tiger Huang | e16645a | 2020-02-25 22:24:39 +0800 | [diff] [blame] | 549 | case ITYPE_LEFT_DISPLAY_CUTOUT: |
| 550 | return "ITYPE_LEFT_DISPLAY_CUTOUT"; |
| 551 | case ITYPE_TOP_DISPLAY_CUTOUT: |
| 552 | return "ITYPE_TOP_DISPLAY_CUTOUT"; |
| 553 | case ITYPE_RIGHT_DISPLAY_CUTOUT: |
| 554 | return "ITYPE_RIGHT_DISPLAY_CUTOUT"; |
| 555 | case ITYPE_BOTTOM_DISPLAY_CUTOUT: |
| 556 | return "ITYPE_BOTTOM_DISPLAY_CUTOUT"; |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 557 | case ITYPE_IME: |
| 558 | return "ITYPE_IME"; |
Heemin Seog | d79e4f4 | 2020-05-06 15:32:50 -0700 | [diff] [blame] | 559 | case ITYPE_CLIMATE_BAR: |
| 560 | return "ITYPE_CLIMATE_BAR"; |
| 561 | case ITYPE_EXTRA_NAVIGATION_BAR: |
| 562 | return "ITYPE_EXTRA_NAVIGATION_BAR"; |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 563 | default: |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 564 | return "ITYPE_UNKNOWN_" + type; |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 565 | } |
| 566 | } |
| 567 | |
| 568 | @Override |
| 569 | public boolean equals(Object o) { |
Jorim Jaggi | ed31259 | 2020-05-25 16:46:56 +0200 | [diff] [blame] | 570 | return equals(o, false, false); |
Yunfan Chen | fae0aea | 2020-02-22 20:57:57 +0900 | [diff] [blame] | 571 | } |
| 572 | |
| 573 | /** |
| 574 | * An equals method can exclude the caption insets. This is useful because we assemble the |
| 575 | * caption insets information on the client side, and when we communicate with server, it's |
| 576 | * excluded. |
| 577 | * @param excludingCaptionInsets {@code true} if we want to compare two InsetsState objects but |
| 578 | * ignore the caption insets source value. |
Jorim Jaggi | ed31259 | 2020-05-25 16:46:56 +0200 | [diff] [blame] | 579 | * @param excludeInvisibleImeFrames If {@link #ITYPE_IME} frames should be ignored when IME is |
| 580 | * not visible. |
Yunfan Chen | fae0aea | 2020-02-22 20:57:57 +0900 | [diff] [blame] | 581 | * @return {@code true} if the two InsetsState objects are equal, {@code false} otherwise. |
| 582 | */ |
| 583 | @VisibleForTesting |
Jorim Jaggi | ed31259 | 2020-05-25 16:46:56 +0200 | [diff] [blame] | 584 | public boolean equals(Object o, boolean excludingCaptionInsets, |
| 585 | boolean excludeInvisibleImeFrames) { |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 586 | if (this == o) { return true; } |
| 587 | if (o == null || getClass() != o.getClass()) { return false; } |
| 588 | |
| 589 | InsetsState state = (InsetsState) o; |
| 590 | |
Tarandeep Singh | a6f3561 | 2019-01-11 19:50:46 -0800 | [diff] [blame] | 591 | if (!mDisplayFrame.equals(state.mDisplayFrame)) { |
| 592 | return false; |
| 593 | } |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 594 | for (int i = 0; i < SIZE; i++) { |
Yunfan Chen | fae0aea | 2020-02-22 20:57:57 +0900 | [diff] [blame] | 595 | if (excludingCaptionInsets) { |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 596 | if (i == ITYPE_CAPTION_BAR) continue; |
Yunfan Chen | fae0aea | 2020-02-22 20:57:57 +0900 | [diff] [blame] | 597 | } |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 598 | InsetsSource source = mSources[i]; |
| 599 | InsetsSource otherSource = state.mSources[i]; |
| 600 | if (source == null && otherSource == null) { |
| 601 | continue; |
| 602 | } |
| 603 | if (source != null && otherSource == null || source == null && otherSource != null) { |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 604 | return false; |
| 605 | } |
Jorim Jaggi | ed31259 | 2020-05-25 16:46:56 +0200 | [diff] [blame] | 606 | if (!otherSource.equals(source, excludeInvisibleImeFrames)) { |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 607 | return false; |
| 608 | } |
| 609 | } |
| 610 | return true; |
| 611 | } |
| 612 | |
| 613 | @Override |
| 614 | public int hashCode() { |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 615 | return Objects.hash(mDisplayFrame, Arrays.hashCode(mSources)); |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 616 | } |
| 617 | |
| 618 | public InsetsState(Parcel in) { |
| 619 | readFromParcel(in); |
| 620 | } |
| 621 | |
| 622 | @Override |
| 623 | public int describeContents() { |
| 624 | return 0; |
| 625 | } |
| 626 | |
| 627 | @Override |
| 628 | public void writeToParcel(Parcel dest, int flags) { |
Tarandeep Singh | a6f3561 | 2019-01-11 19:50:46 -0800 | [diff] [blame] | 629 | dest.writeParcelable(mDisplayFrame, flags); |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 630 | dest.writeParcelableArray(mSources, 0); |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 631 | } |
| 632 | |
Jeff Sharkey | 9e8f83d | 2019-02-28 12:06:45 -0700 | [diff] [blame] | 633 | public static final @android.annotation.NonNull Creator<InsetsState> CREATOR = new Creator<InsetsState>() { |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 634 | |
| 635 | public InsetsState createFromParcel(Parcel in) { |
| 636 | return new InsetsState(in); |
| 637 | } |
| 638 | |
| 639 | public InsetsState[] newArray(int size) { |
| 640 | return new InsetsState[size]; |
| 641 | } |
| 642 | }; |
| 643 | |
| 644 | public void readFromParcel(Parcel in) { |
Tarandeep Singh | a6f3561 | 2019-01-11 19:50:46 -0800 | [diff] [blame] | 645 | mDisplayFrame.set(in.readParcelable(null /* loader */)); |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 646 | mSources = in.readParcelableArray(null, InsetsSource.class); |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 647 | } |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 648 | |
| 649 | @Override |
| 650 | public String toString() { |
Taran Singh | 85661e3 | 2020-05-07 14:45:34 -0700 | [diff] [blame] | 651 | StringJoiner joiner = new StringJoiner(", "); |
Jorim Jaggi | bfa95a7 | 2020-06-18 22:51:49 +0200 | [diff] [blame] | 652 | for (int i = 0; i < SIZE; i++) { |
| 653 | InsetsSource source = mSources[i]; |
Taran Singh | 85661e3 | 2020-05-07 14:45:34 -0700 | [diff] [blame] | 654 | if (source != null) { |
| 655 | joiner.add(source.toString()); |
| 656 | } |
| 657 | } |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 658 | return "InsetsState: {" |
| 659 | + "mDisplayFrame=" + mDisplayFrame |
Taran Singh | 85661e3 | 2020-05-07 14:45:34 -0700 | [diff] [blame] | 660 | + ", mSources= { " + joiner |
| 661 | + " }"; |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 662 | } |
Jorim Jaggi | f96c90a | 2018-09-26 16:55:15 +0200 | [diff] [blame] | 663 | } |
| 664 | |