blob: aab911a0fb496275b9ff96458e379d1e6380123f [file] [log] [blame]
Joe Onorato808182d2010-07-09 18:52:06 -04001/*
2 * Copyright (C) 2010 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
Joe Onoratofd52b182010-11-10 18:00:52 -080017package com.android.systemui.statusbar.phone;
Joe Onorato808182d2010-07-09 18:52:06 -040018
Daniel Sandlerd7e96862012-04-26 01:10:29 -040019import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
21import android.animation.AnimatorSet;
Daniel Sandler0761e4c2011-08-11 00:19:49 -040022import android.animation.ObjectAnimator;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -070023import android.app.ActivityManager;
Joe Onorato808182d2010-07-09 18:52:06 -040024import android.app.ActivityManagerNative;
25import android.app.Dialog;
Daniel Sandler92d33182011-09-11 16:29:05 -040026import android.app.KeyguardManager;
Joe Onorato808182d2010-07-09 18:52:06 -040027import android.app.Notification;
28import android.app.PendingIntent;
Joe Onorato808182d2010-07-09 18:52:06 -040029import android.app.StatusBarManager;
30import android.content.BroadcastReceiver;
31import android.content.Context;
32import android.content.Intent;
33import android.content.IntentFilter;
Michael Jurka3b1fc472011-06-13 10:54:40 -070034import android.content.res.Configuration;
Michael Jurka7f2668c2012-03-27 07:49:52 -070035import android.content.res.Resources;
Romain Guy648342f2012-05-25 10:44:45 -070036import android.graphics.Canvas;
37import android.graphics.ColorFilter;
Joe Onorato808182d2010-07-09 18:52:06 -040038import android.graphics.PixelFormat;
Romain Guy648342f2012-05-25 10:44:45 -070039import android.graphics.PorterDuff;
Joe Onorato808182d2010-07-09 18:52:06 -040040import android.graphics.Rect;
Romain Guy648342f2012-05-25 10:44:45 -070041import android.graphics.drawable.Drawable;
Michael Jurka7f2668c2012-03-27 07:49:52 -070042import android.inputmethodservice.InputMethodService;
Joe Onorato808182d2010-07-09 18:52:06 -040043import android.os.IBinder;
Joe Onorato808182d2010-07-09 18:52:06 -040044import android.os.Message;
Michael Jurka7f2668c2012-03-27 07:49:52 -070045import android.os.RemoteException;
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040046import android.os.ServiceManager;
Joe Onorato808182d2010-07-09 18:52:06 -040047import android.os.SystemClock;
Daniel Sandlerd3090562011-08-09 00:28:44 -040048import android.provider.Settings;
Daniel Sandler36412a72011-08-04 09:35:13 -040049import android.util.DisplayMetrics;
Joe Onorato808182d2010-07-09 18:52:06 -040050import android.util.Log;
Michael Jurka7f2668c2012-03-27 07:49:52 -070051import android.util.Slog;
Jeff Browned5f45a2012-05-03 15:53:47 -070052import android.view.Choreographer;
Joe Onorato808182d2010-07-09 18:52:06 -040053import android.view.Display;
54import android.view.Gravity;
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040055import android.view.IWindowManager;
Joe Onorato808182d2010-07-09 18:52:06 -040056import android.view.KeyEvent;
Joe Onorato808182d2010-07-09 18:52:06 -040057import android.view.MotionEvent;
58import android.view.VelocityTracker;
59import android.view.View;
60import android.view.ViewGroup;
Jim Millerf2a16b22011-07-06 17:32:48 -070061import android.view.ViewGroup.LayoutParams;
Joe Onorato808182d2010-07-09 18:52:06 -040062import android.view.WindowManager;
63import android.view.WindowManagerImpl;
Daniel Sandlerd7e96862012-04-26 01:10:29 -040064import android.view.animation.AccelerateInterpolator;
Joe Onorato808182d2010-07-09 18:52:06 -040065import android.view.animation.Animation;
66import android.view.animation.AnimationUtils;
Daniel Sandler21b274e2012-05-02 15:07:51 -040067import android.widget.FrameLayout;
Joe Onorato808182d2010-07-09 18:52:06 -040068import android.widget.ImageView;
69import android.widget.LinearLayout;
Joe Onorato808182d2010-07-09 18:52:06 -040070import android.widget.ScrollView;
71import android.widget.TextView;
Joe Onorato808182d2010-07-09 18:52:06 -040072import com.android.internal.statusbar.StatusBarIcon;
Joe Onorato808182d2010-07-09 18:52:06 -040073import com.android.internal.statusbar.StatusBarNotification;
Joe Onorato808182d2010-07-09 18:52:06 -040074import com.android.systemui.R;
Michael Jurkaab48b682011-09-12 15:39:45 -070075import com.android.systemui.recent.RecentTasksLoader;
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -050076import com.android.systemui.statusbar.BaseStatusBar;
Michael Jurka7f2668c2012-03-27 07:49:52 -070077import com.android.systemui.statusbar.NotificationData;
Daniel Sandler58b173b2012-05-03 11:25:29 -040078import com.android.systemui.statusbar.NotificationData.Entry;
Jim Miller9a720f52012-05-30 03:19:43 -070079import com.android.systemui.statusbar.CommandQueue;
Daniel Sandler9ff63782012-05-03 23:16:42 -040080import com.android.systemui.statusbar.RotationToggle;
Christian Robertson2e347422011-08-11 14:01:04 -070081import com.android.systemui.statusbar.SignalClusterView;
Michael Jurka7f2668c2012-03-27 07:49:52 -070082import com.android.systemui.statusbar.StatusBarIconView;
Daniel Sandler2b697352011-07-22 16:23:09 -040083import com.android.systemui.statusbar.policy.BatteryController;
Michael Jurka7f2668c2012-03-27 07:49:52 -070084import com.android.systemui.statusbar.policy.DateView;
Daniel Sandler6a858c32012-03-12 14:38:58 -040085import com.android.systemui.statusbar.policy.IntruderAlertView;
Daniel Sandler2b697352011-07-22 16:23:09 -040086import com.android.systemui.statusbar.policy.LocationController;
87import com.android.systemui.statusbar.policy.NetworkController;
Daniel Sandler8ba33c92011-10-04 21:49:30 -040088import com.android.systemui.statusbar.policy.NotificationRowLayout;
Joe Onorato808182d2010-07-09 18:52:06 -040089
Daniel Sandler6a858c32012-03-12 14:38:58 -040090import java.io.FileDescriptor;
91import java.io.PrintWriter;
92import java.util.ArrayList;
93
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -050094public class PhoneStatusBar extends BaseStatusBar {
Joe Onoratofd52b182010-11-10 18:00:52 -080095 static final String TAG = "PhoneStatusBar";
Michael Jurka3b1fc472011-06-13 10:54:40 -070096 public static final boolean DEBUG = false;
Daniel Sandlerc1ebee42012-03-26 19:39:46 -040097 public static final boolean SPEW = DEBUG;
Daniel Sandler7579bca2011-08-18 15:47:26 -040098 public static final boolean DUMPTRUCK = true; // extra dumpsys info
Joe Onorato808182d2010-07-09 18:52:06 -040099
Daniel Sandler96e61c3c82011-08-04 22:49:06 -0400100 // additional instrumentation for testing purposes; intended to be left on during development
Daniel Sandler7c351742011-10-17 10:48:06 -0400101 public static final boolean CHATTY = DEBUG;
Daniel Sandler96e61c3c82011-08-04 22:49:06 -0400102
Joe Onorato808182d2010-07-09 18:52:06 -0400103 public static final String ACTION_STATUSBAR_START
104 = "com.android.internal.policy.statusbar.START";
105
Daniel Sandlerfc753d22012-05-08 13:56:44 -0400106 private static final boolean DIM_BEHIND_EXPANDED_PANEL = false;
Daniel Sandlerfc6fda32012-02-24 22:00:46 -0500107
Daniel Sandler8ba33c92011-10-04 21:49:30 -0400108 private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
109 private static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
Michael Jurka7f2668c2012-03-27 07:49:52 -0700110 // 1020-1030 reserved for BaseStatusBar
Joe Onorato808182d2010-07-09 18:52:06 -0400111
112 // will likely move to a resource or other tunable param at some point
Daniel Sandlerfa7887b2012-03-26 09:43:31 -0400113 private static final int INTRUDER_ALERT_DECAY_MS = 0; // disabled, was 10000;
Joe Onorato808182d2010-07-09 18:52:06 -0400114
Daniel Sandler8cc36e52011-10-17 14:18:46 -0400115 private static final boolean CLOSE_PANEL_WHEN_EMPTIED = true;
116
Daniel Sandler58b173b2012-05-03 11:25:29 -0400117 private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10; // see NotificationManagerService
118 private static final int HIDE_ICONS_BELOW_SCORE = Notification.PRIORITY_LOW * NOTIFICATION_PRIORITY_MULTIPLIER;
119
Daniel Sandlerdc940ea2011-08-25 14:35:53 -0700120 // fling gesture tuning parameters, scaled to display density
121 private float mSelfExpandVelocityPx; // classic value: 2000px/s
122 private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
123 private float mFlingExpandMinVelocityPx; // classic value: 200px/s
124 private float mFlingCollapseMinVelocityPx; // classic value: 200px/s
125 private float mCollapseMinDisplayFraction; // classic value: 0.08 (25px/min(320px,480px) on G1)
126 private float mExpandMinDisplayFraction; // classic value: 0.5 (drag open halfway to expand)
127 private float mFlingGestureMaxXVelocityPx; // classic value: 150px/s
128
129 private float mExpandAccelPx; // classic value: 2000px/s/s
130 private float mCollapseAccelPx; // classic value: 2000px/s/s (will be negated to collapse "up")
131
Joe Onoratofd52b182010-11-10 18:00:52 -0800132 PhoneStatusBarPolicy mIconPolicy;
Joe Onorato808182d2010-07-09 18:52:06 -0400133
Daniel Sandler2b697352011-07-22 16:23:09 -0400134 // These are no longer handled by the policy, because we need custom strategies for them
135 BatteryController mBatteryController;
136 LocationController mLocationController;
137 NetworkController mNetworkController;
Jim Miller5e6af442011-12-02 18:24:26 -0800138
Daniel Sandler7c3e39d2011-07-29 16:30:49 -0400139 int mNaturalBarHeight = -1;
140 int mIconSize = -1;
141 int mIconHPadding = -1;
Joe Onorato808182d2010-07-09 18:52:06 -0400142 Display mDisplay;
143
Daniel Sandler1d4d30a2011-04-28 12:35:29 -0400144 IWindowManager mWindowManager;
145
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400146 StatusBarWindowView mStatusBarWindow;
Joe Onoratofd52b182010-11-10 18:00:52 -0800147 PhoneStatusBarView mStatusBarView;
Daniel Sandlera310af82012-04-24 01:20:13 -0400148
Joe Onorato808182d2010-07-09 18:52:06 -0400149 int mPixelFormat;
Joe Onorato808182d2010-07-09 18:52:06 -0400150 Object mQueueLock = new Object();
151
152 // icons
153 LinearLayout mIcons;
154 IconMerger mNotificationIcons;
Daniel Sandler05e24142011-11-10 11:56:49 -0500155 View mMoreIcon;
Joe Onorato808182d2010-07-09 18:52:06 -0400156 LinearLayout mStatusIcons;
157
158 // expanded notifications
Daniel Sandler079b33d2012-03-02 16:29:41 -0500159 View mNotificationPanel; // the sliding/resizing panel within the notification window
Joe Onorato808182d2010-07-09 18:52:06 -0400160 ScrollView mScrollView;
Joe Onorato808182d2010-07-09 18:52:06 -0400161 View mExpandedContents;
Daniel Sandler21b274e2012-05-02 15:07:51 -0400162 int mNotificationPanelMarginBottomPx, mNotificationPanelMarginLeftPx;
163 int mNotificationPanelGravity;
164
Joe Onorato808182d2010-07-09 18:52:06 -0400165 // top bar
Daniel Sandler1347c302011-08-01 16:47:53 -0400166 View mClearButton;
Daniel Sandlerd3090562011-08-09 00:28:44 -0400167 View mSettingsButton;
Daniel Sandler9ff63782012-05-03 23:16:42 -0400168 RotationToggle mRotationButton;
Daniel Sandlerd3090562011-08-09 00:28:44 -0400169
Joe Onorato808182d2010-07-09 18:52:06 -0400170 // drag bar
171 CloseDragHandle mCloseView;
Daniel Sandler1fac1fd2012-04-30 12:07:30 -0400172 private int mCloseViewHeight;
Jim Miller5e6af442011-12-02 18:24:26 -0800173
Joe Onorato808182d2010-07-09 18:52:06 -0400174 // position
175 int[] mPositionTmp = new int[2];
176 boolean mExpanded;
177 boolean mExpandedVisible;
178
179 // the date view
180 DateView mDateView;
181
182 // for immersive activities
Daniel Sandlerfa7887b2012-03-26 09:43:31 -0400183 private IntruderAlertView mIntruderAlertView;
Joe Onorato808182d2010-07-09 18:52:06 -0400184
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400185 // on-screen navigation buttons
Daniel Sandler0129b312011-05-11 11:54:11 -0400186 private NavigationBarView mNavigationBarView = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400187
Joe Onorato808182d2010-07-09 18:52:06 -0400188 // the tracker view
Joe Onorato808182d2010-07-09 18:52:06 -0400189 int mTrackingPosition; // the position of the top of the tracking view.
190 private boolean mPanelSlightlyVisible;
191
192 // ticker
193 private Ticker mTicker;
194 private View mTickerView;
195 private boolean mTicking;
196
197 // Tracking finger for opening/closing.
198 int mEdgeBorder; // corresponds to R.dimen.status_bar_edge_ignore
199 boolean mTracking;
200 VelocityTracker mVelocityTracker;
201
Jeff Browned5f45a2012-05-03 15:53:47 -0700202 Choreographer mChoreographer;
Joe Onorato808182d2010-07-09 18:52:06 -0400203 boolean mAnimating;
Daniel Sandlerfbab8ae2012-05-09 02:06:29 -0400204 boolean mClosing; // only valid when mAnimating; indicates the initial acceleration
Joe Onorato808182d2010-07-09 18:52:06 -0400205 float mAnimY;
206 float mAnimVel;
207 float mAnimAccel;
Jeff Browned5f45a2012-05-03 15:53:47 -0700208 long mAnimLastTimeNanos;
Joe Onorato808182d2010-07-09 18:52:06 -0400209 boolean mAnimatingReveal = false;
210 int mViewDelta;
211 int[] mAbsPos = new int[2];
Chet Haase2f2022a2011-10-11 06:41:59 -0700212 Runnable mPostCollapseCleanup = null;
213
Daniel Sandlerd7e96862012-04-26 01:10:29 -0400214 private AnimatorSet mLightsOutAnimation;
215 private AnimatorSet mLightsOnAnimation;
Joe Onorato808182d2010-07-09 18:52:06 -0400216
217 // for disabling the status bar
218 int mDisabled = 0;
219
Daniel Sandler60ee2562011-07-22 12:34:33 -0400220 // tracking calls to View.setSystemUiVisibility()
221 int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
222
Daniel Sandler36412a72011-08-04 09:35:13 -0400223 DisplayMetrics mDisplayMetrics = new DisplayMetrics();
Dianne Hackborn1dacf272011-08-02 15:01:22 -0700224
Daniel Sandler328310c2011-09-23 15:56:52 -0400225 private int mNavigationIconHints = 0;
Romain Guyf7f16f72012-05-24 19:13:56 -0700226 private final Animator.AnimatorListener mMakeIconsInvisible = new AnimatorListenerAdapter() {
227 @Override
228 public void onAnimationEnd(Animator animation) {
229 mIcons.setVisibility(View.INVISIBLE);
230 }
231 };
232 private final Animator.AnimatorListener mMakeIconsVisible = new AnimatorListenerAdapter() {
233 @Override
234 public void onAnimationEnd(Animator animation) {
235 mIcons.setVisibility(View.VISIBLE);
236 }
237 };
Daniel Sandler328310c2011-09-23 15:56:52 -0400238
Joe Onorato808182d2010-07-09 18:52:06 -0400239 private class ExpandedDialog extends Dialog {
240 ExpandedDialog(Context context) {
Daniel Sandler36412a72011-08-04 09:35:13 -0400241 super(context, com.android.internal.R.style.Theme_Translucent_NoTitleBar);
Joe Onorato808182d2010-07-09 18:52:06 -0400242 }
243
244 @Override
245 public boolean dispatchKeyEvent(KeyEvent event) {
246 boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
247 switch (event.getKeyCode()) {
248 case KeyEvent.KEYCODE_BACK:
249 if (!down) {
250 animateCollapse();
251 }
252 return true;
253 }
254 return super.dispatchKeyEvent(event);
255 }
256 }
257
258 @Override
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400259 public void start() {
260 mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
261 .getDefaultDisplay();
Joe Onorato808182d2010-07-09 18:52:06 -0400262
Daniel Sandler1d4d30a2011-04-28 12:35:29 -0400263 mWindowManager = IWindowManager.Stub.asInterface(
264 ServiceManager.getService(Context.WINDOW_SERVICE));
265
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500266 super.start(); // calls createAndAddWindows()
Joe Onorato808182d2010-07-09 18:52:06 -0400267
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400268 addNavigationBar();
269
Daniel Sandlerfc6fda32012-02-24 22:00:46 -0500270 if (ENABLE_INTRUDERS) addIntruderView();
Joe Onorato808182d2010-07-09 18:52:06 -0400271
272 // Lastly, call to the icon policy to install/update all the icons.
Joe Onoratofd52b182010-11-10 18:00:52 -0800273 mIconPolicy = new PhoneStatusBarPolicy(mContext);
Joe Onorato808182d2010-07-09 18:52:06 -0400274 }
275
276 // ================================================================================
277 // Constructing the view
278 // ================================================================================
Jim Millere898ac52012-04-06 17:10:57 -0700279 protected PhoneStatusBarView makeStatusBarView() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400280 final Context context = mContext;
Joe Onorato808182d2010-07-09 18:52:06 -0400281
282 Resources res = context.getResources();
283
Daniel Sandler6e8db882011-10-26 15:40:51 -0400284 updateDisplaySize(); // populates mDisplayMetrics
Daniel Sandler7c3e39d2011-07-29 16:30:49 -0400285 loadDimens();
Joe Onorato808182d2010-07-09 18:52:06 -0400286
Dianne Hackborn1dacf272011-08-02 15:01:22 -0700287 mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
288
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400289 mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
Daniel Sandlera310af82012-04-24 01:20:13 -0400290 R.layout.super_status_bar, null);
Daniel Sandlercf336e12011-08-09 15:48:18 -0400291 if (DEBUG) {
Daniel Sandlera310af82012-04-24 01:20:13 -0400292 mStatusBarWindow.setBackgroundColor(0x6000FF80);
Daniel Sandlercf336e12011-08-09 15:48:18 -0400293 }
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400294 mStatusBarWindow.mService = this;
Daniel Sandler21b274e2012-05-02 15:07:51 -0400295 mStatusBarWindow.setOnTouchListener(new View.OnTouchListener() {
296 @Override
297 public boolean onTouch(View v, MotionEvent event) {
298 if (event.getAction() == MotionEvent.ACTION_DOWN) {
299 if (mExpanded && !mAnimating) {
300 animateCollapse();
301 }
302 }
Chris Wren5de6e942012-05-16 14:22:21 -0400303 return mStatusBarWindow.onTouchEvent(event);
Daniel Sandler21b274e2012-05-02 15:07:51 -0400304 }});
305
Daniel Sandlera310af82012-04-24 01:20:13 -0400306 mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
307 mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel);
Daniel Sandler9ff63782012-05-03 23:16:42 -0400308 // don't allow clicks on the panel to pass through to the background where they will cause the panel to close
309 mNotificationPanel.setOnTouchListener(new View.OnTouchListener() {
310 @Override
311 public boolean onTouch(View v, MotionEvent event) {
312 return true;
313 }
314 });
Daniel Sandler8e18dc72012-05-17 00:44:59 -0400315 mNotificationPanel.setSystemUiVisibility(
316 View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER
317 | View.STATUS_BAR_DISABLE_SYSTEM_INFO);
Joe Onorato808182d2010-07-09 18:52:06 -0400318
Romain Guy328b3582012-05-08 15:30:57 -0700319 if (!ActivityManager.isHighEndGfx(mDisplay)) {
320 mStatusBarWindow.setBackground(null);
Romain Guy648342f2012-05-25 10:44:45 -0700321 mNotificationPanel.setBackground(new FastColorDrawable(context.getResources().getColor(
322 R.color.notification_panel_solid_background)));
Romain Guy328b3582012-05-08 15:30:57 -0700323 }
324
Daniel Sandler6b318802012-04-13 14:05:19 -0400325 if (ENABLE_INTRUDERS) {
326 mIntruderAlertView = (IntruderAlertView) View.inflate(context, R.layout.intruder_alert, null);
327 mIntruderAlertView.setVisibility(View.GONE);
328 mIntruderAlertView.setBar(this);
329 }
Joe Onorato808182d2010-07-09 18:52:06 -0400330
Daniel Sandlera310af82012-04-24 01:20:13 -0400331 mStatusBarView.mService = this;
Daniel Sandler60ee2562011-07-22 12:34:33 -0400332
Jeff Browned5f45a2012-05-03 15:53:47 -0700333 mChoreographer = Choreographer.getInstance();
334
Daniel Sandler0129b312011-05-11 11:54:11 -0400335 try {
Daniel Sandler0c4ccff2011-10-19 16:39:14 -0400336 boolean showNav = mWindowManager.hasNavigationBar();
Daniel Sandler4a066c52012-04-20 14:49:13 -0400337 if (DEBUG) Slog.v(TAG, "hasNavigationBar=" + showNav);
Daniel Sandler0129b312011-05-11 11:54:11 -0400338 if (showNav) {
Jim Miller5e6af442011-12-02 18:24:26 -0800339 mNavigationBarView =
Daniel Sandler0129b312011-05-11 11:54:11 -0400340 (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);
Daniel Sandler60ee2562011-07-22 12:34:33 -0400341
Daniel Sandler6da2b762011-09-14 16:04:59 -0400342 mNavigationBarView.setDisabledFlags(mDisabled);
Jim Millere898ac52012-04-06 17:10:57 -0700343 mNavigationBarView.setBar(this);
Daniel Sandler0129b312011-05-11 11:54:11 -0400344 }
Daniel Sandler0c4ccff2011-10-19 16:39:14 -0400345 } catch (RemoteException ex) {
346 // no window manager? good luck with that
Daniel Sandler0129b312011-05-11 11:54:11 -0400347 }
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400348
Joe Onorato808182d2010-07-09 18:52:06 -0400349 // figure out which pixel-format to use for the status bar.
Daniel Sandlerf733c2a2011-09-25 15:03:40 -0400350 mPixelFormat = PixelFormat.OPAQUE;
Daniel Sandlera310af82012-04-24 01:20:13 -0400351 mStatusIcons = (LinearLayout)mStatusBarView.findViewById(R.id.statusIcons);
352 mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons);
Daniel Sandler05e24142011-11-10 11:56:49 -0500353 mNotificationIcons.setOverflowIndicator(mMoreIcon);
Daniel Sandlera310af82012-04-24 01:20:13 -0400354 mIcons = (LinearLayout)mStatusBarView.findViewById(R.id.icons);
355 mTickerView = mStatusBarView.findViewById(R.id.ticker);
Joe Onorato808182d2010-07-09 18:52:06 -0400356
Daniel Sandlera310af82012-04-24 01:20:13 -0400357 mPile = (NotificationRowLayout)mStatusBarWindow.findViewById(R.id.latestItems);
Daniel Sandlerf7a19562012-04-04 14:04:21 -0400358 mPile.setLongPressListener(getNotificationLongClicker());
Daniel Sandler0761e4c2011-08-11 00:19:49 -0400359 mExpandedContents = mPile; // was: expanded.findViewById(R.id.notificationLinearLayout);
Daniel Sandlerd7141482011-08-18 15:14:52 -0400360
Daniel Sandlera310af82012-04-24 01:20:13 -0400361 mClearButton = mStatusBarWindow.findViewById(R.id.clear_all_button);
Joe Onorato808182d2010-07-09 18:52:06 -0400362 mClearButton.setOnClickListener(mClearButtonListener);
Daniel Sandler0761e4c2011-08-11 00:19:49 -0400363 mClearButton.setAlpha(0f);
Romain Guy8900e632012-05-25 12:08:39 -0700364 mClearButton.setVisibility(View.INVISIBLE);
Daniel Sandler8ba33c92011-10-04 21:49:30 -0400365 mClearButton.setEnabled(false);
Daniel Sandlera310af82012-04-24 01:20:13 -0400366 mDateView = (DateView)mStatusBarWindow.findViewById(R.id.date);
367 mSettingsButton = mStatusBarWindow.findViewById(R.id.settings_button);
Daniel Sandlerd3090562011-08-09 00:28:44 -0400368 mSettingsButton.setOnClickListener(mSettingsButtonListener);
Daniel Sandler9ff63782012-05-03 23:16:42 -0400369 mRotationButton = (RotationToggle) mStatusBarWindow.findViewById(R.id.rotation_lock_button);
370
Daniel Sandlera310af82012-04-24 01:20:13 -0400371 mScrollView = (ScrollView)mStatusBarWindow.findViewById(R.id.scroll);
Daniel Sandler079b33d2012-03-02 16:29:41 -0500372 mScrollView.setVerticalScrollBarEnabled(false); // less drawing during pulldowns
Joe Onorato808182d2010-07-09 18:52:06 -0400373
Daniel Sandlera310af82012-04-24 01:20:13 -0400374 mTicker = new MyTicker(context, mStatusBarView);
Joe Onorato808182d2010-07-09 18:52:06 -0400375
Daniel Sandlera310af82012-04-24 01:20:13 -0400376 TickerView tickerView = (TickerView)mStatusBarView.findViewById(R.id.tickerText);
Joe Onorato808182d2010-07-09 18:52:06 -0400377 tickerView.mTicker = mTicker;
378
Daniel Sandlera310af82012-04-24 01:20:13 -0400379 mCloseView = (CloseDragHandle)mStatusBarWindow.findViewById(R.id.close);
Joe Onorato808182d2010-07-09 18:52:06 -0400380 mCloseView.mService = this;
Daniel Sandler1fac1fd2012-04-30 12:07:30 -0400381 mCloseViewHeight = res.getDimensionPixelSize(R.dimen.close_handle_height);
Joe Onorato808182d2010-07-09 18:52:06 -0400382
383 mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
384
Joe Onorato808182d2010-07-09 18:52:06 -0400385 // set the inital view visibility
386 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400387
Daniel Sandler2b697352011-07-22 16:23:09 -0400388 // Other icons
389 mLocationController = new LocationController(mContext); // will post a notification
390 mBatteryController = new BatteryController(mContext);
Daniel Sandlera310af82012-04-24 01:20:13 -0400391 mBatteryController.addIconView((ImageView)mStatusBarView.findViewById(R.id.battery));
Daniel Sandler2b697352011-07-22 16:23:09 -0400392 mNetworkController = new NetworkController(mContext);
Jim Miller5e6af442011-12-02 18:24:26 -0800393 final SignalClusterView signalCluster =
Daniel Sandlera310af82012-04-24 01:20:13 -0400394 (SignalClusterView)mStatusBarView.findViewById(R.id.signal_cluster);
Christian Robertson2e347422011-08-11 14:01:04 -0700395 mNetworkController.addSignalCluster(signalCluster);
Daniel Sandler28f89d42011-08-15 14:04:15 -0400396 signalCluster.setNetworkController(mNetworkController);
Jim Miller5e6af442011-12-02 18:24:26 -0800397// final ImageView wimaxRSSI =
Daniel Sandler633eabe2011-11-09 16:49:44 -0500398// (ImageView)sb.findViewById(R.id.wimax_signal);
399// if (wimaxRSSI != null) {
400// mNetworkController.addWimaxIconView(wimaxRSSI);
401// }
Michael Jurka3b1fc472011-06-13 10:54:40 -0700402 // Recents Panel
Michael Jurkaab48b682011-09-12 15:39:45 -0700403 mRecentTasksLoader = new RecentTasksLoader(context);
Jim Miller17dfec72011-07-08 19:09:55 -0700404 updateRecentsPanel();
Michael Jurka3b1fc472011-06-13 10:54:40 -0700405
Joe Onorato808182d2010-07-09 18:52:06 -0400406 // receive broadcasts
407 IntentFilter filter = new IntentFilter();
408 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
409 filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
410 filter.addAction(Intent.ACTION_SCREEN_OFF);
411 context.registerReceiver(mBroadcastReceiver, filter);
412
Daniel Sandlera310af82012-04-24 01:20:13 -0400413 return mStatusBarView;
Joe Onorato808182d2010-07-09 18:52:06 -0400414 }
415
Michael Jurka7f2668c2012-03-27 07:49:52 -0700416 @Override
Jim Millerf2a16b22011-07-06 17:32:48 -0700417 protected WindowManager.LayoutParams getRecentsLayoutParams(LayoutParams layoutParams) {
Michael Jurka3cd0a592011-08-16 12:40:30 -0700418 boolean opaque = false;
Michael Jurka3b1fc472011-06-13 10:54:40 -0700419 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
Jim Millerf2a16b22011-07-06 17:32:48 -0700420 layoutParams.width,
421 layoutParams.height,
Michael Jurka3b1fc472011-06-13 10:54:40 -0700422 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
423 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
424 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700425 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
Michael Jurka3cd0a592011-08-16 12:40:30 -0700426 (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700427 if (ActivityManager.isHighEndGfx(mDisplay)) {
428 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
Michael Jurkaf16fc512012-02-27 15:02:23 -0800429 } else {
430 lp.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
Michael Jurkaf3abbad2012-06-04 14:00:32 -0700431 lp.dimAmount = 0.75f;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700432 }
Michael Jurka3b1fc472011-06-13 10:54:40 -0700433 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
434 lp.setTitle("RecentsPanel");
Michael Jurka99a96552012-01-27 17:23:38 -0800435 lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
Michael Jurka3b1fc472011-06-13 10:54:40 -0700436 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
437 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
438 return lp;
439 }
440
Jim Millere898ac52012-04-06 17:10:57 -0700441 @Override
442 protected WindowManager.LayoutParams getSearchLayoutParams(LayoutParams layoutParams) {
443 boolean opaque = false;
444 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
445 LayoutParams.MATCH_PARENT,
446 LayoutParams.MATCH_PARENT,
447 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
448 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
449 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
450 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
451 (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
452 if (ActivityManager.isHighEndGfx(mDisplay)) {
453 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
Jim Millere898ac52012-04-06 17:10:57 -0700454 }
455 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
456 lp.setTitle("SearchPanel");
457 // TODO: Define custom animation for Search panel
458 lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
459 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
460 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
461 return lp;
462 }
463
Jim Miller17dfec72011-07-08 19:09:55 -0700464 protected void updateRecentsPanel() {
Daniel Sandler4a066c52012-04-20 14:49:13 -0400465 super.updateRecentsPanel(R.layout.status_bar_recent_panel);
Michael Jurka4eaa9832012-02-29 15:51:49 -0800466 // Make .03 alpha the minimum so you always see the item a bit-- slightly below
467 // .03, the item disappears entirely (as if alpha = 0) and that discontinuity looks
468 // a bit jarring
469 mRecentsPanel.setMinSwipeAlpha(0.03f);
Michael Jurka8b2e37e2012-05-08 20:06:13 -0700470 if (mNavigationBarView != null) {
471 mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPanel);
472 }
Michael Jurka3b1fc472011-06-13 10:54:40 -0700473 }
474
Jim Millere898ac52012-04-06 17:10:57 -0700475 @Override
476 protected void updateSearchPanel() {
477 super.updateSearchPanel();
Jim Miller354619c2012-04-27 17:33:44 -0700478 mSearchPanelView.setStatusBarView(mNavigationBarView);
Jim Millere898ac52012-04-06 17:10:57 -0700479 mNavigationBarView.setDelegateView(mSearchPanelView);
480 }
481
482 @Override
483 public void showSearchPanel() {
Jim Millerb490c3e2012-05-31 13:34:16 -0700484 super.showSearchPanel();
Jim Millere898ac52012-04-06 17:10:57 -0700485 WindowManager.LayoutParams lp =
486 (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
487 lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
Jim Millere898ac52012-04-06 17:10:57 -0700488 WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp);
489 }
490
491 @Override
492 public void hideSearchPanel() {
493 super.hideSearchPanel();
494 WindowManager.LayoutParams lp =
495 (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
496 lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
Jim Millere898ac52012-04-06 17:10:57 -0700497 WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp);
498 }
499
Joe Onorato808182d2010-07-09 18:52:06 -0400500 protected int getStatusBarGravity() {
501 return Gravity.TOP | Gravity.FILL_HORIZONTAL;
502 }
503
Joe Onoratodc100302011-01-11 17:07:41 -0800504 public int getStatusBarHeight() {
Daniel Sandlera310af82012-04-24 01:20:13 -0400505 if (mNaturalBarHeight < 0) {
506 final Resources res = mContext.getResources();
Jim Millera073e572012-05-23 17:03:27 -0700507 mNaturalBarHeight =
Daniel Sandlera310af82012-04-24 01:20:13 -0400508 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
509 }
510 return mNaturalBarHeight;
Joe Onoratodc100302011-01-11 17:07:41 -0800511 }
512
Daniel Sandler1fac1fd2012-04-30 12:07:30 -0400513 private int getCloseViewHeight() {
514 return mCloseViewHeight;
515 }
516
Daniel Sandler5c8da942011-06-28 00:29:04 -0400517 private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
518 public void onClick(View v) {
519 toggleRecentApps();
520 }
521 };
Chris Wren0c8275b2012-05-08 13:36:48 -0400522
Jim Miller9a720f52012-05-30 03:19:43 -0700523 private int mShowSearchHoldoff = 0;
524 private Runnable mShowSearchPanel = new Runnable() {
525 public void run() {
526 showSearchPanel();
527 }
528 };
529
Jim Millere898ac52012-04-06 17:10:57 -0700530 View.OnTouchListener mHomeSearchActionListener = new View.OnTouchListener() {
531 public boolean onTouch(View v, MotionEvent event) {
532 switch(event.getAction()) {
Jim Miller9a720f52012-05-30 03:19:43 -0700533 case MotionEvent.ACTION_DOWN:
534 if (!shouldDisableNavbarGestures()) {
535 mHandler.removeCallbacks(mShowSearchPanel);
536 mHandler.postDelayed(mShowSearchPanel, mShowSearchHoldoff);
537 }
538 break;
539
540 case MotionEvent.ACTION_UP:
541 case MotionEvent.ACTION_CANCEL:
542 mHandler.removeCallbacks(mShowSearchPanel);
543 break;
544 }
545 return false;
Jim Millere898ac52012-04-06 17:10:57 -0700546 }
547 };
Daniel Sandler5c8da942011-06-28 00:29:04 -0400548
Michael Jurka412cba82011-10-17 09:05:00 -0700549 private void prepareNavigationBarView() {
550 mNavigationBarView.reorient();
551
552 mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
553 mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPanel);
Jim Miller998bb762012-05-21 13:37:27 -0700554 mNavigationBarView.getHomeButton().setOnTouchListener(mHomeSearchActionListener);
Jim Millere898ac52012-04-06 17:10:57 -0700555 updateSearchPanel();
Michael Jurka412cba82011-10-17 09:05:00 -0700556 }
557
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400558 // For small-screen devices (read: phones) that lack hardware navigation buttons
559 private void addNavigationBar() {
Daniel Sandler4a066c52012-04-20 14:49:13 -0400560 if (DEBUG) Slog.v(TAG, "addNavigationBar: about to add " + mNavigationBarView);
Daniel Sandler0129b312011-05-11 11:54:11 -0400561 if (mNavigationBarView == null) return;
Jim Miller17dfec72011-07-08 19:09:55 -0700562
Michael Jurka412cba82011-10-17 09:05:00 -0700563 prepareNavigationBarView();
Daniel Sandler5c8da942011-06-28 00:29:04 -0400564
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400565 WindowManagerImpl.getDefault().addView(
566 mNavigationBarView, getNavigationBarLayoutParams());
567 }
568
569 private void repositionNavigationBar() {
Daniel Sandler0129b312011-05-11 11:54:11 -0400570 if (mNavigationBarView == null) return;
Jim Miller17dfec72011-07-08 19:09:55 -0700571
Michael Jurka412cba82011-10-17 09:05:00 -0700572 prepareNavigationBarView();
Daniel Sandler5c8da942011-06-28 00:29:04 -0400573
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400574 WindowManagerImpl.getDefault().updateViewLayout(
575 mNavigationBarView, getNavigationBarLayoutParams());
576 }
577
578 private WindowManager.LayoutParams getNavigationBarLayoutParams() {
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400579 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
Dianne Hackborn1f903c32011-09-13 19:18:06 -0700580 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400581 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
582 0
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400583 | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
584 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
Dianne Hackborndf89e652011-10-06 22:35:11 -0700585 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
Jim Millerd99e7fd2012-05-08 16:30:42 -0700586 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
Daniel Sandlera3884492011-08-16 15:55:44 -0400587 PixelFormat.OPAQUE);
Daniel Sandlerc638c1e2011-08-24 16:19:23 -0700588 // this will allow the navbar to run in an overlay on devices that support this
589 if (ActivityManager.isHighEndGfx(mDisplay)) {
590 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
591 }
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400592
593 lp.setTitle("NavigationBar");
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400594 lp.windowAnimations = 0;
595
596 return lp;
597 }
598
Joe Onoratodc100302011-01-11 17:07:41 -0800599 private void addIntruderView() {
600 final int height = getStatusBarHeight();
Joe Onorato808182d2010-07-09 18:52:06 -0400601
602 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
603 ViewGroup.LayoutParams.MATCH_PARENT,
604 ViewGroup.LayoutParams.WRAP_CONTENT,
Daniel Sandlerfa7887b2012-03-26 09:43:31 -0400605 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, // above the status bar!
Joe Onorato808182d2010-07-09 18:52:06 -0400606 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
607 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
608 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
609 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
Jeff Brown46e75292010-11-10 16:53:45 -0800610 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
611 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
Joe Onorato808182d2010-07-09 18:52:06 -0400612 PixelFormat.TRANSLUCENT);
613 lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
Daniel Sandlerfa7887b2012-03-26 09:43:31 -0400614 //lp.y += height * 1.5; // FIXME
Joe Onorato808182d2010-07-09 18:52:06 -0400615 lp.setTitle("IntruderAlert");
Dianne Hackborn59aed382011-08-02 17:31:44 -0700616 lp.packageName = mContext.getPackageName();
617 lp.windowAnimations = R.style.Animation_StatusBar_IntruderAlert;
Joe Onorato808182d2010-07-09 18:52:06 -0400618
619 WindowManagerImpl.getDefault().addView(mIntruderAlertView, lp);
620 }
621
622 public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
623 if (SPEW) Slog.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
624 + " icon=" + icon);
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700625 StatusBarIconView view = new StatusBarIconView(mContext, slot, null);
Joe Onorato808182d2010-07-09 18:52:06 -0400626 view.set(icon);
627 mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize));
628 }
629
630 public void updateIcon(String slot, int index, int viewIndex,
631 StatusBarIcon old, StatusBarIcon icon) {
632 if (SPEW) Slog.d(TAG, "updateIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
633 + " old=" + old + " icon=" + icon);
634 StatusBarIconView view = (StatusBarIconView)mStatusIcons.getChildAt(viewIndex);
635 view.set(icon);
636 }
637
638 public void removeIcon(String slot, int index, int viewIndex) {
639 if (SPEW) Slog.d(TAG, "removeIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex);
640 mStatusIcons.removeViewAt(viewIndex);
641 }
642
643 public void addNotification(IBinder key, StatusBarNotification notification) {
Daniel Sandler2561b0b2012-02-13 21:04:12 -0500644 /* if (DEBUG) */ Slog.d(TAG, "addNotification score=" + notification.score);
Joe Onorato808182d2010-07-09 18:52:06 -0400645 StatusBarIconView iconView = addNotificationViews(key, notification);
646 if (iconView == null) return;
647
648 boolean immersive = false;
649 try {
650 immersive = ActivityManagerNative.getDefault().isTopActivityImmersive();
Daniel Sandler8355e932011-08-11 00:27:45 -0400651 if (DEBUG) {
652 Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
653 }
Joe Onorato808182d2010-07-09 18:52:06 -0400654 } catch (RemoteException ex) {
655 }
Daniel Sandler6b318802012-04-13 14:05:19 -0400656
657 /*
658 * DISABLED due to missing API
Daniel Sandlerfc6fda32012-02-24 22:00:46 -0500659 if (ENABLE_INTRUDERS && (
Daniel Sandlerfa7887b2012-03-26 09:43:31 -0400660 // TODO(dsandler): Only if the screen is on
661 notification.notification.intruderView != null)) {
Daniel Sandler2561b0b2012-02-13 21:04:12 -0500662 Slog.d(TAG, "Presenting high-priority notification");
663 // special new transient ticker mode
664 // 1. Populate mIntruderAlertView
Jim Millere898ac52012-04-06 17:10:57 -0700665
Daniel Sandlerfa7887b2012-03-26 09:43:31 -0400666 if (notification.notification.intruderView == null) {
667 Slog.e(TAG, notification.notification.toString() + " wanted to intrude but intruderView was null");
668 return;
669 }
Joe Onorato808182d2010-07-09 18:52:06 -0400670
Daniel Sandlerfa7887b2012-03-26 09:43:31 -0400671 // bind the click event to the content area
672 PendingIntent contentIntent = notification.notification.contentIntent;
673 final View.OnClickListener listener = (contentIntent != null)
674 ? new NotificationClicker(contentIntent,
675 notification.pkg, notification.tag, notification.id)
676 : null;
Joe Onorato808182d2010-07-09 18:52:06 -0400677
Daniel Sandlerfa7887b2012-03-26 09:43:31 -0400678 mIntruderAlertView.applyIntruderContent(notification.notification.intruderView, listener);
Joe Onorato808182d2010-07-09 18:52:06 -0400679
Daniel Sandlerfa7887b2012-03-26 09:43:31 -0400680 mCurrentlyIntrudingNotification = notification;
Jim Millere898ac52012-04-06 17:10:57 -0700681
Daniel Sandler2561b0b2012-02-13 21:04:12 -0500682 // 2. Animate mIntruderAlertView in
683 mHandler.sendEmptyMessage(MSG_SHOW_INTRUDER);
Joe Onorato808182d2010-07-09 18:52:06 -0400684
Daniel Sandler2561b0b2012-02-13 21:04:12 -0500685 // 3. Set alarm to age the notification off (TODO)
686 mHandler.removeMessages(MSG_HIDE_INTRUDER);
Daniel Sandlerfa7887b2012-03-26 09:43:31 -0400687 if (INTRUDER_ALERT_DECAY_MS > 0) {
688 mHandler.sendEmptyMessageDelayed(MSG_HIDE_INTRUDER, INTRUDER_ALERT_DECAY_MS);
689 }
Jim Millera073e572012-05-23 17:03:27 -0700690 } else
Daniel Sandler6b318802012-04-13 14:05:19 -0400691 */
Jim Millera073e572012-05-23 17:03:27 -0700692
Daniel Sandler6b318802012-04-13 14:05:19 -0400693 if (notification.notification.fullScreenIntent != null) {
Joe Onorato808182d2010-07-09 18:52:06 -0400694 // not immersive & a full-screen alert should be shown
Daniel Sandler8355e932011-08-11 00:27:45 -0400695 Slog.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
Joe Onorato808182d2010-07-09 18:52:06 -0400696 try {
697 notification.notification.fullScreenIntent.send();
698 } catch (PendingIntent.CanceledException e) {
699 }
700 } else {
701 // usual case: status bar visible & not immersive
702
Daniel Sandlerfa7887b2012-03-26 09:43:31 -0400703 // show the ticker if there isn't an intruder too
704 if (mCurrentlyIntrudingNotification == null) {
Chris Wren0c8275b2012-05-08 13:36:48 -0400705 tick(null, notification, true);
Daniel Sandlerfa7887b2012-03-26 09:43:31 -0400706 }
Joe Onorato808182d2010-07-09 18:52:06 -0400707 }
708
709 // Recalculate the position of the sliding windows and the titles.
710 setAreThereNotifications();
711 updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
712 }
713
Joe Onorato808182d2010-07-09 18:52:06 -0400714 public void removeNotification(IBinder key) {
Joe Onorato808182d2010-07-09 18:52:06 -0400715 StatusBarNotification old = removeNotificationViews(key);
Daniel Sandlerfa7887b2012-03-26 09:43:31 -0400716 if (SPEW) Slog.d(TAG, "removeNotification key=" + key + " old=" + old);
Joe Onorato808182d2010-07-09 18:52:06 -0400717
718 if (old != null) {
719 // Cancel the ticker if it's still running
720 mTicker.removeEntry(old);
721
722 // Recalculate the position of the sliding windows and the titles.
Joe Onorato808182d2010-07-09 18:52:06 -0400723 updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
Jim Millere898ac52012-04-06 17:10:57 -0700724
Daniel Sandler6b318802012-04-13 14:05:19 -0400725 if (ENABLE_INTRUDERS && old == mCurrentlyIntrudingNotification) {
Daniel Sandlerfa7887b2012-03-26 09:43:31 -0400726 mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
727 }
Daniel Sandler8cc36e52011-10-17 14:18:46 -0400728
729 if (CLOSE_PANEL_WHEN_EMPTIED && mNotificationData.size() == 0 && !mAnimating) {
730 animateCollapse();
731 }
Joe Onorato808182d2010-07-09 18:52:06 -0400732 }
Daniel Sandler0761e4c2011-08-11 00:19:49 -0400733
734 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400735 }
736
Michael Jurka3b1fc472011-06-13 10:54:40 -0700737 @Override
738 protected void onConfigurationChanged(Configuration newConfig) {
Jim Miller17dfec72011-07-08 19:09:55 -0700739 updateRecentsPanel();
Jim Miller9a720f52012-05-30 03:19:43 -0700740 mShowSearchHoldoff = mContext.getResources().getInteger(
741 R.integer.config_show_search_delay);
Michael Jurka3b1fc472011-06-13 10:54:40 -0700742 }
743
Daniel Sandler7c3e39d2011-07-29 16:30:49 -0400744 private void loadNotificationShade() {
Daniel Sandler26cda272012-05-22 15:44:08 -0400745 if (mPile == null) return;
746
Daniel Sandler7c3e39d2011-07-29 16:30:49 -0400747 int N = mNotificationData.size();
748
749 ArrayList<View> toShow = new ArrayList<View>();
750
Daniel Sandler26cda272012-05-22 15:44:08 -0400751 final boolean provisioned = isDeviceProvisioned();
752 // If the device hasn't been through Setup, we only show system notifications
Daniel Sandler7c3e39d2011-07-29 16:30:49 -0400753 for (int i=0; i<N; i++) {
Daniel Sandler26cda272012-05-22 15:44:08 -0400754 Entry ent = mNotificationData.get(N-i-1);
755 if (provisioned || "android".equals(ent.notification.pkg)) {
756 toShow.add(ent.row);
757 }
Daniel Sandler7c3e39d2011-07-29 16:30:49 -0400758 }
759
760 ArrayList<View> toRemove = new ArrayList<View>();
761 for (int i=0; i<mPile.getChildCount(); i++) {
762 View child = mPile.getChildAt(i);
763 if (!toShow.contains(child)) {
764 toRemove.add(child);
Joe Onorato808182d2010-07-09 18:52:06 -0400765 }
766 }
Daniel Sandler7c3e39d2011-07-29 16:30:49 -0400767
768 for (View remove : toRemove) {
769 mPile.removeView(remove);
770 }
771
772 for (int i=0; i<toShow.size(); i++) {
773 View v = toShow.get(i);
774 if (v.getParent() == null) {
Daniel Sandler2561b0b2012-02-13 21:04:12 -0500775 mPile.addView(v, i);
Daniel Sandler7c3e39d2011-07-29 16:30:49 -0400776 }
777 }
Daniel Sandler26cda272012-05-22 15:44:08 -0400778
779 mSettingsButton.setEnabled(isDeviceProvisioned());
Daniel Sandler7c3e39d2011-07-29 16:30:49 -0400780 }
781
782 private void reloadAllNotificationIcons() {
783 if (mNotificationIcons == null) return;
784 mNotificationIcons.removeAllViews();
785 updateNotificationIcons();
786 }
787
Chris Wren0c8275b2012-05-08 13:36:48 -0400788 @Override
789 protected void updateNotificationIcons() {
Daniel Sandler26cda272012-05-22 15:44:08 -0400790 if (mNotificationIcons == null) return;
791
Daniel Sandler7c3e39d2011-07-29 16:30:49 -0400792 loadNotificationShade();
793
794 final LinearLayout.LayoutParams params
795 = new LinearLayout.LayoutParams(mIconSize + 2*mIconHPadding, mNaturalBarHeight);
796
797 int N = mNotificationData.size();
798
799 if (DEBUG) {
800 Slog.d(TAG, "refreshing icons: " + N + " notifications, mNotificationIcons=" + mNotificationIcons);
801 }
802
803 ArrayList<View> toShow = new ArrayList<View>();
804
Daniel Sandler26cda272012-05-22 15:44:08 -0400805 final boolean provisioned = isDeviceProvisioned();
806 // If the device hasn't been through Setup, we only show system notifications
Daniel Sandler7c3e39d2011-07-29 16:30:49 -0400807 for (int i=0; i<N; i++) {
Daniel Sandler58b173b2012-05-03 11:25:29 -0400808 Entry ent = mNotificationData.get(N-i-1);
Daniel Sandler26cda272012-05-22 15:44:08 -0400809 if ((provisioned && ent.notification.score >= HIDE_ICONS_BELOW_SCORE)
810 || "android".equals(ent.notification.pkg)) {
Daniel Sandler58b173b2012-05-03 11:25:29 -0400811 toShow.add(ent.icon);
812 }
Daniel Sandler7c3e39d2011-07-29 16:30:49 -0400813 }
814
815 ArrayList<View> toRemove = new ArrayList<View>();
816 for (int i=0; i<mNotificationIcons.getChildCount(); i++) {
817 View child = mNotificationIcons.getChildAt(i);
818 if (!toShow.contains(child)) {
819 toRemove.add(child);
820 }
821 }
822
823 for (View remove : toRemove) {
824 mNotificationIcons.removeView(remove);
825 }
826
827 for (int i=0; i<toShow.size(); i++) {
828 View v = toShow.get(i);
829 if (v.getParent() == null) {
830 mNotificationIcons.addView(v, i, params);
831 }
832 }
833 }
834
Chris Wren0c8275b2012-05-08 13:36:48 -0400835 @Override
836 protected void setAreThereNotifications() {
Daniel Sandler0761e4c2011-08-11 00:19:49 -0400837 final boolean any = mNotificationData.size() > 0;
Joe Onorato808182d2010-07-09 18:52:06 -0400838
Daniel Sandler0761e4c2011-08-11 00:19:49 -0400839 final boolean clearable = any && mNotificationData.hasClearableItems();
840
841 if (DEBUG) {
842 Slog.d(TAG, "setAreThereNotifications: N=" + mNotificationData.size()
843 + " any=" + any + " clearable=" + clearable);
844 }
845
846 if (mClearButton.isShown()) {
847 if (clearable != (mClearButton.getAlpha() == 1.0f)) {
Romain Guy8900e632012-05-25 12:08:39 -0700848 ObjectAnimator clearAnimation = ObjectAnimator.ofFloat(
849 mClearButton, "alpha", clearable ? 1.0f : 0.0f).setDuration(250);
850 clearAnimation.addListener(new AnimatorListenerAdapter() {
851 @Override
852 public void onAnimationEnd(Animator animation) {
853 if (mClearButton.getAlpha() <= 0.0f) {
854 mClearButton.setVisibility(View.INVISIBLE);
855 }
856 }
857
858 @Override
859 public void onAnimationStart(Animator animation) {
860 if (mClearButton.getAlpha() <= 0.0f) {
861 mClearButton.setVisibility(View.VISIBLE);
862 }
863 }
864 });
865 clearAnimation.start();
Daniel Sandler0761e4c2011-08-11 00:19:49 -0400866 }
867 } else {
868 mClearButton.setAlpha(clearable ? 1.0f : 0.0f);
Romain Guy8900e632012-05-25 12:08:39 -0700869 mClearButton.setVisibility(clearable ? View.VISIBLE : View.INVISIBLE);
Daniel Sandler0761e4c2011-08-11 00:19:49 -0400870 }
Daniel Sandler8ba33c92011-10-04 21:49:30 -0400871 mClearButton.setEnabled(clearable);
Romain Guy8900e632012-05-25 12:08:39 -0700872
Daniel Sandlerd7e96862012-04-26 01:10:29 -0400873 final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out);
874 final boolean showDot = (any&&!areLightsOn());
875 if (showDot != (nlo.getAlpha() == 1.0f)) {
876 if (showDot) {
877 nlo.setAlpha(0f);
878 nlo.setVisibility(View.VISIBLE);
879 }
880 nlo.animate()
881 .alpha(showDot?1:0)
882 .setDuration(showDot?750:250)
883 .setInterpolator(new AccelerateInterpolator(2.0f))
884 .setListener(showDot ? null : new AnimatorListenerAdapter() {
885 @Override
886 public void onAnimationEnd(Animator _a) {
887 nlo.setVisibility(View.GONE);
888 }
889 })
890 .start();
891 }
Joe Onorato808182d2010-07-09 18:52:06 -0400892 }
893
Jeff Sharkeyf52c70b2011-08-30 22:05:47 -0700894 public void showClock(boolean show) {
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500895 if (mStatusBarView == null) return;
Jeff Sharkeyf52c70b2011-08-30 22:05:47 -0700896 View clock = mStatusBarView.findViewById(R.id.clock);
897 if (clock != null) {
898 clock.setVisibility(show ? View.VISIBLE : View.GONE);
899 }
900 }
Joe Onorato808182d2010-07-09 18:52:06 -0400901
902 /**
903 * State is one or more of the DISABLE constants from StatusBarManager.
904 */
905 public void disable(int state) {
906 final int old = mDisabled;
907 final int diff = state ^ old;
908 mDisabled = state;
909
Daniel Sandlere21f2882011-08-18 10:14:59 -0400910 if (DEBUG) {
911 Slog.d(TAG, String.format("disable: 0x%08x -> 0x%08x (diff: 0x%08x)",
912 old, state, diff));
913 }
914
Daniel Sandler6da2b762011-09-14 16:04:59 -0400915 StringBuilder flagdbg = new StringBuilder();
916 flagdbg.append("disable: < ");
917 flagdbg.append(((state & StatusBarManager.DISABLE_EXPAND) != 0) ? "EXPAND" : "expand");
918 flagdbg.append(((diff & StatusBarManager.DISABLE_EXPAND) != 0) ? "* " : " ");
919 flagdbg.append(((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) ? "ICONS" : "icons");
920 flagdbg.append(((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) ? "* " : " ");
921 flagdbg.append(((state & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "ALERTS" : "alerts");
922 flagdbg.append(((diff & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "* " : " ");
923 flagdbg.append(((state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) ? "TICKER" : "ticker");
924 flagdbg.append(((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) ? "* " : " ");
925 flagdbg.append(((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "SYSTEM_INFO" : "system_info");
926 flagdbg.append(((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "* " : " ");
Daniel Sandler6da2b762011-09-14 16:04:59 -0400927 flagdbg.append(((state & StatusBarManager.DISABLE_BACK) != 0) ? "BACK" : "back");
928 flagdbg.append(((diff & StatusBarManager.DISABLE_BACK) != 0) ? "* " : " ");
Daniel Sandlerdba93562011-10-06 16:39:58 -0400929 flagdbg.append(((state & StatusBarManager.DISABLE_HOME) != 0) ? "HOME" : "home");
930 flagdbg.append(((diff & StatusBarManager.DISABLE_HOME) != 0) ? "* " : " ");
931 flagdbg.append(((state & StatusBarManager.DISABLE_RECENT) != 0) ? "RECENT" : "recent");
932 flagdbg.append(((diff & StatusBarManager.DISABLE_RECENT) != 0) ? "* " : " ");
Daniel Sandler6da2b762011-09-14 16:04:59 -0400933 flagdbg.append(((state & StatusBarManager.DISABLE_CLOCK) != 0) ? "CLOCK" : "clock");
934 flagdbg.append(((diff & StatusBarManager.DISABLE_CLOCK) != 0) ? "* " : " ");
935 flagdbg.append(">");
936 Slog.d(TAG, flagdbg.toString());
Jim Millera073e572012-05-23 17:03:27 -0700937
Daniel Sandler8e18dc72012-05-17 00:44:59 -0400938 if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
939 mIcons.animate().cancel();
940 if ((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
Romain Guyf7f16f72012-05-24 19:13:56 -0700941 mIcons.animate().alpha(0f).setStartDelay(100).setDuration(200).
942 setListener(mMakeIconsInvisible).start();
Daniel Sandler8e18dc72012-05-17 00:44:59 -0400943 } else {
Romain Guyf7f16f72012-05-24 19:13:56 -0700944 mIcons.animate().alpha(1f).setStartDelay(0).setDuration(300).
945 setListener(mMakeIconsVisible).start();
Daniel Sandler8e18dc72012-05-17 00:44:59 -0400946 }
947 }
Daniel Sandler6da2b762011-09-14 16:04:59 -0400948
Jeff Sharkeyf52c70b2011-08-30 22:05:47 -0700949 if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) {
950 boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0;
951 showClock(show);
952 }
Joe Onorato808182d2010-07-09 18:52:06 -0400953 if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
954 if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
Joe Onorato808182d2010-07-09 18:52:06 -0400955 animateCollapse();
956 }
957 }
Daniel Sandlere21f2882011-08-18 10:14:59 -0400958
Jim Miller5e6af442011-12-02 18:24:26 -0800959 if ((diff & (StatusBarManager.DISABLE_HOME
960 | StatusBarManager.DISABLE_RECENT
Daniel Sandlerdba93562011-10-06 16:39:58 -0400961 | StatusBarManager.DISABLE_BACK)) != 0) {
962 // the nav bar will take care of these
Daniel Sandlerd9283b902011-09-14 21:42:00 -0400963 if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state);
Daniel Sandler6da2b762011-09-14 16:04:59 -0400964
Daniel Sandlerdba93562011-10-06 16:39:58 -0400965 if ((state & StatusBarManager.DISABLE_RECENT) != 0) {
Daniel Sandler6da2b762011-09-14 16:04:59 -0400966 // close recents if it's visible
967 mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
968 mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
969 }
Daniel Sandlere21f2882011-08-18 10:14:59 -0400970 }
971
Joe Onorato808182d2010-07-09 18:52:06 -0400972 if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
973 if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
Joe Onorato808182d2010-07-09 18:52:06 -0400974 if (mTicking) {
975 mTicker.halt();
976 } else {
977 setNotificationIconVisibility(false, com.android.internal.R.anim.fade_out);
978 }
979 } else {
Joe Onorato808182d2010-07-09 18:52:06 -0400980 if (!mExpandedVisible) {
981 setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
982 }
983 }
984 } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
985 if (mTicking && (state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
Joe Onorato808182d2010-07-09 18:52:06 -0400986 mTicker.halt();
987 }
988 }
989 }
990
Michael Jurka7f2668c2012-03-27 07:49:52 -0700991 @Override
Michael Jurkaecc395a2012-03-30 05:31:46 -0700992 protected BaseStatusBar.H createHandler() {
Michael Jurka7f2668c2012-03-27 07:49:52 -0700993 return new PhoneStatusBar.H();
994 }
995
Joe Onorato808182d2010-07-09 18:52:06 -0400996 /**
997 * All changes to the status bar and notifications funnel through here and are batched.
998 */
Michael Jurka7f2668c2012-03-27 07:49:52 -0700999 private class H extends BaseStatusBar.H {
Joe Onorato808182d2010-07-09 18:52:06 -04001000 public void handleMessage(Message m) {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001001 super.handleMessage(m);
Joe Onorato808182d2010-07-09 18:52:06 -04001002 switch (m.what) {
Daniel Sandler8ba33c92011-10-04 21:49:30 -04001003 case MSG_OPEN_NOTIFICATION_PANEL:
1004 animateExpand();
1005 break;
1006 case MSG_CLOSE_NOTIFICATION_PANEL:
1007 animateCollapse();
1008 break;
Joe Onorato808182d2010-07-09 18:52:06 -04001009 case MSG_SHOW_INTRUDER:
1010 setIntruderAlertVisibility(true);
1011 break;
1012 case MSG_HIDE_INTRUDER:
1013 setIntruderAlertVisibility(false);
Daniel Sandlerfa7887b2012-03-26 09:43:31 -04001014 mCurrentlyIntrudingNotification = null;
Joe Onorato808182d2010-07-09 18:52:06 -04001015 break;
1016 }
1017 }
1018 }
1019
Jeff Browned5f45a2012-05-03 15:53:47 -07001020 final Runnable mAnimationCallback = new Runnable() {
1021 @Override
1022 public void run() {
1023 doAnimation(mChoreographer.getFrameTimeNanos());
1024 }
1025 };
1026
1027 final Runnable mRevealAnimationCallback = new Runnable() {
1028 @Override
1029 public void run() {
1030 doRevealAnimation(mChoreographer.getFrameTimeNanos());
1031 }
1032 };
1033
Joe Onorato808182d2010-07-09 18:52:06 -04001034 View.OnFocusChangeListener mFocusChangeListener = new View.OnFocusChangeListener() {
1035 public void onFocusChange(View v, boolean hasFocus) {
1036 // Because 'v' is a ViewGroup, all its children will be (un)selected
1037 // too, which allows marqueeing to work.
1038 v.setSelected(hasFocus);
1039 }
1040 };
1041
1042 private void makeExpandedVisible() {
1043 if (SPEW) Slog.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible);
1044 if (mExpandedVisible) {
1045 return;
1046 }
Jim Millera073e572012-05-23 17:03:27 -07001047
Joe Onorato808182d2010-07-09 18:52:06 -04001048 mExpandedVisible = true;
Daniel Sandler3ac558b2012-05-17 13:38:11 -04001049 mNotificationPanel.setVisibility(View.VISIBLE);
Jim Millerb490c3e2012-05-31 13:34:16 -07001050 makeSlippery(mNavigationBarView, true);
Joe Onorato808182d2010-07-09 18:52:06 -04001051
1052 updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
Daniel Sandlera310af82012-04-24 01:20:13 -04001053
1054 // Expand the window to encompass the full screen in anticipation of the drag.
1055 // This is only possible to do atomically because the status bar is at the top of the screen!
1056 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
Daniel Sandler4391b0b2012-05-10 13:15:26 -04001057 lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
1058 lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
Daniel Sandler21b274e2012-05-02 15:07:51 -04001059 lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
Daniel Sandlera310af82012-04-24 01:20:13 -04001060 final WindowManager wm = WindowManagerImpl.getDefault();
1061 wm.updateViewLayout(mStatusBarWindow, lp);
1062
1063 visibilityChanged(true);
Joe Onorato808182d2010-07-09 18:52:06 -04001064 }
1065
Jim Millerb490c3e2012-05-31 13:34:16 -07001066 private static void makeSlippery(View view, boolean slippery) {
Raph Levien311a9612012-06-01 12:02:13 -07001067 if (view == null) {
1068 return;
1069 }
Jim Millerb490c3e2012-05-31 13:34:16 -07001070 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) view.getLayoutParams();
1071 if (slippery) {
1072 lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY;
1073 } else {
1074 lp.flags &= ~WindowManager.LayoutParams.FLAG_SLIPPERY;
1075 }
1076 WindowManagerImpl.getDefault().updateViewLayout(view, lp);
1077 }
1078
Joe Onorato808182d2010-07-09 18:52:06 -04001079 public void animateExpand() {
1080 if (SPEW) Slog.d(TAG, "Animate expand: expanded=" + mExpanded);
1081 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
1082 return ;
1083 }
1084 if (mExpanded) {
1085 return;
1086 }
1087
1088 prepareTracking(0, true);
Daniel Sandlerdc940ea2011-08-25 14:35:53 -07001089 performFling(0, mSelfExpandVelocityPx, true);
Joe Onorato808182d2010-07-09 18:52:06 -04001090 }
1091
1092 public void animateCollapse() {
Jim Miller9a720f52012-05-30 03:19:43 -07001093 animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
Michael Jurka3b1fc472011-06-13 10:54:40 -07001094 }
1095
Jim Miller9a720f52012-05-30 03:19:43 -07001096 public void animateCollapse(int flags) {
1097 animateCollapse(flags, 1.0f);
Daniel Sandler8ba33c92011-10-04 21:49:30 -04001098 }
Jim Miller5e6af442011-12-02 18:24:26 -08001099
Jim Miller9a720f52012-05-30 03:19:43 -07001100 public void animateCollapse(int flags, float velocityMultiplier) {
Joe Onorato808182d2010-07-09 18:52:06 -04001101 if (SPEW) {
1102 Slog.d(TAG, "animateCollapse(): mExpanded=" + mExpanded
1103 + " mExpandedVisible=" + mExpandedVisible
1104 + " mExpanded=" + mExpanded
1105 + " mAnimating=" + mAnimating
1106 + " mAnimY=" + mAnimY
Jim Miller9a720f52012-05-30 03:19:43 -07001107 + " mAnimVel=" + mAnimVel
1108 + " flags=" + flags);
Joe Onorato808182d2010-07-09 18:52:06 -04001109 }
1110
Jim Miller9a720f52012-05-30 03:19:43 -07001111 if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) {
Michael Jurka3b1fc472011-06-13 10:54:40 -07001112 mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
1113 mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
1114 }
Jim Miller9a720f52012-05-30 03:19:43 -07001115
1116 if ((flags & CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL) == 0) {
1117 mHandler.removeMessages(MSG_CLOSE_SEARCH_PANEL);
1118 mHandler.sendEmptyMessage(MSG_CLOSE_SEARCH_PANEL);
1119 }
Michael Jurka3b1fc472011-06-13 10:54:40 -07001120
Joe Onorato808182d2010-07-09 18:52:06 -04001121 if (!mExpandedVisible) {
1122 return;
1123 }
1124
1125 int y;
1126 if (mAnimating) {
1127 y = (int)mAnimY;
1128 } else {
Daniel Sandler21b274e2012-05-02 15:07:51 -04001129 y = getExpandedViewMaxHeight()-1;
Joe Onorato808182d2010-07-09 18:52:06 -04001130 }
1131 // Let the fling think that we're open so it goes in the right direction
1132 // and doesn't try to re-open the windowshade.
1133 mExpanded = true;
1134 prepareTracking(y, false);
Daniel Sandler8ba33c92011-10-04 21:49:30 -04001135 performFling(y, -mSelfCollapseVelocityPx*velocityMultiplier, true);
Joe Onorato808182d2010-07-09 18:52:06 -04001136 }
1137
1138 void performExpand() {
1139 if (SPEW) Slog.d(TAG, "performExpand: mExpanded=" + mExpanded);
1140 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
1141 return ;
1142 }
1143 if (mExpanded) {
1144 return;
1145 }
1146
1147 mExpanded = true;
1148 makeExpandedVisible();
1149 updateExpandedViewPos(EXPANDED_FULL_OPEN);
1150
1151 if (false) postStartTracing();
1152 }
1153
1154 void performCollapse() {
1155 if (SPEW) Slog.d(TAG, "performCollapse: mExpanded=" + mExpanded
1156 + " mExpandedVisible=" + mExpandedVisible);
1157
1158 if (!mExpandedVisible) {
1159 return;
1160 }
1161 mExpandedVisible = false;
1162 visibilityChanged(false);
Daniel Sandler3ac558b2012-05-17 13:38:11 -04001163 mNotificationPanel.setVisibility(View.INVISIBLE);
Jim Millerb490c3e2012-05-31 13:34:16 -07001164 makeSlippery(mNavigationBarView, false);
Daniel Sandlera310af82012-04-24 01:20:13 -04001165
1166 // Shrink the window to the size of the status bar only
1167 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
1168 lp.height = getStatusBarHeight();
Daniel Sandler4391b0b2012-05-10 13:15:26 -04001169 lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
1170 lp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
Daniel Sandlera310af82012-04-24 01:20:13 -04001171 final WindowManager wm = WindowManagerImpl.getDefault();
1172 wm.updateViewLayout(mStatusBarWindow, lp);
Joe Onorato808182d2010-07-09 18:52:06 -04001173
1174 if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
1175 setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
1176 }
Joe Onorato808182d2010-07-09 18:52:06 -04001177
1178 if (!mExpanded) {
1179 return;
1180 }
1181 mExpanded = false;
Daniel Sandler469e96e2012-05-04 15:56:19 -04001182
1183 // Close any "App info" popups that might have snuck on-screen
1184 dismissPopups();
1185
Chet Haase2f2022a2011-10-11 06:41:59 -07001186 if (mPostCollapseCleanup != null) {
1187 mPostCollapseCleanup.run();
1188 mPostCollapseCleanup = null;
1189 }
Joe Onorato808182d2010-07-09 18:52:06 -04001190 }
1191
Daniel Sandlerfbab8ae2012-05-09 02:06:29 -04001192 void resetLastAnimTime() {
1193 mAnimLastTimeNanos = System.nanoTime();
1194 if (SPEW) {
1195 Throwable t = new Throwable();
1196 t.fillInStackTrace();
1197 Slog.d(TAG, "resetting last anim time=" + mAnimLastTimeNanos, t);
1198 }
1199 }
1200
Jeff Browned5f45a2012-05-03 15:53:47 -07001201 void doAnimation(long frameTimeNanos) {
Joe Onorato808182d2010-07-09 18:52:06 -04001202 if (mAnimating) {
Daniel Sandlerfbab8ae2012-05-09 02:06:29 -04001203 if (SPEW) Slog.d(TAG, "doAnimation dt=" + (frameTimeNanos - mAnimLastTimeNanos));
Joe Onorato808182d2010-07-09 18:52:06 -04001204 if (SPEW) Slog.d(TAG, "doAnimation before mAnimY=" + mAnimY);
Jeff Browned5f45a2012-05-03 15:53:47 -07001205 incrementAnim(frameTimeNanos);
Daniel Sandlerfbab8ae2012-05-09 02:06:29 -04001206 if (SPEW) {
1207 Slog.d(TAG, "doAnimation after mAnimY=" + mAnimY);
1208 Slog.d(TAG, "doAnimation expandedViewMax=" + getExpandedViewMaxHeight());
1209 }
Jeff Brown6098c1f2012-05-03 16:56:20 -07001210
Daniel Sandlerfbab8ae2012-05-09 02:06:29 -04001211 if (mAnimY >= getExpandedViewMaxHeight()-1 && !mClosing) {
Joe Onorato808182d2010-07-09 18:52:06 -04001212 if (SPEW) Slog.d(TAG, "Animation completed to expanded state.");
1213 mAnimating = false;
1214 updateExpandedViewPos(EXPANDED_FULL_OPEN);
1215 performExpand();
Jeff Brown6098c1f2012-05-03 16:56:20 -07001216 return;
Joe Onorato808182d2010-07-09 18:52:06 -04001217 }
Jeff Brown6098c1f2012-05-03 16:56:20 -07001218
Daniel Sandlerfbab8ae2012-05-09 02:06:29 -04001219 if (mAnimY == 0 && mAnimAccel == 0 && mClosing) {
Joe Onorato808182d2010-07-09 18:52:06 -04001220 if (SPEW) Slog.d(TAG, "Animation completed to collapsed state.");
1221 mAnimating = false;
Joe Onorato808182d2010-07-09 18:52:06 -04001222 performCollapse();
Jeff Brown6098c1f2012-05-03 16:56:20 -07001223 return;
Joe Onorato808182d2010-07-09 18:52:06 -04001224 }
Jeff Brown6098c1f2012-05-03 16:56:20 -07001225
Daniel Sandlerfbab8ae2012-05-09 02:06:29 -04001226 if (mAnimY < getStatusBarHeight() && mClosing) {
Jeff Brown6098c1f2012-05-03 16:56:20 -07001227 // Draw one more frame with the bar positioned at the top of the screen
1228 // before ending the animation so that the user sees the bar in
1229 // its final position. The call to performCollapse() causes a window
1230 // relayout which takes time and might cause the animation to skip
1231 // on the very last frame before the bar disappears if we did it now.
1232 mAnimY = 0;
1233 mAnimAccel = 0;
1234 mAnimVel = 0;
Joe Onorato808182d2010-07-09 18:52:06 -04001235 }
Jeff Brown6098c1f2012-05-03 16:56:20 -07001236
1237 updateExpandedViewPos((int)mAnimY);
1238 mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
1239 mAnimationCallback, null);
Joe Onorato808182d2010-07-09 18:52:06 -04001240 }
1241 }
1242
1243 void stopTracking() {
1244 mTracking = false;
Daniel Sandler079b33d2012-03-02 16:29:41 -05001245 mPile.setLayerType(View.LAYER_TYPE_NONE, null);
Joe Onorato808182d2010-07-09 18:52:06 -04001246 mVelocityTracker.recycle();
1247 mVelocityTracker = null;
Daniel Sandlerfc753d22012-05-08 13:56:44 -04001248 mCloseView.setPressed(false);
Joe Onorato808182d2010-07-09 18:52:06 -04001249 }
1250
Jeff Browned5f45a2012-05-03 15:53:47 -07001251 void incrementAnim(long frameTimeNanos) {
1252 final long deltaNanos = Math.max(frameTimeNanos - mAnimLastTimeNanos, 0);
1253 final float t = deltaNanos * 0.000000001f; // ns -> s
Joe Onorato808182d2010-07-09 18:52:06 -04001254 final float y = mAnimY;
1255 final float v = mAnimVel; // px/s
1256 final float a = mAnimAccel; // px/s/s
1257 mAnimY = y + (v*t) + (0.5f*a*t*t); // px
1258 mAnimVel = v + (a*t); // px/s
Jeff Browned5f45a2012-05-03 15:53:47 -07001259 mAnimLastTimeNanos = frameTimeNanos; // ns
Joe Onorato808182d2010-07-09 18:52:06 -04001260 //Slog.d(TAG, "y=" + y + " v=" + v + " a=" + a + " t=" + t + " mAnimY=" + mAnimY
1261 // + " mAnimAccel=" + mAnimAccel);
1262 }
Jim Millera073e572012-05-23 17:03:27 -07001263
Jeff Browned5f45a2012-05-03 15:53:47 -07001264 void doRevealAnimation(long frameTimeNanos) {
Daniel Sandlerfbab8ae2012-05-09 02:06:29 -04001265 if (SPEW) {
1266 Slog.d(TAG, "doRevealAnimation: dt=" + (frameTimeNanos - mAnimLastTimeNanos));
1267 }
Daniel Sandler1fac1fd2012-04-30 12:07:30 -04001268 final int h = getCloseViewHeight() + getStatusBarHeight();
Joe Onorato808182d2010-07-09 18:52:06 -04001269 if (mAnimatingReveal && mAnimating && mAnimY < h) {
Jeff Browned5f45a2012-05-03 15:53:47 -07001270 incrementAnim(frameTimeNanos);
Joe Onorato808182d2010-07-09 18:52:06 -04001271 if (mAnimY >= h) {
1272 mAnimY = h;
1273 updateExpandedViewPos((int)mAnimY);
1274 } else {
1275 updateExpandedViewPos((int)mAnimY);
Jeff Browned5f45a2012-05-03 15:53:47 -07001276 mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
1277 mRevealAnimationCallback, null);
Joe Onorato808182d2010-07-09 18:52:06 -04001278 }
1279 }
1280 }
1281
1282 void prepareTracking(int y, boolean opening) {
Daniel Sandler96e61c3c82011-08-04 22:49:06 -04001283 if (CHATTY) {
1284 Slog.d(TAG, "panel: beginning to track the user's touch, y=" + y + " opening=" + opening);
1285 }
1286
Daniel Sandlerfc753d22012-05-08 13:56:44 -04001287 mCloseView.setPressed(true);
1288
Joe Onorato808182d2010-07-09 18:52:06 -04001289 mTracking = true;
Daniel Sandler079b33d2012-03-02 16:29:41 -05001290 mPile.setLayerType(View.LAYER_TYPE_HARDWARE, null);
Joe Onorato808182d2010-07-09 18:52:06 -04001291 mVelocityTracker = VelocityTracker.obtain();
1292 if (opening) {
Daniel Sandlerdc940ea2011-08-25 14:35:53 -07001293 mAnimAccel = mExpandAccelPx;
1294 mAnimVel = mFlingExpandMinVelocityPx;
Daniel Sandlera310af82012-04-24 01:20:13 -04001295 mAnimY = getStatusBarHeight();
Joe Onorato808182d2010-07-09 18:52:06 -04001296 updateExpandedViewPos((int)mAnimY);
1297 mAnimating = true;
1298 mAnimatingReveal = true;
Daniel Sandlerfbab8ae2012-05-09 02:06:29 -04001299 resetLastAnimTime();
Jeff Browned5f45a2012-05-03 15:53:47 -07001300 mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
1301 mAnimationCallback, null);
1302 mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
1303 mRevealAnimationCallback, null);
1304 mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
1305 mRevealAnimationCallback, null);
Joe Onorato808182d2010-07-09 18:52:06 -04001306 makeExpandedVisible();
1307 } else {
1308 // it's open, close it?
1309 if (mAnimating) {
1310 mAnimating = false;
Jeff Browned5f45a2012-05-03 15:53:47 -07001311 mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
1312 mAnimationCallback, null);
Joe Onorato808182d2010-07-09 18:52:06 -04001313 }
1314 updateExpandedViewPos(y + mViewDelta);
1315 }
1316 }
1317
1318 void performFling(int y, float vel, boolean always) {
Daniel Sandler96e61c3c82011-08-04 22:49:06 -04001319 if (CHATTY) {
1320 Slog.d(TAG, "panel: will fling, y=" + y + " vel=" + vel);
1321 }
1322
Joe Onorato808182d2010-07-09 18:52:06 -04001323 mAnimatingReveal = false;
Joe Onorato808182d2010-07-09 18:52:06 -04001324
1325 mAnimY = y;
1326 mAnimVel = vel;
1327
1328 //Slog.d(TAG, "starting with mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel);
1329
1330 if (mExpanded) {
1331 if (!always && (
Daniel Sandlerdc940ea2011-08-25 14:35:53 -07001332 vel > mFlingCollapseMinVelocityPx
Daniel Sandler21b274e2012-05-02 15:07:51 -04001333 || (y > (getExpandedViewMaxHeight()*(1f-mCollapseMinDisplayFraction)) &&
Daniel Sandlerdc940ea2011-08-25 14:35:53 -07001334 vel > -mFlingExpandMinVelocityPx))) {
Joe Onorato808182d2010-07-09 18:52:06 -04001335 // We are expanded, but they didn't move sufficiently to cause
1336 // us to retract. Animate back to the expanded position.
Daniel Sandlerdc940ea2011-08-25 14:35:53 -07001337 mAnimAccel = mExpandAccelPx;
Joe Onorato808182d2010-07-09 18:52:06 -04001338 if (vel < 0) {
1339 mAnimVel = 0;
1340 }
1341 }
1342 else {
1343 // We are expanded and are now going to animate away.
Daniel Sandlerdc940ea2011-08-25 14:35:53 -07001344 mAnimAccel = -mCollapseAccelPx;
Joe Onorato808182d2010-07-09 18:52:06 -04001345 if (vel > 0) {
1346 mAnimVel = 0;
1347 }
1348 }
1349 } else {
1350 if (always || (
Daniel Sandlerdc940ea2011-08-25 14:35:53 -07001351 vel > mFlingExpandMinVelocityPx
Daniel Sandler21b274e2012-05-02 15:07:51 -04001352 || (y > (getExpandedViewMaxHeight()*(1f-mExpandMinDisplayFraction)) &&
Daniel Sandlerdc940ea2011-08-25 14:35:53 -07001353 vel > -mFlingCollapseMinVelocityPx))) {
Joe Onorato808182d2010-07-09 18:52:06 -04001354 // We are collapsed, and they moved enough to allow us to
1355 // expand. Animate in the notifications.
Daniel Sandlerdc940ea2011-08-25 14:35:53 -07001356 mAnimAccel = mExpandAccelPx;
Joe Onorato808182d2010-07-09 18:52:06 -04001357 if (vel < 0) {
1358 mAnimVel = 0;
1359 }
1360 }
1361 else {
1362 // We are collapsed, but they didn't move sufficiently to cause
1363 // us to retract. Animate back to the collapsed position.
Daniel Sandlerdc940ea2011-08-25 14:35:53 -07001364 mAnimAccel = -mCollapseAccelPx;
Joe Onorato808182d2010-07-09 18:52:06 -04001365 if (vel > 0) {
1366 mAnimVel = 0;
1367 }
1368 }
1369 }
1370 //Slog.d(TAG, "mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel
1371 // + " mAnimAccel=" + mAnimAccel);
1372
Daniel Sandlerfbab8ae2012-05-09 02:06:29 -04001373 resetLastAnimTime();
Joe Onorato808182d2010-07-09 18:52:06 -04001374 mAnimating = true;
Daniel Sandlerfbab8ae2012-05-09 02:06:29 -04001375 mClosing = mAnimAccel < 0;
Jeff Browned5f45a2012-05-03 15:53:47 -07001376
1377 mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
1378 mAnimationCallback, null);
1379 mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
1380 mRevealAnimationCallback, null);
1381 mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
1382 mAnimationCallback, null);
Joe Onorato808182d2010-07-09 18:52:06 -04001383 stopTracking();
1384 }
1385
1386 boolean interceptTouchEvent(MotionEvent event) {
1387 if (SPEW) {
1388 Slog.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled="
1389 + mDisabled);
Daniel Sandler96e61c3c82011-08-04 22:49:06 -04001390 } else if (CHATTY) {
Daniel Sandlerfe172cc2011-09-12 13:47:25 -04001391 if (event.getAction() != MotionEvent.ACTION_MOVE) {
Daniel Sandler96e61c3c82011-08-04 22:49:06 -04001392 Slog.d(TAG, String.format(
Daniel Sandlerfe172cc2011-09-12 13:47:25 -04001393 "panel: %s at (%f, %f) mDisabled=0x%08x",
1394 MotionEvent.actionToString(event.getAction()),
Daniel Sandler96e61c3c82011-08-04 22:49:06 -04001395 event.getRawX(), event.getRawY(), mDisabled));
1396 }
Joe Onorato808182d2010-07-09 18:52:06 -04001397 }
1398
1399 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
1400 return false;
1401 }
1402
Jeff Brown68ebcdf2011-09-12 14:12:17 -07001403 final int action = event.getAction();
Daniel Sandlera310af82012-04-24 01:20:13 -04001404 final int statusBarSize = getStatusBarHeight();
Joe Onorato808182d2010-07-09 18:52:06 -04001405 final int hitSize = statusBarSize*2;
Daniel Sandlerfe172cc2011-09-12 13:47:25 -04001406 final int y = (int)event.getRawY();
Jeff Brown68ebcdf2011-09-12 14:12:17 -07001407 if (action == MotionEvent.ACTION_DOWN) {
Daniel Sandlerd7e96862012-04-26 01:10:29 -04001408 if (!areLightsOn()) {
1409 setLightsOn(true);
1410 }
1411
Joe Onorato808182d2010-07-09 18:52:06 -04001412 if (!mExpanded) {
1413 mViewDelta = statusBarSize - y;
1414 } else {
Daniel Sandlerfc753d22012-05-08 13:56:44 -04001415 mCloseView.getLocationOnScreen(mAbsPos);
1416 mViewDelta = mAbsPos[1] + statusBarSize + getCloseViewHeight() - y; // XXX: not closeViewHeight, but paddingBottom from the 9patch
Joe Onorato808182d2010-07-09 18:52:06 -04001417 }
1418 if ((!mExpanded && y < hitSize) ||
Daniel Sandler21b274e2012-05-02 15:07:51 -04001419 // @@ add taps outside the panel if it's not full-screen
1420 (mExpanded && y > (getExpandedViewMaxHeight()-hitSize))) {
Joe Onorato808182d2010-07-09 18:52:06 -04001421
1422 // We drop events at the edge of the screen to make the windowshade come
1423 // down by accident less, especially when pushing open a device with a keyboard
1424 // that rotates (like g1 and droid)
1425 int x = (int)event.getRawX();
1426 final int edgeBorder = mEdgeBorder;
Daniel Sandler36412a72011-08-04 09:35:13 -04001427 if (x >= edgeBorder && x < mDisplayMetrics.widthPixels - edgeBorder) {
Joe Onorato808182d2010-07-09 18:52:06 -04001428 prepareTracking(y, !mExpanded);// opening if we're not already fully visible
Jeff Brown911fe302011-09-12 14:21:17 -07001429 trackMovement(event);
Joe Onorato808182d2010-07-09 18:52:06 -04001430 }
1431 }
1432 } else if (mTracking) {
Jeff Brown911fe302011-09-12 14:21:17 -07001433 trackMovement(event);
Daniel Sandler1fac1fd2012-04-30 12:07:30 -04001434 final int minY = statusBarSize + getCloseViewHeight();
Jeff Brown68ebcdf2011-09-12 14:12:17 -07001435 if (action == MotionEvent.ACTION_MOVE) {
Daniel Sandler1fac1fd2012-04-30 12:07:30 -04001436 if (mAnimatingReveal && (y + mViewDelta) < minY) {
Joe Onorato808182d2010-07-09 18:52:06 -04001437 // nothing
1438 } else {
1439 mAnimatingReveal = false;
1440 updateExpandedViewPos(y + mViewDelta);
1441 }
Jeff Brown68ebcdf2011-09-12 14:12:17 -07001442 } else if (action == MotionEvent.ACTION_UP
1443 || action == MotionEvent.ACTION_CANCEL) {
Joe Onorato808182d2010-07-09 18:52:06 -04001444 mVelocityTracker.computeCurrentVelocity(1000);
1445
1446 float yVel = mVelocityTracker.getYVelocity();
1447 boolean negative = yVel < 0;
1448
1449 float xVel = mVelocityTracker.getXVelocity();
1450 if (xVel < 0) {
1451 xVel = -xVel;
1452 }
Daniel Sandlerdc940ea2011-08-25 14:35:53 -07001453 if (xVel > mFlingGestureMaxXVelocityPx) {
1454 xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
Joe Onorato808182d2010-07-09 18:52:06 -04001455 }
1456
1457 float vel = (float)Math.hypot(yVel, xVel);
1458 if (negative) {
1459 vel = -vel;
1460 }
1461
Daniel Sandlerdc940ea2011-08-25 14:35:53 -07001462 if (CHATTY) {
Jim Miller5e6af442011-12-02 18:24:26 -08001463 Slog.d(TAG, String.format("gesture: vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f",
1464 mVelocityTracker.getXVelocity(),
Daniel Sandlerdc940ea2011-08-25 14:35:53 -07001465 mVelocityTracker.getYVelocity(),
1466 xVel, yVel,
1467 vel));
1468 }
1469
Daniel Sandlerfe172cc2011-09-12 13:47:25 -04001470 performFling(y + mViewDelta, vel, false);
Joe Onorato808182d2010-07-09 18:52:06 -04001471 }
1472
1473 }
1474 return false;
1475 }
1476
Jeff Brown911fe302011-09-12 14:21:17 -07001477 private void trackMovement(MotionEvent event) {
1478 // Add movement to velocity tracker using raw screen X and Y coordinates instead
1479 // of window coordinates because the window frame may be moving at the same time.
1480 float deltaX = event.getRawX() - event.getX();
1481 float deltaY = event.getRawY() - event.getY();
1482 event.offsetLocation(deltaX, deltaY);
1483 mVelocityTracker.addMovement(event);
1484 event.offsetLocation(-deltaX, -deltaY);
1485 }
1486
Daniel Sandler60ee2562011-07-22 12:34:33 -04001487 @Override // CommandQueue
Daniel Sandler328310c2011-09-23 15:56:52 -04001488 public void setNavigationIconHints(int hints) {
1489 if (hints == mNavigationIconHints) return;
1490
1491 mNavigationIconHints = hints;
1492
1493 if (mNavigationBarView != null) {
1494 mNavigationBarView.setNavigationIconHints(hints);
1495 }
1496 }
1497
1498 @Override // CommandQueue
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001499 public void setSystemUiVisibility(int vis, int mask) {
1500 final int oldVal = mSystemUiVisibility;
1501 final int newVal = (oldVal&~mask) | (vis&mask);
1502 final int diff = newVal ^ oldVal;
Daniel Sandlere137a1e2011-08-17 16:47:19 -04001503
1504 if (diff != 0) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001505 mSystemUiVisibility = newVal;
Daniel Sandler60ee2562011-07-22 12:34:33 -04001506
Daniel Sandlere137a1e2011-08-17 16:47:19 -04001507 if (0 != (diff & View.SYSTEM_UI_FLAG_LOW_PROFILE)) {
1508 final boolean lightsOut = (0 != (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE));
1509 if (lightsOut) {
1510 animateCollapse();
Daniel Sandlerd7e96862012-04-26 01:10:29 -04001511 if (mTicking) {
1512 mTicker.halt();
1513 }
Daniel Sandlere137a1e2011-08-17 16:47:19 -04001514 }
Jim Millera073e572012-05-23 17:03:27 -07001515
Daniel Sandler69314e72011-08-20 00:31:08 -04001516 if (mNavigationBarView != null) {
1517 mNavigationBarView.setLowProfile(lightsOut);
1518 }
Jim Millera073e572012-05-23 17:03:27 -07001519
Daniel Sandlerd7e96862012-04-26 01:10:29 -04001520 setStatusBarLowProfile(lightsOut);
Daniel Sandler60ee2562011-07-22 12:34:33 -04001521 }
1522
1523 notifyUiVisibilityChanged();
Joe Onorato93056472010-09-10 10:30:46 -04001524 }
Daniel Sandler1d4d30a2011-04-28 12:35:29 -04001525 }
1526
Daniel Sandlerd7e96862012-04-26 01:10:29 -04001527 private void setStatusBarLowProfile(boolean lightsOut) {
1528 if (mLightsOutAnimation == null) {
1529 final View notifications = mStatusBarView.findViewById(R.id.notification_icon_area);
1530 final View systemIcons = mStatusBarView.findViewById(R.id.statusIcons);
1531 final View signal = mStatusBarView.findViewById(R.id.signal_cluster);
1532 final View battery = mStatusBarView.findViewById(R.id.battery);
1533 final View clock = mStatusBarView.findViewById(R.id.clock);
1534
1535 mLightsOutAnimation = new AnimatorSet();
1536 mLightsOutAnimation.playTogether(
1537 ObjectAnimator.ofFloat(notifications, View.ALPHA, 0),
1538 ObjectAnimator.ofFloat(systemIcons, View.ALPHA, 0),
1539 ObjectAnimator.ofFloat(signal, View.ALPHA, 0),
1540 ObjectAnimator.ofFloat(battery, View.ALPHA, 0.5f),
1541 ObjectAnimator.ofFloat(clock, View.ALPHA, 0.5f)
1542 );
1543 mLightsOutAnimation.setDuration(750);
Jim Millera073e572012-05-23 17:03:27 -07001544
Daniel Sandlerd7e96862012-04-26 01:10:29 -04001545 mLightsOnAnimation = new AnimatorSet();
1546 mLightsOnAnimation.playTogether(
1547 ObjectAnimator.ofFloat(notifications, View.ALPHA, 1),
1548 ObjectAnimator.ofFloat(systemIcons, View.ALPHA, 1),
1549 ObjectAnimator.ofFloat(signal, View.ALPHA, 1),
1550 ObjectAnimator.ofFloat(battery, View.ALPHA, 1),
1551 ObjectAnimator.ofFloat(clock, View.ALPHA, 1)
1552 );
1553 mLightsOnAnimation.setDuration(250);
1554 }
Jim Millera073e572012-05-23 17:03:27 -07001555
Daniel Sandlerd7e96862012-04-26 01:10:29 -04001556 mLightsOutAnimation.cancel();
1557 mLightsOnAnimation.cancel();
1558
1559 final Animator a = lightsOut ? mLightsOutAnimation : mLightsOnAnimation;
1560 a.start();
1561
1562 setAreThereNotifications();
1563 }
1564
1565 private boolean areLightsOn() {
1566 return 0 == (mSystemUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE);
1567 }
Jim Millera073e572012-05-23 17:03:27 -07001568
Daniel Sandler60ee2562011-07-22 12:34:33 -04001569 public void setLightsOn(boolean on) {
1570 Log.v(TAG, "setLightsOn(" + on + ")");
1571 if (on) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001572 setSystemUiVisibility(0, View.SYSTEM_UI_FLAG_LOW_PROFILE);
Daniel Sandler60ee2562011-07-22 12:34:33 -04001573 } else {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07001574 setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE, View.SYSTEM_UI_FLAG_LOW_PROFILE);
Daniel Sandler60ee2562011-07-22 12:34:33 -04001575 }
1576 }
1577
1578 private void notifyUiVisibilityChanged() {
Daniel Sandler1d4d30a2011-04-28 12:35:29 -04001579 try {
Daniel Sandler60ee2562011-07-22 12:34:33 -04001580 mWindowManager.statusBarVisibilityChanged(mSystemUiVisibility);
Daniel Sandler1d4d30a2011-04-28 12:35:29 -04001581 } catch (RemoteException ex) {
1582 }
Joe Onorato93056472010-09-10 10:30:46 -04001583 }
1584
Daniel Sandler5c8da942011-06-28 00:29:04 -04001585 public void topAppWindowChanged(boolean showMenu) {
1586 if (DEBUG) {
1587 Slog.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
1588 }
1589 if (mNavigationBarView != null) {
Daniel Sandlerf1ebcee2011-09-15 16:02:56 -04001590 mNavigationBarView.setMenuVisibility(showMenu);
Daniel Sandler5c8da942011-06-28 00:29:04 -04001591 }
1592
1593 // See above re: lights-out policy for legacy apps.
1594 if (showMenu) setLightsOn(true);
1595 }
1596
Daniel Sandler328310c2011-09-23 15:56:52 -04001597 @Override
1598 public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
1599 boolean altBack = (backDisposition == InputMethodService.BACK_DISPOSITION_WILL_DISMISS)
1600 || ((vis & InputMethodService.IME_VISIBLE) != 0);
1601
1602 mCommandQueue.setNavigationIconHints(
1603 altBack ? (mNavigationIconHints | StatusBarManager.NAVIGATION_HINT_BACK_ALT)
1604 : (mNavigationIconHints & ~StatusBarManager.NAVIGATION_HINT_BACK_ALT));
1605 }
1606
Jeff Brown2992ea72011-01-28 22:04:14 -08001607 @Override
1608 public void setHardKeyboardStatus(boolean available, boolean enabled) { }
Daniel Sandlere02d8082010-10-08 15:13:22 -04001609
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04001610 private class NotificationClicker implements View.OnClickListener {
Joe Onorato808182d2010-07-09 18:52:06 -04001611 private PendingIntent mIntent;
1612 private String mPkg;
1613 private String mTag;
1614 private int mId;
1615
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04001616 NotificationClicker(PendingIntent intent, String pkg, String tag, int id) {
Joe Onorato808182d2010-07-09 18:52:06 -04001617 mIntent = intent;
1618 mPkg = pkg;
1619 mTag = tag;
1620 mId = id;
1621 }
1622
1623 public void onClick(View v) {
1624 try {
1625 // The intent we are sending is for the application, which
1626 // won't have permission to immediately start an activity after
1627 // the user switches to home. We know it is safe to do at this
1628 // point, so make sure new activity switches are now allowed.
1629 ActivityManagerNative.getDefault().resumeAppSwitches();
Dianne Hackborn90c52de2011-09-23 12:57:44 -07001630 // Also, notifications can be launched from the lock screen,
1631 // so dismiss the lock screen when the activity starts.
1632 ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
Joe Onorato808182d2010-07-09 18:52:06 -04001633 } catch (RemoteException e) {
1634 }
1635
1636 if (mIntent != null) {
1637 int[] pos = new int[2];
1638 v.getLocationOnScreen(pos);
1639 Intent overlay = new Intent();
1640 overlay.setSourceBounds(
1641 new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
1642 try {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001643 mIntent.send(mContext, 0, overlay);
Joe Onorato808182d2010-07-09 18:52:06 -04001644 } catch (PendingIntent.CanceledException e) {
1645 // the stack trace isn't very helpful here. Just log the exception message.
1646 Slog.w(TAG, "Sending contentIntent failed: " + e);
1647 }
Daniel Sandler92d33182011-09-11 16:29:05 -04001648
1649 KeyguardManager kgm =
1650 (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
1651 if (kgm != null) kgm.exitKeyguardSecurely(null);
Joe Onorato808182d2010-07-09 18:52:06 -04001652 }
1653
1654 try {
1655 mBarService.onNotificationClick(mPkg, mTag, mId);
1656 } catch (RemoteException ex) {
1657 // system process is dead if we're here.
1658 }
1659
1660 // close the shade if it was open
1661 animateCollapse();
1662
1663 // If this click was on the intruder alert, hide that instead
1664 mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
1665 }
1666 }
1667
Chris Wren0c8275b2012-05-08 13:36:48 -04001668 @Override
1669 protected void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
Daniel Sandlerd7e96862012-04-26 01:10:29 -04001670 // no ticking in lights-out mode
1671 if (!areLightsOn()) return;
Jim Millera073e572012-05-23 17:03:27 -07001672
Daniel Sandler26cda272012-05-22 15:44:08 -04001673 // no ticking in Setup
1674 if (!isDeviceProvisioned()) return;
1675
Joe Onorato808182d2010-07-09 18:52:06 -04001676 // Show the ticker if one is requested. Also don't do this
1677 // until status bar window is attached to the window manager,
1678 // because... well, what's the point otherwise? And trying to
1679 // run a ticker without being attached will crash!
Daniel Sandlera310af82012-04-24 01:20:13 -04001680 if (n.notification.tickerText != null && mStatusBarWindow.getWindowToken() != null) {
Joe Onorato808182d2010-07-09 18:52:06 -04001681 if (0 == (mDisabled & (StatusBarManager.DISABLE_NOTIFICATION_ICONS
1682 | StatusBarManager.DISABLE_NOTIFICATION_TICKER))) {
1683 mTicker.addEntry(n);
1684 }
1685 }
1686 }
1687
Joe Onorato808182d2010-07-09 18:52:06 -04001688 private class MyTicker extends Ticker {
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001689 MyTicker(Context context, View sb) {
Joe Onorato808182d2010-07-09 18:52:06 -04001690 super(context, sb);
1691 }
1692
1693 @Override
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001694 public void tickerStarting() {
Joe Onorato808182d2010-07-09 18:52:06 -04001695 mTicking = true;
1696 mIcons.setVisibility(View.GONE);
1697 mTickerView.setVisibility(View.VISIBLE);
1698 mTickerView.startAnimation(loadAnim(com.android.internal.R.anim.push_up_in, null));
1699 mIcons.startAnimation(loadAnim(com.android.internal.R.anim.push_up_out, null));
Joe Onorato808182d2010-07-09 18:52:06 -04001700 }
1701
1702 @Override
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001703 public void tickerDone() {
Joe Onorato808182d2010-07-09 18:52:06 -04001704 mIcons.setVisibility(View.VISIBLE);
1705 mTickerView.setVisibility(View.GONE);
1706 mIcons.startAnimation(loadAnim(com.android.internal.R.anim.push_down_in, null));
1707 mTickerView.startAnimation(loadAnim(com.android.internal.R.anim.push_down_out,
1708 mTickingDoneListener));
Joe Onorato808182d2010-07-09 18:52:06 -04001709 }
1710
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001711 public void tickerHalting() {
Joe Onorato808182d2010-07-09 18:52:06 -04001712 mIcons.setVisibility(View.VISIBLE);
1713 mTickerView.setVisibility(View.GONE);
1714 mIcons.startAnimation(loadAnim(com.android.internal.R.anim.fade_in, null));
1715 mTickerView.startAnimation(loadAnim(com.android.internal.R.anim.fade_out,
1716 mTickingDoneListener));
Joe Onorato808182d2010-07-09 18:52:06 -04001717 }
1718 }
1719
1720 Animation.AnimationListener mTickingDoneListener = new Animation.AnimationListener() {;
1721 public void onAnimationEnd(Animation animation) {
1722 mTicking = false;
1723 }
1724 public void onAnimationRepeat(Animation animation) {
1725 }
1726 public void onAnimationStart(Animation animation) {
1727 }
1728 };
1729
1730 private Animation loadAnim(int id, Animation.AnimationListener listener) {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001731 Animation anim = AnimationUtils.loadAnimation(mContext, id);
Joe Onorato808182d2010-07-09 18:52:06 -04001732 if (listener != null) {
1733 anim.setAnimationListener(listener);
1734 }
1735 return anim;
1736 }
1737
Daniel Sandler48852952011-12-01 14:34:23 -05001738 public static String viewInfo(View v) {
1739 return "[(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom()
1740 + ") " + v.getWidth() + "x" + v.getHeight() + "]";
Joe Onorato808182d2010-07-09 18:52:06 -04001741 }
1742
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001743 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Joe Onorato808182d2010-07-09 18:52:06 -04001744 synchronized (mQueueLock) {
1745 pw.println("Current Status Bar state:");
1746 pw.println(" mExpanded=" + mExpanded
1747 + ", mExpandedVisible=" + mExpandedVisible);
1748 pw.println(" mTicking=" + mTicking);
1749 pw.println(" mTracking=" + mTracking);
1750 pw.println(" mAnimating=" + mAnimating
1751 + ", mAnimY=" + mAnimY + ", mAnimVel=" + mAnimVel
1752 + ", mAnimAccel=" + mAnimAccel);
Jeff Browned5f45a2012-05-03 15:53:47 -07001753 pw.println(" mAnimLastTimeNanos=" + mAnimLastTimeNanos);
Dianne Hackborn1dacf272011-08-02 15:01:22 -07001754 pw.println(" mAnimatingReveal=" + mAnimatingReveal
Joe Onorato808182d2010-07-09 18:52:06 -04001755 + " mViewDelta=" + mViewDelta);
Daniel Sandler36412a72011-08-04 09:35:13 -04001756 pw.println(" mDisplayMetrics=" + mDisplayMetrics);
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04001757 pw.println(" mPile: " + viewInfo(mPile));
Joe Onorato808182d2010-07-09 18:52:06 -04001758 pw.println(" mCloseView: " + viewInfo(mCloseView));
1759 pw.println(" mTickerView: " + viewInfo(mTickerView));
1760 pw.println(" mScrollView: " + viewInfo(mScrollView)
1761 + " scroll " + mScrollView.getScrollX() + "," + mScrollView.getScrollY());
Joe Onorato808182d2010-07-09 18:52:06 -04001762 }
Joe Onorato808182d2010-07-09 18:52:06 -04001763
Daniel Sandler48852952011-12-01 14:34:23 -05001764 pw.print(" mNavigationBarView=");
1765 if (mNavigationBarView == null) {
1766 pw.println("null");
1767 } else {
1768 mNavigationBarView.dump(fd, pw, args);
1769 }
1770
Daniel Sandler7579bca2011-08-18 15:47:26 -04001771 if (DUMPTRUCK) {
1772 synchronized (mNotificationData) {
1773 int N = mNotificationData.size();
1774 pw.println(" notification icons: " + N);
1775 for (int i=0; i<N; i++) {
1776 NotificationData.Entry e = mNotificationData.get(i);
1777 pw.println(" [" + i + "] key=" + e.key + " icon=" + e.icon);
1778 StatusBarNotification n = e.notification;
Daniel Sandler2561b0b2012-02-13 21:04:12 -05001779 pw.println(" pkg=" + n.pkg + " id=" + n.id + " score=" + n.score);
Daniel Sandler7579bca2011-08-18 15:47:26 -04001780 pw.println(" notification=" + n.notification);
1781 pw.println(" tickerText=\"" + n.notification.tickerText + "\"");
1782 }
1783 }
1784
1785 int N = mStatusIcons.getChildCount();
1786 pw.println(" system icons: " + N);
1787 for (int i=0; i<N; i++) {
1788 StatusBarIconView ic = (StatusBarIconView) mStatusIcons.getChildAt(i);
1789 pw.println(" [" + i + "] icon=" + ic);
1790 }
Jim Miller5e6af442011-12-02 18:24:26 -08001791
Daniel Sandler89d97132011-09-08 15:31:57 -04001792 if (false) {
1793 pw.println("see the logcat for a dump of the views we have created.");
1794 // must happen on ui thread
1795 mHandler.post(new Runnable() {
1796 public void run() {
1797 mStatusBarView.getLocationOnScreen(mAbsPos);
1798 Slog.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
1799 + ") " + mStatusBarView.getWidth() + "x"
Daniel Sandlera310af82012-04-24 01:20:13 -04001800 + getStatusBarHeight());
Daniel Sandler89d97132011-09-08 15:31:57 -04001801 mStatusBarView.debug();
Daniel Sandler89d97132011-09-08 15:31:57 -04001802 }
1803 });
1804 }
Joe Onorato808182d2010-07-09 18:52:06 -04001805 }
Daniel Sandler89d97132011-09-08 15:31:57 -04001806
1807 mNetworkController.dump(fd, pw, args);
Joe Onorato808182d2010-07-09 18:52:06 -04001808 }
1809
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -05001810 @Override
1811 public void createAndAddWindows() {
1812 addStatusBarWindow();
Joe Onorato808182d2010-07-09 18:52:06 -04001813 }
Jim Millere898ac52012-04-06 17:10:57 -07001814
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -05001815 private void addStatusBarWindow() {
1816 // Put up the view
1817 final int height = getStatusBarHeight();
Joe Onorato808182d2010-07-09 18:52:06 -04001818
Daniel Sandlera310af82012-04-24 01:20:13 -04001819 // Now that the status bar window encompasses the sliding panel and its
1820 // translucent backdrop, the entire thing is made TRANSLUCENT and is
1821 // hardware-accelerated.
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -05001822 final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
1823 ViewGroup.LayoutParams.MATCH_PARENT,
1824 height,
1825 WindowManager.LayoutParams.TYPE_STATUS_BAR,
1826 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
1827 | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
1828 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
Daniel Sandlera310af82012-04-24 01:20:13 -04001829 PixelFormat.TRANSLUCENT);
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -05001830
Daniel Sandlera310af82012-04-24 01:20:13 -04001831 if (ActivityManager.isHighEndGfx(mDisplay)) {
1832 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
1833 }
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -05001834
1835 lp.gravity = getStatusBarGravity();
1836 lp.setTitle("StatusBar");
1837 lp.packageName = mContext.getPackageName();
Jim Millere898ac52012-04-06 17:10:57 -07001838
Daniel Sandlera310af82012-04-24 01:20:13 -04001839 makeStatusBarView();
1840 WindowManagerImpl.getDefault().addView(mStatusBarWindow, lp);
Joe Onorato808182d2010-07-09 18:52:06 -04001841 }
1842
Joe Onorato808182d2010-07-09 18:52:06 -04001843 void setNotificationIconVisibility(boolean visible, int anim) {
1844 int old = mNotificationIcons.getVisibility();
1845 int v = visible ? View.VISIBLE : View.INVISIBLE;
1846 if (old != v) {
1847 mNotificationIcons.setVisibility(v);
1848 mNotificationIcons.startAnimation(loadAnim(anim, null));
1849 }
1850 }
1851
Dianne Hackborn1dacf272011-08-02 15:01:22 -07001852 void updateExpandedInvisiblePosition() {
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -05001853 mTrackingPosition = -mDisplayMetrics.heightPixels;
Dianne Hackborn1dacf272011-08-02 15:01:22 -07001854 }
1855
Daniel Sandler1fac1fd2012-04-30 12:07:30 -04001856 static final float saturate(float a) {
1857 return a < 0f ? 0f : (a > 1f ? 1f : a);
1858 }
1859
Chris Wren8fd12652012-05-09 21:25:57 -04001860 @Override
1861 protected int getExpandedViewMaxHeight() {
Daniel Sandler21b274e2012-05-02 15:07:51 -04001862 return mDisplayMetrics.heightPixels - mNotificationPanelMarginBottomPx;
1863 }
1864
Chris Wren0c8275b2012-05-08 13:36:48 -04001865 @Override
1866 protected void updateExpandedViewPos(int expandedPosition) {
Joe Onorato808182d2010-07-09 18:52:06 -04001867 if (SPEW) {
1868 Slog.d(TAG, "updateExpandedViewPos before expandedPosition=" + expandedPosition
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -05001869 //+ " mTrackingParams.y=" + ((mTrackingParams == null) ? "?" : mTrackingParams.y)
Daniel Sandler21b274e2012-05-02 15:07:51 -04001870 + " mTrackingPosition=" + mTrackingPosition
1871 + " gravity=" + mNotificationPanelGravity);
Joe Onorato808182d2010-07-09 18:52:06 -04001872 }
1873
Daniel Sandler079b33d2012-03-02 16:29:41 -05001874 int panelh = 0;
Daniel Sandler21b274e2012-05-02 15:07:51 -04001875 final int disph = getExpandedViewMaxHeight();
Joe Onorato808182d2010-07-09 18:52:06 -04001876
1877 // If the expanded view is not visible, make sure they're still off screen.
1878 // Maybe the view was resized.
1879 if (!mExpandedVisible) {
Dianne Hackborn1dacf272011-08-02 15:01:22 -07001880 updateExpandedInvisiblePosition();
Joe Onorato808182d2010-07-09 18:52:06 -04001881 return;
1882 }
1883
1884 // tracking view...
1885 int pos;
1886 if (expandedPosition == EXPANDED_FULL_OPEN) {
Daniel Sandler079b33d2012-03-02 16:29:41 -05001887 panelh = disph;
Joe Onorato808182d2010-07-09 18:52:06 -04001888 }
1889 else if (expandedPosition == EXPANDED_LEAVE_ALONE) {
Daniel Sandler079b33d2012-03-02 16:29:41 -05001890 panelh = mTrackingPosition;
Joe Onorato808182d2010-07-09 18:52:06 -04001891 }
1892 else {
1893 if (expandedPosition <= disph) {
Daniel Sandler079b33d2012-03-02 16:29:41 -05001894 panelh = expandedPosition;
Joe Onorato808182d2010-07-09 18:52:06 -04001895 } else {
Daniel Sandler079b33d2012-03-02 16:29:41 -05001896 panelh = disph;
Joe Onorato808182d2010-07-09 18:52:06 -04001897 }
Joe Onorato808182d2010-07-09 18:52:06 -04001898 }
Jim Millere898ac52012-04-06 17:10:57 -07001899
Daniel Sandler079b33d2012-03-02 16:29:41 -05001900 // catch orientation changes and other peculiar cases
Daniel Sandlera310af82012-04-24 01:20:13 -04001901 if (panelh > disph || (panelh < disph && !mTracking && !mAnimating)) {
Daniel Sandler079b33d2012-03-02 16:29:41 -05001902 panelh = disph;
Daniel Sandlera310af82012-04-24 01:20:13 -04001903 } else if (panelh < 0) {
1904 panelh = 0;
1905 }
Jim Millere898ac52012-04-06 17:10:57 -07001906
Daniel Sandler079b33d2012-03-02 16:29:41 -05001907 mTrackingPosition = panelh;
Daniel Sandlera310af82012-04-24 01:20:13 -04001908
Daniel Sandler21b274e2012-05-02 15:07:51 -04001909 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mNotificationPanel.getLayoutParams();
Daniel Sandler079b33d2012-03-02 16:29:41 -05001910 lp.height = panelh;
Daniel Sandler21b274e2012-05-02 15:07:51 -04001911 lp.gravity = mNotificationPanelGravity;
1912 lp.leftMargin = mNotificationPanelMarginLeftPx;
Daniel Sandlera310af82012-04-24 01:20:13 -04001913 if (SPEW) {
Daniel Sandler21b274e2012-05-02 15:07:51 -04001914 Slog.v(TAG, "updated cropView height=" + panelh + " grav=" + lp.gravity);
Daniel Sandlera310af82012-04-24 01:20:13 -04001915 }
Daniel Sandler21b274e2012-05-02 15:07:51 -04001916 mNotificationPanel.setLayoutParams(lp);
Romain Guy328b3582012-05-08 15:30:57 -07001917
Daniel Sandlerfc753d22012-05-08 13:56:44 -04001918 if (DIM_BEHIND_EXPANDED_PANEL && ActivityManager.isHighEndGfx(mDisplay)) {
Romain Guy328b3582012-05-08 15:30:57 -07001919 // woo, special effects
1920 final int barh = getCloseViewHeight() + getStatusBarHeight();
1921 final float frac = saturate((float)(panelh - barh) / (disph - barh));
1922 final int color = ((int)(0xB0 * Math.sin(frac * 1.57f))) << 24;
1923 mStatusBarWindow.setBackgroundColor(color);
1924 }
Joe Onorato808182d2010-07-09 18:52:06 -04001925 }
1926
Dianne Hackborn1dacf272011-08-02 15:01:22 -07001927 void updateDisplaySize() {
Daniel Sandler36412a72011-08-04 09:35:13 -04001928 mDisplay.getMetrics(mDisplayMetrics);
Dianne Hackborn1dacf272011-08-02 15:01:22 -07001929 }
1930
Joe Onorato808182d2010-07-09 18:52:06 -04001931 void performDisableActions(int net) {
1932 int old = mDisabled;
1933 int diff = net ^ old;
1934 mDisabled = net;
1935
1936 // act accordingly
1937 if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
1938 if ((net & StatusBarManager.DISABLE_EXPAND) != 0) {
1939 Slog.d(TAG, "DISABLE_EXPAND: yes");
1940 animateCollapse();
1941 }
1942 }
1943 if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
1944 if ((net & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
1945 Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
1946 if (mTicking) {
1947 mNotificationIcons.setVisibility(View.INVISIBLE);
1948 mTicker.halt();
1949 } else {
1950 setNotificationIconVisibility(false, com.android.internal.R.anim.fade_out);
1951 }
1952 } else {
1953 Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: no");
1954 if (!mExpandedVisible) {
1955 setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
1956 }
1957 }
1958 } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
1959 if (mTicking && (net & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
1960 mTicker.halt();
1961 }
1962 }
1963 }
1964
1965 private View.OnClickListener mClearButtonListener = new View.OnClickListener() {
Daniel Sandler8ba33c92011-10-04 21:49:30 -04001966 final int mini(int a, int b) {
1967 return (b>a?a:b);
1968 }
Joe Onorato808182d2010-07-09 18:52:06 -04001969 public void onClick(View v) {
Daniel Sandler8ba33c92011-10-04 21:49:30 -04001970 synchronized (mNotificationData) {
Chet Haase2f2022a2011-10-11 06:41:59 -07001971 // animate-swipe all dismissable notifications, then animate the shade closed
1972 int numChildren = mPile.getChildCount();
Daniel Sandler8ba33c92011-10-04 21:49:30 -04001973
Chet Haase2f2022a2011-10-11 06:41:59 -07001974 int scrollTop = mScrollView.getScrollY();
1975 int scrollBottom = scrollTop + mScrollView.getHeight();
1976 final ArrayList<View> snapshot = new ArrayList<View>(numChildren);
1977 for (int i=0; i<numChildren; i++) {
Daniel Sandler8ba33c92011-10-04 21:49:30 -04001978 final View child = mPile.getChildAt(i);
Chet Haase2f2022a2011-10-11 06:41:59 -07001979 if (mPile.canChildBeDismissed(child) && child.getBottom() > scrollTop &&
1980 child.getTop() < scrollBottom) {
1981 snapshot.add(child);
1982 }
Daniel Sandler8ba33c92011-10-04 21:49:30 -04001983 }
Craig Mautner93a035c2012-04-09 15:23:59 -07001984 if (snapshot.isEmpty()) {
Jim Miller9a720f52012-05-30 03:19:43 -07001985 animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
Craig Mautner93a035c2012-04-09 15:23:59 -07001986 return;
1987 }
Daniel Sandler8ba33c92011-10-04 21:49:30 -04001988 new Thread(new Runnable() {
1989 @Override
1990 public void run() {
Chet Haase2f2022a2011-10-11 06:41:59 -07001991 // Decrease the delay for every row we animate to give the sense of
1992 // accelerating the swipes
1993 final int ROW_DELAY_DECREMENT = 10;
1994 int currentDelay = 140;
1995 int totalDelay = 0;
Daniel Sandler8ba33c92011-10-04 21:49:30 -04001996
Chet Haase2f2022a2011-10-11 06:41:59 -07001997 // Set the shade-animating state to avoid doing other work during
1998 // all of these animations. In particular, avoid layout and
1999 // redrawing when collapsing the shade.
2000 mPile.setViewRemoval(false);
Daniel Sandler8ba33c92011-10-04 21:49:30 -04002001
Chet Haase2f2022a2011-10-11 06:41:59 -07002002 mPostCollapseCleanup = new Runnable() {
Craig Mautner93a035c2012-04-09 15:23:59 -07002003 @Override
Daniel Sandler8ba33c92011-10-04 21:49:30 -04002004 public void run() {
2005 try {
Chet Haase2f2022a2011-10-11 06:41:59 -07002006 mPile.setViewRemoval(true);
Daniel Sandler8ba33c92011-10-04 21:49:30 -04002007 mBarService.onClearAllNotifications();
Chet Haase2f2022a2011-10-11 06:41:59 -07002008 } catch (Exception ex) { }
Daniel Sandler8ba33c92011-10-04 21:49:30 -04002009 }
Chet Haase2f2022a2011-10-11 06:41:59 -07002010 };
Daniel Sandler8ba33c92011-10-04 21:49:30 -04002011
Chet Haase2f2022a2011-10-11 06:41:59 -07002012 View sampleView = snapshot.get(0);
2013 int width = sampleView.getWidth();
Craig Mautner93a035c2012-04-09 15:23:59 -07002014 final int velocity = width * 8; // 1000/8 = 125 ms duration
2015 for (final View _v : snapshot) {
Chet Haase2f2022a2011-10-11 06:41:59 -07002016 mHandler.postDelayed(new Runnable() {
Daniel Sandler8ba33c92011-10-04 21:49:30 -04002017 @Override
2018 public void run() {
Chet Haase2f2022a2011-10-11 06:41:59 -07002019 mPile.dismissRowAnimated(_v, velocity);
Daniel Sandler8ba33c92011-10-04 21:49:30 -04002020 }
Chet Haase2f2022a2011-10-11 06:41:59 -07002021 }, totalDelay);
2022 currentDelay = Math.max(50, currentDelay - ROW_DELAY_DECREMENT);
2023 totalDelay += currentDelay;
Daniel Sandler8ba33c92011-10-04 21:49:30 -04002024 }
Chet Haase2f2022a2011-10-11 06:41:59 -07002025 // Delay the collapse animation until after all swipe animations have
2026 // finished. Provide some buffer because there may be some extra delay
2027 // before actually starting each swipe animation. Ideally, we'd
2028 // synchronize the end of those animations with the start of the collaps
2029 // exactly.
2030 mHandler.postDelayed(new Runnable() {
Craig Mautner93a035c2012-04-09 15:23:59 -07002031 @Override
Chet Haase2f2022a2011-10-11 06:41:59 -07002032 public void run() {
Jim Miller9a720f52012-05-30 03:19:43 -07002033 animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
Chet Haase2f2022a2011-10-11 06:41:59 -07002034 }
2035 }, totalDelay + 225);
Daniel Sandler8ba33c92011-10-04 21:49:30 -04002036 }
2037 }).start();
Joe Onorato808182d2010-07-09 18:52:06 -04002038 }
Joe Onorato808182d2010-07-09 18:52:06 -04002039 }
2040 };
2041
Daniel Sandlerd3090562011-08-09 00:28:44 -04002042 private View.OnClickListener mSettingsButtonListener = new View.OnClickListener() {
2043 public void onClick(View v) {
Daniel Sandler26cda272012-05-22 15:44:08 -04002044 // We take this as a good indicator that Setup is running and we shouldn't
2045 // allow you to go somewhere else
2046 if (!isDeviceProvisioned()) return;
Jim Miller5e6af442011-12-02 18:24:26 -08002047 try {
2048 // Dismiss the lock screen when Settings starts.
2049 ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
2050 } catch (RemoteException e) {
2051 }
Daniel Sandlerd3090562011-08-09 00:28:44 -04002052 v.getContext().startActivity(new Intent(Settings.ACTION_SETTINGS)
2053 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
2054 animateCollapse();
2055 }
2056 };
2057
Joe Onorato808182d2010-07-09 18:52:06 -04002058 private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
2059 public void onReceive(Context context, Intent intent) {
2060 String action = intent.getAction();
2061 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
2062 || Intent.ACTION_SCREEN_OFF.equals(action)) {
Jim Miller9a720f52012-05-30 03:19:43 -07002063 int flags = CommandQueue.FLAG_EXCLUDE_NONE;
Michael Jurka3b1fc472011-06-13 10:54:40 -07002064 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
Daniel Sandleredbdd3a2011-06-21 12:57:08 -04002065 String reason = intent.getStringExtra("reason");
Jim Miller9a720f52012-05-30 03:19:43 -07002066 if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
2067 flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
Michael Jurka3b1fc472011-06-13 10:54:40 -07002068 }
2069 }
Jim Miller9a720f52012-05-30 03:19:43 -07002070 animateCollapse(flags);
Joe Onorato808182d2010-07-09 18:52:06 -04002071 }
2072 else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
2073 updateResources();
Daniel Sandler21b274e2012-05-02 15:07:51 -04002074 repositionNavigationBar();
2075 updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
Joe Onorato808182d2010-07-09 18:52:06 -04002076 }
2077 }
2078 };
2079
2080 private void setIntruderAlertVisibility(boolean vis) {
Daniel Sandler6b318802012-04-13 14:05:19 -04002081 if (!ENABLE_INTRUDERS) return;
Daniel Sandlerfa7887b2012-03-26 09:43:31 -04002082 if (DEBUG) {
2083 Slog.v(TAG, (vis ? "showing" : "hiding") + " intruder alert window");
2084 }
Joe Onorato808182d2010-07-09 18:52:06 -04002085 mIntruderAlertView.setVisibility(vis ? View.VISIBLE : View.GONE);
2086 }
2087
Daniel Sandlerfa7887b2012-03-26 09:43:31 -04002088 public void dismissIntruder() {
2089 if (mCurrentlyIntrudingNotification == null) return;
2090
2091 try {
2092 mBarService.onNotificationClear(
2093 mCurrentlyIntrudingNotification.pkg,
Jim Millera073e572012-05-23 17:03:27 -07002094 mCurrentlyIntrudingNotification.tag,
Daniel Sandlerfa7887b2012-03-26 09:43:31 -04002095 mCurrentlyIntrudingNotification.id);
2096 } catch (android.os.RemoteException ex) {
2097 // oh well
2098 }
2099 }
Jim Millere898ac52012-04-06 17:10:57 -07002100
Joe Onorato808182d2010-07-09 18:52:06 -04002101 /**
2102 * Reload some of our resources when the configuration changes.
2103 *
2104 * We don't reload everything when the configuration changes -- we probably
2105 * should, but getting that smooth is tough. Someday we'll fix that. In the
2106 * meantime, just update the things that we know change.
2107 */
2108 void updateResources() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04002109 final Context context = mContext;
2110 final Resources res = context.getResources();
Joe Onorato808182d2010-07-09 18:52:06 -04002111
Daniel Sandler1347c302011-08-01 16:47:53 -04002112 if (mClearButton instanceof TextView) {
2113 ((TextView)mClearButton).setText(context.getText(R.string.status_bar_clear_all_button));
2114 }
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04002115 loadDimens();
2116 }
Jim Miller5e6af442011-12-02 18:24:26 -08002117
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04002118 protected void loadDimens() {
2119 final Resources res = mContext.getResources();
2120
2121 mNaturalBarHeight = res.getDimensionPixelSize(
2122 com.android.internal.R.dimen.status_bar_height);
2123
2124 int newIconSize = res.getDimensionPixelSize(
2125 com.android.internal.R.dimen.status_bar_icon_size);
2126 int newIconHPadding = res.getDimensionPixelSize(
2127 R.dimen.status_bar_icon_padding);
2128
2129 if (newIconHPadding != mIconHPadding || newIconSize != mIconSize) {
2130// Slog.d(TAG, "size=" + newIconSize + " padding=" + newIconHPadding);
2131 mIconHPadding = newIconHPadding;
2132 mIconSize = newIconSize;
2133 //reloadAllNotificationIcons(); // reload the tray
2134 }
2135
Joe Onorato808182d2010-07-09 18:52:06 -04002136 mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
2137
Daniel Sandlerdc940ea2011-08-25 14:35:53 -07002138 mSelfExpandVelocityPx = res.getDimension(R.dimen.self_expand_velocity);
2139 mSelfCollapseVelocityPx = res.getDimension(R.dimen.self_collapse_velocity);
2140 mFlingExpandMinVelocityPx = res.getDimension(R.dimen.fling_expand_min_velocity);
2141 mFlingCollapseMinVelocityPx = res.getDimension(R.dimen.fling_collapse_min_velocity);
2142
2143 mCollapseMinDisplayFraction = res.getFraction(R.dimen.collapse_min_display_fraction, 1, 1);
2144 mExpandMinDisplayFraction = res.getFraction(R.dimen.expand_min_display_fraction, 1, 1);
2145
2146 mExpandAccelPx = res.getDimension(R.dimen.expand_accel);
2147 mCollapseAccelPx = res.getDimension(R.dimen.collapse_accel);
2148
2149 mFlingGestureMaxXVelocityPx = res.getDimension(R.dimen.fling_gesture_max_x_velocity);
Jim Millera073e572012-05-23 17:03:27 -07002150
Daniel Sandler21b274e2012-05-02 15:07:51 -04002151 mNotificationPanelMarginBottomPx
2152 = (int) res.getDimension(R.dimen.notification_panel_margin_bottom);
2153 mNotificationPanelMarginLeftPx
2154 = (int) res.getDimension(R.dimen.notification_panel_margin_left);
2155 mNotificationPanelGravity = res.getInteger(R.integer.notification_panel_layout_gravity);
2156 if (mNotificationPanelGravity <= 0) {
Jim Millera073e572012-05-23 17:03:27 -07002157 mNotificationPanelGravity = Gravity.CENTER_VERTICAL | Gravity.TOP;
Daniel Sandler21b274e2012-05-02 15:07:51 -04002158 }
Daniel Sandlerdc940ea2011-08-25 14:35:53 -07002159
Joe Onorato808182d2010-07-09 18:52:06 -04002160 if (false) Slog.v(TAG, "updateResources");
2161 }
2162
2163 //
2164 // tracing
2165 //
2166
2167 void postStartTracing() {
2168 mHandler.postDelayed(mStartTracing, 3000);
2169 }
2170
2171 void vibrate() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04002172 android.os.Vibrator vib = (android.os.Vibrator)mContext.getSystemService(
2173 Context.VIBRATOR_SERVICE);
Joe Onorato808182d2010-07-09 18:52:06 -04002174 vib.vibrate(250);
2175 }
2176
2177 Runnable mStartTracing = new Runnable() {
2178 public void run() {
2179 vibrate();
2180 SystemClock.sleep(250);
2181 Slog.d(TAG, "startTracing");
2182 android.os.Debug.startMethodTracing("/data/statusbar-traces/trace");
2183 mHandler.postDelayed(mStopTracing, 10000);
2184 }
2185 };
2186
2187 Runnable mStopTracing = new Runnable() {
2188 public void run() {
2189 android.os.Debug.stopMethodTracing();
2190 Slog.d(TAG, "stopTracing");
2191 vibrate();
2192 }
2193 };
Chris Wren0c8275b2012-05-08 13:36:48 -04002194
2195 @Override
2196 protected void haltTicker() {
2197 mTicker.halt();
2198 }
Jim Miller670d9dd2012-05-12 13:28:26 -07002199
2200 @Override
Jim Millerb4238e02012-05-14 15:26:20 -07002201 protected boolean shouldDisableNavbarGestures() {
2202 return mExpanded || (mDisabled & StatusBarManager.DISABLE_HOME) != 0;
Jim Miller670d9dd2012-05-12 13:28:26 -07002203 }
Joe Onorato808182d2010-07-09 18:52:06 -04002204
Romain Guy648342f2012-05-25 10:44:45 -07002205 private static class FastColorDrawable extends Drawable {
2206 private final int mColor;
2207
2208 public FastColorDrawable(int color) {
2209 mColor = 0xff000000 | color;
2210 }
2211
2212 @Override
2213 public void draw(Canvas canvas) {
2214 canvas.drawColor(mColor, PorterDuff.Mode.SRC);
2215 }
2216
2217 @Override
2218 public void setAlpha(int alpha) {
2219 }
2220
2221 @Override
2222 public void setColorFilter(ColorFilter cf) {
2223 }
2224
2225 @Override
2226 public int getOpacity() {
2227 return PixelFormat.OPAQUE;
2228 }
2229
2230 @Override
2231 public void setBounds(int left, int top, int right, int bottom) {
2232 }
2233
2234 @Override
2235 public void setBounds(Rect bounds) {
2236 }
2237 }
2238}