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.app.StatusBarManager;
     20 import android.content.Context;
     21 import android.graphics.Canvas;
     22 import android.graphics.Paint;
     23 import android.graphics.PorterDuff;
     24 import android.graphics.PorterDuffXfermode;
     25 import android.graphics.Rect;
     26 import android.media.session.MediaSessionLegacyHelper;
     27 import android.os.IBinder;
     28 import android.util.AttributeSet;
     29 import android.view.KeyEvent;
     30 import android.view.MotionEvent;
     31 import android.view.View;
     32 import android.view.ViewRootImpl;
     33 import android.view.WindowManager;
     34 import android.view.WindowManagerGlobal;
     35 import android.widget.FrameLayout;
     36 
     37 import com.android.systemui.R;
     38 import com.android.systemui.statusbar.BaseStatusBar;
     39 import com.android.systemui.statusbar.DragDownHelper;
     40 import com.android.systemui.statusbar.StatusBarState;
     41 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
     42 
     43 
     44 public class StatusBarWindowView extends FrameLayout {
     45     public static final String TAG = "StatusBarWindowView";
     46     public static final boolean DEBUG = BaseStatusBar.DEBUG;
     47 
     48     private DragDownHelper mDragDownHelper;
     49     private NotificationStackScrollLayout mStackScrollLayout;
     50     private NotificationPanelView mNotificationPanel;
     51     private View mBrightnessMirror;
     52 
     53     PhoneStatusBar mService;
     54     private final Paint mTransparentSrcPaint = new Paint();
     55 
     56     public StatusBarWindowView(Context context, AttributeSet attrs) {
     57         super(context, attrs);
     58         setMotionEventSplittingEnabled(false);
     59         mTransparentSrcPaint.setColor(0);
     60         mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
     61     }
     62 
     63     @Override
     64     protected boolean fitSystemWindows(Rect insets) {
     65         if (getFitsSystemWindows()) {
     66             boolean changed = insets.left != getPaddingLeft()
     67                     || insets.top != getPaddingTop()
     68                     || insets.right != getPaddingRight()
     69                     || insets.bottom != getPaddingBottom();
     70             if (changed) {
     71                 setPadding(insets.left, insets.top, insets.right, 0);
     72             }
     73             insets.left = 0;
     74             insets.top = 0;
     75             insets.right = 0;
     76         } else {
     77             boolean changed = getPaddingLeft() != 0
     78                     || getPaddingRight() != 0
     79                     || getPaddingTop() != 0
     80                     || getPaddingBottom() != 0;
     81             if (changed) {
     82                 setPadding(0, 0, 0, 0);
     83             }
     84         }
     85         return false;
     86     }
     87 
     88     @Override
     89     protected void onAttachedToWindow () {
     90         super.onAttachedToWindow();
     91 
     92         mStackScrollLayout = (NotificationStackScrollLayout) findViewById(
     93                 R.id.notification_stack_scroller);
     94         mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
     95         mDragDownHelper = new DragDownHelper(getContext(), this, mStackScrollLayout, mService);
     96         mBrightnessMirror = findViewById(R.id.brightness_mirror);
     97 
     98         // We really need to be able to animate while window animations are going on
     99         // so that activities may be started asynchronously from panel animations
    100         final ViewRootImpl root = getViewRootImpl();
    101         if (root != null) {
    102             root.setDrawDuringWindowsAnimating(true);
    103         }
    104 
    105         // We need to ensure that our window doesn't suffer from overdraw which would normally
    106         // occur if our window is translucent. Since we are drawing the whole window anyway with
    107         // the scrim, we don't need the window to be cleared in the beginning.
    108         if (mService.isScrimSrcModeEnabled()) {
    109             IBinder windowToken = getWindowToken();
    110             WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
    111             lp.token = windowToken;
    112             setLayoutParams(lp);
    113             WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true);
    114             setWillNotDraw(false);
    115         } else {
    116             setWillNotDraw(!DEBUG);
    117         }
    118     }
    119 
    120     @Override
    121     public boolean dispatchKeyEvent(KeyEvent event) {
    122         boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
    123         switch (event.getKeyCode()) {
    124             case KeyEvent.KEYCODE_BACK:
    125                 if (!down) {
    126                     mService.onBackPressed();
    127                 }
    128                 return true;
    129             case KeyEvent.KEYCODE_MENU:
    130                 if (!down) {
    131                     return mService.onMenuPressed();
    132                 }
    133             case KeyEvent.KEYCODE_SPACE:
    134                 if (!down) {
    135                     return mService.onSpacePressed();
    136                 }
    137                 break;
    138             case KeyEvent.KEYCODE_VOLUME_DOWN:
    139             case KeyEvent.KEYCODE_VOLUME_UP:
    140                 if (mService.isDozing()) {
    141                     MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(event, true);
    142                     return true;
    143                 }
    144                 break;
    145         }
    146         if (mService.interceptMediaKey(event)) {
    147             return true;
    148         }
    149         return super.dispatchKeyEvent(event);
    150     }
    151 
    152     @Override
    153     public boolean dispatchTouchEvent(MotionEvent ev) {
    154         if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == VISIBLE) {
    155             // Disallow new pointers while the brightness mirror is visible. This is so that you
    156             // can't touch anything other than the brightness slider while the mirror is showing
    157             // and the rest of the panel is transparent.
    158             if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
    159                 return false;
    160             }
    161         }
    162         return super.dispatchTouchEvent(ev);
    163     }
    164 
    165     @Override
    166     public boolean onInterceptTouchEvent(MotionEvent ev) {
    167         boolean intercept = false;
    168         if (mNotificationPanel.isFullyExpanded()
    169                 && mStackScrollLayout.getVisibility() == View.VISIBLE
    170                 && mService.getBarState() == StatusBarState.KEYGUARD
    171                 && !mService.isBouncerShowing()) {
    172             intercept = mDragDownHelper.onInterceptTouchEvent(ev);
    173             // wake up on a touch down event, if dozing
    174             if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
    175                 mService.wakeUpIfDozing(ev.getEventTime(), true);
    176             }
    177         }
    178         if (!intercept) {
    179             super.onInterceptTouchEvent(ev);
    180         }
    181         if (intercept) {
    182             MotionEvent cancellation = MotionEvent.obtain(ev);
    183             cancellation.setAction(MotionEvent.ACTION_CANCEL);
    184             mStackScrollLayout.onInterceptTouchEvent(cancellation);
    185             mNotificationPanel.onInterceptTouchEvent(cancellation);
    186             cancellation.recycle();
    187         }
    188         return intercept;
    189     }
    190 
    191     @Override
    192     public boolean onTouchEvent(MotionEvent ev) {
    193         boolean handled = false;
    194         if (mService.getBarState() == StatusBarState.KEYGUARD && !mService.isQsExpanded()) {
    195             handled = mDragDownHelper.onTouchEvent(ev);
    196         }
    197         if (!handled) {
    198             handled = super.onTouchEvent(ev);
    199         }
    200         final int action = ev.getAction();
    201         if (!handled && (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)) {
    202             mService.setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
    203         }
    204         return handled;
    205     }
    206 
    207     @Override
    208     public void onDraw(Canvas canvas) {
    209         super.onDraw(canvas);
    210         if (mService.isScrimSrcModeEnabled()) {
    211             // We need to ensure that our window is always drawn fully even when we have paddings,
    212             // since we simulate it to be opaque.
    213             int paddedBottom = getHeight() - getPaddingBottom();
    214             int paddedRight = getWidth() - getPaddingRight();
    215             if (getPaddingTop() != 0) {
    216                 canvas.drawRect(0, 0, getWidth(), getPaddingTop(), mTransparentSrcPaint);
    217             }
    218             if (getPaddingBottom() != 0) {
    219                 canvas.drawRect(0, paddedBottom, getWidth(), getHeight(), mTransparentSrcPaint);
    220             }
    221             if (getPaddingLeft() != 0) {
    222                 canvas.drawRect(0, getPaddingTop(), getPaddingLeft(), paddedBottom,
    223                         mTransparentSrcPaint);
    224             }
    225             if (getPaddingRight() != 0) {
    226                 canvas.drawRect(paddedRight, getPaddingTop(), getWidth(), paddedBottom,
    227                         mTransparentSrcPaint);
    228             }
    229         }
    230         if (DEBUG) {
    231             Paint pt = new Paint();
    232             pt.setColor(0x80FFFF00);
    233             pt.setStrokeWidth(12.0f);
    234             pt.setStyle(Paint.Style.STROKE);
    235             canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), pt);
    236         }
    237     }
    238 
    239     public void cancelExpandHelper() {
    240         if (mStackScrollLayout != null) {
    241             mStackScrollLayout.cancelExpandHelper();
    242         }
    243     }
    244 }
    245 
    246