blob: a79a41b077975b3f3a669027e7b499f75f2efcbb [file] [log] [blame]
Daniel Sandlerc4f2a562012-05-04 11:55:46 -04001/*
2 * Copyright (C) 2012 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
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070019import android.annotation.ColorInt;
20import android.annotation.DrawableRes;
21import android.annotation.LayoutRes;
John Spurlock257f2832013-09-21 18:41:53 -040022import android.app.StatusBarManager;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040023import android.content.Context;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070024import android.content.res.Configuration;
Adrian Roos2f2bd9a2015-06-04 18:11:14 -070025import android.content.res.TypedArray;
Daniel Sandler198a0302012-08-17 16:04:31 -040026import android.graphics.Canvas;
27import android.graphics.Paint;
Selim Cineka0fad3b2014-09-19 17:20:05 +020028import android.graphics.PorterDuff;
29import android.graphics.PorterDuffXfermode;
John Spurlockfba91202014-04-22 12:58:26 -040030import android.graphics.Rect;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070031import android.graphics.drawable.Drawable;
Jaewan Kim50269362016-12-23 11:22:02 +090032import android.media.AudioManager;
John Spurlock0b99ea92014-10-01 15:32:22 -040033import android.media.session.MediaSessionLegacyHelper;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070034import android.net.Uri;
35import android.os.Bundle;
Selim Cineka0fad3b2014-09-19 17:20:05 +020036import android.os.IBinder;
Adrian Roos8008bd12017-02-22 15:02:09 +010037import android.os.SystemClock;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040038import android.util.AttributeSet;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070039import android.view.ActionMode;
Selim Cinek48a92a52017-05-02 20:02:30 -070040import android.view.InputDevice;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070041import android.view.InputQueue;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040042import android.view.KeyEvent;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070043import android.view.LayoutInflater;
44import android.view.Menu;
45import android.view.MenuItem;
Chris Wren5de6e942012-05-16 14:22:21 -040046import android.view.MotionEvent;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070047import android.view.SurfaceHolder;
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -070048import android.view.View;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070049import android.view.ViewGroup;
50import android.view.ViewTreeObserver;
51import android.view.Window;
Selim Cineka0fad3b2014-09-19 17:20:05 +020052import android.view.WindowManager;
53import android.view.WindowManagerGlobal;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040054import android.widget.FrameLayout;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040055
Selim Cinekf8c4add2017-06-08 09:54:58 -070056import com.android.internal.annotations.VisibleForTesting;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070057import com.android.internal.view.FloatingActionMode;
58import com.android.internal.widget.FloatingToolbar;
Chris Wren5de6e942012-05-16 14:22:21 -040059import com.android.systemui.R;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070060import com.android.systemui.classifier.FalsingManager;
Jorim Jaggiecbab362014-04-23 16:13:15 +020061import com.android.systemui.statusbar.DragDownHelper;
62import com.android.systemui.statusbar.StatusBarState;
Selim Cinekfab078b2014-03-27 22:45:58 +010063import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
Chris Wren5de6e942012-05-16 14:22:21 -040064
Selim Cinekfc5c1992018-01-29 12:40:32 -080065import java.io.FileDescriptor;
66import java.io.PrintWriter;
67
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040068
Jorim Jaggiecbab362014-04-23 16:13:15 +020069public class StatusBarWindowView extends FrameLayout {
Daniel Sandler198a0302012-08-17 16:04:31 -040070 public static final String TAG = "StatusBarWindowView";
Jason Monk2a6ea9c2017-01-26 11:14:51 -050071 public static final boolean DEBUG = StatusBar.DEBUG;
Chris Wren5de6e942012-05-16 14:22:21 -040072
Jorim Jaggiecbab362014-04-23 16:13:15 +020073 private DragDownHelper mDragDownHelper;
Adrian Roos8008bd12017-02-22 15:02:09 +010074 private DoubleTapHelper mDoubleTapHelper;
Selim Cinekb6d85eb2014-03-28 20:21:01 +010075 private NotificationStackScrollLayout mStackScrollLayout;
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -070076 private NotificationPanelView mNotificationPanel;
Adrian Roos9dc32092014-09-02 23:34:10 +020077 private View mBrightnessMirror;
Chris Wren5de6e942012-05-16 14:22:21 -040078
Adrian Roos2f2bd9a2015-06-04 18:11:14 -070079 private int mRightInset = 0;
Adrian Roos85d202b2016-06-02 16:27:47 -070080 private int mLeftInset = 0;
Adrian Roos2f2bd9a2015-06-04 18:11:14 -070081
Jason Monk2a6ea9c2017-01-26 11:14:51 -050082 private StatusBar mService;
Selim Cineka0fad3b2014-09-19 17:20:05 +020083 private final Paint mTransparentSrcPaint = new Paint();
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070084 private FalsingManager mFalsingManager;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040085
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070086 // Implements the floating action mode for TextView's Cut/Copy/Past menu. Normally provided by
87 // DecorView, but since this is a special window we have to roll our own.
88 private View mFloatingActionModeOriginatingView;
89 private ActionMode mFloatingActionMode;
90 private FloatingToolbar mFloatingToolbar;
91 private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener;
Selim Cinek48a92a52017-05-02 20:02:30 -070092 private boolean mTouchCancelled;
93 private boolean mTouchActive;
Selim Cinek2627d722018-01-19 12:16:49 -080094 private boolean mExpandAnimationRunning;
Selim Cinek7e222c3c2018-01-25 12:22:41 -080095 private boolean mExpandAnimationPending;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070096
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040097 public StatusBarWindowView(Context context, AttributeSet attrs) {
98 super(context, attrs);
Chris Wren5de6e942012-05-16 14:22:21 -040099 setMotionEventSplittingEnabled(false);
Selim Cineka0fad3b2014-09-19 17:20:05 +0200100 mTransparentSrcPaint.setColor(0);
101 mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700102 mFalsingManager = FalsingManager.getInstance(context);
Adrian Roos8008bd12017-02-22 15:02:09 +0100103 mDoubleTapHelper = new DoubleTapHelper(this, active -> {}, () -> {
104 mService.wakeUpIfDozing(SystemClock.uptimeMillis(), this);
105 return true;
106 }, null, null);
Chris Wren5de6e942012-05-16 14:22:21 -0400107 }
108
109 @Override
John Spurlockfba91202014-04-22 12:58:26 -0400110 protected boolean fitSystemWindows(Rect insets) {
111 if (getFitsSystemWindows()) {
Adrian Roos85d202b2016-06-02 16:27:47 -0700112 boolean paddingChanged = insets.top != getPaddingTop()
Jorim Jaggi416493b2014-09-13 03:57:32 +0200113 || insets.bottom != getPaddingBottom();
Jorim Jaggiaa806142015-05-20 18:04:16 -0700114
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700115 // Super-special right inset handling, because scrims and backdrop need to ignore it.
Adrian Roos85d202b2016-06-02 16:27:47 -0700116 if (insets.right != mRightInset || insets.left != mLeftInset) {
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700117 mRightInset = insets.right;
Adrian Roos85d202b2016-06-02 16:27:47 -0700118 mLeftInset = insets.left;
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700119 applyMargins();
120 }
Adrian Roos85d202b2016-06-02 16:27:47 -0700121 // Drop top inset, and pass through bottom inset.
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700122 if (paddingChanged) {
Adrian Roos85d202b2016-06-02 16:27:47 -0700123 setPadding(0, 0, 0, 0);
Jorim Jaggi416493b2014-09-13 03:57:32 +0200124 }
Jorim Jaggid7daab72014-05-06 22:22:20 +0200125 insets.left = 0;
126 insets.top = 0;
127 insets.right = 0;
John Spurlockfba91202014-04-22 12:58:26 -0400128 } else {
Adrian Roos85d202b2016-06-02 16:27:47 -0700129 if (mRightInset != 0 || mLeftInset != 0) {
Adrian Roose49e4092015-06-10 18:50:18 -0700130 mRightInset = 0;
Adrian Roos85d202b2016-06-02 16:27:47 -0700131 mLeftInset = 0;
Adrian Roose49e4092015-06-10 18:50:18 -0700132 applyMargins();
133 }
Jorim Jaggi416493b2014-09-13 03:57:32 +0200134 boolean changed = getPaddingLeft() != 0
135 || getPaddingRight() != 0
136 || getPaddingTop() != 0
137 || getPaddingBottom() != 0;
138 if (changed) {
139 setPadding(0, 0, 0, 0);
140 }
Jorim Jaggiaa806142015-05-20 18:04:16 -0700141 insets.top = 0;
John Spurlockfba91202014-04-22 12:58:26 -0400142 }
Jorim Jaggid7daab72014-05-06 22:22:20 +0200143 return false;
John Spurlockfba91202014-04-22 12:58:26 -0400144 }
145
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700146 private void applyMargins() {
147 final int N = getChildCount();
148 for (int i = 0; i < N; i++) {
149 View child = getChildAt(i);
150 if (child.getLayoutParams() instanceof LayoutParams) {
151 LayoutParams lp = (LayoutParams) child.getLayoutParams();
Adrian Roos85d202b2016-06-02 16:27:47 -0700152 if (!lp.ignoreRightInset
153 && (lp.rightMargin != mRightInset || lp.leftMargin != mLeftInset)) {
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700154 lp.rightMargin = mRightInset;
Adrian Roos85d202b2016-06-02 16:27:47 -0700155 lp.leftMargin = mLeftInset;
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700156 child.requestLayout();
157 }
158 }
159 }
160 }
161
162 @Override
163 public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
164 return new LayoutParams(getContext(), attrs);
165 }
166
167 @Override
168 protected FrameLayout.LayoutParams generateDefaultLayoutParams() {
169 return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
170 }
171
John Spurlockfba91202014-04-22 12:58:26 -0400172 @Override
Selim Cinek4e6b2d32015-06-25 20:15:33 -0400173 protected void onFinishInflate() {
174 super.onFinishInflate();
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100175 mStackScrollLayout = (NotificationStackScrollLayout) findViewById(
176 R.id.notification_stack_scroller);
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700177 mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
Adrian Roos9dc32092014-09-02 23:34:10 +0200178 mBrightnessMirror = findViewById(R.id.brightness_mirror);
Selim Cinek4e6b2d32015-06-25 20:15:33 -0400179 }
180
dooyoung.hwange4b841e2016-11-16 08:59:23 +0900181 @Override
182 public void onViewAdded(View child) {
183 super.onViewAdded(child);
184 if (child.getId() == R.id.brightness_mirror) {
185 mBrightnessMirror = child;
186 }
187 }
188
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500189 public void setService(StatusBar service) {
Selim Cinek4e6b2d32015-06-25 20:15:33 -0400190 mService = service;
Selim Cinekf8c4add2017-06-08 09:54:58 -0700191 setDragDownHelper(new DragDownHelper(getContext(), this, mStackScrollLayout, mService));
192 }
193
194 @VisibleForTesting
195 void setDragDownHelper(DragDownHelper dragDownHelper) {
196 mDragDownHelper = dragDownHelper;
Selim Cinek4e6b2d32015-06-25 20:15:33 -0400197 }
198
199 @Override
200 protected void onAttachedToWindow () {
201 super.onAttachedToWindow();
Daniel Sandlerb10d8852013-05-08 15:57:06 -0400202
Selim Cineka0fad3b2014-09-19 17:20:05 +0200203 // We need to ensure that our window doesn't suffer from overdraw which would normally
204 // occur if our window is translucent. Since we are drawing the whole window anyway with
205 // the scrim, we don't need the window to be cleared in the beginning.
Jorim Jaggi0e664392014-09-27 01:30:22 +0200206 if (mService.isScrimSrcModeEnabled()) {
207 IBinder windowToken = getWindowToken();
208 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
209 lp.token = windowToken;
210 setLayoutParams(lp);
211 WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true);
212 setWillNotDraw(false);
213 } else {
214 setWillNotDraw(!DEBUG);
215 }
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400216 }
217
218 @Override
219 public boolean dispatchKeyEvent(KeyEvent event) {
Adrian Roos56cf73a2016-07-18 14:23:32 -0700220 if (mService.interceptMediaKey(event)) {
221 return true;
222 }
223 if (super.dispatchKeyEvent(event)) {
224 return true;
225 }
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400226 boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
227 switch (event.getKeyCode()) {
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +0200228 case KeyEvent.KEYCODE_BACK:
229 if (!down) {
230 mService.onBackPressed();
231 }
232 return true;
233 case KeyEvent.KEYCODE_MENU:
234 if (!down) {
235 return mService.onMenuPressed();
236 }
Jorim Jaggi34250762014-07-03 23:51:19 +0200237 case KeyEvent.KEYCODE_SPACE:
238 if (!down) {
239 return mService.onSpacePressed();
240 }
John Spurlock0b99ea92014-10-01 15:32:22 -0400241 break;
John Spurlockd06aa572014-09-10 10:40:49 -0400242 case KeyEvent.KEYCODE_VOLUME_DOWN:
243 case KeyEvent.KEYCODE_VOLUME_UP:
John Spurlock0b99ea92014-10-01 15:32:22 -0400244 if (mService.isDozing()) {
Jaewan Kim50269362016-12-23 11:22:02 +0900245 MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
246 event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
John Spurlock0b99ea92014-10-01 15:32:22 -0400247 return true;
John Spurlockd06aa572014-09-10 10:40:49 -0400248 }
John Spurlock0b99ea92014-10-01 15:32:22 -0400249 break;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400250 }
Adrian Roos56cf73a2016-07-18 14:23:32 -0700251 return false;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400252 }
Chris Wren5de6e942012-05-16 14:22:21 -0400253
Selim Cinekd95ca7c2017-07-26 12:20:38 -0700254 public void setTouchActive(boolean touchActive) {
255 mTouchActive = touchActive;
Selim Cinekd95ca7c2017-07-26 12:20:38 -0700256 }
257
Chris Wren5de6e942012-05-16 14:22:21 -0400258 @Override
Adrian Roos9dc32092014-09-02 23:34:10 +0200259 public boolean dispatchTouchEvent(MotionEvent ev) {
Selim Cinek48a92a52017-05-02 20:02:30 -0700260 boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN;
Adrian Roosa6c03f82017-07-26 16:20:30 +0200261 boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL;
262 if (!isCancel && mService.shouldIgnoreTouch()) {
263 return false;
264 }
Selim Cinek48a92a52017-05-02 20:02:30 -0700265 if (isDown && mNotificationPanel.isFullyCollapsed()) {
Jorim Jaggie05256e2016-09-08 14:58:20 -0700266 mNotificationPanel.startExpandLatencyTracking();
267 }
Selim Cinek48a92a52017-05-02 20:02:30 -0700268 if (isDown) {
Selim Cinekd95ca7c2017-07-26 12:20:38 -0700269 setTouchActive(true);
Selim Cinek48a92a52017-05-02 20:02:30 -0700270 mTouchCancelled = false;
271 } else if (ev.getActionMasked() == MotionEvent.ACTION_UP
272 || ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
Selim Cinekd95ca7c2017-07-26 12:20:38 -0700273 setTouchActive(false);
Selim Cinek48a92a52017-05-02 20:02:30 -0700274 }
Selim Cinek7e222c3c2018-01-25 12:22:41 -0800275 if (mTouchCancelled || mExpandAnimationRunning || mExpandAnimationPending) {
Selim Cinek48a92a52017-05-02 20:02:30 -0700276 return false;
277 }
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700278 mFalsingManager.onTouchEvent(ev, getWidth(), getHeight());
Adrian Roos9dc32092014-09-02 23:34:10 +0200279 if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == VISIBLE) {
280 // Disallow new pointers while the brightness mirror is visible. This is so that you
281 // can't touch anything other than the brightness slider while the mirror is showing
282 // and the rest of the panel is transparent.
283 if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
284 return false;
285 }
286 }
Selim Cinek48a92a52017-05-02 20:02:30 -0700287 if (isDown) {
Mady Mellor7a9b2a62016-03-23 07:41:47 -0700288 mStackScrollLayout.closeControlsIfOutsideTouch(ev);
289 }
Adrian Roos67cca742017-04-13 16:52:51 -0700290 if (mService.isDozing()) {
291 mService.mDozeScrimController.extendPulse();
292 }
Mady Mellor7a9b2a62016-03-23 07:41:47 -0700293
Adrian Roos9dc32092014-09-02 23:34:10 +0200294 return super.dispatchTouchEvent(ev);
295 }
296
297 @Override
Chris Wren5de6e942012-05-16 14:22:21 -0400298 public boolean onInterceptTouchEvent(MotionEvent ev) {
Selim Cinekbe2c4432017-05-30 12:11:09 -0700299 if (mService.isDozing() && !mStackScrollLayout.hasPulsingNotifications()) {
Adrian Roos8008bd12017-02-22 15:02:09 +0100300 // Capture all touch events in always-on.
Adrian Roosebea7a72016-10-26 12:51:26 -0700301 return true;
302 }
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700303 boolean intercept = false;
Selim Cinekfab078b2014-03-27 22:45:58 +0100304 if (mNotificationPanel.isFullyExpanded()
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200305 && mStackScrollLayout.getVisibility() == View.VISIBLE
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200306 && mService.getBarState() == StatusBarState.KEYGUARD
Adrian Roos500263a2017-01-23 14:49:54 -0800307 && !mService.isBouncerShowing()
308 && !mService.isDozing()) {
Jorim Jaggiecbab362014-04-23 16:13:15 +0200309 intercept = mDragDownHelper.onInterceptTouchEvent(ev);
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700310 }
311 if (!intercept) {
312 super.onInterceptTouchEvent(ev);
313 }
Chris Wren5de6e942012-05-16 14:22:21 -0400314 if (intercept) {
Dianne Hackborna4b7f2f2012-05-21 11:28:41 -0700315 MotionEvent cancellation = MotionEvent.obtain(ev);
316 cancellation.setAction(MotionEvent.ACTION_CANCEL);
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100317 mStackScrollLayout.onInterceptTouchEvent(cancellation);
Selim Cinek31094df2014-08-14 19:28:15 +0200318 mNotificationPanel.onInterceptTouchEvent(cancellation);
Dianne Hackborna4b7f2f2012-05-21 11:28:41 -0700319 cancellation.recycle();
Chris Wren5de6e942012-05-16 14:22:21 -0400320 }
321 return intercept;
322 }
323
324 @Override
325 public boolean onTouchEvent(MotionEvent ev) {
Adrian Roos8008bd12017-02-22 15:02:09 +0100326 boolean handled = false;
327 if (mService.isDozing()) {
328 mDoubleTapHelper.onTouchEvent(ev);
329 handled = true;
330 }
Selim Cinekf8c4add2017-06-08 09:54:58 -0700331 if ((mService.getBarState() == StatusBarState.KEYGUARD && !handled)
332 || mDragDownHelper.isDraggingDown()) {
Selim Cinek740c1112016-12-22 16:39:54 +0100333 // we still want to finish our drag down gesture when locking the screen
Jorim Jaggiecbab362014-04-23 16:13:15 +0200334 handled = mDragDownHelper.onTouchEvent(ev);
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700335 }
336 if (!handled) {
337 handled = super.onTouchEvent(ev);
338 }
John Spurlock257f2832013-09-21 18:41:53 -0400339 final int action = ev.getAction();
John Spurlockd157ca02013-11-04 10:28:05 -0500340 if (!handled && (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)) {
John Spurlock257f2832013-09-21 18:41:53 -0400341 mService.setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
342 }
Chris Wren5de6e942012-05-16 14:22:21 -0400343 return handled;
344 }
Daniel Sandler198a0302012-08-17 16:04:31 -0400345
346 @Override
347 public void onDraw(Canvas canvas) {
348 super.onDraw(canvas);
Jorim Jaggi0e664392014-09-27 01:30:22 +0200349 if (mService.isScrimSrcModeEnabled()) {
350 // We need to ensure that our window is always drawn fully even when we have paddings,
351 // since we simulate it to be opaque.
352 int paddedBottom = getHeight() - getPaddingBottom();
353 int paddedRight = getWidth() - getPaddingRight();
354 if (getPaddingTop() != 0) {
355 canvas.drawRect(0, 0, getWidth(), getPaddingTop(), mTransparentSrcPaint);
356 }
357 if (getPaddingBottom() != 0) {
358 canvas.drawRect(0, paddedBottom, getWidth(), getHeight(), mTransparentSrcPaint);
359 }
360 if (getPaddingLeft() != 0) {
361 canvas.drawRect(0, getPaddingTop(), getPaddingLeft(), paddedBottom,
362 mTransparentSrcPaint);
363 }
364 if (getPaddingRight() != 0) {
365 canvas.drawRect(paddedRight, getPaddingTop(), getWidth(), paddedBottom,
366 mTransparentSrcPaint);
367 }
Selim Cineka0fad3b2014-09-19 17:20:05 +0200368 }
Daniel Sandler198a0302012-08-17 16:04:31 -0400369 if (DEBUG) {
370 Paint pt = new Paint();
371 pt.setColor(0x80FFFF00);
372 pt.setStrokeWidth(12.0f);
373 pt.setStyle(Paint.Style.STROKE);
374 canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), pt);
375 }
376 }
Daniel Sandlerac47ff72012-10-23 10:41:44 -0400377
378 public void cancelExpandHelper() {
Selim Cinek1408eb52014-06-02 14:45:38 +0200379 if (mStackScrollLayout != null) {
380 mStackScrollLayout.cancelExpandHelper();
Daniel Sandler1a3bdd52012-10-23 19:21:20 -0400381 }
Daniel Sandlerac47ff72012-10-23 10:41:44 -0400382 }
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700383
Selim Cinek48a92a52017-05-02 20:02:30 -0700384 public void cancelCurrentTouch() {
385 if (mTouchActive) {
386 final long now = SystemClock.uptimeMillis();
387 MotionEvent event = MotionEvent.obtain(now, now,
388 MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
389 event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
390 dispatchTouchEvent(event);
391 event.recycle();
392 mTouchCancelled = true;
393 }
394 }
395
Selim Cinek2627d722018-01-19 12:16:49 -0800396 public void setExpandAnimationRunning(boolean expandAnimationRunning) {
397 mExpandAnimationRunning = expandAnimationRunning;
398 }
399
Selim Cinek7e222c3c2018-01-25 12:22:41 -0800400 public void setExpandAnimationPending(boolean pending) {
401 mExpandAnimationPending = pending;
402 }
403
Selim Cinekfc5c1992018-01-29 12:40:32 -0800404 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
405 pw.print(" mExpandAnimationPending="); pw.println(mExpandAnimationPending);
406 pw.print(" mExpandAnimationRunning="); pw.println(mExpandAnimationRunning);
407 pw.print(" mTouchCancelled="); pw.println(mTouchCancelled);
408 pw.print(" mTouchActive="); pw.println(mTouchActive);
409 }
410
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700411 public class LayoutParams extends FrameLayout.LayoutParams {
412
413 public boolean ignoreRightInset;
414
415 public LayoutParams(int width, int height) {
416 super(width, height);
417 }
418
419 public LayoutParams(Context c, AttributeSet attrs) {
420 super(c, attrs);
421
422 TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.StatusBarWindowView_Layout);
423 ignoreRightInset = a.getBoolean(
424 R.styleable.StatusBarWindowView_Layout_ignoreRightInset, false);
425 a.recycle();
426 }
427 }
Adrian Roos0bd8a4b2016-03-14 16:21:44 -0700428
429 @Override
430 public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback,
431 int type) {
432 if (type == ActionMode.TYPE_FLOATING) {
433 return startActionMode(originalView, callback, type);
434 }
435 return super.startActionModeForChild(originalView, callback, type);
436 }
437
438 private ActionMode createFloatingActionMode(
439 View originatingView, ActionMode.Callback2 callback) {
440 if (mFloatingActionMode != null) {
441 mFloatingActionMode.finish();
442 }
443 cleanupFloatingActionModeViews();
Tarandeep Singhc9c83a92017-08-29 14:39:22 -0700444 mFloatingToolbar = new FloatingToolbar(mFakeWindow);
Adrian Roos0bd8a4b2016-03-14 16:21:44 -0700445 final FloatingActionMode mode =
Abodunrinwa Toki17293cc2017-05-22 14:16:04 +0100446 new FloatingActionMode(mContext, callback, originatingView, mFloatingToolbar);
Adrian Roos0bd8a4b2016-03-14 16:21:44 -0700447 mFloatingActionModeOriginatingView = originatingView;
448 mFloatingToolbarPreDrawListener =
449 new ViewTreeObserver.OnPreDrawListener() {
450 @Override
451 public boolean onPreDraw() {
452 mode.updateViewLocationInWindow();
453 return true;
454 }
455 };
456 return mode;
457 }
458
459 private void setHandledFloatingActionMode(ActionMode mode) {
460 mFloatingActionMode = mode;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -0700461 mFloatingActionMode.invalidate(); // Will show the floating toolbar if necessary.
462 mFloatingActionModeOriginatingView.getViewTreeObserver()
463 .addOnPreDrawListener(mFloatingToolbarPreDrawListener);
464 }
465
466 private void cleanupFloatingActionModeViews() {
467 if (mFloatingToolbar != null) {
468 mFloatingToolbar.dismiss();
469 mFloatingToolbar = null;
470 }
471 if (mFloatingActionModeOriginatingView != null) {
472 if (mFloatingToolbarPreDrawListener != null) {
473 mFloatingActionModeOriginatingView.getViewTreeObserver()
474 .removeOnPreDrawListener(mFloatingToolbarPreDrawListener);
475 mFloatingToolbarPreDrawListener = null;
476 }
477 mFloatingActionModeOriginatingView = null;
478 }
479 }
480
481 private ActionMode startActionMode(
482 View originatingView, ActionMode.Callback callback, int type) {
483 ActionMode.Callback2 wrappedCallback = new ActionModeCallback2Wrapper(callback);
484 ActionMode mode = createFloatingActionMode(originatingView, wrappedCallback);
485 if (mode != null && wrappedCallback.onCreateActionMode(mode, mode.getMenu())) {
486 setHandledFloatingActionMode(mode);
487 } else {
488 mode = null;
489 }
490 return mode;
491 }
492
493 private class ActionModeCallback2Wrapper extends ActionMode.Callback2 {
494 private final ActionMode.Callback mWrapped;
495
496 public ActionModeCallback2Wrapper(ActionMode.Callback wrapped) {
497 mWrapped = wrapped;
498 }
499
500 public boolean onCreateActionMode(ActionMode mode, Menu menu) {
501 return mWrapped.onCreateActionMode(mode, menu);
502 }
503
504 public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
505 requestFitSystemWindows();
506 return mWrapped.onPrepareActionMode(mode, menu);
507 }
508
509 public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
510 return mWrapped.onActionItemClicked(mode, item);
511 }
512
513 public void onDestroyActionMode(ActionMode mode) {
514 mWrapped.onDestroyActionMode(mode);
515 if (mode == mFloatingActionMode) {
516 cleanupFloatingActionModeViews();
517 mFloatingActionMode = null;
518 }
519 requestFitSystemWindows();
520 }
521
522 @Override
523 public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
524 if (mWrapped instanceof ActionMode.Callback2) {
525 ((ActionMode.Callback2) mWrapped).onGetContentRect(mode, view, outRect);
526 } else {
527 super.onGetContentRect(mode, view, outRect);
528 }
529 }
530 }
531
532 /**
533 * Minimal window to satisfy FloatingToolbar.
534 */
535 private Window mFakeWindow = new Window(mContext) {
536 @Override
537 public void takeSurface(SurfaceHolder.Callback2 callback) {
538 }
539
540 @Override
541 public void takeInputQueue(InputQueue.Callback callback) {
542 }
543
544 @Override
545 public boolean isFloating() {
546 return false;
547 }
548
549 @Override
550 public void alwaysReadCloseOnTouchAttr() {
551 }
552
553 @Override
554 public void setContentView(@LayoutRes int layoutResID) {
555 }
556
557 @Override
558 public void setContentView(View view) {
559 }
560
561 @Override
562 public void setContentView(View view, ViewGroup.LayoutParams params) {
563 }
564
565 @Override
566 public void addContentView(View view, ViewGroup.LayoutParams params) {
567 }
568
569 @Override
570 public void clearContentView() {
571 }
572
573 @Override
574 public View getCurrentFocus() {
575 return null;
576 }
577
578 @Override
579 public LayoutInflater getLayoutInflater() {
580 return null;
581 }
582
583 @Override
584 public void setTitle(CharSequence title) {
585 }
586
587 @Override
588 public void setTitleColor(@ColorInt int textColor) {
589 }
590
591 @Override
592 public void openPanel(int featureId, KeyEvent event) {
593 }
594
595 @Override
596 public void closePanel(int featureId) {
597 }
598
599 @Override
600 public void togglePanel(int featureId, KeyEvent event) {
601 }
602
603 @Override
604 public void invalidatePanelMenu(int featureId) {
605 }
606
607 @Override
608 public boolean performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags) {
609 return false;
610 }
611
612 @Override
613 public boolean performPanelIdentifierAction(int featureId, int id, int flags) {
614 return false;
615 }
616
617 @Override
618 public void closeAllPanels() {
619 }
620
621 @Override
622 public boolean performContextMenuIdentifierAction(int id, int flags) {
623 return false;
624 }
625
626 @Override
627 public void onConfigurationChanged(Configuration newConfig) {
628 }
629
630 @Override
631 public void setBackgroundDrawable(Drawable drawable) {
632 }
633
634 @Override
635 public void setFeatureDrawableResource(int featureId, @DrawableRes int resId) {
636 }
637
638 @Override
639 public void setFeatureDrawableUri(int featureId, Uri uri) {
640 }
641
642 @Override
643 public void setFeatureDrawable(int featureId, Drawable drawable) {
644 }
645
646 @Override
647 public void setFeatureDrawableAlpha(int featureId, int alpha) {
648 }
649
650 @Override
651 public void setFeatureInt(int featureId, int value) {
652 }
653
654 @Override
655 public void takeKeyEvents(boolean get) {
656 }
657
658 @Override
659 public boolean superDispatchKeyEvent(KeyEvent event) {
660 return false;
661 }
662
663 @Override
664 public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
665 return false;
666 }
667
668 @Override
669 public boolean superDispatchTouchEvent(MotionEvent event) {
670 return false;
671 }
672
673 @Override
674 public boolean superDispatchTrackballEvent(MotionEvent event) {
675 return false;
676 }
677
678 @Override
679 public boolean superDispatchGenericMotionEvent(MotionEvent event) {
680 return false;
681 }
682
683 @Override
684 public View getDecorView() {
685 return StatusBarWindowView.this;
686 }
687
688 @Override
689 public View peekDecorView() {
690 return null;
691 }
692
693 @Override
694 public Bundle saveHierarchyState() {
695 return null;
696 }
697
698 @Override
699 public void restoreHierarchyState(Bundle savedInstanceState) {
700 }
701
702 @Override
703 protected void onActive() {
704 }
705
706 @Override
707 public void setChildDrawable(int featureId, Drawable drawable) {
708 }
709
710 @Override
711 public void setChildInt(int featureId, int value) {
712 }
713
714 @Override
715 public boolean isShortcutKey(int keyCode, KeyEvent event) {
716 return false;
717 }
718
719 @Override
720 public void setVolumeControlStream(int streamType) {
721 }
722
723 @Override
724 public int getVolumeControlStream() {
725 return 0;
726 }
727
728 @Override
729 public int getStatusBarColor() {
730 return 0;
731 }
732
733 @Override
734 public void setStatusBarColor(@ColorInt int color) {
735 }
736
737 @Override
738 public int getNavigationBarColor() {
739 return 0;
740 }
741
742 @Override
743 public void setNavigationBarColor(@ColorInt int color) {
744 }
745
746 @Override
747 public void setDecorCaptionShade(int decorCaptionShade) {
748 }
749
750 @Override
751 public void setResizingCaptionDrawable(Drawable drawable) {
752 }
753
754 @Override
Andrii Kulian933076d2016-03-29 17:04:42 -0700755 public void onMultiWindowModeChanged() {
Adrian Roos0bd8a4b2016-03-14 16:21:44 -0700756 }
757
758 @Override
Winson Chung4d8681f2017-05-23 16:22:08 -0700759 public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
760 }
761
762 @Override
Adrian Roos0bd8a4b2016-03-14 16:21:44 -0700763 public void reportActivityRelaunched() {
764 }
765 };
766
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400767}
768