Home | History | Annotate | Download | only in phone
      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 
     66 public class StatusBarWindowView extends FrameLayout {
     67     public static final String TAG = "StatusBarWindowView";
     68     public static final boolean DEBUG = StatusBar.DEBUG;
     69 
     70     private DragDownHelper mDragDownHelper;
     71     private DoubleTapHelper mDoubleTapHelper;
     72     private NotificationStackScrollLayout mStackScrollLayout;
     73     private NotificationPanelView mNotificationPanel;
     74     private View mBrightnessMirror;
     75 
     76     private int mRightInset = 0;
     77     private int mLeftInset = 0;
     78 
     79     private StatusBar mService;
     80     private final Paint mTransparentSrcPaint = new Paint();
     81     private FalsingManager mFalsingManager;
     82 
     83     // Implements the floating action mode for TextView's Cut/Copy/Past menu. Normally provided by
     84     // DecorView, but since this is a special window we have to roll our own.
     85     private View mFloatingActionModeOriginatingView;
     86     private ActionMode mFloatingActionMode;
     87     private FloatingToolbar mFloatingToolbar;
     88     private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener;
     89     private boolean mTouchCancelled;
     90     private boolean mTouchActive;
     91 
     92     public StatusBarWindowView(Context context, AttributeSet attrs) {
     93         super(context, attrs);
     94         setMotionEventSplittingEnabled(false);
     95         mTransparentSrcPaint.setColor(0);
     96         mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
     97         mFalsingManager = FalsingManager.getInstance(context);
     98         mDoubleTapHelper = new DoubleTapHelper(this, active -> {}, () -> {
     99             mService.wakeUpIfDozing(SystemClock.uptimeMillis(), this);
    100             return true;
    101         }, null, null);
    102     }
    103 
    104     @Override
    105     protected boolean fitSystemWindows(Rect insets) {
    106         if (getFitsSystemWindows()) {
    107             boolean paddingChanged = insets.top != getPaddingTop()
    108                     || insets.bottom != getPaddingBottom();
    109 
    110             // Super-special right inset handling, because scrims and backdrop need to ignore it.
    111             if (insets.right != mRightInset || insets.left != mLeftInset) {
    112                 mRightInset = insets.right;
    113                 mLeftInset = insets.left;
    114                 applyMargins();
    115             }
    116             // Drop top inset, and pass through bottom inset.
    117             if (paddingChanged) {
    118                 setPadding(0, 0, 0, 0);
    119             }
    120             insets.left = 0;
    121             insets.top = 0;
    122             insets.right = 0;
    123         } else {
    124             if (mRightInset != 0 || mLeftInset != 0) {
    125                 mRightInset = 0;
    126                 mLeftInset = 0;
    127                 applyMargins();
    128             }
    129             boolean changed = getPaddingLeft() != 0
    130                     || getPaddingRight() != 0
    131                     || getPaddingTop() != 0
    132                     || getPaddingBottom() != 0;
    133             if (changed) {
    134                 setPadding(0, 0, 0, 0);
    135             }
    136             insets.top = 0;
    137         }
    138         return false;
    139     }
    140 
    141     private void applyMargins() {
    142         final int N = getChildCount();
    143         for (int i = 0; i < N; i++) {
    144             View child = getChildAt(i);
    145             if (child.getLayoutParams() instanceof LayoutParams) {
    146                 LayoutParams lp = (LayoutParams) child.getLayoutParams();
    147                 if (!lp.ignoreRightInset
    148                         && (lp.rightMargin != mRightInset || lp.leftMargin != mLeftInset)) {
    149                     lp.rightMargin = mRightInset;
    150                     lp.leftMargin = mLeftInset;
    151                     child.requestLayout();
    152                 }
    153             }
    154         }
    155     }
    156 
    157     @Override
    158     public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
    159         return new LayoutParams(getContext(), attrs);
    160     }
    161 
    162     @Override
    163     protected FrameLayout.LayoutParams generateDefaultLayoutParams() {
    164         return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    165     }
    166 
    167     @Override
    168     protected void onFinishInflate() {
    169         super.onFinishInflate();
    170         mStackScrollLayout = (NotificationStackScrollLayout) findViewById(
    171                 R.id.notification_stack_scroller);
    172         mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
    173         mBrightnessMirror = findViewById(R.id.brightness_mirror);
    174     }
    175 
    176     @Override
    177     public void onViewAdded(View child) {
    178         super.onViewAdded(child);
    179         if (child.getId() == R.id.brightness_mirror) {
    180             mBrightnessMirror = child;
    181         }
    182     }
    183 
    184     public void setService(StatusBar service) {
    185         mService = service;
    186         setDragDownHelper(new DragDownHelper(getContext(), this, mStackScrollLayout, mService));
    187     }
    188 
    189     @VisibleForTesting
    190     void setDragDownHelper(DragDownHelper dragDownHelper) {
    191         mDragDownHelper = dragDownHelper;
    192     }
    193 
    194     @Override
    195     protected void onAttachedToWindow () {
    196         super.onAttachedToWindow();
    197 
    198         // We need to ensure that our window doesn't suffer from overdraw which would normally
    199         // occur if our window is translucent. Since we are drawing the whole window anyway with
    200         // the scrim, we don't need the window to be cleared in the beginning.
    201         if (mService.isScrimSrcModeEnabled()) {
    202             IBinder windowToken = getWindowToken();
    203             WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
    204             lp.token = windowToken;
    205             setLayoutParams(lp);
    206             WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true);
    207             setWillNotDraw(false);
    208         } else {
    209             setWillNotDraw(!DEBUG);
    210         }
    211     }
    212 
    213     @Override
    214     public boolean dispatchKeyEvent(KeyEvent event) {
    215         if (mService.interceptMediaKey(event)) {
    216             return true;
    217         }
    218         if (super.dispatchKeyEvent(event)) {
    219             return true;
    220         }
    221         boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
    222         switch (event.getKeyCode()) {
    223             case KeyEvent.KEYCODE_BACK:
    224                 if (!down) {
    225                     mService.onBackPressed();
    226                 }
    227                 return true;
    228             case KeyEvent.KEYCODE_MENU:
    229                 if (!down) {
    230                     return mService.onMenuPressed();
    231                 }
    232             case KeyEvent.KEYCODE_SPACE:
    233                 if (!down) {
    234                     return mService.onSpacePressed();
    235                 }
    236                 break;
    237             case KeyEvent.KEYCODE_VOLUME_DOWN:
    238             case KeyEvent.KEYCODE_VOLUME_UP:
    239                 if (mService.isDozing()) {
    240                     MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
    241                             event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
    242                     return true;
    243                 }
    244                 break;
    245         }
    246         return false;
    247     }
    248 
    249     public void setTouchActive(boolean touchActive) {
    250         mTouchActive = touchActive;
    251         mStackScrollLayout.setTouchActive(touchActive);
    252     }
    253 
    254     @Override
    255     public boolean dispatchTouchEvent(MotionEvent ev) {
    256         boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN;
    257         boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL;
    258         if (!isCancel && mService.shouldIgnoreTouch()) {
    259             return false;
    260         }
    261         if (isDown && mNotificationPanel.isFullyCollapsed()) {
    262             mNotificationPanel.startExpandLatencyTracking();
    263         }
    264         if (isDown) {
    265             setTouchActive(true);
    266             mTouchCancelled = false;
    267         } else if (ev.getActionMasked() == MotionEvent.ACTION_UP
    268                 || ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
    269             setTouchActive(false);
    270         }
    271         if (mTouchCancelled) {
    272             return false;
    273         }
    274         mFalsingManager.onTouchEvent(ev, getWidth(), getHeight());
    275         if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == VISIBLE) {
    276             // Disallow new pointers while the brightness mirror is visible. This is so that you
    277             // can't touch anything other than the brightness slider while the mirror is showing
    278             // and the rest of the panel is transparent.
    279             if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
    280                 return false;
    281             }
    282         }
    283         if (isDown) {
    284             mStackScrollLayout.closeControlsIfOutsideTouch(ev);
    285         }
    286         if (mService.isDozing()) {
    287             mService.mDozeScrimController.extendPulse();
    288         }
    289 
    290         return super.dispatchTouchEvent(ev);
    291     }
    292 
    293     @Override
    294     public boolean onInterceptTouchEvent(MotionEvent ev) {
    295         if (mService.isDozing() && !mStackScrollLayout.hasPulsingNotifications()) {
    296             // Capture all touch events in always-on.
    297             return true;
    298         }
    299         boolean intercept = false;
    300         if (mNotificationPanel.isFullyExpanded()
    301                 && mStackScrollLayout.getVisibility() == View.VISIBLE
    302                 && mService.getBarState() == StatusBarState.KEYGUARD
    303                 && !mService.isBouncerShowing()
    304                 && !mService.isDozing()) {
    305             intercept = mDragDownHelper.onInterceptTouchEvent(ev);
    306         }
    307         if (!intercept) {
    308             super.onInterceptTouchEvent(ev);
    309         }
    310         if (intercept) {
    311             MotionEvent cancellation = MotionEvent.obtain(ev);
    312             cancellation.setAction(MotionEvent.ACTION_CANCEL);
    313             mStackScrollLayout.onInterceptTouchEvent(cancellation);
    314             mNotificationPanel.onInterceptTouchEvent(cancellation);
    315             cancellation.recycle();
    316         }
    317         return intercept;
    318     }
    319 
    320     @Override
    321     public boolean onTouchEvent(MotionEvent ev) {
    322         boolean handled = false;
    323         if (mService.isDozing()) {
    324             mDoubleTapHelper.onTouchEvent(ev);
    325             handled = true;
    326         }
    327         if ((mService.getBarState() == StatusBarState.KEYGUARD && !handled)
    328                 || mDragDownHelper.isDraggingDown()) {
    329             // we still want to finish our drag down gesture when locking the screen
    330             handled = mDragDownHelper.onTouchEvent(ev);
    331         }
    332         if (!handled) {
    333             handled = super.onTouchEvent(ev);
    334         }
    335         final int action = ev.getAction();
    336         if (!handled && (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)) {
    337             mService.setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
    338         }
    339         return handled;
    340     }
    341 
    342     @Override
    343     public void onDraw(Canvas canvas) {
    344         super.onDraw(canvas);
    345         if (mService.isScrimSrcModeEnabled()) {
    346             // We need to ensure that our window is always drawn fully even when we have paddings,
    347             // since we simulate it to be opaque.
    348             int paddedBottom = getHeight() - getPaddingBottom();
    349             int paddedRight = getWidth() - getPaddingRight();
    350             if (getPaddingTop() != 0) {
    351                 canvas.drawRect(0, 0, getWidth(), getPaddingTop(), mTransparentSrcPaint);
    352             }
    353             if (getPaddingBottom() != 0) {
    354                 canvas.drawRect(0, paddedBottom, getWidth(), getHeight(), mTransparentSrcPaint);
    355             }
    356             if (getPaddingLeft() != 0) {
    357                 canvas.drawRect(0, getPaddingTop(), getPaddingLeft(), paddedBottom,
    358                         mTransparentSrcPaint);
    359             }
    360             if (getPaddingRight() != 0) {
    361                 canvas.drawRect(paddedRight, getPaddingTop(), getWidth(), paddedBottom,
    362                         mTransparentSrcPaint);
    363             }
    364         }
    365         if (DEBUG) {
    366             Paint pt = new Paint();
    367             pt.setColor(0x80FFFF00);
    368             pt.setStrokeWidth(12.0f);
    369             pt.setStyle(Paint.Style.STROKE);
    370             canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), pt);
    371         }
    372     }
    373 
    374     public void cancelExpandHelper() {
    375         if (mStackScrollLayout != null) {
    376             mStackScrollLayout.cancelExpandHelper();
    377         }
    378     }
    379 
    380     public void cancelCurrentTouch() {
    381         if (mTouchActive) {
    382             final long now = SystemClock.uptimeMillis();
    383             MotionEvent event = MotionEvent.obtain(now, now,
    384                     MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
    385             event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
    386             dispatchTouchEvent(event);
    387             event.recycle();
    388             mTouchCancelled = true;
    389         }
    390     }
    391 
    392     public class LayoutParams extends FrameLayout.LayoutParams {
    393 
    394         public boolean ignoreRightInset;
    395 
    396         public LayoutParams(int width, int height) {
    397             super(width, height);
    398         }
    399 
    400         public LayoutParams(Context c, AttributeSet attrs) {
    401             super(c, attrs);
    402 
    403             TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.StatusBarWindowView_Layout);
    404             ignoreRightInset = a.getBoolean(
    405                     R.styleable.StatusBarWindowView_Layout_ignoreRightInset, false);
    406             a.recycle();
    407         }
    408     }
    409 
    410     @Override
    411     public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback,
    412             int type) {
    413         if (type == ActionMode.TYPE_FLOATING) {
    414             return startActionMode(originalView, callback, type);
    415         }
    416         return super.startActionModeForChild(originalView, callback, type);
    417     }
    418 
    419     private ActionMode createFloatingActionMode(
    420             View originatingView, ActionMode.Callback2 callback) {
    421         if (mFloatingActionMode != null) {
    422             mFloatingActionMode.finish();
    423         }
    424         cleanupFloatingActionModeViews();
    425         mFloatingToolbar = new FloatingToolbar(mFakeWindow);
    426         final FloatingActionMode mode =
    427                 new FloatingActionMode(mContext, callback, originatingView, mFloatingToolbar);
    428         mFloatingActionModeOriginatingView = originatingView;
    429         mFloatingToolbarPreDrawListener =
    430                 new ViewTreeObserver.OnPreDrawListener() {
    431                     @Override
    432                     public boolean onPreDraw() {
    433                         mode.updateViewLocationInWindow();
    434                         return true;
    435                     }
    436                 };
    437         return mode;
    438     }
    439 
    440     private void setHandledFloatingActionMode(ActionMode mode) {
    441         mFloatingActionMode = mode;
    442         mFloatingActionMode.invalidate();  // Will show the floating toolbar if necessary.
    443         mFloatingActionModeOriginatingView.getViewTreeObserver()
    444                 .addOnPreDrawListener(mFloatingToolbarPreDrawListener);
    445     }
    446 
    447     private void cleanupFloatingActionModeViews() {
    448         if (mFloatingToolbar != null) {
    449             mFloatingToolbar.dismiss();
    450             mFloatingToolbar = null;
    451         }
    452         if (mFloatingActionModeOriginatingView != null) {
    453             if (mFloatingToolbarPreDrawListener != null) {
    454                 mFloatingActionModeOriginatingView.getViewTreeObserver()
    455                         .removeOnPreDrawListener(mFloatingToolbarPreDrawListener);
    456                 mFloatingToolbarPreDrawListener = null;
    457             }
    458             mFloatingActionModeOriginatingView = null;
    459         }
    460     }
    461 
    462     private ActionMode startActionMode(
    463             View originatingView, ActionMode.Callback callback, int type) {
    464         ActionMode.Callback2 wrappedCallback = new ActionModeCallback2Wrapper(callback);
    465         ActionMode mode = createFloatingActionMode(originatingView, wrappedCallback);
    466         if (mode != null && wrappedCallback.onCreateActionMode(mode, mode.getMenu())) {
    467             setHandledFloatingActionMode(mode);
    468         } else {
    469             mode = null;
    470         }
    471         return mode;
    472     }
    473 
    474     private class ActionModeCallback2Wrapper extends ActionMode.Callback2 {
    475         private final ActionMode.Callback mWrapped;
    476 
    477         public ActionModeCallback2Wrapper(ActionMode.Callback wrapped) {
    478             mWrapped = wrapped;
    479         }
    480 
    481         public boolean onCreateActionMode(ActionMode mode, Menu menu) {
    482             return mWrapped.onCreateActionMode(mode, menu);
    483         }
    484 
    485         public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
    486             requestFitSystemWindows();
    487             return mWrapped.onPrepareActionMode(mode, menu);
    488         }
    489 
    490         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
    491             return mWrapped.onActionItemClicked(mode, item);
    492         }
    493 
    494         public void onDestroyActionMode(ActionMode mode) {
    495             mWrapped.onDestroyActionMode(mode);
    496             if (mode == mFloatingActionMode) {
    497                 cleanupFloatingActionModeViews();
    498                 mFloatingActionMode = null;
    499             }
    500             requestFitSystemWindows();
    501         }
    502 
    503         @Override
    504         public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
    505             if (mWrapped instanceof ActionMode.Callback2) {
    506                 ((ActionMode.Callback2) mWrapped).onGetContentRect(mode, view, outRect);
    507             } else {
    508                 super.onGetContentRect(mode, view, outRect);
    509             }
    510         }
    511     }
    512 
    513     /**
    514      * Minimal window to satisfy FloatingToolbar.
    515      */
    516     private Window mFakeWindow = new Window(mContext) {
    517         @Override
    518         public void takeSurface(SurfaceHolder.Callback2 callback) {
    519         }
    520 
    521         @Override
    522         public void takeInputQueue(InputQueue.Callback callback) {
    523         }
    524 
    525         @Override
    526         public boolean isFloating() {
    527             return false;
    528         }
    529 
    530         @Override
    531         public void alwaysReadCloseOnTouchAttr() {
    532         }
    533 
    534         @Override
    535         public void setContentView(@LayoutRes int layoutResID) {
    536         }
    537 
    538         @Override
    539         public void setContentView(View view) {
    540         }
    541 
    542         @Override
    543         public void setContentView(View view, ViewGroup.LayoutParams params) {
    544         }
    545 
    546         @Override
    547         public void addContentView(View view, ViewGroup.LayoutParams params) {
    548         }
    549 
    550         @Override
    551         public void clearContentView() {
    552         }
    553 
    554         @Override
    555         public View getCurrentFocus() {
    556             return null;
    557         }
    558 
    559         @Override
    560         public LayoutInflater getLayoutInflater() {
    561             return null;
    562         }
    563 
    564         @Override
    565         public void setTitle(CharSequence title) {
    566         }
    567 
    568         @Override
    569         public void setTitleColor(@ColorInt int textColor) {
    570         }
    571 
    572         @Override
    573         public void openPanel(int featureId, KeyEvent event) {
    574         }
    575 
    576         @Override
    577         public void closePanel(int featureId) {
    578         }
    579 
    580         @Override
    581         public void togglePanel(int featureId, KeyEvent event) {
    582         }
    583 
    584         @Override
    585         public void invalidatePanelMenu(int featureId) {
    586         }
    587 
    588         @Override
    589         public boolean performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags) {
    590             return false;
    591         }
    592 
    593         @Override
    594         public boolean performPanelIdentifierAction(int featureId, int id, int flags) {
    595             return false;
    596         }
    597 
    598         @Override
    599         public void closeAllPanels() {
    600         }
    601 
    602         @Override
    603         public boolean performContextMenuIdentifierAction(int id, int flags) {
    604             return false;
    605         }
    606 
    607         @Override
    608         public void onConfigurationChanged(Configuration newConfig) {
    609         }
    610 
    611         @Override
    612         public void setBackgroundDrawable(Drawable drawable) {
    613         }
    614 
    615         @Override
    616         public void setFeatureDrawableResource(int featureId, @DrawableRes int resId) {
    617         }
    618 
    619         @Override
    620         public void setFeatureDrawableUri(int featureId, Uri uri) {
    621         }
    622 
    623         @Override
    624         public void setFeatureDrawable(int featureId, Drawable drawable) {
    625         }
    626 
    627         @Override
    628         public void setFeatureDrawableAlpha(int featureId, int alpha) {
    629         }
    630 
    631         @Override
    632         public void setFeatureInt(int featureId, int value) {
    633         }
    634 
    635         @Override
    636         public void takeKeyEvents(boolean get) {
    637         }
    638 
    639         @Override
    640         public boolean superDispatchKeyEvent(KeyEvent event) {
    641             return false;
    642         }
    643 
    644         @Override
    645         public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
    646             return false;
    647         }
    648 
    649         @Override
    650         public boolean superDispatchTouchEvent(MotionEvent event) {
    651             return false;
    652         }
    653 
    654         @Override
    655         public boolean superDispatchTrackballEvent(MotionEvent event) {
    656             return false;
    657         }
    658 
    659         @Override
    660         public boolean superDispatchGenericMotionEvent(MotionEvent event) {
    661             return false;
    662         }
    663 
    664         @Override
    665         public View getDecorView() {
    666             return StatusBarWindowView.this;
    667         }
    668 
    669         @Override
    670         public View peekDecorView() {
    671             return null;
    672         }
    673 
    674         @Override
    675         public Bundle saveHierarchyState() {
    676             return null;
    677         }
    678 
    679         @Override
    680         public void restoreHierarchyState(Bundle savedInstanceState) {
    681         }
    682 
    683         @Override
    684         protected void onActive() {
    685         }
    686 
    687         @Override
    688         public void setChildDrawable(int featureId, Drawable drawable) {
    689         }
    690 
    691         @Override
    692         public void setChildInt(int featureId, int value) {
    693         }
    694 
    695         @Override
    696         public boolean isShortcutKey(int keyCode, KeyEvent event) {
    697             return false;
    698         }
    699 
    700         @Override
    701         public void setVolumeControlStream(int streamType) {
    702         }
    703 
    704         @Override
    705         public int getVolumeControlStream() {
    706             return 0;
    707         }
    708 
    709         @Override
    710         public int getStatusBarColor() {
    711             return 0;
    712         }
    713 
    714         @Override
    715         public void setStatusBarColor(@ColorInt int color) {
    716         }
    717 
    718         @Override
    719         public int getNavigationBarColor() {
    720             return 0;
    721         }
    722 
    723         @Override
    724         public void setNavigationBarColor(@ColorInt int color) {
    725         }
    726 
    727         @Override
    728         public void setDecorCaptionShade(int decorCaptionShade) {
    729         }
    730 
    731         @Override
    732         public void setResizingCaptionDrawable(Drawable drawable) {
    733         }
    734 
    735         @Override
    736         public void onMultiWindowModeChanged() {
    737         }
    738 
    739         @Override
    740         public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
    741         }
    742 
    743         @Override
    744         public void reportActivityRelaunched() {
    745         }
    746     };
    747 
    748 }
    749 
    750