• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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.ActivityManager;
20 import android.app.StatusBarManager;
21 import android.content.Context;
22 import android.content.res.Resources;
23 import android.content.res.Resources.NotFoundException;
24 import android.util.AttributeSet;
25 import android.util.EventLog;
26 import android.util.Slog;
27 import android.view.MotionEvent;
28 import android.view.View;
29 import android.view.accessibility.AccessibilityEvent;
30 
31 import com.android.systemui.EventLogTags;
32 import com.android.systemui.R;
33 
34 public class PhoneStatusBarView extends PanelBar {
35     private static final String TAG = "PhoneStatusBarView";
36     private static final boolean DEBUG = PhoneStatusBar.DEBUG;
37     private static final boolean DEBUG_GESTURES = true;
38 
39     PhoneStatusBar mBar;
40     int mScrimColor;
41     float mSettingsPanelDragzoneFrac;
42     float mSettingsPanelDragzoneMin;
43 
44     boolean mFullWidthNotifications;
45     PanelView mFadingPanel = null;
46     PanelView mLastFullyOpenedPanel = null;
47     PanelView mNotificationPanel, mSettingsPanel;
48     private boolean mShouldFade;
49 
PhoneStatusBarView(Context context, AttributeSet attrs)50     public PhoneStatusBarView(Context context, AttributeSet attrs) {
51         super(context, attrs);
52 
53         Resources res = getContext().getResources();
54         mScrimColor = res.getColor(R.color.notification_panel_scrim_color);
55         mSettingsPanelDragzoneMin = res.getDimension(R.dimen.settings_panel_dragzone_min);
56         try {
57             mSettingsPanelDragzoneFrac = res.getFraction(R.dimen.settings_panel_dragzone_fraction, 1, 1);
58         } catch (NotFoundException ex) {
59             mSettingsPanelDragzoneFrac = 0f;
60         }
61         mFullWidthNotifications = mSettingsPanelDragzoneFrac <= 0f;
62     }
63 
setBar(PhoneStatusBar bar)64     public void setBar(PhoneStatusBar bar) {
65         mBar = bar;
66     }
67 
hasFullWidthNotifications()68     public boolean hasFullWidthNotifications() {
69         return mFullWidthNotifications;
70     }
71 
72     @Override
onAttachedToWindow()73     public void onAttachedToWindow() {
74         for (PanelView pv : mPanels) {
75             pv.setRubberbandingEnabled(!mFullWidthNotifications);
76         }
77     }
78 
79     @Override
addPanel(PanelView pv)80     public void addPanel(PanelView pv) {
81         super.addPanel(pv);
82         if (pv.getId() == R.id.notification_panel) {
83             mNotificationPanel = pv;
84         } else if (pv.getId() == R.id.settings_panel){
85             mSettingsPanel = pv;
86         }
87         pv.setRubberbandingEnabled(!mFullWidthNotifications);
88     }
89 
90     @Override
panelsEnabled()91     public boolean panelsEnabled() {
92         return ((mBar.mDisabled & StatusBarManager.DISABLE_EXPAND) == 0);
93     }
94 
95     @Override
onRequestSendAccessibilityEvent(View child, AccessibilityEvent event)96     public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
97         if (super.onRequestSendAccessibilityEvent(child, event)) {
98             // The status bar is very small so augment the view that the user is touching
99             // with the content of the status bar a whole. This way an accessibility service
100             // may announce the current item as well as the entire content if appropriate.
101             AccessibilityEvent record = AccessibilityEvent.obtain();
102             onInitializeAccessibilityEvent(record);
103             dispatchPopulateAccessibilityEvent(record);
104             event.appendRecord(record);
105             return true;
106         }
107         return false;
108     }
109 
110     @Override
selectPanelForTouch(MotionEvent touch)111     public PanelView selectPanelForTouch(MotionEvent touch) {
112         final float x = touch.getX();
113         final boolean isLayoutRtl = isLayoutRtl();
114 
115         if (mFullWidthNotifications) {
116             // No double swiping. If either panel is open, nothing else can be pulled down.
117             return ((mSettingsPanel == null ? 0 : mSettingsPanel.getExpandedHeight())
118                         + mNotificationPanel.getExpandedHeight() > 0)
119                     ? null
120                     : mNotificationPanel;
121         }
122 
123         // We split the status bar into thirds: the left 2/3 are for notifications, and the
124         // right 1/3 for quick settings. If you pull the status bar down a second time you'll
125         // toggle panels no matter where you pull it down.
126 
127         final float w = getMeasuredWidth();
128         float region = (w * mSettingsPanelDragzoneFrac);
129 
130         if (DEBUG) {
131             Slog.v(TAG, String.format(
132                 "w=%.1f frac=%.3f region=%.1f min=%.1f x=%.1f w-x=%.1f",
133                 w, mSettingsPanelDragzoneFrac, region, mSettingsPanelDragzoneMin, x, (w-x)));
134         }
135 
136         if (region < mSettingsPanelDragzoneMin) region = mSettingsPanelDragzoneMin;
137 
138         final boolean showSettings = isLayoutRtl ? (x < region) : (w - region < x);
139         return showSettings ? mSettingsPanel : mNotificationPanel;
140     }
141 
142     @Override
onPanelPeeked()143     public void onPanelPeeked() {
144         super.onPanelPeeked();
145         mBar.makeExpandedVisible(true);
146     }
147 
148     @Override
startOpeningPanel(PanelView panel)149     public void startOpeningPanel(PanelView panel) {
150         super.startOpeningPanel(panel);
151         // we only want to start fading if this is the "first" or "last" panel,
152         // which is kind of tricky to determine
153         mShouldFade = (mFadingPanel == null || mFadingPanel.isFullyExpanded());
154         if (DEBUG) {
155             Slog.v(TAG, "start opening: " + panel + " shouldfade=" + mShouldFade);
156         }
157         mFadingPanel = panel;
158     }
159 
160     @Override
onAllPanelsCollapsed()161     public void onAllPanelsCollapsed() {
162         super.onAllPanelsCollapsed();
163         // give animations time to settle
164         mBar.makeExpandedInvisibleSoon();
165         mFadingPanel = null;
166         mLastFullyOpenedPanel = null;
167     }
168 
169     @Override
onPanelFullyOpened(PanelView openPanel)170     public void onPanelFullyOpened(PanelView openPanel) {
171         super.onPanelFullyOpened(openPanel);
172         if (openPanel != mLastFullyOpenedPanel) {
173             openPanel.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
174         }
175         mFadingPanel = openPanel;
176         mLastFullyOpenedPanel = openPanel;
177         mShouldFade = true; // now you own the fade, mister
178     }
179 
180     @Override
onTouchEvent(MotionEvent event)181     public boolean onTouchEvent(MotionEvent event) {
182         boolean barConsumedEvent = mBar.interceptTouchEvent(event);
183 
184         if (DEBUG_GESTURES) {
185             if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
186                 EventLog.writeEvent(EventLogTags.SYSUI_PANELBAR_TOUCH,
187                         event.getActionMasked(), (int) event.getX(), (int) event.getY(),
188                         barConsumedEvent ? 1 : 0);
189             }
190         }
191 
192         return barConsumedEvent || super.onTouchEvent(event);
193     }
194 
195     @Override
onInterceptTouchEvent(MotionEvent event)196     public boolean onInterceptTouchEvent(MotionEvent event) {
197         return mBar.interceptTouchEvent(event) || super.onInterceptTouchEvent(event);
198     }
199 
200     @Override
panelExpansionChanged(PanelView panel, float frac)201     public void panelExpansionChanged(PanelView panel, float frac) {
202         super.panelExpansionChanged(panel, frac);
203 
204         if (DEBUG) {
205             Slog.v(TAG, "panelExpansionChanged: f=" + frac);
206         }
207 
208         if (panel == mFadingPanel && mScrimColor != 0 && ActivityManager.isHighEndGfx()) {
209             if (mShouldFade) {
210                 frac = mPanelExpandedFractionSum; // don't judge me
211                 // let's start this 20% of the way down the screen
212                 frac = frac * 1.2f - 0.2f;
213                 if (frac <= 0) {
214                     mBar.mStatusBarWindow.setBackgroundColor(0);
215                 } else {
216                     // woo, special effects
217                     final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
218                     // attenuate background color alpha by k
219                     final int color = (int) ((mScrimColor >>> 24) * k) << 24 | (mScrimColor & 0xFFFFFF);
220                     mBar.mStatusBarWindow.setBackgroundColor(color);
221                 }
222             }
223         }
224 
225         // fade out the panel as it gets buried into the status bar to avoid overdrawing the
226         // status bar on the last frame of a close animation
227         final int H = mBar.getStatusBarHeight();
228         final float ph = panel.getExpandedHeight() + panel.getPaddingBottom();
229         float alpha = 1f;
230         if (ph < 2*H) {
231             if (ph < H) alpha = 0f;
232             else alpha = (ph - H) / H;
233             alpha = alpha * alpha; // get there faster
234         }
235         if (panel.getAlpha() != alpha) {
236             panel.setAlpha(alpha);
237         }
238 
239         mBar.updateCarrierLabelVisibility(false);
240     }
241 }
242