blob: aa0b7b656e1c5a36bc8a5de7e53c723e42a0b9f0 [file] [log] [blame]
yoshiki iguchi4e30e762018-02-06 12:09:23 +09001/*
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
17package com.android.systemui.statusbar.phone;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.content.Context;
Adrian Roos22af6502018-02-22 16:57:08 +010022import android.content.res.Configuration;
yoshiki iguchi4e30e762018-02-06 12:09:23 +090023import android.content.res.Resources;
Issei Suzuki43190bd2018-08-20 17:28:41 +020024import android.graphics.Rect;
Jorim Jaggi71aaa402018-06-06 17:22:56 +020025import android.graphics.Region;
26import android.graphics.Region.Op;
yoshiki iguchi4e30e762018-02-06 12:09:23 +090027import android.util.Log;
28import android.util.Pools;
Jorim Jaggi71aaa402018-06-06 17:22:56 +020029import android.view.DisplayCutout;
30import android.view.Gravity;
yoshiki iguchi4e30e762018-02-06 12:09:23 +090031import android.view.View;
32import android.view.ViewTreeObserver;
33
Gus Prevasab336792018-11-14 13:52:20 -050034import androidx.collection.ArraySet;
35
Jason Monk1fd3fc32018-08-14 17:20:09 -040036import com.android.systemui.Dependency;
yoshiki iguchi4e30e762018-02-06 12:09:23 +090037import com.android.systemui.Dumpable;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080038import com.android.systemui.R;
Jorim Jaggi71aaa402018-06-06 17:22:56 +020039import com.android.systemui.ScreenDecorations;
Mady Mellord1c78b262018-11-06 18:04:40 -080040import com.android.systemui.bubbles.BubbleController;
Jason Monk1fd3fc32018-08-14 17:20:09 -040041import com.android.systemui.statusbar.StatusBarState;
Jason Monk1fd3fc32018-08-14 17:20:09 -040042import com.android.systemui.statusbar.StatusBarStateController;
Gus Prevasab336792018-11-14 13:52:20 -050043import com.android.systemui.statusbar.StatusBarStateController.StateListener;
44import com.android.systemui.statusbar.notification.NotificationData;
yoshiki iguchi4e30e762018-02-06 12:09:23 +090045import com.android.systemui.statusbar.notification.VisualStabilityManager;
Gus Prevasab336792018-11-14 13:52:20 -050046import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
Adrian Roos22af6502018-02-22 16:57:08 +010047import com.android.systemui.statusbar.policy.ConfigurationController;
yoshiki iguchi4e30e762018-02-06 12:09:23 +090048import com.android.systemui.statusbar.policy.HeadsUpManager;
49import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
50
51import java.io.FileDescriptor;
52import java.io.PrintWriter;
53import java.util.HashSet;
54import java.util.Stack;
55
56/**
57 * A implementation of HeadsUpManager for phone and car.
58 */
59public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
Mady Mellord1c78b262018-11-06 18:04:40 -080060 ViewTreeObserver.OnComputeInternalInsetsListener, VisualStabilityManager.Callback,
61 OnHeadsUpChangedListener, ConfigurationController.ConfigurationListener {
yoshiki iguchi4e30e762018-02-06 12:09:23 +090062 private static final String TAG = "HeadsUpManagerPhone";
yoshiki iguchi4e30e762018-02-06 12:09:23 +090063
64 private final View mStatusBarWindowView;
yoshiki iguchi4e30e762018-02-06 12:09:23 +090065 private final NotificationGroupManager mGroupManager;
66 private final StatusBar mBar;
67 private final VisualStabilityManager mVisualStabilityManager;
yoshiki iguchi4e30e762018-02-06 12:09:23 +090068 private boolean mReleaseOnExpandFinish;
Selim Cinekaa9db1f2018-02-27 17:35:47 -080069
70 private int mStatusBarHeight;
71 private int mHeadsUpInset;
Jorim Jaggi71aaa402018-06-06 17:22:56 +020072 private int mDisplayCutoutTouchableRegionSize;
yoshiki iguchi4e30e762018-02-06 12:09:23 +090073 private boolean mTrackingHeadsUp;
74 private HashSet<String> mSwipedOutKeys = new HashSet<>();
75 private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>();
76 private ArraySet<NotificationData.Entry> mEntriesToRemoveWhenReorderingAllowed
77 = new ArraySet<>();
78 private boolean mIsExpanded;
79 private int[] mTmpTwoArray = new int[2];
80 private boolean mHeadsUpGoingAway;
81 private boolean mWaitingOnCollapseWhenGoingAway;
Mady Mellord1c78b262018-11-06 18:04:40 -080082 private boolean mBubbleGoingAway;
yoshiki iguchi4e30e762018-02-06 12:09:23 +090083 private boolean mIsObserving;
84 private int mStatusBarState;
85
Jason Monk1fd3fc32018-08-14 17:20:09 -040086 private final StateListener mStateListener = this::setStatusBarState;
Jason Monke59dc402018-08-16 12:05:01 -040087 private AnimationStateHandler mAnimationStateHandler;
Mady Mellord1c78b262018-11-06 18:04:40 -080088 private BubbleController mBubbleController = Dependency.get(BubbleController.class);
Jason Monk1fd3fc32018-08-14 17:20:09 -040089
yoshiki iguchi4e30e762018-02-06 12:09:23 +090090 private final Pools.Pool<HeadsUpEntryPhone> mEntryPool = new Pools.Pool<HeadsUpEntryPhone>() {
91 private Stack<HeadsUpEntryPhone> mPoolObjects = new Stack<>();
92
93 @Override
94 public HeadsUpEntryPhone acquire() {
95 if (!mPoolObjects.isEmpty()) {
96 return mPoolObjects.pop();
97 }
98 return new HeadsUpEntryPhone();
99 }
100
101 @Override
102 public boolean release(@NonNull HeadsUpEntryPhone instance) {
103 mPoolObjects.push(instance);
104 return true;
105 }
106 };
107
108 ///////////////////////////////////////////////////////////////////////////////////////////////
109 // Constructor:
110
111 public HeadsUpManagerPhone(@NonNull final Context context, @NonNull View statusBarWindowView,
112 @NonNull NotificationGroupManager groupManager, @NonNull StatusBar bar,
113 @NonNull VisualStabilityManager visualStabilityManager) {
114 super(context);
115
116 mStatusBarWindowView = statusBarWindowView;
117 mGroupManager = groupManager;
118 mBar = bar;
119 mVisualStabilityManager = visualStabilityManager;
120
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800121 initResources();
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900122
123 addListener(new OnHeadsUpChangedListener() {
124 @Override
125 public void onHeadsUpPinnedModeChanged(boolean hasPinnedNotification) {
Kevind4f66a42018-08-03 13:12:51 -0700126 if (Log.isLoggable(TAG, Log.WARN)) {
127 Log.w(TAG, "onHeadsUpPinnedModeChanged");
128 }
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900129 updateTouchableRegionListener();
130 }
131 });
Jason Monkaf08c152018-12-04 11:12:39 -0500132 Dependency.get(StatusBarStateController.class).addCallback(mStateListener);
Mady Mellord1c78b262018-11-06 18:04:40 -0800133 mBubbleController.setBubbleStateChangeListener((hasBubbles) -> {
134 if (!hasBubbles) {
135 mBubbleGoingAway = true;
136 }
137 updateTouchableRegionListener();
138 });
Jason Monk1fd3fc32018-08-14 17:20:09 -0400139 }
140
Jason Monke59dc402018-08-16 12:05:01 -0400141 public void setAnimationStateHandler(AnimationStateHandler handler) {
142 mAnimationStateHandler = handler;
143 }
144
Jason Monk1fd3fc32018-08-14 17:20:09 -0400145 public void destroy() {
Jason Monkaf08c152018-12-04 11:12:39 -0500146 Dependency.get(StatusBarStateController.class).removeCallback(mStateListener);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900147 }
148
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800149 private void initResources() {
150 Resources resources = mContext.getResources();
151 mStatusBarHeight = resources.getDimensionPixelSize(
152 com.android.internal.R.dimen.status_bar_height);
153 mHeadsUpInset = mStatusBarHeight + resources.getDimensionPixelSize(
154 R.dimen.heads_up_status_bar_padding);
Jorim Jaggi71aaa402018-06-06 17:22:56 +0200155 mDisplayCutoutTouchableRegionSize = resources.getDimensionPixelSize(
156 R.dimen.display_cutout_touchable_region_size);
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800157 }
158
159 @Override
160 public void onDensityOrFontScaleChanged() {
161 super.onDensityOrFontScaleChanged();
162 initResources();
163 }
164
Jorim Jaggi71aaa402018-06-06 17:22:56 +0200165 @Override
166 public void onOverlayChanged() {
167 initResources();
168 }
169
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900170 ///////////////////////////////////////////////////////////////////////////////////////////////
171 // Public methods:
172
173 /**
174 * Decides whether a click is invalid for a notification, i.e it has not been shown long enough
175 * that a user might have consciously clicked on it.
176 *
177 * @param key the key of the touched notification
178 * @return whether the touch is invalid and should be discarded
179 */
180 public boolean shouldSwallowClick(@NonNull String key) {
181 HeadsUpManager.HeadsUpEntry entry = getHeadsUpEntry(key);
Kevind4f66a42018-08-03 13:12:51 -0700182 return entry != null && mClock.currentTimeMillis() < entry.mPostTime;
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900183 }
184
185 public void onExpandingFinished() {
186 if (mReleaseOnExpandFinish) {
187 releaseAllImmediately();
188 mReleaseOnExpandFinish = false;
189 } else {
190 for (NotificationData.Entry entry : mEntriesToRemoveAfterExpand) {
Kevina97ea052018-09-11 13:53:18 -0700191 if (isAlerting(entry.key)) {
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900192 // Maybe the heads-up was removed already
Kevind4f66a42018-08-03 13:12:51 -0700193 removeAlertEntry(entry.key);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900194 }
195 }
196 }
197 mEntriesToRemoveAfterExpand.clear();
198 }
199
200 /**
201 * Sets the tracking-heads-up flag. If the flag is true, HeadsUpManager doesn't remove the entry
202 * from the list even after a Heads Up Notification is gone.
203 */
204 public void setTrackingHeadsUp(boolean trackingHeadsUp) {
205 mTrackingHeadsUp = trackingHeadsUp;
206 }
207
208 /**
209 * Notify that the status bar panel gets expanded or collapsed.
210 *
211 * @param isExpanded True to notify expanded, false to notify collapsed.
212 */
213 public void setIsPanelExpanded(boolean isExpanded) {
214 if (isExpanded != mIsExpanded) {
215 mIsExpanded = isExpanded;
216 if (isExpanded) {
217 // make sure our state is sane
218 mWaitingOnCollapseWhenGoingAway = false;
219 mHeadsUpGoingAway = false;
220 updateTouchableRegionListener();
221 }
Mady Mellord1c78b262018-11-06 18:04:40 -0800222 if (mBubbleController.hasBubbles() || !mIsExpanded) {
223 updateTouchableRegionListener();
224 }
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900225 }
226 }
227
228 /**
229 * Set the current state of the statusbar.
230 */
Jason Monk1fd3fc32018-08-14 17:20:09 -0400231 private void setStatusBarState(int statusBarState) {
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900232 mStatusBarState = statusBarState;
233 }
234
235 /**
236 * Set that we are exiting the headsUp pinned mode, but some notifications might still be
237 * animating out. This is used to keep the touchable regions in a sane state.
238 */
239 public void setHeadsUpGoingAway(boolean headsUpGoingAway) {
240 if (headsUpGoingAway != mHeadsUpGoingAway) {
241 mHeadsUpGoingAway = headsUpGoingAway;
242 if (!headsUpGoingAway) {
243 waitForStatusBarLayout();
244 }
245 updateTouchableRegionListener();
246 }
247 }
248
249 /**
250 * Notifies that a remote input textbox in notification gets active or inactive.
251 * @param entry The entry of the target notification.
252 * @param remoteInputActive True to notify active, False to notify inactive.
253 */
254 public void setRemoteInputActive(
255 @NonNull NotificationData.Entry entry, boolean remoteInputActive) {
256 HeadsUpEntryPhone headsUpEntry = getHeadsUpEntryPhone(entry.key);
257 if (headsUpEntry != null && headsUpEntry.remoteInputActive != remoteInputActive) {
258 headsUpEntry.remoteInputActive = remoteInputActive;
259 if (remoteInputActive) {
260 headsUpEntry.removeAutoRemovalCallbacks();
261 } else {
262 headsUpEntry.updateEntry(false /* updatePostTime */);
263 }
264 }
265 }
266
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900267 ///////////////////////////////////////////////////////////////////////////////////////////////
268 // HeadsUpManager public methods overrides:
269
270 @Override
271 public boolean isTrackingHeadsUp() {
272 return mTrackingHeadsUp;
273 }
274
Kevind4f66a42018-08-03 13:12:51 -0700275 @Override
276 public void snooze() {
277 super.snooze();
278 mReleaseOnExpandFinish = true;
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900279 }
280
281 public void addSwipedOutNotification(@NonNull String key) {
282 mSwipedOutKeys.add(key);
283 }
284
285 ///////////////////////////////////////////////////////////////////////////////////////////////
286 // Dumpable overrides:
287
288 @Override
289 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
290 pw.println("HeadsUpManagerPhone state:");
291 dumpInternal(fd, pw, args);
292 }
293
294 ///////////////////////////////////////////////////////////////////////////////////////////////
295 // ViewTreeObserver.OnComputeInternalInsetsListener overrides:
296
297 /**
298 * Overridden from TreeObserver.
299 */
300 @Override
301 public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
302 if (mIsExpanded || mBar.isBouncerShowing()) {
303 // The touchable region is always the full area when expanded
304 return;
305 }
306 if (hasPinnedHeadsUp()) {
Evan Laird94492852018-10-25 13:43:01 -0400307 NotificationData.Entry topEntry = getTopEntry();
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900308 if (topEntry.isChildInGroup()) {
Evan Laird94492852018-10-25 13:43:01 -0400309 final NotificationData.Entry groupSummary
310 = mGroupManager.getGroupSummary(topEntry.notification);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900311 if (groupSummary != null) {
312 topEntry = groupSummary;
313 }
314 }
Evan Laird94492852018-10-25 13:43:01 -0400315 ExpandableNotificationRow topRow = topEntry.getRow();
316 topRow.getLocationOnScreen(mTmpTwoArray);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900317 int minX = mTmpTwoArray[0];
Evan Laird94492852018-10-25 13:43:01 -0400318 int maxX = mTmpTwoArray[0] + topRow.getWidth();
319 int height = topRow.getIntrinsicHeight();
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900320
321 info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800322 info.touchableRegion.set(minX, 0, maxX, mHeadsUpInset + height);
Jorim Jaggi71aaa402018-06-06 17:22:56 +0200323 } else {
324 setCollapsedTouchableInsets(info);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900325 }
Mady Mellord1c78b262018-11-06 18:04:40 -0800326 Rect r = mBubbleController.getTouchableRegion();
327 if (r != null) {
328 info.touchableRegion.union(r);
329 }
330 mBubbleGoingAway = false;
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900331 }
332
Jorim Jaggi71aaa402018-06-06 17:22:56 +0200333 private void setCollapsedTouchableInsets(ViewTreeObserver.InternalInsetsInfo info) {
334 info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
335 info.touchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
336 updateRegionForNotch(info.touchableRegion);
337 }
338
339 private void updateRegionForNotch(Region region) {
340 DisplayCutout cutout = mStatusBarWindowView.getRootWindowInsets().getDisplayCutout();
341 if (cutout == null) {
342 return;
343 }
344
345 // Expand touchable region such that we also catch touches that just start below the notch
346 // area.
Issei Suzuki43190bd2018-08-20 17:28:41 +0200347 Rect bounds = new Rect();
348 ScreenDecorations.DisplayCutoutView.boundsFromDirection(cutout, Gravity.TOP, bounds);
349 bounds.offset(0, mDisplayCutoutTouchableRegionSize);
Jorim Jaggi71aaa402018-06-06 17:22:56 +0200350 region.op(bounds, Op.UNION);
Jorim Jaggi71aaa402018-06-06 17:22:56 +0200351 }
352
Adrian Roos22af6502018-02-22 16:57:08 +0100353 @Override
354 public void onConfigChanged(Configuration newConfig) {
355 Resources resources = mContext.getResources();
356 mStatusBarHeight = resources.getDimensionPixelSize(
357 com.android.internal.R.dimen.status_bar_height);
358 }
359
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900360 ///////////////////////////////////////////////////////////////////////////////////////////////
361 // VisualStabilityManager.Callback overrides:
362
363 @Override
364 public void onReorderingAllowed() {
Jason Monke59dc402018-08-16 12:05:01 -0400365 mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(false);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900366 for (NotificationData.Entry entry : mEntriesToRemoveWhenReorderingAllowed) {
Kevina97ea052018-09-11 13:53:18 -0700367 if (isAlerting(entry.key)) {
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900368 // Maybe the heads-up was removed already
Kevind4f66a42018-08-03 13:12:51 -0700369 removeAlertEntry(entry.key);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900370 }
371 }
372 mEntriesToRemoveWhenReorderingAllowed.clear();
Jason Monke59dc402018-08-16 12:05:01 -0400373 mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(true);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900374 }
375
376 ///////////////////////////////////////////////////////////////////////////////////////////////
377 // HeadsUpManager utility (protected) methods overrides:
378
379 @Override
Kevind4f66a42018-08-03 13:12:51 -0700380 protected HeadsUpEntry createAlertEntry() {
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900381 return mEntryPool.acquire();
382 }
383
384 @Override
Kevind4f66a42018-08-03 13:12:51 -0700385 protected void onAlertEntryRemoved(AlertEntry alertEntry) {
386 super.onAlertEntryRemoved(alertEntry);
387 mEntryPool.release((HeadsUpEntryPhone) alertEntry);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900388 }
389
390 @Override
391 protected boolean shouldHeadsUpBecomePinned(NotificationData.Entry entry) {
392 return mStatusBarState != StatusBarState.KEYGUARD && !mIsExpanded
393 || super.shouldHeadsUpBecomePinned(entry);
394 }
395
396 @Override
397 protected void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
398 super.dumpInternal(fd, pw, args);
Jason Monk1fd3fc32018-08-14 17:20:09 -0400399 pw.print(" mBarState="); pw.println(mStatusBarState);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900400 }
401
402 ///////////////////////////////////////////////////////////////////////////////////////////////
403 // Private utility methods:
404
405 @Nullable
406 private HeadsUpEntryPhone getHeadsUpEntryPhone(@NonNull String key) {
Kevind4f66a42018-08-03 13:12:51 -0700407 return (HeadsUpEntryPhone) mAlertEntries.get(key);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900408 }
409
410 @Nullable
411 private HeadsUpEntryPhone getTopHeadsUpEntryPhone() {
412 return (HeadsUpEntryPhone) getTopHeadsUpEntry();
413 }
414
Kevina5ff1fa2018-08-21 16:35:48 -0700415 @Override
416 protected boolean canRemoveImmediately(@NonNull String key) {
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900417 if (mSwipedOutKeys.contains(key)) {
418 // We always instantly dismiss views being manually swiped out.
419 mSwipedOutKeys.remove(key);
420 return true;
421 }
422
423 HeadsUpEntryPhone headsUpEntry = getHeadsUpEntryPhone(key);
424 HeadsUpEntryPhone topEntry = getTopHeadsUpEntryPhone();
Kevina5ff1fa2018-08-21 16:35:48 -0700425
426 return headsUpEntry == null || headsUpEntry != topEntry || super.canRemoveImmediately(key);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900427 }
428
429 /**
430 * We need to wait on the whole panel to collapse, before we can remove the touchable region
431 * listener.
432 */
433 private void waitForStatusBarLayout() {
434 mWaitingOnCollapseWhenGoingAway = true;
435 mStatusBarWindowView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
436 @Override
437 public void onLayoutChange(View v, int left, int top, int right, int bottom,
438 int oldLeft,
439 int oldTop, int oldRight, int oldBottom) {
440 if (mStatusBarWindowView.getHeight() <= mStatusBarHeight) {
441 mStatusBarWindowView.removeOnLayoutChangeListener(this);
442 mWaitingOnCollapseWhenGoingAway = false;
443 updateTouchableRegionListener();
444 }
445 }
446 });
447 }
448
Mady Mellord1c78b262018-11-06 18:04:40 -0800449 // TODO: some kind of TouchableRegionManager to deal with this, HeadsUpManager is not really
450 // the right place
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900451 private void updateTouchableRegionListener() {
452 boolean shouldObserve = hasPinnedHeadsUp() || mHeadsUpGoingAway
Mady Mellord1c78b262018-11-06 18:04:40 -0800453 || mBubbleController.hasBubbles() || mBubbleGoingAway
Jorim Jaggi71aaa402018-06-06 17:22:56 +0200454 || mWaitingOnCollapseWhenGoingAway
455 || mStatusBarWindowView.getRootWindowInsets().getDisplayCutout() != null;
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900456 if (shouldObserve == mIsObserving) {
457 return;
458 }
459 if (shouldObserve) {
460 mStatusBarWindowView.getViewTreeObserver().addOnComputeInternalInsetsListener(this);
461 mStatusBarWindowView.requestLayout();
462 } else {
463 mStatusBarWindowView.getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
464 }
465 mIsObserving = shouldObserve;
466 }
467
468 ///////////////////////////////////////////////////////////////////////////////////////////////
469 // HeadsUpEntryPhone:
470
471 protected class HeadsUpEntryPhone extends HeadsUpManager.HeadsUpEntry {
472 public void setEntry(@NonNull final NotificationData.Entry entry) {
473 Runnable removeHeadsUpRunnable = () -> {
474 if (!mVisualStabilityManager.isReorderingAllowed()) {
475 mEntriesToRemoveWhenReorderingAllowed.add(entry);
476 mVisualStabilityManager.addReorderingAllowedCallback(
477 HeadsUpManagerPhone.this);
478 } else if (!mTrackingHeadsUp) {
Kevind4f66a42018-08-03 13:12:51 -0700479 removeAlertEntry(entry.key);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900480 } else {
481 mEntriesToRemoveAfterExpand.add(entry);
482 }
483 };
484
Kevind4f66a42018-08-03 13:12:51 -0700485 setEntry(entry, removeHeadsUpRunnable);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900486 }
487
488 @Override
489 public void updateEntry(boolean updatePostTime) {
490 super.updateEntry(updatePostTime);
491
Kevind4f66a42018-08-03 13:12:51 -0700492 if (mEntriesToRemoveAfterExpand.contains(mEntry)) {
493 mEntriesToRemoveAfterExpand.remove(mEntry);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900494 }
Kevind4f66a42018-08-03 13:12:51 -0700495 if (mEntriesToRemoveWhenReorderingAllowed.contains(mEntry)) {
496 mEntriesToRemoveWhenReorderingAllowed.remove(mEntry);
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900497 }
498 }
499
500 @Override
Kevind4f66a42018-08-03 13:12:51 -0700501 public void setExpanded(boolean expanded) {
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900502 if (this.expanded == expanded) {
503 return;
504 }
505
506 this.expanded = expanded;
507 if (expanded) {
508 removeAutoRemovalCallbacks();
509 } else {
510 updateEntry(false /* updatePostTime */);
511 }
512 }
513 }
Jason Monke59dc402018-08-16 12:05:01 -0400514
515 public interface AnimationStateHandler {
516 void setHeadsUpGoingAwayAnimationsAllowed(boolean allowed);
517 }
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900518}