1 /*
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 
17 package com.android.systemui.statusbar.phone;
18 
19 import android.annotation.ColorInt;
20 import android.annotation.DrawableRes;
21 import android.annotation.LayoutRes;
22 import android.app.StatusBarManager;
23 import android.content.Context;
24 import android.content.res.Configuration;
25 import android.content.res.TypedArray;
26 import android.graphics.Canvas;
27 import android.graphics.Paint;
28 import android.graphics.PorterDuff;
29 import android.graphics.PorterDuffXfermode;
30 import android.graphics.Rect;
31 import android.graphics.drawable.Drawable;
32 import android.media.AudioManager;
33 import android.media.session.MediaSessionLegacyHelper;
34 import android.net.Uri;
35 import android.os.Bundle;
36 import android.os.IBinder;
37 import android.os.SystemClock;
38 import android.util.AttributeSet;
39 import android.view.ActionMode;
40 import android.view.InputDevice;
41 import android.view.InputQueue;
42 import android.view.KeyEvent;
43 import android.view.LayoutInflater;
44 import android.view.Menu;
45 import android.view.MenuItem;
46 import android.view.MotionEvent;
47 import android.view.SurfaceHolder;
48 import android.view.View;
49 import android.view.ViewGroup;
50 import android.view.ViewTreeObserver;
51 import android.view.Window;
52 import android.view.WindowManager;
53 import android.view.WindowManagerGlobal;
54 import android.widget.FrameLayout;
55 
56 import com.android.internal.annotations.VisibleForTesting;
57 import com.android.internal.view.FloatingActionMode;
58 import com.android.internal.widget.FloatingToolbar;
59 import com.android.systemui.R;
60 import com.android.systemui.classifier.FalsingManager;
61 import com.android.systemui.statusbar.DragDownHelper;
62 import com.android.systemui.statusbar.StatusBarState;
63 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
64 
65 import java.io.FileDescriptor;
66 import java.io.PrintWriter;
67 
68 
69 public class StatusBarWindowView extends FrameLayout {
70     public static final String TAG = "StatusBarWindowView";
71     public static final boolean DEBUG = StatusBar.DEBUG;
72 
73     private DragDownHelper mDragDownHelper;
74     private DoubleTapHelper mDoubleTapHelper;
75     private NotificationStackScrollLayout mStackScrollLayout;
76     private NotificationPanelView mNotificationPanel;
77     private View mBrightnessMirror;
78 
79     private int mRightInset = 0;
80     private int mLeftInset = 0;
81 
82     private StatusBar mService;
83     private final Paint mTransparentSrcPaint = new Paint();
84     private FalsingManager mFalsingManager;
85 
86     // 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;
92     private boolean mTouchCancelled;
93     private boolean mTouchActive;
94     private boolean mExpandAnimationRunning;
95     private boolean mExpandAnimationPending;
96 
StatusBarWindowView(Context context, AttributeSet attrs)97     public StatusBarWindowView(Context context, AttributeSet attrs) {
98         super(context, attrs);
99         setMotionEventSplittingEnabled(false);
100         mTransparentSrcPaint.setColor(0);
101         mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
102         mFalsingManager = FalsingManager.getInstance(context);
103         mDoubleTapHelper = new DoubleTapHelper(this, active -> {}, () -> {
104             mService.wakeUpIfDozing(SystemClock.uptimeMillis(), this);
105             return true;
106         }, null, null);
107     }
108 
109     @Override
fitSystemWindows(Rect insets)110     protected boolean fitSystemWindows(Rect insets) {
111         if (getFitsSystemWindows()) {
112             boolean paddingChanged = insets.top != getPaddingTop()
113                     || insets.bottom != getPaddingBottom();
114 
115             // Super-special right inset handling, because scrims and backdrop need to ignore it.
116             if (insets.right != mRightInset || insets.left != mLeftInset) {
117                 mRightInset = insets.right;
118                 mLeftInset = insets.left;
119                 applyMargins();
120             }
121             // Drop top inset, and pass through bottom inset.
122             if (paddingChanged) {
123                 setPadding(0, 0, 0, 0);
124             }
125             insets.left = 0;
126             insets.top = 0;
127             insets.right = 0;
128         } else {
129             if (mRightInset != 0 || mLeftInset != 0) {
130                 mRightInset = 0;
131                 mLeftInset = 0;
132                 applyMargins();
133             }
134             boolean changed = getPaddingLeft() != 0
135                     || getPaddingRight() != 0
136                     || getPaddingTop() != 0
137                     || getPaddingBottom() != 0;
138             if (changed) {
139                 setPadding(0, 0, 0, 0);
140             }
141             insets.top = 0;
142         }
143         return false;
144     }
145 
applyMargins()146     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();
152                 if (!lp.ignoreRightInset
153                         && (lp.rightMargin != mRightInset || lp.leftMargin != mLeftInset)) {
154                     lp.rightMargin = mRightInset;
155                     lp.leftMargin = mLeftInset;
156                     child.requestLayout();
157                 }
158             }
159         }
160     }
161 
162     @Override
generateLayoutParams(AttributeSet attrs)163     public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
164         return new LayoutParams(getContext(), attrs);
165     }
166 
167     @Override
generateDefaultLayoutParams()168     protected FrameLayout.LayoutParams generateDefaultLayoutParams() {
169         return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
170     }
171 
172     @Override
onFinishInflate()173     protected void onFinishInflate() {
174         super.onFinishInflate();
175         mStackScrollLayout = (NotificationStackScrollLayout) findViewById(
176                 R.id.notification_stack_scroller);
177         mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
178         mBrightnessMirror = findViewById(R.id.brightness_mirror);
179     }
180 
181     @Override
onViewAdded(View child)182     public void onViewAdded(View child) {
183         super.onViewAdded(child);
184         if (child.getId() == R.id.brightness_mirror) {
185             mBrightnessMirror = child;
186         }
187     }
188 
setService(StatusBar service)189     public void setService(StatusBar service) {
190         mService = service;
191         setDragDownHelper(new DragDownHelper(getContext(), this, mStackScrollLayout, mService));
192     }
193 
194     @VisibleForTesting
setDragDownHelper(DragDownHelper dragDownHelper)195     void setDragDownHelper(DragDownHelper dragDownHelper) {
196         mDragDownHelper = dragDownHelper;
197     }
198 
199     @Override
onAttachedToWindow()200     protected void onAttachedToWindow () {
201         super.onAttachedToWindow();
202 
203         // 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.
206         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         }
216     }
217 
218     @Override
dispatchKeyEvent(KeyEvent event)219     public boolean dispatchKeyEvent(KeyEvent event) {
220         if (mService.interceptMediaKey(event)) {
221             return true;
222         }
223         if (super.dispatchKeyEvent(event)) {
224             return true;
225         }
226         boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
227         switch (event.getKeyCode()) {
228             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                 }
237             case KeyEvent.KEYCODE_SPACE:
238                 if (!down) {
239                     return mService.onSpacePressed();
240                 }
241                 break;
242             case KeyEvent.KEYCODE_VOLUME_DOWN:
243             case KeyEvent.KEYCODE_VOLUME_UP:
244                 if (mService.isDozing()) {
245                     MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
246                             event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
247                     return true;
248                 }
249                 break;
250         }
251         return false;
252     }
253 
setTouchActive(boolean touchActive)254     public void setTouchActive(boolean touchActive) {
255         mTouchActive = touchActive;
256     }
257 
258     @Override
dispatchTouchEvent(MotionEvent ev)259     public boolean dispatchTouchEvent(MotionEvent ev) {
260         boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN;
261         boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL;
262         if (!isCancel && mService.shouldIgnoreTouch()) {
263             return false;
264         }
265         if (isDown && mNotificationPanel.isFullyCollapsed()) {
266             mNotificationPanel.startExpandLatencyTracking();
267         }
268         if (isDown) {
269             setTouchActive(true);
270             mTouchCancelled = false;
271         } else if (ev.getActionMasked() == MotionEvent.ACTION_UP
272                 || ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
273             setTouchActive(false);
274         }
275         if (mTouchCancelled || mExpandAnimationRunning || mExpandAnimationPending) {
276             return false;
277         }
278         mFalsingManager.onTouchEvent(ev, getWidth(), getHeight());
279         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         }
287         if (isDown) {
288             mStackScrollLayout.closeControlsIfOutsideTouch(ev);
289         }
290         if (mService.isDozing()) {
291             mService.mDozeScrimController.extendPulse();
292         }
293 
294         return super.dispatchTouchEvent(ev);
295     }
296 
297     @Override
onInterceptTouchEvent(MotionEvent ev)298     public boolean onInterceptTouchEvent(MotionEvent ev) {
299         if (mService.isDozing() && !mStackScrollLayout.hasPulsingNotifications()) {
300             // Capture all touch events in always-on.
301             return true;
302         }
303         boolean intercept = false;
304         if (mNotificationPanel.isFullyExpanded()
305                 && mStackScrollLayout.getVisibility() == View.VISIBLE
306                 && mService.getBarState() == StatusBarState.KEYGUARD
307                 && !mService.isBouncerShowing()
308                 && !mService.isDozing()) {
309             intercept = mDragDownHelper.onInterceptTouchEvent(ev);
310         }
311         if (!intercept) {
312             super.onInterceptTouchEvent(ev);
313         }
314         if (intercept) {
315             MotionEvent cancellation = MotionEvent.obtain(ev);
316             cancellation.setAction(MotionEvent.ACTION_CANCEL);
317             mStackScrollLayout.onInterceptTouchEvent(cancellation);
318             mNotificationPanel.onInterceptTouchEvent(cancellation);
319             cancellation.recycle();
320         }
321         return intercept;
322     }
323 
324     @Override
onTouchEvent(MotionEvent ev)325     public boolean onTouchEvent(MotionEvent ev) {
326         boolean handled = false;
327         if (mService.isDozing()) {
328             mDoubleTapHelper.onTouchEvent(ev);
329             handled = true;
330         }
331         if ((mService.getBarState() == StatusBarState.KEYGUARD && !handled)
332                 || mDragDownHelper.isDraggingDown()) {
333             // we still want to finish our drag down gesture when locking the screen
334             handled = mDragDownHelper.onTouchEvent(ev);
335         }
336         if (!handled) {
337             handled = super.onTouchEvent(ev);
338         }
339         final int action = ev.getAction();
340         if (!handled && (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)) {
341             mService.setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
342         }
343         return handled;
344     }
345 
346     @Override
onDraw(Canvas canvas)347     public void onDraw(Canvas canvas) {
348         super.onDraw(canvas);
349         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             }
368         }
369         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     }
377 
cancelExpandHelper()378     public void cancelExpandHelper() {
379         if (mStackScrollLayout != null) {
380             mStackScrollLayout.cancelExpandHelper();
381         }
382     }
383 
cancelCurrentTouch()384     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 
setExpandAnimationRunning(boolean expandAnimationRunning)396     public void setExpandAnimationRunning(boolean expandAnimationRunning) {
397         mExpandAnimationRunning = expandAnimationRunning;
398     }
399 
setExpandAnimationPending(boolean pending)400     public void setExpandAnimationPending(boolean pending) {
401         mExpandAnimationPending = pending;
402     }
403 
dump(FileDescriptor fd, PrintWriter pw, String[] args)404     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 
411     public class LayoutParams extends FrameLayout.LayoutParams {
412 
413         public boolean ignoreRightInset;
414 
LayoutParams(int width, int height)415         public LayoutParams(int width, int height) {
416             super(width, height);
417         }
418 
LayoutParams(Context c, AttributeSet attrs)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     }
428 
429     @Override
startActionModeForChild(View originalView, ActionMode.Callback callback, int type)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 
createFloatingActionMode( View originatingView, ActionMode.Callback2 callback)438     private ActionMode createFloatingActionMode(
439             View originatingView, ActionMode.Callback2 callback) {
440         if (mFloatingActionMode != null) {
441             mFloatingActionMode.finish();
442         }
443         cleanupFloatingActionModeViews();
444         mFloatingToolbar = new FloatingToolbar(mFakeWindow);
445         final FloatingActionMode mode =
446                 new FloatingActionMode(mContext, callback, originatingView, mFloatingToolbar);
447         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 
setHandledFloatingActionMode(ActionMode mode)459     private void setHandledFloatingActionMode(ActionMode mode) {
460         mFloatingActionMode = mode;
461         mFloatingActionMode.invalidate();  // Will show the floating toolbar if necessary.
462         mFloatingActionModeOriginatingView.getViewTreeObserver()
463                 .addOnPreDrawListener(mFloatingToolbarPreDrawListener);
464     }
465 
cleanupFloatingActionModeViews()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 
startActionMode( View originatingView, ActionMode.Callback callback, int type)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 
ActionModeCallback2Wrapper(ActionMode.Callback wrapped)496         public ActionModeCallback2Wrapper(ActionMode.Callback wrapped) {
497             mWrapped = wrapped;
498         }
499 
onCreateActionMode(ActionMode mode, Menu menu)500         public boolean onCreateActionMode(ActionMode mode, Menu menu) {
501             return mWrapped.onCreateActionMode(mode, menu);
502         }
503 
onPrepareActionMode(ActionMode mode, Menu menu)504         public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
505             requestFitSystemWindows();
506             return mWrapped.onPrepareActionMode(mode, menu);
507         }
508 
onActionItemClicked(ActionMode mode, MenuItem item)509         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
510             return mWrapped.onActionItemClicked(mode, item);
511         }
512 
onDestroyActionMode(ActionMode mode)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
onGetContentRect(ActionMode mode, View view, Rect outRect)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
755         public void onMultiWindowModeChanged() {
756         }
757 
758         @Override
759         public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
760         }
761 
762         @Override
763         public void reportActivityRelaunched() {
764         }
765     };
766 
767 }
768 
769