blob: ec875f8f0e1a2552e66b39b58d614cc6ce64d4e4 [file] [log] [blame]
Mady Mellordea7ecf2018-12-10 15:47:40 -08001/*
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.bubbles;
18
Yuncheol Heo5d62e752020-04-08 14:54:24 -070019import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
Mady Mellorc41ed322019-09-25 11:19:26 -070020import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
21import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Yunfan Chenb83940c2020-04-06 16:43:09 +090022import static android.graphics.PixelFormat.TRANSPARENT;
Mady Mellor390bff42019-04-05 15:09:01 -070023import static android.view.Display.INVALID_DISPLAY;
Yunfan Chenb83940c2020-04-06 16:43:09 +090024import static android.view.InsetsState.ITYPE_IME;
Joshua Tsuji06785ab2020-06-08 11:18:40 -040025import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
Jorim Jaggi924ef752020-01-29 17:26:55 +010026import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
27import static android.view.ViewRootImpl.sNewInsetsMode;
Yunfan Chenb83940c2020-04-06 16:43:09 +090028import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
29import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
30import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
31import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
Beverlya53fb0d2020-01-29 15:26:13 -050032
Mark Renoufdb861c92019-07-26 13:58:17 -040033import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_EXPANDED_VIEW;
Issei Suzukia8d07312019-06-07 12:56:19 +020034import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
35import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
Mady Mellorca0c24c2019-05-16 16:14:32 -070036
Joshua Tsuji847b1d422020-06-01 13:42:19 -040037import android.annotation.SuppressLint;
Mady Mellor60101c92019-04-11 19:04:00 -070038import android.app.ActivityOptions;
Mark Renouf5c732b32019-06-12 15:14:54 -040039import android.app.ActivityTaskManager;
Mady Mellor3dff9e62019-02-05 18:12:53 -080040import android.app.ActivityView;
Mady Mellor9801e852019-01-22 14:50:28 -080041import android.app.PendingIntent;
Mark Renouf5c732b32019-06-12 15:14:54 -040042import android.content.ComponentName;
Mady Mellordea7ecf2018-12-10 15:47:40 -080043import android.content.Context;
Mady Mellor9801e852019-01-22 14:50:28 -080044import android.content.Intent;
Lyn Han26bb1982020-06-08 15:38:01 -070045import android.content.res.Configuration;
Mady Mellordea7ecf2018-12-10 15:47:40 -080046import android.content.res.Resources;
Mady Mellordd497052019-01-30 17:23:48 -080047import android.content.res.TypedArray;
Mady Mellordea7ecf2018-12-10 15:47:40 -080048import android.graphics.Color;
Mady Mellor3dff9e62019-02-05 18:12:53 -080049import android.graphics.Insets;
Joshua Tsuji06785ab2020-06-08 11:18:40 -040050import android.graphics.Outline;
Mady Mellor3dff9e62019-02-05 18:12:53 -080051import android.graphics.Point;
Mady Mellor47b11e32019-07-11 19:06:21 -070052import android.graphics.Rect;
Mady Mellordea7ecf2018-12-10 15:47:40 -080053import android.graphics.drawable.ShapeDrawable;
Yunfan Chenb83940c2020-04-06 16:43:09 +090054import android.hardware.display.VirtualDisplay;
55import android.os.Binder;
Mark Renouf5c732b32019-06-12 15:14:54 -040056import android.os.RemoteException;
Mady Mellordea7ecf2018-12-10 15:47:40 -080057import android.util.AttributeSet;
Mady Mellor9801e852019-01-22 14:50:28 -080058import android.util.Log;
Yunfan Chenb83940c2020-04-06 16:43:09 +090059import android.view.Gravity;
Joshua Tsuji06785ab2020-06-08 11:18:40 -040060import android.view.SurfaceControl;
61import android.view.SurfaceView;
Mady Mellordea7ecf2018-12-10 15:47:40 -080062import android.view.View;
Joshua Tsuji06785ab2020-06-08 11:18:40 -040063import android.view.ViewGroup;
64import android.view.ViewOutlineProvider;
Mady Mellor3dff9e62019-02-05 18:12:53 -080065import android.view.WindowInsets;
Mady Mellora96c9ed2019-06-07 12:55:26 -070066import android.view.WindowManager;
Lyn Han670fa802020-05-05 12:56:33 -070067import android.view.accessibility.AccessibilityNodeInfo;
Joshua Tsuji06785ab2020-06-08 11:18:40 -040068import android.widget.FrameLayout;
Mady Mellordea7ecf2018-12-10 15:47:40 -080069import android.widget.LinearLayout;
70
Joshua Tsuji06785ab2020-06-08 11:18:40 -040071import androidx.annotation.Nullable;
72
Mark Renouf34d04f32019-05-13 15:53:18 -040073import com.android.internal.policy.ScreenDecorationsUtils;
Mady Mellor3dff9e62019-02-05 18:12:53 -080074import com.android.systemui.Dependency;
Mady Mellordea7ecf2018-12-10 15:47:40 -080075import com.android.systemui.R;
76import com.android.systemui.recents.TriangleShape;
Lyn Han754e77b2019-04-30 14:34:49 -070077import com.android.systemui.statusbar.AlphaOptimizedButton;
Mady Mellordea7ecf2018-12-10 15:47:40 -080078
79/**
Lyn Han02cca812019-04-02 16:27:32 -070080 * Container for the expanded bubble view, handles rendering the caret and settings icon.
Mady Mellordea7ecf2018-12-10 15:47:40 -080081 */
Joshua Tsuji6855cab2020-04-16 01:05:39 -040082public class BubbleExpandedView extends LinearLayout {
Issei Suzukia8d07312019-06-07 12:56:19 +020083 private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleExpandedView" : TAG_BUBBLES;
Yunfan Chenb83940c2020-04-06 16:43:09 +090084 private static final String WINDOW_TITLE = "ImeInsetsWindowWithoutContent";
Mady Mellordea7ecf2018-12-10 15:47:40 -080085
Issei Suzuki734bc942019-06-05 13:59:52 +020086 private enum ActivityViewStatus {
87 // ActivityView is being initialized, cannot start an activity yet.
88 INITIALIZING,
89 // ActivityView is initialized, and ready to start an activity.
90 INITIALIZED,
91 // Activity runs in the ActivityView.
92 ACTIVITY_STARTED,
93 // ActivityView is released, so activity launching will no longer be permitted.
94 RELEASED,
95 }
Mady Mellordea7ecf2018-12-10 15:47:40 -080096
97 // The triangle pointing to the expanded view
98 private View mPointerView;
Mady Mellor44ee2fe2019-01-30 17:51:16 -080099 private int mPointerMargin;
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400100 @Nullable private int[] mExpandedViewContainerLocation;
Mady Mellore8e07712019-01-23 12:45:33 -0800101
Lyn Han754e77b2019-04-30 14:34:49 -0700102 private AlphaOptimizedButton mSettingsIcon;
Mady Mellore8e07712019-01-23 12:45:33 -0800103
Mady Mellor3dff9e62019-02-05 18:12:53 -0800104 // Views for expanded state
Mady Mellor3dff9e62019-02-05 18:12:53 -0800105 private ActivityView mActivityView;
106
Issei Suzuki734bc942019-06-05 13:59:52 +0200107 private ActivityViewStatus mActivityViewStatus = ActivityViewStatus.INITIALIZING;
Mark Renouf5c732b32019-06-12 15:14:54 -0400108 private int mTaskId = -1;
109
Lyn Hanb58c7562020-01-07 14:29:20 -0800110 private PendingIntent mPendingIntent;
Mady Mellor3dff9e62019-02-05 18:12:53 -0800111
Mady Mellor5d8f1402019-02-21 18:23:52 -0800112 private boolean mKeyboardVisible;
113 private boolean mNeedsNewHeight;
114
Mady Mellora96c9ed2019-06-07 12:55:26 -0700115 private Point mDisplaySize;
Mady Mellorfe7ec032019-01-30 17:32:49 -0800116 private int mMinHeight;
Lyn Hancd4f87e2020-02-19 20:33:45 -0800117 private int mOverflowHeight;
Lyn Han02cca812019-04-02 16:27:32 -0700118 private int mSettingsIconHeight;
Lyn Han02cca812019-04-02 16:27:32 -0700119 private int mPointerWidth;
120 private int mPointerHeight;
Mark Renouf34d04f32019-05-13 15:53:18 -0400121 private ShapeDrawable mPointerDrawable;
Mady Mellordea7ecf2018-12-10 15:47:40 -0800122
Lyn Hanb58c7562020-01-07 14:29:20 -0800123 @Nullable private Bubble mBubble;
124
125 private boolean mIsOverflow;
Mady Mellore8e07712019-01-23 12:45:33 -0800126
Mady Mellor3dff9e62019-02-05 18:12:53 -0800127 private BubbleController mBubbleController = Dependency.get(BubbleController.class);
Mady Mellor9be3bed2019-08-21 17:26:26 -0700128 private WindowManager mWindowManager;
Mady Mellor9801e852019-01-22 14:50:28 -0800129
Mady Mellor9801e852019-01-22 14:50:28 -0800130 private BubbleStackView mStackView;
Yunfan Chenb83940c2020-04-06 16:43:09 +0900131 private View mVirtualImeView;
132 private WindowManager mVirtualDisplayWindowManager;
133 private boolean mImeShowing = false;
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400134 private float mCornerRadius = 0f;
135
136 /**
137 * Container for the ActivityView that has a solid, round-rect background that shows if the
138 * ActivityView hasn't loaded.
139 */
140 private FrameLayout mActivityViewContainer = new FrameLayout(getContext());
141
142 /** The SurfaceView that the ActivityView draws to. */
143 @Nullable private SurfaceView mActivitySurface;
Mady Mellor9801e852019-01-22 14:50:28 -0800144
Mady Mellor3dff9e62019-02-05 18:12:53 -0800145 private ActivityView.StateCallback mStateCallback = new ActivityView.StateCallback() {
146 @Override
147 public void onActivityViewReady(ActivityView view) {
Mark Renoufdb861c92019-07-26 13:58:17 -0400148 if (DEBUG_BUBBLE_EXPANDED_VIEW) {
149 Log.d(TAG, "onActivityViewReady: mActivityViewStatus=" + mActivityViewStatus
150 + " bubble=" + getBubbleKey());
151 }
Issei Suzuki734bc942019-06-05 13:59:52 +0200152 switch (mActivityViewStatus) {
153 case INITIALIZING:
154 case INITIALIZED:
155 // Custom options so there is no activity transition animation
156 ActivityOptions options = ActivityOptions.makeCustomAnimation(getContext(),
157 0 /* enterResId */, 0 /* exitResId */);
Winson Chung06200522020-03-31 22:47:02 -0700158 options.setTaskAlwaysOnTop(true);
Yuncheol Heo5d62e752020-04-08 14:54:24 -0700159 options.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
Issei Suzuki734bc942019-06-05 13:59:52 +0200160 // Post to keep the lifecycle normal
Mark Renoufdb861c92019-07-26 13:58:17 -0400161 post(() -> {
162 if (DEBUG_BUBBLE_EXPANDED_VIEW) {
163 Log.d(TAG, "onActivityViewReady: calling startActivity, "
164 + "bubble=" + getBubbleKey());
165 }
Mady Mellor8454ddf2019-08-15 11:16:23 -0700166 try {
Lyn Hanb58c7562020-01-07 14:29:20 -0800167 if (!mIsOverflow && mBubble.usingShortcutInfo()) {
Mady Mellor80d5ed12020-04-10 21:17:30 -0700168 options.setApplyActivityFlagsForBubbles(true);
Mady Mellorb547e5e2019-12-02 10:15:56 -0800169 mActivityView.startShortcutActivity(mBubble.getShortcutInfo(),
170 options, null /* sourceBounds */);
171 } else {
172 Intent fillInIntent = new Intent();
173 // Apply flags to make behaviour match documentLaunchMode=always.
174 fillInIntent.addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
175 fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
Lyn Hanb58c7562020-01-07 14:29:20 -0800176 mActivityView.startActivity(mPendingIntent, fillInIntent, options);
Mady Mellorb547e5e2019-12-02 10:15:56 -0800177 }
Mady Mellor8454ddf2019-08-15 11:16:23 -0700178 } catch (RuntimeException e) {
179 // If there's a runtime exception here then there's something
180 // wrong with the intent, we can't really recover / try to populate
181 // the bubble again so we'll just remove it.
182 Log.w(TAG, "Exception while displaying bubble: " + getBubbleKey()
183 + ", " + e.getMessage() + "; removing bubble");
Pinyao Ting3c930612020-05-19 00:26:03 +0000184 mBubbleController.removeBubble(getBubbleKey(),
Mady Mellor8454ddf2019-08-15 11:16:23 -0700185 BubbleController.DISMISS_INVALID_INTENT);
186 }
Mark Renoufdb861c92019-07-26 13:58:17 -0400187 });
Issei Suzuki734bc942019-06-05 13:59:52 +0200188 mActivityViewStatus = ActivityViewStatus.ACTIVITY_STARTED;
Mady Mellor6d002032019-02-13 13:45:17 -0800189 }
Mady Mellor3dff9e62019-02-05 18:12:53 -0800190 }
191
192 @Override
193 public void onActivityViewDestroyed(ActivityView view) {
Mark Renoufdb861c92019-07-26 13:58:17 -0400194 if (DEBUG_BUBBLE_EXPANDED_VIEW) {
195 Log.d(TAG, "onActivityViewDestroyed: mActivityViewStatus=" + mActivityViewStatus
196 + " bubble=" + getBubbleKey());
197 }
Issei Suzuki734bc942019-06-05 13:59:52 +0200198 mActivityViewStatus = ActivityViewStatus.RELEASED;
Mady Mellor3dff9e62019-02-05 18:12:53 -0800199 }
200
Mark Renouf5c732b32019-06-12 15:14:54 -0400201 @Override
202 public void onTaskCreated(int taskId, ComponentName componentName) {
Mark Renoufdb861c92019-07-26 13:58:17 -0400203 if (DEBUG_BUBBLE_EXPANDED_VIEW) {
204 Log.d(TAG, "onTaskCreated: taskId=" + taskId
205 + " bubble=" + getBubbleKey());
206 }
Mark Renouf5c732b32019-06-12 15:14:54 -0400207 // Since Bubble ActivityView applies singleTaskDisplay this is
208 // guaranteed to only be called once per ActivityView. The taskId is
209 // saved to use for removeTask, preventing appearance in recent tasks.
210 mTaskId = taskId;
Mady Mellor3dff9e62019-02-05 18:12:53 -0800211 }
212
213 /**
214 * This is only called for tasks on this ActivityView, which is also set to
215 * single-task mode -- meaning never more than one task on this display. If a task
216 * is being removed, it's the top Activity finishing and this bubble should
217 * be removed or collapsed.
218 */
219 @Override
220 public void onTaskRemovalStarted(int taskId) {
Mark Renoufdb861c92019-07-26 13:58:17 -0400221 if (DEBUG_BUBBLE_EXPANDED_VIEW) {
222 Log.d(TAG, "onTaskRemovalStarted: taskId=" + taskId
223 + " mActivityViewStatus=" + mActivityViewStatus
224 + " bubble=" + getBubbleKey());
225 }
Mady Mellordd6fe612020-04-15 11:47:55 -0700226 if (mBubble != null) {
Mady Mellorff076eb2019-11-13 10:12:06 -0800227 // Must post because this is called from a binder thread.
Pinyao Ting3c930612020-05-19 00:26:03 +0000228 post(() -> mBubbleController.removeBubble(mBubble.getKey(),
Mady Mellorff076eb2019-11-13 10:12:06 -0800229 BubbleController.DISMISS_TASK_FINISHED));
Mady Mellor3dff9e62019-02-05 18:12:53 -0800230 }
231 }
232 };
Mady Mellore8e07712019-01-23 12:45:33 -0800233
Mady Mellor3d82e682019-02-05 13:34:48 -0800234 public BubbleExpandedView(Context context) {
Mady Mellordea7ecf2018-12-10 15:47:40 -0800235 this(context, null);
236 }
237
Mady Mellor3d82e682019-02-05 13:34:48 -0800238 public BubbleExpandedView(Context context, AttributeSet attrs) {
Mady Mellordea7ecf2018-12-10 15:47:40 -0800239 this(context, attrs, 0);
240 }
241
Mady Mellor3d82e682019-02-05 13:34:48 -0800242 public BubbleExpandedView(Context context, AttributeSet attrs, int defStyleAttr) {
Mady Mellordea7ecf2018-12-10 15:47:40 -0800243 this(context, attrs, defStyleAttr, 0);
244 }
245
Mady Mellor3d82e682019-02-05 13:34:48 -0800246 public BubbleExpandedView(Context context, AttributeSet attrs, int defStyleAttr,
Mady Mellordea7ecf2018-12-10 15:47:40 -0800247 int defStyleRes) {
248 super(context, attrs, defStyleAttr, defStyleRes);
Lyn Hanbc985c52020-05-18 17:57:58 -0700249 updateDimensions();
250 }
251
252 void updateDimensions() {
Mady Mellora96c9ed2019-06-07 12:55:26 -0700253 mDisplaySize = new Point();
Lyn Hanbc985c52020-05-18 17:57:58 -0700254 mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Mady Mellor8fe411d2019-08-16 11:27:53 -0700255 // Get the real size -- this includes screen decorations (notches, statusbar, navbar).
Mady Mellor9be3bed2019-08-21 17:26:26 -0700256 mWindowManager.getDefaultDisplay().getRealSize(mDisplaySize);
Mady Mellor47b11e32019-07-11 19:06:21 -0700257 Resources res = getResources();
258 mMinHeight = res.getDimensionPixelSize(R.dimen.bubble_expanded_default_height);
Lyn Hancd4f87e2020-02-19 20:33:45 -0800259 mOverflowHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height);
Mady Mellor47b11e32019-07-11 19:06:21 -0700260 mPointerMargin = res.getDimensionPixelSize(R.dimen.bubble_pointer_margin);
Mady Mellordea7ecf2018-12-10 15:47:40 -0800261 }
262
Joshua Tsuji847b1d422020-06-01 13:42:19 -0400263 @SuppressLint("ClickableViewAccessibility")
Mady Mellordea7ecf2018-12-10 15:47:40 -0800264 @Override
265 protected void onFinishInflate() {
266 super.onFinishInflate();
Mark Renoufdb861c92019-07-26 13:58:17 -0400267 if (DEBUG_BUBBLE_EXPANDED_VIEW) {
268 Log.d(TAG, "onFinishInflate: bubble=" + getBubbleKey());
269 }
Mady Mellordea7ecf2018-12-10 15:47:40 -0800270
271 Resources res = getResources();
272 mPointerView = findViewById(R.id.pointer_view);
Lyn Han02cca812019-04-02 16:27:32 -0700273 mPointerWidth = res.getDimensionPixelSize(R.dimen.bubble_pointer_width);
274 mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
Mady Mellordd497052019-01-30 17:23:48 -0800275
Mark Renouf34d04f32019-05-13 15:53:18 -0400276 mPointerDrawable = new ShapeDrawable(TriangleShape.create(
Lyn Han5aa27e22019-05-15 10:55:07 -0700277 mPointerWidth, mPointerHeight, true /* pointUp */));
Mady Mellora96c9ed2019-06-07 12:55:26 -0700278 mPointerView.setVisibility(INVISIBLE);
Mady Mellor9801e852019-01-22 14:50:28 -0800279
Lyn Han02cca812019-04-02 16:27:32 -0700280 mSettingsIconHeight = getContext().getResources().getDimensionPixelSize(
Mady Mellor5a3e94b2020-02-07 12:16:21 -0800281 R.dimen.bubble_manage_button_height);
Lyn Han02cca812019-04-02 16:27:32 -0700282 mSettingsIcon = findViewById(R.id.settings_button);
Lyn Han02cca812019-04-02 16:27:32 -0700283
Mady Mellor3dff9e62019-02-05 18:12:53 -0800284 mActivityView = new ActivityView(mContext, null /* attrs */, 0 /* defStyle */,
shawnlinba532af2020-06-02 17:48:37 +0800285 true /* singleTaskInstance */, false /* usePublicVirtualDisplay*/,
286 true /* disableSurfaceViewBackgroundLayer */);
Lyn Hanb58c7562020-01-07 14:29:20 -0800287
lumarkdc9b3192019-07-23 21:18:17 +0800288 // Set ActivityView's alpha value as zero, since there is no view content to be shown.
Issei Suzukicac2a502019-04-16 16:52:50 +0200289 setContentVisibility(false);
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400290
291 mActivityViewContainer.setBackgroundColor(Color.WHITE);
292 mActivityViewContainer.setOutlineProvider(new ViewOutlineProvider() {
293 @Override
294 public void getOutline(View view, Outline outline) {
295 outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), mCornerRadius);
296 }
297 });
298 mActivityViewContainer.setClipToOutline(true);
299 mActivityViewContainer.addView(mActivityView);
300 mActivityViewContainer.setLayoutParams(
301 new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
302 addView(mActivityViewContainer);
303
304 if (mActivityView != null
305 && mActivityView.getChildCount() > 0
306 && mActivityView.getChildAt(0) instanceof SurfaceView) {
307 // Retrieve the surface from the ActivityView so we can screenshot it and change its
308 // z-ordering. This should always be possible, since ActivityView's constructor adds the
309 // SurfaceView as its first child.
310 mActivitySurface = (SurfaceView) mActivityView.getChildAt(0);
311 }
Mady Mellor3dff9e62019-02-05 18:12:53 -0800312
Lyn Han5aa27e22019-05-15 10:55:07 -0700313 // Expanded stack layout, top to bottom:
314 // Expanded view container
315 // ==> bubble row
316 // ==> expanded view
317 // ==> activity view
318 // ==> manage button
319 bringChildToFront(mActivityView);
320 bringChildToFront(mSettingsIcon);
Mady Mellor52b1ac62019-04-10 16:59:03 -0700321
Mark Renouf34d04f32019-05-13 15:53:18 -0400322 applyThemeAttrs();
323
Mady Mellor5d8f1402019-02-21 18:23:52 -0800324 setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> {
325 // Keep track of IME displaying because we should not make any adjustments that might
326 // cause a config change while the IME is displayed otherwise it'll loose focus.
Mady Mellor3dff9e62019-02-05 18:12:53 -0800327 final int keyboardHeight = insets.getSystemWindowInsetBottom()
328 - insets.getStableInsetBottom();
Mady Mellor5d8f1402019-02-21 18:23:52 -0800329 mKeyboardVisible = keyboardHeight != 0;
330 if (!mKeyboardVisible && mNeedsNewHeight) {
331 updateHeight();
332 }
Mady Mellor3dff9e62019-02-05 18:12:53 -0800333 return view.onApplyWindowInsets(insets);
334 });
Joshua Tsuji847b1d422020-06-01 13:42:19 -0400335
336 final int expandedViewPadding =
337 res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
338
339 setPadding(
340 expandedViewPadding, expandedViewPadding, expandedViewPadding, expandedViewPadding);
341 setOnTouchListener((view, motionEvent) -> {
342 if (!usingActivityView()) {
343 return false;
344 }
345
346 final Rect avBounds = new Rect();
347 mActivityView.getBoundsOnScreen(avBounds);
348
349 // Consume and ignore events on the expanded view padding that are within the
350 // ActivityView's vertical bounds. These events are part of a back gesture, and so they
351 // should not collapse the stack (which all other touches on areas around the AV would
352 // do).
353 if (motionEvent.getRawY() >= avBounds.top && motionEvent.getRawY() <= avBounds.bottom) {
354 return true;
355 }
356
357 return false;
358 });
Joshua Tsuji519d4c12020-05-29 15:22:31 -0400359
360 // BubbleStackView is forced LTR, but we want to respect the locale for expanded view layout
361 // so the Manage button appears on the right.
362 setLayoutDirection(LAYOUT_DIRECTION_LOCALE);
Mady Mellore8e07712019-01-23 12:45:33 -0800363 }
364
Mark Renoufdb861c92019-07-26 13:58:17 -0400365 private String getBubbleKey() {
366 return mBubble != null ? mBubble.getKey() : "null";
367 }
368
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400369 /**
370 * Asks the ActivityView's surface to draw on top of all other views in the window. This is
371 * useful for ordering surfaces during animations, but should otherwise be set to false so that
372 * bubbles and menus can draw over the ActivityView.
373 */
374 void setSurfaceZOrderedOnTop(boolean onTop) {
375 if (mActivitySurface == null) {
376 return;
377 }
378
379 mActivitySurface.setZOrderedOnTop(onTop, true);
380 }
381
382 /** Return a GraphicBuffer with the contents of the ActivityView's underlying surface. */
383 @Nullable SurfaceControl.ScreenshotGraphicBuffer snapshotActivitySurface() {
384 if (mActivitySurface == null) {
385 return null;
386 }
387
388 return SurfaceControl.captureLayers(
389 mActivitySurface.getSurfaceControl(),
390 new Rect(0, 0, mActivityView.getWidth(), mActivityView.getHeight()),
391 1 /* scale */);
392 }
393
394 int[] getActivityViewLocationOnScreen() {
395 if (mActivityView != null) {
396 return mActivityView.getLocationOnScreen();
397 } else {
398 return new int[]{0, 0};
399 }
400 }
401
Joshua Tsuji6855cab2020-04-16 01:05:39 -0400402 void setManageClickListener(OnClickListener manageClickListener) {
403 findViewById(R.id.settings_button).setOnClickListener(manageClickListener);
404 }
405
406 /**
407 * Updates the ActivityView's obscured touchable region. This calls onLocationChanged, which
408 * results in a call to {@link BubbleStackView#subtractObscuredTouchableRegion}. This is useful
409 * if a view has been added or removed from on top of the ActivityView, such as the manage menu.
410 */
411 void updateObscuredTouchableRegion() {
Mady Mellor64db51a2020-05-27 19:00:14 -0700412 if (mActivityView != null) {
413 mActivityView.onLocationChanged();
414 }
Joshua Tsuji6855cab2020-04-16 01:05:39 -0400415 }
416
Mark Renouf34d04f32019-05-13 15:53:18 -0400417 void applyThemeAttrs() {
Lyn Han61bfdb32019-12-10 14:34:12 -0800418 final TypedArray ta = mContext.obtainStyledAttributes(
Joshua Tsujidd082b62020-05-20 22:26:24 -0400419 new int[] {android.R.attr.dialogCornerRadius});
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400420 mCornerRadius = ta.getDimensionPixelSize(0, 0);
Mark Renouf34d04f32019-05-13 15:53:18 -0400421 ta.recycle();
422
Lyn Hanedb55e22020-02-12 18:55:39 -0800423 if (mActivityView != null && ScreenDecorationsUtils.supportsRoundedCornersOnWindows(
424 mContext.getResources())) {
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400425 mActivityView.setCornerRadius(mCornerRadius);
Mark Renouf34d04f32019-05-13 15:53:18 -0400426 }
Lyn Han26bb1982020-06-08 15:38:01 -0700427
428 final int mode =
429 getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
430 switch (mode) {
431 case Configuration.UI_MODE_NIGHT_NO:
432 mPointerDrawable.setTint(getResources().getColor(R.color.bubbles_pointer_light));
433 break;
434 case Configuration.UI_MODE_NIGHT_YES:
435 mPointerDrawable.setTint(getResources().getColor(R.color.bubbles_pointer_dark));
436 break;
437 }
438 mPointerView.setBackground(mPointerDrawable);
Mark Renouf34d04f32019-05-13 15:53:18 -0400439 }
440
Joshua Tsuji847b1d422020-06-01 13:42:19 -0400441 /**
442 * Hides the IME if it's showing. This is currently done by dispatching a back press to the AV.
443 */
444 void hideImeIfVisible() {
445 if (mKeyboardVisible) {
446 performBackPressIfNeeded();
447 }
448 }
449
Mady Mellor5d8f1402019-02-21 18:23:52 -0800450 @Override
451 protected void onDetachedFromWindow() {
452 super.onDetachedFromWindow();
Joshua Tsuji847b1d422020-06-01 13:42:19 -0400453 hideImeIfVisible();
Mady Mellor5d8f1402019-02-21 18:23:52 -0800454 mKeyboardVisible = false;
455 mNeedsNewHeight = false;
456 if (mActivityView != null) {
Mady Melloraf02fa42020-03-04 14:22:16 -0800457 if (sNewInsetsMode == NEW_INSETS_MODE_FULL) {
Yunfan Chenb83940c2020-04-06 16:43:09 +0900458 setImeWindowToDisplay(0, 0);
Mady Melloraf02fa42020-03-04 14:22:16 -0800459 } else {
460 mActivityView.setForwardedInsets(Insets.of(0, 0, 0, 0));
461 }
Mady Mellor5d8f1402019-02-21 18:23:52 -0800462 }
Mark Renoufdb861c92019-07-26 13:58:17 -0400463 if (DEBUG_BUBBLE_EXPANDED_VIEW) {
464 Log.d(TAG, "onDetachedFromWindow: bubble=" + getBubbleKey());
465 }
Mady Mellor5d8f1402019-02-21 18:23:52 -0800466 }
467
468 /**
Issei Suzukicac2a502019-04-16 16:52:50 +0200469 * Set visibility of contents in the expanded state.
470 *
471 * @param visibility {@code true} if the contents should be visible on the screen.
472 *
473 * Note that this contents visibility doesn't affect visibility at {@link android.view.View},
474 * and setting {@code false} actually means rendering the contents in transparent.
475 */
476 void setContentVisibility(boolean visibility) {
Mark Renoufdb861c92019-07-26 13:58:17 -0400477 if (DEBUG_BUBBLE_EXPANDED_VIEW) {
478 Log.d(TAG, "setContentVisibility: visibility=" + visibility
479 + " bubble=" + getBubbleKey());
480 }
Issei Suzukicac2a502019-04-16 16:52:50 +0200481 final float alpha = visibility ? 1f : 0f;
482 mPointerView.setAlpha(alpha);
483 if (mActivityView != null) {
484 mActivityView.setAlpha(alpha);
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400485 mActivityView.bringToFront();
Issei Suzukicac2a502019-04-16 16:52:50 +0200486 }
487 }
488
489 /**
Mady Mellor5d8f1402019-02-21 18:23:52 -0800490 * Called by {@link BubbleStackView} when the insets for the expanded state should be updated.
491 * This should be done post-move and post-animation.
492 */
493 void updateInsets(WindowInsets insets) {
494 if (usingActivityView()) {
Mady Mellor8fe411d2019-08-16 11:27:53 -0700495 int[] screenLoc = mActivityView.getLocationOnScreen();
496 final int activityViewBottom = screenLoc[1] + mActivityView.getHeight();
Mady Mellor9be3bed2019-08-21 17:26:26 -0700497 final int keyboardTop = mDisplaySize.y - Math.max(insets.getSystemWindowInsetBottom(),
498 insets.getDisplayCutout() != null
499 ? insets.getDisplayCutout().getSafeInsetBottom()
500 : 0);
Mady Mellor8fe411d2019-08-16 11:27:53 -0700501 final int insetsBottom = Math.max(activityViewBottom - keyboardTop, 0);
Jorim Jaggi924ef752020-01-29 17:26:55 +0100502
Jorim Jaggi924ef752020-01-29 17:26:55 +0100503 if (sNewInsetsMode == NEW_INSETS_MODE_FULL) {
Yunfan Chenb83940c2020-04-06 16:43:09 +0900504 setImeWindowToDisplay(getWidth(), insetsBottom);
Jorim Jaggi924ef752020-01-29 17:26:55 +0100505 } else {
506 mActivityView.setForwardedInsets(Insets.of(0, 0, 0, insetsBottom));
507 }
Mady Mellor5d8f1402019-02-21 18:23:52 -0800508 }
509 }
510
Yunfan Chenb83940c2020-04-06 16:43:09 +0900511 private void setImeWindowToDisplay(int w, int h) {
512 if (getVirtualDisplayId() == INVALID_DISPLAY) {
513 return;
514 }
515 if (h == 0 || w == 0) {
516 if (mImeShowing) {
517 mVirtualImeView.setVisibility(GONE);
518 mImeShowing = false;
519 }
520 return;
521 }
522 final Context virtualDisplayContext = mContext.createDisplayContext(
523 getVirtualDisplay().getDisplay());
524
525 if (mVirtualDisplayWindowManager == null) {
526 mVirtualDisplayWindowManager =
527 (WindowManager) virtualDisplayContext.getSystemService(Context.WINDOW_SERVICE);
528 }
529 if (mVirtualImeView == null) {
530 mVirtualImeView = new View(virtualDisplayContext);
531 mVirtualImeView.setVisibility(VISIBLE);
532 mVirtualDisplayWindowManager.addView(mVirtualImeView,
533 getVirtualImeViewAttrs(w, h));
534 } else {
535 mVirtualDisplayWindowManager.updateViewLayout(mVirtualImeView,
536 getVirtualImeViewAttrs(w, h));
537 mVirtualImeView.setVisibility(VISIBLE);
538 }
539
540 mImeShowing = true;
541 }
542
543 private WindowManager.LayoutParams getVirtualImeViewAttrs(int w, int h) {
544 // To use TYPE_NAVIGATION_BAR_PANEL instead of TYPE_IME_BAR to bypass the IME window type
545 // token check when adding the window.
546 final WindowManager.LayoutParams attrs =
547 new WindowManager.LayoutParams(w, h, TYPE_NAVIGATION_BAR_PANEL,
548 FLAG_LAYOUT_NO_LIMITS | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE,
549 TRANSPARENT);
550 attrs.gravity = Gravity.BOTTOM;
551 attrs.setTitle(WINDOW_TITLE);
552 attrs.token = new Binder();
553 attrs.providesInsetsTypes = new int[]{ITYPE_IME};
554 attrs.alpha = 0.0f;
555 return attrs;
556 }
557
Mady Mellor247ca2c2019-12-02 16:18:59 -0800558 void setStackView(BubbleStackView stackView) {
Mady Mellor9801e852019-01-22 14:50:28 -0800559 mStackView = stackView;
Mady Mellor6d002032019-02-13 13:45:17 -0800560 }
561
Lyn Hanb58c7562020-01-07 14:29:20 -0800562 public void setOverflow(boolean overflow) {
563 mIsOverflow = overflow;
564
565 Intent target = new Intent(mContext, BubbleOverflowActivity.class);
566 mPendingIntent = PendingIntent.getActivity(mContext, /* requestCode */ 0,
567 target, PendingIntent.FLAG_UPDATE_CURRENT);
568 mSettingsIcon.setVisibility(GONE);
569 }
570
Mady Mellor6d002032019-02-13 13:45:17 -0800571 /**
Mady Mellor247ca2c2019-12-02 16:18:59 -0800572 * Sets the bubble used to populate this view.
Mady Mellor6d002032019-02-13 13:45:17 -0800573 */
Mady Mellor247ca2c2019-12-02 16:18:59 -0800574 void update(Bubble bubble) {
575 if (DEBUG_BUBBLE_EXPANDED_VIEW) {
576 Log.d(TAG, "update: bubble=" + (bubble != null ? bubble.getKey() : "null"));
577 }
Mady Mellor458a6262020-06-07 21:09:19 -0700578 boolean isNew = mBubble == null || didBackingContentChange(bubble);
Lyn Hanb58c7562020-01-07 14:29:20 -0800579 if (isNew || bubble != null && bubble.getKey().equals(mBubble.getKey())) {
Mady Mellor247ca2c2019-12-02 16:18:59 -0800580 mBubble = bubble;
581 mSettingsIcon.setContentDescription(getResources().getString(
582 R.string.bubbles_settings_button_description, bubble.getAppName()));
583
Lyn Han670fa802020-05-05 12:56:33 -0700584 mSettingsIcon.setAccessibilityDelegate(
585 new AccessibilityDelegate() {
586 @Override
587 public void onInitializeAccessibilityNodeInfo(View host,
588 AccessibilityNodeInfo info) {
589 super.onInitializeAccessibilityNodeInfo(host, info);
590 // On focus, have TalkBack say
591 // "Actions available. Use swipe up then right to view."
592 // in addition to the default "double tap to activate".
593 mStackView.setupLocalMenu(info);
594 }
595 });
596
Mady Mellor247ca2c2019-12-02 16:18:59 -0800597 if (isNew) {
Lyn Hanb58c7562020-01-07 14:29:20 -0800598 mPendingIntent = mBubble.getBubbleIntent();
599 if (mPendingIntent != null || mBubble.getShortcutInfo() != null) {
Mady Mellor247ca2c2019-12-02 16:18:59 -0800600 setContentVisibility(false);
601 mActivityView.setVisibility(VISIBLE);
602 }
603 }
604 applyThemeAttrs();
605 } else {
606 Log.w(TAG, "Trying to update entry with different key, new bubble: "
607 + bubble.getKey() + " old bubble: " + bubble.getKey());
608 }
609 }
610
Mady Mellor458a6262020-06-07 21:09:19 -0700611 private boolean didBackingContentChange(Bubble newBubble) {
612 boolean prevWasIntentBased = mBubble != null && mPendingIntent != null;
613 boolean newIsIntentBased = newBubble.getBubbleIntent() != null;
614 return prevWasIntentBased != newIsIntentBased;
615 }
616
Mady Mellor247ca2c2019-12-02 16:18:59 -0800617 /**
618 * Lets activity view know it should be shown / populated with activity content.
619 */
620 void populateExpandedView() {
Mark Renoufdb861c92019-07-26 13:58:17 -0400621 if (DEBUG_BUBBLE_EXPANDED_VIEW) {
622 Log.d(TAG, "populateExpandedView: "
623 + "bubble=" + getBubbleKey());
624 }
625
Mady Mellor5029fa62019-03-05 12:16:21 -0800626 if (usingActivityView()) {
627 mActivityView.setCallback(mStateCallback);
628 } else {
Issei Suzukia91f3962019-06-07 11:48:23 +0200629 Log.e(TAG, "Cannot populate expanded view.");
Mady Mellor5029fa62019-03-05 12:16:21 -0800630 }
Mady Mellor9801e852019-01-22 14:50:28 -0800631 }
632
Mark Renouf041d7262019-02-06 12:09:41 -0500633 boolean performBackPressIfNeeded() {
Mady Mellor323fb0b2019-03-25 12:15:22 -0700634 if (!usingActivityView()) {
Mark Renouf041d7262019-02-06 12:09:41 -0500635 return false;
636 }
637 mActivityView.performBackPress();
638 return true;
639 }
640
Mady Mellorfe7ec032019-01-30 17:32:49 -0800641 void updateHeight() {
Mark Renoufdb861c92019-07-26 13:58:17 -0400642 if (DEBUG_BUBBLE_EXPANDED_VIEW) {
643 Log.d(TAG, "updateHeight: bubble=" + getBubbleKey());
644 }
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400645
646 if (mExpandedViewContainerLocation == null) {
647 return;
648 }
649
Mady Mellorfe7ec032019-01-30 17:32:49 -0800650 if (usingActivityView()) {
Lyn Hancd4f87e2020-02-19 20:33:45 -0800651 float desiredHeight = mOverflowHeight;
Lyn Hanb58c7562020-01-07 14:29:20 -0800652 if (!mIsOverflow) {
653 desiredHeight = Math.max(mBubble.getDesiredHeight(mContext), mMinHeight);
654 }
Mady Mellor8fe411d2019-08-16 11:27:53 -0700655 float height = Math.min(desiredHeight, getMaxExpandedHeight());
Lyn Hancd4f87e2020-02-19 20:33:45 -0800656 height = Math.max(height, mIsOverflow? mOverflowHeight : mMinHeight);
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400657 ViewGroup.LayoutParams lp = mActivityView.getLayoutParams();
Lyn Hancd4f87e2020-02-19 20:33:45 -0800658 mNeedsNewHeight = lp.height != height;
Mady Mellor5d8f1402019-02-21 18:23:52 -0800659 if (!mKeyboardVisible) {
660 // If the keyboard is visible... don't adjust the height because that will cause
661 // a configuration change and the keyboard will be lost.
Mady Mellor7af771a2019-03-07 15:04:54 -0800662 lp.height = (int) height;
Mady Mellor5d8f1402019-02-21 18:23:52 -0800663 mActivityView.setLayoutParams(lp);
664 mNeedsNewHeight = false;
665 }
Mark Renoufdb861c92019-07-26 13:58:17 -0400666 if (DEBUG_BUBBLE_EXPANDED_VIEW) {
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400667 Log.d(TAG, "updateHeight: bubble=" + getBubbleKey()
668 + " height=" + height
Mark Renoufdb861c92019-07-26 13:58:17 -0400669 + " mNeedsNewHeight=" + mNeedsNewHeight);
670 }
Mady Mellorfe7ec032019-01-30 17:32:49 -0800671 }
672 }
673
Mady Mellora96c9ed2019-06-07 12:55:26 -0700674 private int getMaxExpandedHeight() {
Mady Mellor9be3bed2019-08-21 17:26:26 -0700675 mWindowManager.getDefaultDisplay().getRealSize(mDisplaySize);
Mady Mellor8fe411d2019-08-16 11:27:53 -0700676 int bottomInset = getRootWindowInsets() != null
677 ? getRootWindowInsets().getStableInsetBottom()
678 : 0;
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400679
680 return mDisplaySize.y
681 - mExpandedViewContainerLocation[1]
682 - getPaddingTop()
683 - getPaddingBottom()
684 - mSettingsIconHeight
685 - mPointerHeight
Mady Mellor8fe411d2019-08-16 11:27:53 -0700686 - mPointerMargin - bottomInset;
Mady Mellora96c9ed2019-06-07 12:55:26 -0700687 }
688
Mady Mellor47b11e32019-07-11 19:06:21 -0700689 /**
Mady Mellor3dff9e62019-02-05 18:12:53 -0800690 * Update appearance of the expanded view being displayed.
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400691 *
692 * @param containerLocationOnScreen The location on-screen of the container the expanded view is
693 * added to. This allows us to calculate max height without
694 * waiting for layout.
Mady Mellor3dff9e62019-02-05 18:12:53 -0800695 */
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400696 public void updateView(int[] containerLocationOnScreen) {
Mark Renoufdb861c92019-07-26 13:58:17 -0400697 if (DEBUG_BUBBLE_EXPANDED_VIEW) {
698 Log.d(TAG, "updateView: bubble="
699 + getBubbleKey());
700 }
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400701
702 mExpandedViewContainerLocation = containerLocationOnScreen;
703
Mady Mellor3dff9e62019-02-05 18:12:53 -0800704 if (usingActivityView()
705 && mActivityView.getVisibility() == VISIBLE
706 && mActivityView.isAttachedToWindow()) {
707 mActivityView.onLocationChanged();
Joshua Tsuji06785ab2020-06-08 11:18:40 -0400708 updateHeight();
Mady Mellor3dff9e62019-02-05 18:12:53 -0800709 }
710 }
711
712 /**
Mady Mellordea7ecf2018-12-10 15:47:40 -0800713 * Set the x position that the tip of the triangle should point to.
714 */
Mady Mellor3dff9e62019-02-05 18:12:53 -0800715 public void setPointerPosition(float x) {
Lyn Han9a2f5cf2019-05-23 11:01:41 -0700716 float halfPointerWidth = mPointerWidth / 2f;
717 float pointerLeft = x - halfPointerWidth;
718 mPointerView.setTranslationX(pointerLeft);
Lyn Hanf74ba672019-05-20 16:08:48 -0700719 mPointerView.setVisibility(VISIBLE);
Mady Mellordea7ecf2018-12-10 15:47:40 -0800720 }
721
722 /**
Mady Mellor5a3e94b2020-02-07 12:16:21 -0800723 * Position of the manage button displayed in the expanded view. Used for placing user
724 * education about the manage button.
725 */
Joshua Tsuji6855cab2020-04-16 01:05:39 -0400726 public void getManageButtonBoundsOnScreen(Rect rect) {
727 mSettingsIcon.getBoundsOnScreen(rect);
Mady Mellor5a3e94b2020-02-07 12:16:21 -0800728 }
729
730 /**
Mady Mellor3dff9e62019-02-05 18:12:53 -0800731 * Removes and releases an ActivityView if one was previously created for this bubble.
Mady Mellordea7ecf2018-12-10 15:47:40 -0800732 */
Mady Mellor94d94a72019-03-05 18:16:59 -0800733 public void cleanUpExpandedState() {
Mark Renoufdb861c92019-07-26 13:58:17 -0400734 if (DEBUG_BUBBLE_EXPANDED_VIEW) {
735 Log.d(TAG, "cleanUpExpandedState: mActivityViewStatus=" + mActivityViewStatus
736 + ", bubble=" + getBubbleKey());
737 }
Mady Mellor3dff9e62019-02-05 18:12:53 -0800738 if (mActivityView == null) {
Mark Renouf89b1a4a2018-12-04 14:59:45 -0500739 return;
740 }
Issei Suzuki734bc942019-06-05 13:59:52 +0200741 switch (mActivityViewStatus) {
742 case INITIALIZED:
743 case ACTIVITY_STARTED:
744 mActivityView.release();
Mady Mellordea7ecf2018-12-10 15:47:40 -0800745 }
Mark Renouf5c732b32019-06-12 15:14:54 -0400746 if (mTaskId != -1) {
747 try {
748 ActivityTaskManager.getService().removeTask(mTaskId);
749 } catch (RemoteException e) {
750 Log.w(TAG, "Failed to remove taskId " + mTaskId);
751 }
752 mTaskId = -1;
Mady Mellordea7ecf2018-12-10 15:47:40 -0800753 }
Mark Renouf28c250d2019-02-25 16:47:34 -0500754 removeView(mActivityView);
Mark Renouf5c732b32019-06-12 15:14:54 -0400755
Mady Mellor3dff9e62019-02-05 18:12:53 -0800756 mActivityView = null;
Issei Suzuki734bc942019-06-05 13:59:52 +0200757 }
758
759 /**
760 * Called when the last task is removed from a {@link android.hardware.display.VirtualDisplay}
761 * which {@link ActivityView} uses.
762 */
763 void notifyDisplayEmpty() {
Mark Renoufdb861c92019-07-26 13:58:17 -0400764 if (DEBUG_BUBBLE_EXPANDED_VIEW) {
765 Log.d(TAG, "notifyDisplayEmpty: bubble="
766 + getBubbleKey()
767 + " mActivityViewStatus=" + mActivityViewStatus);
768 }
Issei Suzuki734bc942019-06-05 13:59:52 +0200769 if (mActivityViewStatus == ActivityViewStatus.ACTIVITY_STARTED) {
770 mActivityViewStatus = ActivityViewStatus.INITIALIZED;
771 }
Mady Mellordea7ecf2018-12-10 15:47:40 -0800772 }
773
Mady Mellor3dff9e62019-02-05 18:12:53 -0800774 private boolean usingActivityView() {
Lyn Hanb58c7562020-01-07 14:29:20 -0800775 return (mPendingIntent != null || mBubble.getShortcutInfo() != null)
Mady Mellor2ac2d3a2020-01-08 17:18:54 -0800776 && mActivityView != null;
Mady Mellor3dff9e62019-02-05 18:12:53 -0800777 }
778
Mady Mellor390bff42019-04-05 15:09:01 -0700779 /**
780 * @return the display id of the virtual display.
781 */
782 public int getVirtualDisplayId() {
783 if (usingActivityView()) {
784 return mActivityView.getVirtualDisplayId();
785 }
786 return INVALID_DISPLAY;
787 }
Yunfan Chenb83940c2020-04-06 16:43:09 +0900788
789 private VirtualDisplay getVirtualDisplay() {
790 if (usingActivityView()) {
791 return mActivityView.getVirtualDisplay();
792 }
793 return null;
794 }
Mady Mellordea7ecf2018-12-10 15:47:40 -0800795}