blob: eaa5cc9d34fe586db6ff09a946168ec8cc790133 [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
17package com.android.systemui.statusbar.tablet;
18
Joe Onoratof3c3c4f2010-10-21 11:09:02 -040019import java.io.FileDescriptor;
20import java.io.PrintWriter;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -040021import java.util.ArrayList;
Daniel Sandlerb9606992010-11-19 14:47:59 -050022import java.util.Map;
23import java.util.IdentityHashMap;
Joe Onoratof3c3c4f2010-10-21 11:09:02 -040024
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -040025import android.animation.LayoutTransition;
26import android.animation.ObjectAnimator;
Daniel Sandlerb9606992010-11-19 14:47:59 -050027import android.animation.AnimatorSet;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040028import android.app.ActivityManagerNative;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040029import android.app.PendingIntent;
Joe Onoratoef1e7762010-09-17 18:38:38 -040030import android.app.Notification;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040031import android.app.StatusBarManager;
Joe Onorato808182d2010-07-09 18:52:06 -040032import android.content.Context;
33import android.content.Intent;
Daniel Sandler0ad460b2010-12-14 12:14:53 -050034import android.content.res.Configuration;
Joe Onorato808182d2010-07-09 18:52:06 -040035import android.content.res.Resources;
Daniel Sandler9120d552010-07-23 09:11:14 -040036import android.graphics.PixelFormat;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040037import android.graphics.Rect;
Joe Onorato4daaeaf2010-11-17 20:43:12 -080038import android.graphics.drawable.Drawable;
39import android.graphics.drawable.LayerDrawable;
Daniel Sandler9120d552010-07-23 09:11:14 -040040import android.os.Handler;
Joe Onorato808182d2010-07-09 18:52:06 -040041import android.os.IBinder;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040042import android.os.Message;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040043import android.os.RemoteException;
Daniel Sandler10163c62010-12-08 11:51:05 -050044import android.os.ServiceManager;
Joe Onoratoef1e7762010-09-17 18:38:38 -040045import android.text.TextUtils;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040046import android.util.Slog;
Joe Onorato55d2d762010-09-26 13:02:01 -070047import android.view.animation.Animation;
Daniel Sandlerce70d912010-09-02 11:59:41 -040048import android.view.animation.AnimationUtils;
Joe Onorato808182d2010-07-09 18:52:06 -040049import android.view.Gravity;
Daniel Sandler10163c62010-12-08 11:51:05 -050050import android.view.IWindowManager;
51import android.view.KeyEvent;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040052import android.view.LayoutInflater;
Joe Onoratob62ac122010-09-20 16:16:32 -040053import android.view.MotionEvent;
Daniel Sandler8304da42010-10-25 15:53:25 -040054import android.view.VelocityTracker;
Joe Onorato808182d2010-07-09 18:52:06 -040055import android.view.View;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -040056import android.view.ViewConfiguration;
Daniel Sandler9120d552010-07-23 09:11:14 -040057import android.view.ViewGroup;
58import android.view.WindowManager;
59import android.view.WindowManagerImpl;
Joe Onoratoef1e7762010-09-17 18:38:38 -040060import android.widget.FrameLayout;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040061import android.widget.ImageView;
Joe Onorato808182d2010-07-09 18:52:06 -040062import android.widget.LinearLayout;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040063import android.widget.RemoteViews;
64import android.widget.ScrollView;
65import android.widget.TextSwitcher;
Daniel Sandler9120d552010-07-23 09:11:14 -040066import android.widget.TextView;
Joe Onorato808182d2010-07-09 18:52:06 -040067
68import com.android.internal.statusbar.StatusBarIcon;
Joe Onorato808182d2010-07-09 18:52:06 -040069import com.android.internal.statusbar.StatusBarNotification;
70
Joe Onorato808182d2010-07-09 18:52:06 -040071import com.android.systemui.R;
Joe Onoratofd52b182010-11-10 18:00:52 -080072import com.android.systemui.statusbar.*;
73import com.android.systemui.statusbar.policy.BatteryController;
74import com.android.systemui.statusbar.policy.NetworkController;
75import com.android.systemui.recent.RecentApplicationsActivity;
Joe Onorato808182d2010-07-09 18:52:06 -040076
Joe Onoratodc100302011-01-11 17:07:41 -080077public class TabletStatusBar extends StatusBar implements
78 HeightReceiver.OnBarHeightChangedListener {
Daniel Sandlerfb970e92010-08-20 10:57:17 -040079 public static final boolean DEBUG = false;
Joe Onoratofd52b182010-11-10 18:00:52 -080080 public static final String TAG = "TabletStatusBar";
Joe Onorato808182d2010-07-09 18:52:06 -040081
Daniel Sandler0ad460b2010-12-14 12:14:53 -050082 public static final int MAX_NOTIFICATION_ICONS = 5;
satok82beadf2010-12-27 19:03:06 +090083 // IME switcher icon is big and occupy width of two icons
satok51133822011-01-25 15:01:48 +090084 public static final int MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE = MAX_NOTIFICATION_ICONS - 1;
Daniel Sandler0ad460b2010-12-14 12:14:53 -050085
Joe Onoratob62ac122010-09-20 16:16:32 -040086 public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
87 public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -040088 public static final int MSG_OPEN_NOTIFICATION_PEEK = 1002;
89 public static final int MSG_CLOSE_NOTIFICATION_PEEK = 1003;
Jim Miller44c66fe2010-10-20 18:32:52 -070090 public static final int MSG_OPEN_RECENTS_PANEL = 1020;
91 public static final int MSG_CLOSE_RECENTS_PANEL = 1021;
Daniel Sandler0ad460b2010-12-14 12:14:53 -050092 public static final int MSG_SHOW_CHROME = 1030;
93 public static final int MSG_HIDE_CHROME = 1031;
satok82beadf2010-12-27 19:03:06 +090094 public static final int MSG_OPEN_INPUT_METHODS_PANEL = 1040;
95 public static final int MSG_CLOSE_INPUT_METHODS_PANEL = 1041;
Jim Miller44c66fe2010-10-20 18:32:52 -070096
Daniel Sandler10163c62010-12-08 11:51:05 -050097 // Fitts' Law assistance for LatinIME; TODO: replace with a more general approach
98 private static final boolean FAKE_SPACE_BAR = true;
99
Joe Onoratodc100302011-01-11 17:07:41 -0800100 // The height of the bar, as definied by the build. It may be taller if we're plugged
101 // into hdmi.
102 int mNaturalBarHeight = -1;
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500103 int mIconSize = -1;
104 int mIconHPadding = -1;
Daniel Sandler9120d552010-07-23 09:11:14 -0400105
106 H mHandler = new H();
107
Daniel Sandler10163c62010-12-08 11:51:05 -0500108 IWindowManager mWindowManager;
109
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400110 // tracking all current notifications
111 private NotificationData mNotns = new NotificationData();
Jim Miller44c66fe2010-10-20 18:32:52 -0700112
Joe Onoratob62ac122010-09-20 16:16:32 -0400113 TabletStatusBarView mStatusBarView;
Joe Onoratofd52b182010-11-10 18:00:52 -0800114 View mNotificationArea;
115 View mNotificationTrigger;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400116 NotificationIconArea mNotificationIconArea;
Joe Onorato091e1b82010-09-26 18:04:44 -0700117 View mNavigationArea;
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500118
Joe Onorato536c58f2010-11-28 17:52:28 -0800119 ImageView mBackButton;
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500120 View mHomeButton;
Daniel Sandlere02d8082010-10-08 15:13:22 -0400121 View mMenuButton;
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400122 View mRecentButton;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400123
Joe Onoratoec51a822011-01-04 16:33:01 -0800124 ViewGroup mNotificationAndImeArea;
satokcd7cd292010-11-20 15:46:23 +0900125 InputMethodButton mInputMethodSwitchButton;
satok06487a52010-10-29 11:37:18 +0900126
Joe Onoratoddf680b2010-09-26 13:59:40 -0700127 NotificationPanel mNotificationPanel;
Joe Onorato8a576712010-11-15 16:50:34 -0800128 NotificationPeekPanel mNotificationPeekWindow;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400129 ViewGroup mNotificationPeekRow;
130 int mNotificationPeekIndex;
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500131 IBinder mNotificationPeekKey;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400132 LayoutTransition mNotificationPeekScrubLeft, mNotificationPeekScrubRight;
133
134 int mNotificationPeekTapDuration;
135 int mNotificationFlingVelocity;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400136
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400137 ViewGroup mPile;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400138
Joe Onoratodc100302011-01-11 17:07:41 -0800139 HeightReceiver mHeightReceiver;
Joe Onoratofd52b182010-11-10 18:00:52 -0800140 BatteryController mBatteryController;
141 NetworkController mNetworkController;
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400142
Daniel Sandlerce70d912010-09-02 11:59:41 -0400143 View mBarContents;
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500144
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500145 // hide system chrome ("lights out") support
146 View mShadow;
Daniel Sandlerce70d912010-09-02 11:59:41 -0400147
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400148 NotificationIconArea.IconLayout mIconLayout;
149
Joe Onoratoef1e7762010-09-17 18:38:38 -0400150 TabletTicker mTicker;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400151
Daniel Sandler10163c62010-12-08 11:51:05 -0500152 View mFakeSpaceBar;
153 KeyEvent mSpaceBarKeyEvent = null;
154
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400155 // for disabling the status bar
156 int mDisabled = 0;
157
Joe Onorato55d2d762010-09-26 13:02:01 -0700158 boolean mNotificationsOn = true;
Jim Miller44c66fe2010-10-20 18:32:52 -0700159 private RecentAppsPanel mRecentsPanel;
satok82beadf2010-12-27 19:03:06 +0900160 private InputMethodsPanel mInputMethodsPanel;
Joe Onorato55d2d762010-09-26 13:02:01 -0700161
Daniel Sandlerc51451a2010-12-16 19:06:46 -0500162 public Context getContext() { return mContext; }
163
Daniel Sandler9120d552010-07-23 09:11:14 -0400164 protected void addPanelWindows() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400165 final Context context = mContext;
166
Jim Miller44c66fe2010-10-20 18:32:52 -0700167 // Notification Panel
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400168 mNotificationPanel = (NotificationPanel)View.inflate(context,
Joe Onorato755cc742010-11-27 15:45:35 -0800169 R.layout.status_bar_notification_panel, null);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800170 mNotificationPanel.show(false, false);
Joe Onoratob62ac122010-09-20 16:16:32 -0400171 mNotificationPanel.setOnTouchListener(
Joe Onoratoddf680b2010-09-26 13:59:40 -0700172 new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PANEL, mNotificationPanel));
Joe Onoratob62ac122010-09-20 16:16:32 -0400173
Joe Onoratofd52b182010-11-10 18:00:52 -0800174 // the battery and network icons
175 mBatteryController.addIconView((ImageView)mNotificationPanel.findViewById(R.id.battery));
176 mBatteryController.addLabelView(
177 (TextView)mNotificationPanel.findViewById(R.id.battery_text));
Joe Onoratoddbba422010-11-23 15:42:28 -0800178 mNetworkController.addCombinedSignalIconView(
Joe Onorato42f8e132010-11-29 15:52:43 -0800179 (ImageView)mNotificationPanel.findViewById(R.id.network_signal));
180 mNetworkController.addDataTypeIconView(
181 (ImageView)mNotificationPanel.findViewById(R.id.network_type));
Joe Onoratofd52b182010-11-10 18:00:52 -0800182 mNetworkController.addLabelView(
183 (TextView)mNotificationPanel.findViewById(R.id.network_text));
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500184 mNetworkController.addLabelView(
185 (TextView)mBarContents.findViewById(R.id.network_text));
Joe Onoratofd52b182010-11-10 18:00:52 -0800186
Joe Onorato55d2d762010-09-26 13:02:01 -0700187 mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400188
Daniel Sandler9120d552010-07-23 09:11:14 -0400189 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
Daniel Sandleradd26202011-01-20 02:53:43 -0500190 512, // ViewGroup.LayoutParams.MATCH_PARENT,
Joe Onoratocf2b1992010-11-16 21:36:42 -0800191 ViewGroup.LayoutParams.MATCH_PARENT,
Daniel Sandler9120d552010-07-23 09:11:14 -0400192 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
193 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
Jeff Brown46e75292010-11-10 16:53:45 -0800194 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
Joe Onorato7c270fa2010-12-08 17:31:42 -0800195 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
196 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
Daniel Sandler9120d552010-07-23 09:11:14 -0400197 PixelFormat.TRANSLUCENT);
Joe Onoratoea70e632010-09-27 17:59:37 -0700198 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
Daniel Sandler9120d552010-07-23 09:11:14 -0400199 lp.setTitle("NotificationPanel");
Joe Onorato7c270fa2010-12-08 17:31:42 -0800200 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
201 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
202 lp.windowAnimations = com.android.internal.R.style.Animation; // == no animation
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500203// lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
Daniel Sandler9120d552010-07-23 09:11:14 -0400204
205 WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
206
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400207 // Notification preview window
Joe Onorato8a576712010-11-15 16:50:34 -0800208 mNotificationPeekWindow = (NotificationPeekPanel) View.inflate(context,
Joe Onorato755cc742010-11-27 15:45:35 -0800209 R.layout.status_bar_notification_peek, null);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400210 mNotificationPeekRow = (ViewGroup) mNotificationPeekWindow.findViewById(R.id.content);
211 mNotificationPeekWindow.setVisibility(View.GONE);
212 mNotificationPeekWindow.setOnTouchListener(
Joe Onorato5e759462010-11-28 17:43:50 -0800213 new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PEEK, mNotificationPeekWindow));
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400214 mNotificationPeekScrubRight = new LayoutTransition();
Jim Miller85babff2011-01-11 14:26:03 -0800215 mNotificationPeekScrubRight.setAnimator(LayoutTransition.APPEARING,
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400216 ObjectAnimator.ofInt(null, "left", -512, 0));
Jim Miller85babff2011-01-11 14:26:03 -0800217 mNotificationPeekScrubRight.setAnimator(LayoutTransition.DISAPPEARING,
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400218 ObjectAnimator.ofInt(null, "left", -512, 0));
219 mNotificationPeekScrubRight.setDuration(500);
220
221 mNotificationPeekScrubLeft = new LayoutTransition();
Jim Miller85babff2011-01-11 14:26:03 -0800222 mNotificationPeekScrubLeft.setAnimator(LayoutTransition.APPEARING,
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400223 ObjectAnimator.ofInt(null, "left", 512, 0));
Jim Miller85babff2011-01-11 14:26:03 -0800224 mNotificationPeekScrubLeft.setAnimator(LayoutTransition.DISAPPEARING,
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400225 ObjectAnimator.ofInt(null, "left", 512, 0));
226 mNotificationPeekScrubLeft.setDuration(500);
227
228 // XXX: setIgnoreChildren?
229 lp = new WindowManager.LayoutParams(
230 512, // ViewGroup.LayoutParams.WRAP_CONTENT,
231 ViewGroup.LayoutParams.WRAP_CONTENT,
232 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
233 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
Jeff Brown46e75292010-11-10 16:53:45 -0800234 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
235 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400236 PixelFormat.TRANSLUCENT);
237 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
238 lp.setTitle("NotificationPeekWindow");
239 lp.windowAnimations = com.android.internal.R.style.Animation_Toast;
240
241 WindowManagerImpl.getDefault().addView(mNotificationPeekWindow, lp);
242
Jim Miller44c66fe2010-10-20 18:32:52 -0700243 // Recents Panel
Jim Miller85babff2011-01-11 14:26:03 -0800244 mRecentsPanel = (RecentAppsPanel) View.inflate(context,
245 R.layout.status_bar_recent_panel, null);
246 mRecentsPanel.setVisibility(View.GONE);
247 mRecentsPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL,
248 mRecentsPanel));
249 mStatusBarView.setIgnoreChildren(2, mRecentButton, mRecentsPanel);
Jim Miller44c66fe2010-10-20 18:32:52 -0700250
Jim Miller85babff2011-01-11 14:26:03 -0800251 lp = new WindowManager.LayoutParams(
252 ViewGroup.LayoutParams.WRAP_CONTENT,
253 ViewGroup.LayoutParams.WRAP_CONTENT,
254 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
255 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
256 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
257 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
258 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
259 PixelFormat.TRANSLUCENT);
260 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
261 lp.setTitle("RecentsPanel");
262 lp.windowAnimations = R.style.Animation_RecentPanel;
Jim Miller44c66fe2010-10-20 18:32:52 -0700263
Jim Miller85babff2011-01-11 14:26:03 -0800264 WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
265 mRecentsPanel.setBar(this);
satok82beadf2010-12-27 19:03:06 +0900266
267 // Input methods Panel
268 mInputMethodsPanel = (InputMethodsPanel) View.inflate(context,
269 R.layout.status_bar_input_methods_panel, null);
270 mInputMethodsPanel.setVisibility(View.GONE);
271 mInputMethodsPanel.setOnTouchListener(new TouchOutsideListener(
272 MSG_CLOSE_INPUT_METHODS_PANEL, mInputMethodsPanel));
satok913f42d2011-01-17 16:58:10 +0900273 mInputMethodsPanel.setImeSwitchButton(mInputMethodSwitchButton);
satok82beadf2010-12-27 19:03:06 +0900274 mStatusBarView.setIgnoreChildren(3, mInputMethodSwitchButton, mInputMethodsPanel);
275 lp = new WindowManager.LayoutParams(
276 ViewGroup.LayoutParams.WRAP_CONTENT,
277 ViewGroup.LayoutParams.WRAP_CONTENT,
278 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
279 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
280 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
281 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
282 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
283 PixelFormat.TRANSLUCENT);
284 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
285 lp.setTitle("InputMethodsPanel");
286 lp.windowAnimations = R.style.Animation_RecentPanel;
287
288 WindowManagerImpl.getDefault().addView(mInputMethodsPanel, lp);
Daniel Sandler9120d552010-07-23 09:11:14 -0400289 }
Joe Onorato808182d2010-07-09 18:52:06 -0400290
291 @Override
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400292 public void start() {
293 super.start(); // will add the main bar view
Joe Onorato808182d2010-07-09 18:52:06 -0400294 }
295
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500296 @Override
Joe Onoratodc100302011-01-11 17:07:41 -0800297 protected void onConfigurationChanged(Configuration newConfig) {
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500298 loadDimens();
299 }
300
301 protected void loadDimens() {
302 final Resources res = mContext.getResources();
303
Joe Onoratodc100302011-01-11 17:07:41 -0800304 mNaturalBarHeight = res.getDimensionPixelSize(
305 com.android.internal.R.dimen.status_bar_height);
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500306
307 int newIconSize = res.getDimensionPixelSize(
308 com.android.internal.R.dimen.status_bar_icon_size);
309 int newIconHPadding = res.getDimensionPixelSize(
310 R.dimen.status_bar_icon_padding);
311
312 if (newIconHPadding != mIconHPadding || newIconSize != mIconSize) {
313// Slog.d(TAG, "size=" + newIconSize + " padding=" + newIconHPadding);
314 mIconHPadding = newIconHPadding;
315 mIconSize = newIconSize;
316 reloadAllNotificationIcons(); // reload the tray
317 }
318 }
319
Joe Onorato808182d2010-07-09 18:52:06 -0400320 protected View makeStatusBarView() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400321 final Context context = mContext;
Jim Miller85babff2011-01-11 14:26:03 -0800322
Daniel Sandler10163c62010-12-08 11:51:05 -0500323 mWindowManager = IWindowManager.Stub.asInterface(
324 ServiceManager.getService(Context.WINDOW_SERVICE));
Joe Onorato808182d2010-07-09 18:52:06 -0400325
Joe Onoratodc100302011-01-11 17:07:41 -0800326 // This guy will listen for HDMI plugged broadcasts so we can resize the
327 // status bar as appropriate.
328 mHeightReceiver = new HeightReceiver(mContext);
329 mHeightReceiver.registerReceiver();
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500330 loadDimens();
Joe Onorato808182d2010-07-09 18:52:06 -0400331
Joe Onoratob62ac122010-09-20 16:16:32 -0400332 final TabletStatusBarView sb = (TabletStatusBarView)View.inflate(
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400333 context, R.layout.status_bar, null);
Joe Onorato808182d2010-07-09 18:52:06 -0400334 mStatusBarView = sb;
335
Joe Onoratob62ac122010-09-20 16:16:32 -0400336 sb.setHandler(mHandler);
337
Daniel Sandlerce70d912010-09-02 11:59:41 -0400338 mBarContents = sb.findViewById(R.id.bar_contents);
Joe Onoratof63b0f42010-09-12 17:03:19 -0400339
Joe Onoratofd52b182010-11-10 18:00:52 -0800340 // the whole right-hand side of the bar
341 mNotificationArea = sb.findViewById(R.id.notificationArea);
342
Joe Onorato55d2d762010-09-26 13:02:01 -0700343 // the button to open the notification area
Joe Onoratofd52b182010-11-10 18:00:52 -0800344 mNotificationTrigger = sb.findViewById(R.id.notificationTrigger);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400345 mNotificationTrigger.setOnClickListener(mOnClickListener);
Joe Onorato55d2d762010-09-26 13:02:01 -0700346
Joe Onorato808182d2010-07-09 18:52:06 -0400347 // the more notifications icon
348 mNotificationIconArea = (NotificationIconArea)sb.findViewById(R.id.notificationIcons);
349
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400350 // where the icons go
351 mIconLayout = (NotificationIconArea.IconLayout) sb.findViewById(R.id.icons);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400352 mIconLayout.setOnTouchListener(new NotificationIconTouchListener());
353
354 ViewConfiguration vc = ViewConfiguration.get(context);
355 mNotificationPeekTapDuration = vc.getTapTimeout();
356 mNotificationFlingVelocity = 300; // px/s
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400357
Daniel Sandlerc51451a2010-12-16 19:06:46 -0500358 mTicker = new TabletTicker(this);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400359
Joe Onoratofd52b182010-11-10 18:00:52 -0800360 // The icons
361 mBatteryController = new BatteryController(mContext);
362 mBatteryController.addIconView((ImageView)sb.findViewById(R.id.battery));
363 mNetworkController = new NetworkController(mContext);
Joe Onorato42f8e132010-11-29 15:52:43 -0800364 mNetworkController.addCombinedSignalIconView(
365 (ImageView)sb.findViewById(R.id.network_signal));
366 mNetworkController.addDataTypeIconView(
367 (ImageView)sb.findViewById(R.id.network_type));
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400368
Joe Onorato091e1b82010-09-26 18:04:44 -0700369 // The navigation buttons
370 mNavigationArea = sb.findViewById(R.id.navigationArea);
Joe Onorato536c58f2010-11-28 17:52:28 -0800371 mBackButton = (ImageView)mNavigationArea.findViewById(R.id.back);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500372 mHomeButton = mNavigationArea.findViewById(R.id.home);
Daniel Sandlere02d8082010-10-08 15:13:22 -0400373 mMenuButton = mNavigationArea.findViewById(R.id.menu);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500374 mRecentButton = mNavigationArea.findViewById(R.id.recent_apps);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500375 mRecentButton.setOnClickListener(mOnClickListener);
Joe Onorato091e1b82010-09-26 18:04:44 -0700376
satok06487a52010-10-29 11:37:18 +0900377 // The bar contents buttons
Joe Onoratoec51a822011-01-04 16:33:01 -0800378 mNotificationAndImeArea = (ViewGroup)sb.findViewById(R.id.notificationAndImeArea);
satokcd7cd292010-11-20 15:46:23 +0900379 mInputMethodSwitchButton = (InputMethodButton) sb.findViewById(R.id.imeSwitchButton);
satok82beadf2010-12-27 19:03:06 +0900380 // Overwrite the lister
381 mInputMethodSwitchButton.setOnClickListener(mOnClickListener);
satok06487a52010-10-29 11:37:18 +0900382
Daniel Sandler10163c62010-12-08 11:51:05 -0500383 // for redirecting errant bar taps to the IME
384 mFakeSpaceBar = sb.findViewById(R.id.fake_space_bar);
385
Daniel Sandlerb9606992010-11-19 14:47:59 -0500386 // "shadows" of the status bar features, for lights-out mode
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500387 mShadow = sb.findViewById(R.id.bar_shadow);
388 mShadow.setOnTouchListener(
389 new View.OnTouchListener() {
390 public boolean onTouch(View v, MotionEvent ev) {
391 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
Daniel Sandlerd7201552011-01-28 09:58:02 -0500392 // even though setting the systemUI visibility below will turn these views
393 // on, we need them to come up faster so that they can catch this motion
394 // event
395 mShadow.setVisibility(View.GONE);
396 mBarContents.setVisibility(View.VISIBLE);
397
Joe Onorato55bf3802011-01-25 13:42:10 -0800398 try {
399 mBarService.setSystemUiVisibility(View.STATUS_BAR_VISIBLE);
400 } catch (RemoteException ex) {
401 // system process dead
402 }
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500403 }
404 return false;
405 }
406 });
Daniel Sandlerb9606992010-11-19 14:47:59 -0500407
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500408 // tuning parameters
409 final int LIGHTS_GOING_OUT_SYSBAR_DURATION = 600;
410 final int LIGHTS_GOING_OUT_SHADOW_DURATION = 1000;
411 final int LIGHTS_GOING_OUT_SHADOW_DELAY = 500;
412
413 final int LIGHTS_COMING_UP_SYSBAR_DURATION = 200;
414// final int LIGHTS_COMING_UP_SYSBAR_DELAY = 50;
415 final int LIGHTS_COMING_UP_SHADOW_DURATION = 0;
416
417 LayoutTransition xition = new LayoutTransition();
418 xition.setAnimator(LayoutTransition.APPEARING,
419 ObjectAnimator.ofFloat(null, "alpha", 0.5f, 1f));
420 xition.setDuration(LayoutTransition.APPEARING, LIGHTS_COMING_UP_SYSBAR_DURATION);
421 xition.setStartDelay(LayoutTransition.APPEARING, 0);
422 xition.setAnimator(LayoutTransition.DISAPPEARING,
423 ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
424 xition.setDuration(LayoutTransition.DISAPPEARING, LIGHTS_GOING_OUT_SYSBAR_DURATION);
425 xition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
426 ((ViewGroup)sb.findViewById(R.id.bar_contents_holder)).setLayoutTransition(xition);
427
428 xition = new LayoutTransition();
429 xition.setAnimator(LayoutTransition.APPEARING,
430 ObjectAnimator.ofFloat(null, "alpha", 0f, 1f));
431 xition.setDuration(LayoutTransition.APPEARING, LIGHTS_GOING_OUT_SHADOW_DURATION);
432 xition.setStartDelay(LayoutTransition.APPEARING, LIGHTS_GOING_OUT_SHADOW_DELAY);
433 xition.setAnimator(LayoutTransition.DISAPPEARING,
434 ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
435 xition.setDuration(LayoutTransition.DISAPPEARING, LIGHTS_COMING_UP_SHADOW_DURATION);
436 xition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
437 ((ViewGroup)sb.findViewById(R.id.bar_shadow_holder)).setLayoutTransition(xition);
Daniel Sandlerb9606992010-11-19 14:47:59 -0500438
Joe Onorato5dd11692010-09-27 15:34:04 -0700439 // set the initial view visibility
440 setAreThereNotifications();
441
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400442 // Add the windows
443 addPanelWindows();
444
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400445 mPile = (ViewGroup)mNotificationPanel.findViewById(R.id.content);
446 mPile.removeAllViews();
Jim Miller44c66fe2010-10-20 18:32:52 -0700447
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400448 ScrollView scroller = (ScrollView)mPile.getParent();
449 scroller.setFillViewport(true);
450
Joe Onoratodc100302011-01-11 17:07:41 -0800451 mHeightReceiver.addOnBarHeightChangedListener(this);
452
Joe Onorato808182d2010-07-09 18:52:06 -0400453 return sb;
454 }
455
Joe Onoratodc100302011-01-11 17:07:41 -0800456 public int getStatusBarHeight() {
457 return mHeightReceiver.getHeight();
458 }
459
Joe Onorato808182d2010-07-09 18:52:06 -0400460 protected int getStatusBarGravity() {
461 return Gravity.BOTTOM | Gravity.FILL_HORIZONTAL;
462 }
463
Joe Onoratodc100302011-01-11 17:07:41 -0800464 public void onBarHeightChanged(int height) {
465 final WindowManager.LayoutParams lp
466 = (WindowManager.LayoutParams)mStatusBarView.getLayoutParams();
467 if (lp == null) {
468 // haven't been added yet
469 return;
470 }
471 if (lp.height != height) {
472 lp.height = height;
473 final WindowManager wm = WindowManagerImpl.getDefault();
474 wm.updateViewLayout(mStatusBarView, lp);
475 }
476 }
477
Daniel Sandler9120d552010-07-23 09:11:14 -0400478 private class H extends Handler {
Daniel Sandler9120d552010-07-23 09:11:14 -0400479 public void handleMessage(Message m) {
480 switch (m.what) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400481 case MSG_OPEN_NOTIFICATION_PEEK:
482 if (DEBUG) Slog.d(TAG, "opening notification peek window; arg=" + m.arg1);
483 if (m.arg1 >= 0) {
484 final int N = mNotns.size();
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500485 if (mNotificationPeekIndex >= 0 && mNotificationPeekIndex < N) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400486 NotificationData.Entry entry = mNotns.get(N-1-mNotificationPeekIndex);
487 entry.icon.setBackgroundColor(0);
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500488 mNotificationPeekIndex = -1;
489 mNotificationPeekKey = null;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400490 }
491
492 final int peekIndex = m.arg1;
493 if (peekIndex < N) {
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500494 //Slog.d(TAG, "loading peek: " + peekIndex);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400495 NotificationData.Entry entry = mNotns.get(N-1-peekIndex);
496 NotificationData.Entry copy = new NotificationData.Entry(
Jim Miller85babff2011-01-11 14:26:03 -0800497 entry.key,
498 entry.notification,
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400499 entry.icon);
500 inflateViews(copy, mNotificationPeekRow);
501
502 entry.icon.setBackgroundColor(0x20FFFFFF);
503
504// mNotificationPeekRow.setLayoutTransition(
Jim Miller85babff2011-01-11 14:26:03 -0800505// peekIndex < mNotificationPeekIndex
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400506// ? mNotificationPeekScrubLeft
507// : mNotificationPeekScrubRight);
508
509 mNotificationPeekRow.removeAllViews();
510 mNotificationPeekRow.addView(copy.row);
511
512 mNotificationPeekWindow.setVisibility(View.VISIBLE);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800513 mNotificationPanel.show(false, true);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400514
515 mNotificationPeekIndex = peekIndex;
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500516 mNotificationPeekKey = entry.key;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400517 }
518 }
519 break;
520 case MSG_CLOSE_NOTIFICATION_PEEK:
521 if (DEBUG) Slog.d(TAG, "closing notification peek window");
522 mNotificationPeekWindow.setVisibility(View.GONE);
523 mNotificationPeekRow.removeAllViews();
524 final int N = mNotns.size();
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500525 if (mNotificationPeekIndex >= 0 && mNotificationPeekIndex < N) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400526 NotificationData.Entry entry = mNotns.get(N-1-mNotificationPeekIndex);
527 entry.icon.setBackgroundColor(0);
528 }
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500529
530 mNotificationPeekIndex = -1;
531 mNotificationPeekKey = null;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400532 break;
Daniel Sandler9120d552010-07-23 09:11:14 -0400533 case MSG_OPEN_NOTIFICATION_PANEL:
534 if (DEBUG) Slog.d(TAG, "opening notifications panel");
Joe Onorato7c270fa2010-12-08 17:31:42 -0800535 if (!mNotificationPanel.isShowing()) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400536 mNotificationPeekWindow.setVisibility(View.GONE);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800537 mNotificationPanel.show(true, true);
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500538 mNotificationArea.setVisibility(View.GONE);
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800539 mTicker.halt();
Joe Onorato091e1b82010-09-26 18:04:44 -0700540 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400541 break;
542 case MSG_CLOSE_NOTIFICATION_PANEL:
543 if (DEBUG) Slog.d(TAG, "closing notifications panel");
Joe Onorato7c270fa2010-12-08 17:31:42 -0800544 if (mNotificationPanel.isShowing()) {
545 mNotificationPanel.show(false, true);
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500546 mNotificationArea.setVisibility(View.VISIBLE);
Joe Onorato091e1b82010-09-26 18:04:44 -0700547 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400548 break;
Jim Miller44c66fe2010-10-20 18:32:52 -0700549 case MSG_OPEN_RECENTS_PANEL:
550 if (DEBUG) Slog.d(TAG, "opening recents panel");
Jim Miller85babff2011-01-11 14:26:03 -0800551 if (mRecentsPanel != null) {
552 mRecentsPanel.setVisibility(View.VISIBLE);
553 mRecentsPanel.show(true, true);
554 }
Jim Miller44c66fe2010-10-20 18:32:52 -0700555 break;
556 case MSG_CLOSE_RECENTS_PANEL:
557 if (DEBUG) Slog.d(TAG, "closing recents panel");
Jim Miller85babff2011-01-11 14:26:03 -0800558 if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
559 mRecentsPanel.show(false, true);
560 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400561 break;
satok82beadf2010-12-27 19:03:06 +0900562 case MSG_OPEN_INPUT_METHODS_PANEL:
563 if (DEBUG) Slog.d(TAG, "opening input methods panel");
564 if (mInputMethodsPanel != null) mInputMethodsPanel.setVisibility(View.VISIBLE);
565 break;
566 case MSG_CLOSE_INPUT_METHODS_PANEL:
567 if (DEBUG) Slog.d(TAG, "closing input methods panel");
568 if (mInputMethodsPanel != null) mInputMethodsPanel.setVisibility(View.GONE);
569 break;
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500570 case MSG_SHOW_CHROME:
Daniel Sandlere03d1bc2010-11-17 21:36:40 -0500571 if (DEBUG) Slog.d(TAG, "hiding shadows (lights on)");
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500572 mBarContents.setVisibility(View.VISIBLE);
573 mShadow.setVisibility(View.GONE);
Joe Onorato664644d2011-01-23 17:53:23 -0800574 notifyLightsChanged(true);
Daniel Sandler06e66302010-11-05 15:00:06 -0400575 break;
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500576 case MSG_HIDE_CHROME:
Daniel Sandlere03d1bc2010-11-17 21:36:40 -0500577 if (DEBUG) Slog.d(TAG, "showing shadows (lights out)");
Daniel Sandler06e66302010-11-05 15:00:06 -0400578 animateCollapse();
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500579 mBarContents.setVisibility(View.GONE);
580 mShadow.setVisibility(View.VISIBLE);
Joe Onorato664644d2011-01-23 17:53:23 -0800581 notifyLightsChanged(false);
Daniel Sandlere03d1bc2010-11-17 21:36:40 -0500582 break;
Daniel Sandler9120d552010-07-23 09:11:14 -0400583 }
584 }
585 }
Daniel Sandler271ea122010-10-22 14:06:10 -0400586
Joe Onorato664644d2011-01-23 17:53:23 -0800587 private void notifyLightsChanged(boolean shown) {
588 try {
589 Slog.d(TAG, "lights " + (shown?"on":"out"));
590 mWindowManager.statusBarVisibilityChanged(
591 shown ? View.STATUS_BAR_VISIBLE : View.STATUS_BAR_HIDDEN);
592 } catch (RemoteException ex) {
593 }
594 }
595
Joe Onorato808182d2010-07-09 18:52:06 -0400596 public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400597 if (DEBUG) Slog.d(TAG, "addIcon(" + slot + ") -> " + icon);
Joe Onorato808182d2010-07-09 18:52:06 -0400598 }
599
600 public void updateIcon(String slot, int index, int viewIndex,
601 StatusBarIcon old, StatusBarIcon icon) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400602 if (DEBUG) Slog.d(TAG, "updateIcon(" + slot + ") -> " + icon);
Joe Onorato808182d2010-07-09 18:52:06 -0400603 }
604
605 public void removeIcon(String slot, int index, int viewIndex) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400606 if (DEBUG) Slog.d(TAG, "removeIcon(" + slot + ")");
Joe Onorato808182d2010-07-09 18:52:06 -0400607 }
608
609 public void addNotification(IBinder key, StatusBarNotification notification) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400610 if (DEBUG) Slog.d(TAG, "addNotification(" + key + " -> " + notification + ")");
611 addNotificationViews(key, notification);
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400612
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800613 final boolean immersive = isImmersive();
Joe Onoratocf2b1992010-11-16 21:36:42 -0800614 if (false && immersive) {
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400615 // TODO: immersive mode popups for tablet
616 } else if (notification.notification.fullScreenIntent != null) {
617 // not immersive & a full-screen alert should be shown
Joe Onoratof68b5002011-01-16 17:00:34 -0800618 Slog.w(TAG, "Notification has fullScreenIntent and activity is not immersive;"
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400619 + " sending fullScreenIntent");
620 try {
621 notification.notification.fullScreenIntent.send();
622 } catch (PendingIntent.CanceledException e) {
623 }
624 } else {
Joe Onoratoeeed9942011-01-04 17:13:53 -0800625 tick(key, notification, true);
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400626 }
Joe Onorato5dd11692010-09-27 15:34:04 -0700627
628 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400629 }
630
631 public void updateNotification(IBinder key, StatusBarNotification notification) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400632 if (DEBUG) Slog.d(TAG, "updateNotification(" + key + " -> " + notification + ") // TODO");
Jim Miller44c66fe2010-10-20 18:32:52 -0700633
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400634 final NotificationData.Entry oldEntry = mNotns.findByKey(key);
Daniel Sandler379020a2010-07-29 16:20:06 -0400635 if (oldEntry == null) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400636 Slog.w(TAG, "updateNotification for unknown key: " + key);
637 return;
638 }
639
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400640 final StatusBarNotification oldNotification = oldEntry.notification;
641 final RemoteViews oldContentView = oldNotification.notification.contentView;
642
643 final RemoteViews contentView = notification.notification.contentView;
644
Daniel Sandler373a9982010-11-30 12:03:59 -0500645 if (DEBUG) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400646 Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
647 + " ongoing=" + oldNotification.isOngoing()
648 + " expanded=" + oldEntry.expanded
649 + " contentView=" + oldContentView);
650 Slog.d(TAG, "new notification: when=" + notification.notification.when
651 + " ongoing=" + oldNotification.isOngoing()
652 + " contentView=" + contentView);
653 }
654
655 // Can we just reapply the RemoteViews in place? If when didn't change, the order
656 // didn't change.
Joe Onorato80a44402011-01-15 16:22:24 -0800657 boolean contentsUnchanged = oldEntry.expanded != null
658 && contentView != null && oldContentView != null
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400659 && contentView.getPackage() != null
660 && oldContentView.getPackage() != null
661 && oldContentView.getPackage().equals(contentView.getPackage())
Joe Onoratoc9596d62011-01-12 17:03:11 -0800662 && oldContentView.getLayoutId() == contentView.getLayoutId();
Daniel Sandler373a9982010-11-30 12:03:59 -0500663 ViewGroup rowParent = (ViewGroup) oldEntry.row.getParent();
Joe Onorato80a44402011-01-15 16:22:24 -0800664 boolean orderUnchanged = notification.notification.when==oldNotification.notification.when
665 && notification.isOngoing() == oldNotification.isOngoing();
Joe Onoratoc9596d62011-01-12 17:03:11 -0800666 boolean isLastAnyway = rowParent.indexOfChild(oldEntry.row) == rowParent.getChildCount()-1;
667 if (contentsUnchanged && (orderUnchanged || isLastAnyway)) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400668 if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
669 oldEntry.notification = notification;
670 try {
671 // Reapply the RemoteViews
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400672 contentView.reapply(mContext, oldEntry.content);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400673 // update the contentIntent
674 final PendingIntent contentIntent = notification.notification.contentIntent;
675 if (contentIntent != null) {
676 oldEntry.content.setOnClickListener(new NotificationClicker(contentIntent,
677 notification.pkg, notification.tag, notification.id));
Joe Onorato184498c2010-10-08 17:57:18 -0400678 } else {
679 oldEntry.content.setOnClickListener(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400680 }
681 // Update the icon.
682 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
683 notification.notification.icon, notification.notification.iconLevel,
684 notification.notification.number);
685 if (!oldEntry.icon.set(ic)) {
686 handleNotificationError(key, notification, "Couldn't update icon: " + ic);
687 return;
688 }
Joe Onorato80a44402011-01-15 16:22:24 -0800689 // Update the large icon
690 if (notification.notification.largeIcon != null) {
691 oldEntry.largeIcon.setImageBitmap(notification.notification.largeIcon);
692 } else {
693 oldEntry.largeIcon.getLayoutParams().width = 0;
694 oldEntry.largeIcon.setVisibility(View.INVISIBLE);
695 }
Jim Miller85babff2011-01-11 14:26:03 -0800696
Daniel Sandler7ef29b52010-12-16 17:29:50 -0500697 if (key == mNotificationPeekKey) {
698 // must update the peek window
699 Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
700 peekMsg.arg1 = mNotificationPeekIndex;
701 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
702 mHandler.sendMessage(peekMsg);
703 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400704 }
705 catch (RuntimeException e) {
706 // It failed to add cleanly. Log, and remove the view from the panel.
707 Slog.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
708 removeNotificationViews(key);
709 addNotificationViews(key, notification);
710 }
711 } else {
712 if (DEBUG) Slog.d(TAG, "not reusing notification for key: " + key);
713 removeNotificationViews(key);
714 addNotificationViews(key, notification);
715 }
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800716 // fullScreenIntent doesn't happen on updates. You need to clear & repost a new
717 // notification.
718 final boolean immersive = isImmersive();
719 if (false && immersive) {
720 // TODO: immersive mode
721 } else {
Joe Onoratoeeed9942011-01-04 17:13:53 -0800722 tick(key, notification, false);
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800723 }
Joe Onorato5dd11692010-09-27 15:34:04 -0700724
725 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400726 }
727
728 public void removeNotification(IBinder key) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400729 if (DEBUG) Slog.d(TAG, "removeNotification(" + key + ") // TODO");
730 removeNotificationViews(key);
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800731 mTicker.remove(key);
Joe Onorato5dd11692010-09-27 15:34:04 -0700732 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400733 }
734
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500735 public void showClock(boolean show) {
736 View clock = mBarContents.findViewById(R.id.clock);
737 View network_text = mBarContents.findViewById(R.id.network_text);
738 if (clock != null) {
739 clock.setVisibility(show ? View.VISIBLE : View.GONE);
740 }
741 if (network_text != null) {
742 network_text.setVisibility((!show) ? View.VISIBLE : View.GONE);
743 }
744 }
745
Joe Onorato808182d2010-07-09 18:52:06 -0400746 public void disable(int state) {
Joe Onorato091e1b82010-09-26 18:04:44 -0700747 int old = mDisabled;
748 int diff = state ^ old;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400749 mDisabled = state;
750
Joe Onorato091e1b82010-09-26 18:04:44 -0700751 // act accordingly
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500752 if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) {
753 boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0;
Joe Onoratof68b5002011-01-16 17:00:34 -0800754 Slog.i(TAG, "DISABLE_CLOCK: " + (show ? "no" : "yes"));
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500755 showClock(show);
756 }
Daniel Sandler6f6cf3c2010-12-16 12:54:03 -0500757 if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
758 boolean show = (state & StatusBarManager.DISABLE_SYSTEM_INFO) == 0;
Joe Onoratof68b5002011-01-16 17:00:34 -0800759 Slog.i(TAG, "DISABLE_SYSTEM_INFO: " + (show ? "no" : "yes"));
Daniel Sandler6f6cf3c2010-12-16 12:54:03 -0500760 mNotificationTrigger.setVisibility(show ? View.VISIBLE : View.GONE);
761 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400762 if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
763 if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
Joe Onoratof68b5002011-01-16 17:00:34 -0800764 Slog.i(TAG, "DISABLE_EXPAND: yes");
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400765 animateCollapse();
766 }
767 }
768 if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
769 if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
Joe Onoratof68b5002011-01-16 17:00:34 -0800770 Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
Daniel Sandlerb9606992010-11-19 14:47:59 -0500771 // synchronize with current shadow state
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500772 mNotificationIconArea.setVisibility(View.GONE);
Joe Onorato091e1b82010-09-26 18:04:44 -0700773 mTicker.halt();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400774 } else {
Joe Onoratof68b5002011-01-16 17:00:34 -0800775 Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: no");
Daniel Sandlerb9606992010-11-19 14:47:59 -0500776 // synchronize with current shadow state
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500777 mNotificationIconArea.setVisibility(View.VISIBLE);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400778 }
779 } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
Joe Onorato091e1b82010-09-26 18:04:44 -0700780 if ((state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
Joe Onoratoef1e7762010-09-17 18:38:38 -0400781 mTicker.halt();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400782 }
783 }
Joe Onorato091e1b82010-09-26 18:04:44 -0700784 if ((diff & StatusBarManager.DISABLE_NAVIGATION) != 0) {
785 if ((state & StatusBarManager.DISABLE_NAVIGATION) != 0) {
Joe Onoratof68b5002011-01-16 17:00:34 -0800786 Slog.i(TAG, "DISABLE_NAVIGATION: yes");
Joe Onoratofd52b182010-11-10 18:00:52 -0800787 mNavigationArea.setVisibility(View.GONE);
satokb70c82d2010-12-20 17:59:19 +0900788 mInputMethodSwitchButton.setScreenLocked(true);
Joe Onorato091e1b82010-09-26 18:04:44 -0700789 } else {
Joe Onoratof68b5002011-01-16 17:00:34 -0800790 Slog.i(TAG, "DISABLE_NAVIGATION: no");
Joe Onoratofd52b182010-11-10 18:00:52 -0800791 mNavigationArea.setVisibility(View.VISIBLE);
satokb70c82d2010-12-20 17:59:19 +0900792 mInputMethodSwitchButton.setScreenLocked(false);
Joe Onorato091e1b82010-09-26 18:04:44 -0700793 }
794 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400795 }
796
Joe Onoratoef1e7762010-09-17 18:38:38 -0400797 private boolean hasTicker(Notification n) {
Joe Onorato46439ce2010-11-19 13:56:21 -0800798 return n.tickerView != null || !TextUtils.isEmpty(n.tickerText);
Joe Onoratoef1e7762010-09-17 18:38:38 -0400799 }
800
Joe Onoratoeeed9942011-01-04 17:13:53 -0800801 private void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
Joe Onorato55d2d762010-09-26 13:02:01 -0700802 // Don't show the ticker when the windowshade is open.
Joe Onorato7c270fa2010-12-08 17:31:42 -0800803 if (mNotificationPanel.isShowing()) {
Joe Onorato55d2d762010-09-26 13:02:01 -0700804 return;
805 }
Joe Onoratoeeed9942011-01-04 17:13:53 -0800806 // If they asked for FLAG_ONLY_ALERT_ONCE, then only show this notification
807 // if it's a new notification.
808 if (!firstTime && (n.notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) {
809 return;
810 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400811 // Show the ticker if one is requested. Also don't do this
812 // until status bar window is attached to the window manager,
813 // because... well, what's the point otherwise? And trying to
814 // run a ticker without being attached will crash!
Joe Onoratoef1e7762010-09-17 18:38:38 -0400815 if (hasTicker(n.notification) && mStatusBarView.getWindowToken() != null) {
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400816 if (0 == (mDisabled & (StatusBarManager.DISABLE_NOTIFICATION_ICONS
817 | StatusBarManager.DISABLE_NOTIFICATION_TICKER))) {
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800818 mTicker.add(key, n);
Joe Onoratoec51a822011-01-04 16:33:01 -0800819 mNotificationAndImeArea.setVisibility(View.GONE);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400820 }
821 }
822 }
823
Daniel Sandlerb8027d82010-12-16 19:35:54 -0500824 // called by TabletTicker when it's done with all queued ticks
825 public void doneTicking() {
Joe Onoratoec51a822011-01-04 16:33:01 -0800826 mNotificationAndImeArea.setVisibility(View.VISIBLE);
Daniel Sandlerb8027d82010-12-16 19:35:54 -0500827 }
828
Joe Onorato808182d2010-07-09 18:52:06 -0400829 public void animateExpand() {
Joe Onoratob62ac122010-09-20 16:16:32 -0400830 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
831 mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
Joe Onorato808182d2010-07-09 18:52:06 -0400832 }
833
834 public void animateCollapse() {
Joe Onoratob62ac122010-09-20 16:16:32 -0400835 mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PANEL);
836 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PANEL);
Jim Miller44c66fe2010-10-20 18:32:52 -0700837 mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
838 mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
satok82beadf2010-12-27 19:03:06 +0900839 mHandler.removeMessages(MSG_CLOSE_INPUT_METHODS_PANEL);
840 mHandler.sendEmptyMessage(MSG_CLOSE_INPUT_METHODS_PANEL);
Daniel Sandler9120d552010-07-23 09:11:14 -0400841 }
842
Joe Onoratofd52b182010-11-10 18:00:52 -0800843 // called by StatusBar
Daniel Sandler06e66302010-11-05 15:00:06 -0400844 @Override
Joe Onorato93056472010-09-10 10:30:46 -0400845 public void setLightsOn(boolean on) {
Daniel Sandler59485d742010-12-02 00:11:33 -0500846 // Policy note: if the frontmost activity needs the menu key, we assume it is a legacy app
847 // that can't handle lights-out mode.
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500848 if (mMenuButton.getVisibility() == View.VISIBLE) {
Daniel Sandler59485d742010-12-02 00:11:33 -0500849 on = true;
850 }
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500851 mHandler.removeMessages(MSG_HIDE_CHROME);
852 mHandler.removeMessages(MSG_SHOW_CHROME);
853 mHandler.sendEmptyMessage(on ? MSG_SHOW_CHROME : MSG_HIDE_CHROME);
Joe Onorato93056472010-09-10 10:30:46 -0400854 }
855
Daniel Sandlere02d8082010-10-08 15:13:22 -0400856 public void setMenuKeyVisible(boolean visible) {
857 if (DEBUG) {
858 Slog.d(TAG, (visible?"showing":"hiding") + " the MENU button");
859 }
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500860 mMenuButton.setVisibility(visible ? View.VISIBLE : View.GONE);
Daniel Sandler59485d742010-12-02 00:11:33 -0500861
862 // See above re: lights-out policy for legacy apps.
863 if (visible) setLightsOn(true);
Daniel Sandlere02d8082010-10-08 15:13:22 -0400864 }
865
satokcd7cd292010-11-20 15:46:23 +0900866 public void setIMEButtonVisible(IBinder token, boolean visible) {
satok06487a52010-10-29 11:37:18 +0900867 if (DEBUG) {
868 Slog.d(TAG, (visible?"showing":"hiding") + " the IME button");
869 }
satokcd7cd292010-11-20 15:46:23 +0900870 mInputMethodSwitchButton.setIMEButtonVisible(token, visible);
satok51133822011-01-25 15:01:48 +0900871 updateNotificationIcons();
satok913f42d2011-01-17 16:58:10 +0900872 mInputMethodsPanel.setImeToken(token);
Joe Onorato536c58f2010-11-28 17:52:28 -0800873 mBackButton.setImageResource(
874 visible ? R.drawable.ic_sysbar_back_ime : R.drawable.ic_sysbar_back);
Daniel Sandler10163c62010-12-08 11:51:05 -0500875 if (FAKE_SPACE_BAR) {
876 mFakeSpaceBar.setVisibility(visible ? View.VISIBLE : View.GONE);
877 }
satok06487a52010-10-29 11:37:18 +0900878 }
879
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800880 private boolean isImmersive() {
881 try {
882 return ActivityManagerNative.getDefault().isTopActivityImmersive();
883 //Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
884 } catch (RemoteException ex) {
885 // the end is nigh
886 return false;
887 }
888 }
Jim Miller85babff2011-01-11 14:26:03 -0800889
Joe Onorato5dd11692010-09-27 15:34:04 -0700890 private void setAreThereNotifications() {
891 final boolean hasClearable = mNotns.hasClearableItems();
Joe Onorato5dd11692010-09-27 15:34:04 -0700892 }
893
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400894 /**
895 * Cancel this notification and tell the status bar service about the failure. Hold no locks.
896 */
897 void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
898 removeNotification(key);
899 try {
900 mBarService.onNotificationError(n.pkg, n.tag, n.id, n.uid, n.initialPid, message);
901 } catch (RemoteException ex) {
902 // The end is nigh.
903 }
904 }
905
Daniel Sandler10163c62010-12-08 11:51:05 -0500906 private void sendKey(KeyEvent key) {
907 try {
908 if (DEBUG) Slog.d(TAG, "injecting key event: " + key);
909 mWindowManager.injectInputEventNoWait(key);
910 } catch (RemoteException ex) {
911 }
912 }
913
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400914 private View.OnClickListener mOnClickListener = new View.OnClickListener() {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400915 public void onClick(View v) {
Joe Onoratofd52b182010-11-10 18:00:52 -0800916 if (v == mNotificationTrigger) {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400917 onClickNotificationTrigger();
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400918 } else if (v == mRecentButton) {
919 onClickRecentButton();
satok82beadf2010-12-27 19:03:06 +0900920 } else if (v == mInputMethodSwitchButton) {
921 onClickInputMethodSwitchButton();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400922 }
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400923 }
924 };
925
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400926 public void onClickNotificationTrigger() {
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500927 if (DEBUG) Slog.d(TAG, "clicked notification icons; disabled=" + mDisabled);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400928 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
Daniel Sandler271ea122010-10-22 14:06:10 -0400929 if (!mNotificationsOn) {
930 mNotificationsOn = true;
Daniel Sandlercf3c7cf2010-10-22 15:30:12 -0400931 mIconLayout.setVisibility(View.VISIBLE); // TODO: animation
Daniel Sandler271ea122010-10-22 14:06:10 -0400932 } else {
Joe Onorato7c270fa2010-12-08 17:31:42 -0800933 int msg = !mNotificationPanel.isShowing()
Daniel Sandler271ea122010-10-22 14:06:10 -0400934 ? MSG_OPEN_NOTIFICATION_PANEL
935 : MSG_CLOSE_NOTIFICATION_PANEL;
936 mHandler.removeMessages(msg);
937 mHandler.sendEmptyMessage(msg);
938 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400939 }
940 }
941
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400942 public void onClickRecentButton() {
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500943 if (DEBUG) Slog.d(TAG, "clicked recent apps; disabled=" + mDisabled);
Jim Miller44c66fe2010-10-20 18:32:52 -0700944 if (mRecentsPanel == null) {
945 Intent intent = new Intent();
946 intent.setClass(mContext, RecentApplicationsActivity.class);
947 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
948 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
949 mContext.startActivity(intent);
950 } else {
951 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
952 int msg = (mRecentsPanel.getVisibility() == View.GONE)
953 ? MSG_OPEN_RECENTS_PANEL
954 : MSG_CLOSE_RECENTS_PANEL;
955 mHandler.removeMessages(msg);
956 mHandler.sendEmptyMessage(msg);
957 }
958 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400959 }
Joe Onorato55d2d762010-09-26 13:02:01 -0700960
satok82beadf2010-12-27 19:03:06 +0900961 public void onClickInputMethodSwitchButton() {
962 if (DEBUG) Slog.d(TAG, "clicked input methods panel; disabled=" + mDisabled);
963 int msg = (mInputMethodsPanel.getVisibility() == View.GONE) ?
964 MSG_OPEN_INPUT_METHODS_PANEL : MSG_CLOSE_INPUT_METHODS_PANEL;
965 mHandler.removeMessages(msg);
966 mHandler.sendEmptyMessage(msg);
967 }
968
Daniel Sandlerc51451a2010-12-16 19:06:46 -0500969 public NotificationClicker makeClicker(PendingIntent intent, String pkg, String tag, int id) {
970 return new NotificationClicker(intent, pkg, tag, id);
971 }
972
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400973 private class NotificationClicker implements View.OnClickListener {
974 private PendingIntent mIntent;
975 private String mPkg;
976 private String mTag;
977 private int mId;
978
979 NotificationClicker(PendingIntent intent, String pkg, String tag, int id) {
980 mIntent = intent;
981 mPkg = pkg;
982 mTag = tag;
983 mId = id;
984 }
985
986 public void onClick(View v) {
987 try {
988 // The intent we are sending is for the application, which
989 // won't have permission to immediately start an activity after
990 // the user switches to home. We know it is safe to do at this
991 // point, so make sure new activity switches are now allowed.
992 ActivityManagerNative.getDefault().resumeAppSwitches();
993 } catch (RemoteException e) {
994 }
995
996 if (mIntent != null) {
997 int[] pos = new int[2];
998 v.getLocationOnScreen(pos);
999 Intent overlay = new Intent();
1000 overlay.setSourceBounds(
1001 new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
1002 try {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001003 mIntent.send(mContext, 0, overlay);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001004 } catch (PendingIntent.CanceledException e) {
1005 // the stack trace isn't very helpful here. Just log the exception message.
1006 Slog.w(TAG, "Sending contentIntent failed: " + e);
1007 }
1008 }
1009
1010 try {
1011 mBarService.onNotificationClick(mPkg, mTag, mId);
1012 } catch (RemoteException ex) {
1013 // system process is dead if we're here.
1014 }
1015
1016 // close the shade if it was open
1017 animateCollapse();
1018
1019 // If this click was on the intruder alert, hide that instead
1020// mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
1021 }
1022 }
1023
1024 StatusBarNotification removeNotificationViews(IBinder key) {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001025 NotificationData.Entry entry = mNotns.remove(key);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001026 if (entry == null) {
1027 Slog.w(TAG, "removeNotification for unknown key: " + key);
1028 return null;
1029 }
1030 // Remove the expanded view.
1031 ViewGroup rowParent = (ViewGroup)entry.row.getParent();
1032 if (rowParent != null) rowParent.removeView(entry.row);
Daniel Sandlera8e5b062010-12-01 13:53:08 -05001033
1034 if (key == mNotificationPeekKey) {
1035 // must close the peek as well, since it's gone
1036 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
1037 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001038 // Remove the icon.
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001039// ViewGroup iconParent = (ViewGroup)entry.icon.getParent();
1040// if (iconParent != null) iconParent.removeView(entry.icon);
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001041 updateNotificationIcons();
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001042
1043 return entry.notification;
1044 }
1045
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001046 private class NotificationIconTouchListener implements View.OnTouchListener {
1047 VelocityTracker mVT;
1048
1049 public NotificationIconTouchListener() {
1050 }
1051
1052 public boolean onTouch(View v, MotionEvent event) {
1053 boolean peeking = mNotificationPeekWindow.getVisibility() != View.GONE;
Joe Onorato7c270fa2010-12-08 17:31:42 -08001054 boolean panelShowing = mNotificationPanel.isShowing();
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001055 if (panelShowing) return false;
1056
1057 switch (event.getAction()) {
1058 case MotionEvent.ACTION_DOWN:
1059 mVT = VelocityTracker.obtain();
1060
1061 // fall through
1062 case MotionEvent.ACTION_OUTSIDE:
1063 case MotionEvent.ACTION_MOVE:
1064 // peek and switch icons if necessary
1065 int numIcons = mIconLayout.getChildCount();
Joe Onorato5e759462010-11-28 17:43:50 -08001066 int peekIndex = (int)((float)event.getX() * numIcons / mIconLayout.getWidth());
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001067 if (peekIndex > numIcons - 1) peekIndex = numIcons - 1;
1068 else if (peekIndex < 0) peekIndex = 0;
1069
1070 if (!peeking || mNotificationPeekIndex != peekIndex) {
1071 if (DEBUG) Slog.d(TAG, "will peek at notification #" + peekIndex);
1072 Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
1073 peekMsg.arg1 = peekIndex;
1074
1075 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
1076
1077 // no delay if we're scrubbing left-right
Joe Onorato5e759462010-11-28 17:43:50 -08001078 mHandler.sendMessage(peekMsg);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001079 }
1080
1081 // check for fling
1082 if (mVT != null) {
1083 mVT.addMovement(event);
1084 mVT.computeCurrentVelocity(1000);
1085 // require a little more oomph once we're already in peekaboo mode
1086 if (!panelShowing && (
1087 (peeking && mVT.getYVelocity() < -mNotificationFlingVelocity*3)
1088 || (mVT.getYVelocity() < -mNotificationFlingVelocity))) {
1089 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
1090 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
1091 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
1092 mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
1093 }
1094 }
1095 return true;
1096 case MotionEvent.ACTION_UP:
1097 case MotionEvent.ACTION_CANCEL:
1098 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
1099 if (peeking) {
Joe Onorato5e759462010-11-28 17:43:50 -08001100 mHandler.sendEmptyMessageDelayed(MSG_CLOSE_NOTIFICATION_PEEK, 5000);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001101 }
1102 mVT.recycle();
1103 mVT = null;
1104 return true;
1105 }
1106 return false;
1107 }
1108 }
1109
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001110 StatusBarIconView addNotificationViews(IBinder key, StatusBarNotification notification) {
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001111 if (DEBUG) {
1112 Slog.d(TAG, "addNotificationViews(key=" + key + ", notification=" + notification);
1113 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001114 // Construct the icon.
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001115 final StatusBarIconView iconView = new StatusBarIconView(mContext,
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001116 notification.pkg + "/0x" + Integer.toHexString(notification.id));
1117 iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
1118
1119 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
1120 notification.notification.icon,
1121 notification.notification.iconLevel,
1122 notification.notification.number);
1123 if (!iconView.set(ic)) {
1124 handleNotificationError(key, notification, "Couldn't attach StatusBarIcon: " + ic);
1125 return null;
1126 }
1127 // Construct the expanded view.
1128 NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001129 if (!inflateViews(entry, mPile)) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001130 handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
1131 + notification);
1132 return null;
1133 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001134
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001135 // Add the icon.
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001136 mNotns.add(entry);
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001137 updateNotificationIcons();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001138
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001139 return iconView;
1140 }
1141
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001142 private void reloadAllNotificationIcons() {
1143 if (mIconLayout == null) return;
1144 mIconLayout.removeAllViews();
1145 updateNotificationIcons();
1146 }
1147
1148 private void updateNotificationIcons() {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001149 // XXX: need to implement a new limited linear layout class
1150 // to avoid removing & readding everything
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001151
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001152 if (mIconLayout == null) return;
1153
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001154 final LinearLayout.LayoutParams params
Joe Onoratodc100302011-01-11 17:07:41 -08001155 = new LinearLayout.LayoutParams(mIconSize + 2*mIconHPadding, mNaturalBarHeight);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001156
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001157 int N = mNotns.size();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001158
1159 if (DEBUG) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001160 Slog.d(TAG, "refreshing icons: " + N + " notifications, mIconLayout=" + mIconLayout);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001161 }
1162
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001163 ArrayList<View> toShow = new ArrayList<View>();
1164
satok82beadf2010-12-27 19:03:06 +09001165 // When IME button is visible, the number of notification icons should be decremented
1166 // to fit the upper limit.
1167 final int maxNotificationIconsCount =
1168 (mInputMethodSwitchButton.getVisibility() != View.GONE) ?
1169 MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE : MAX_NOTIFICATION_ICONS;
1170 for (int i=0; i< maxNotificationIconsCount; i++) {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001171 if (i>=N) break;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001172 toShow.add(mNotns.get(N-i-1).icon);
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001173 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001174
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001175 ArrayList<View> toRemove = new ArrayList<View>();
1176 for (int i=0; i<mIconLayout.getChildCount(); i++) {
1177 View child = mIconLayout.getChildAt(i);
1178 if (!toShow.contains(child)) {
1179 toRemove.add(child);
1180 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001181 }
Daniel Sandler271ea122010-10-22 14:06:10 -04001182
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001183 for (View remove : toRemove) {
1184 mIconLayout.removeView(remove);
1185 }
1186
1187 for (int i=0; i<toShow.size(); i++) {
1188 View v = toShow.get(i);
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001189 v.setPadding(mIconHPadding, 0, mIconHPadding, 0);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001190 if (v.getParent() == null) {
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001191 mIconLayout.addView(v, i, params);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001192 }
1193 }
1194
1195 loadNotificationPanel();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001196 }
1197
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001198 private void loadNotificationPanel() {
1199 int N = mNotns.size();
1200
1201 ArrayList<View> toShow = new ArrayList<View>();
1202
1203 for (int i=0; i<N; i++) {
1204 View row = mNotns.get(N-i-1).row;
1205 toShow.add(row);
1206 }
1207
1208 ArrayList<View> toRemove = new ArrayList<View>();
1209 for (int i=0; i<mPile.getChildCount(); i++) {
1210 View child = mPile.getChildAt(i);
1211 if (!toShow.contains(child)) {
1212 toRemove.add(child);
1213 }
1214 }
1215
1216 for (View remove : toRemove) {
1217 mPile.removeView(remove);
1218 }
1219
1220 for (int i=0; i<toShow.size(); i++) {
1221 View v = toShow.get(i);
1222 if (v.getParent() == null) {
1223 mPile.addView(toShow.get(i));
1224 }
1225 }
Daniel Sandler40c15452011-01-22 01:26:22 -05001226
1227 mNotificationPanel.setNotificationCount(N);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001228 }
1229
Joe Onorato4daaeaf2010-11-17 20:43:12 -08001230 void workAroundBadLayerDrawableOpacity(View v) {
1231 LayerDrawable d = (LayerDrawable)v.getBackground();
Daniel Sandlerf844dc42011-01-24 23:44:47 -05001232 if (d == null) return;
Joe Onorato4daaeaf2010-11-17 20:43:12 -08001233 v.setBackgroundDrawable(null);
1234 d.setOpacity(PixelFormat.TRANSLUCENT);
1235 v.setBackgroundDrawable(d);
1236 }
1237
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001238 private boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) {
1239 StatusBarNotification sbn = entry.notification;
1240 RemoteViews remoteViews = sbn.notification.contentView;
1241 if (remoteViews == null) {
1242 return false;
1243 }
1244
1245 // create the row view
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001246 LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(
1247 Context.LAYOUT_INFLATER_SERVICE);
Joe Onorato755cc742010-11-27 15:45:35 -08001248 View row = inflater.inflate(R.layout.status_bar_notification_row, parent, false);
Joe Onorato4daaeaf2010-11-17 20:43:12 -08001249 workAroundBadLayerDrawableOpacity(row);
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001250 View vetoButton = row.findViewById(R.id.veto);
Joe Onoratoa4a65032010-09-27 15:53:44 -07001251 if (entry.notification.isClearable()) {
1252 final String _pkg = sbn.pkg;
1253 final String _tag = sbn.tag;
1254 final int _id = sbn.id;
Jim Miller44c66fe2010-10-20 18:32:52 -07001255 vetoButton.setOnClickListener(new View.OnClickListener() {
Joe Onoratoa4a65032010-09-27 15:53:44 -07001256 public void onClick(View v) {
1257 try {
1258 mBarService.onNotificationClear(_pkg, _tag, _id);
1259 } catch (RemoteException ex) {
1260 // system process is dead if we're here.
1261 }
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001262 }
Joe Onoratoa4a65032010-09-27 15:53:44 -07001263 });
1264 } else {
Joe Onorato100748e2011-01-07 11:03:54 -08001265 if ((sbn.notification.flags & Notification.FLAG_ONGOING_EVENT) == 0) {
1266 vetoButton.setVisibility(View.INVISIBLE);
1267 } else {
1268 vetoButton.setVisibility(View.GONE);
1269 }
Joe Onoratoa4a65032010-09-27 15:53:44 -07001270 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001271
Joe Onorato561d3852010-11-20 18:09:34 -08001272 // the large icon
1273 ImageView largeIcon = (ImageView)row.findViewById(R.id.large_icon);
1274 if (sbn.notification.largeIcon != null) {
1275 largeIcon.setImageBitmap(sbn.notification.largeIcon);
1276 } else {
1277 largeIcon.getLayoutParams().width = 0;
1278 largeIcon.setVisibility(View.INVISIBLE);
1279 }
1280
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001281 // bind the click event to the content area
1282 ViewGroup content = (ViewGroup)row.findViewById(R.id.content);
1283 // XXX: update to allow controls within notification views
1284 content.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
1285// content.setOnFocusChangeListener(mFocusChangeListener);
1286 PendingIntent contentIntent = sbn.notification.contentIntent;
1287 if (contentIntent != null) {
1288 content.setOnClickListener(new NotificationClicker(contentIntent,
1289 sbn.pkg, sbn.tag, sbn.id));
Joe Onorato184498c2010-10-08 17:57:18 -04001290 } else {
1291 content.setOnClickListener(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001292 }
1293
1294 View expanded = null;
1295 Exception exception = null;
1296 try {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001297 expanded = remoteViews.apply(mContext, content);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001298 }
1299 catch (RuntimeException e) {
1300 exception = e;
1301 }
1302 if (expanded == null) {
Joe Onorato46439ce2010-11-19 13:56:21 -08001303 final String ident = sbn.pkg + "/0x" + Integer.toHexString(sbn.id);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001304 Slog.e(TAG, "couldn't inflate view for notification " + ident, exception);
1305 return false;
1306 } else {
1307 content.addView(expanded);
1308 row.setDrawingCacheEnabled(true);
1309 }
1310
1311 entry.row = row;
1312 entry.content = content;
1313 entry.expanded = expanded;
Joe Onorato80a44402011-01-15 16:22:24 -08001314 entry.largeIcon = largeIcon;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001315
1316 return true;
1317 }
Daniel Sandlerce70d912010-09-02 11:59:41 -04001318
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001319/*
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001320 public class ShadowController {
1321 boolean mShowShadows;
Daniel Sandlerb9606992010-11-19 14:47:59 -05001322 Map<View, View> mShadowsForElements = new IdentityHashMap<View, View>(7);
1323 Map<View, View> mElementsForShadows = new IdentityHashMap<View, View>(7);
1324 LayoutTransition mElementTransition, mShadowTransition;
1325
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001326 View mTouchTarget;
Daniel Sandlerce70d912010-09-02 11:59:41 -04001327
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001328 ShadowController(boolean showShadows) {
1329 mShowShadows = showShadows;
1330 mTouchTarget = null;
Daniel Sandlerb9606992010-11-19 14:47:59 -05001331
1332 mElementTransition = new LayoutTransition();
1333// AnimatorSet s = new AnimatorSet();
1334// s.play(ObjectAnimator.ofInt(null, "top", 48, 0))
1335// .with(ObjectAnimator.ofFloat(null, "scaleY", 0.5f, 1f))
1336// .with(ObjectAnimator.ofFloat(null, "alpha", 0.5f, 1f))
1337// ;
1338 mElementTransition.setAnimator(LayoutTransition.APPEARING, //s);
1339 ObjectAnimator.ofInt(null, "top", 48, 0));
1340 mElementTransition.setDuration(LayoutTransition.APPEARING, 100);
1341 mElementTransition.setStartDelay(LayoutTransition.APPEARING, 0);
1342
1343// s = new AnimatorSet();
1344// s.play(ObjectAnimator.ofInt(null, "top", 0, 48))
1345// .with(ObjectAnimator.ofFloat(null, "scaleY", 1f, 0.5f))
1346// .with(ObjectAnimator.ofFloat(null, "alpha", 1f, 0.5f))
1347// ;
1348 mElementTransition.setAnimator(LayoutTransition.DISAPPEARING, //s);
1349 ObjectAnimator.ofInt(null, "top", 0, 48));
1350 mElementTransition.setDuration(LayoutTransition.DISAPPEARING, 400);
1351
1352 mShadowTransition = new LayoutTransition();
Jim Miller85babff2011-01-11 14:26:03 -08001353 mShadowTransition.setAnimator(LayoutTransition.APPEARING,
Daniel Sandlerb9606992010-11-19 14:47:59 -05001354 ObjectAnimator.ofFloat(null, "alpha", 0f, 1f));
1355 mShadowTransition.setDuration(LayoutTransition.APPEARING, 200);
1356 mShadowTransition.setStartDelay(LayoutTransition.APPEARING, 100);
Jim Miller85babff2011-01-11 14:26:03 -08001357 mShadowTransition.setAnimator(LayoutTransition.DISAPPEARING,
Daniel Sandlerb9606992010-11-19 14:47:59 -05001358 ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
1359 mShadowTransition.setDuration(LayoutTransition.DISAPPEARING, 100);
1360
1361 ViewGroup bar = (ViewGroup) TabletStatusBar.this.mBarContents;
1362 bar.setLayoutTransition(mElementTransition);
1363 ViewGroup nav = (ViewGroup) TabletStatusBar.this.mNavigationArea;
1364 nav.setLayoutTransition(mElementTransition);
1365 ViewGroup shadowGroup = (ViewGroup) bar.findViewById(R.id.shadows);
1366 shadowGroup.setLayoutTransition(mShadowTransition);
1367 }
1368
1369 public void add(View element, View shadow) {
1370 shadow.setOnTouchListener(makeTouchListener());
1371 mShadowsForElements.put(element, shadow);
1372 mElementsForShadows.put(shadow, element);
Joe Onoratof63b0f42010-09-12 17:03:19 -04001373 }
1374
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001375 public boolean getShadowState() {
1376 return mShowShadows;
Joe Onoratof63b0f42010-09-12 17:03:19 -04001377 }
1378
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001379 public View.OnTouchListener makeTouchListener() {
1380 return new View.OnTouchListener() {
1381 public boolean onTouch(View v, MotionEvent ev) {
1382 final int action = ev.getAction();
1383
1384 if (DEBUG) Slog.d(TAG, "ShadowController: v=" + v + ", ev=" + ev);
1385
1386 // currently redirecting events?
1387 if (mTouchTarget == null) {
Daniel Sandlerb9606992010-11-19 14:47:59 -05001388 mTouchTarget = mElementsForShadows.get(v);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001389 }
1390
1391 if (mTouchTarget != null && mTouchTarget.getVisibility() != View.GONE) {
1392 boolean last = false;
1393 switch (action) {
1394 case MotionEvent.ACTION_CANCEL:
1395 case MotionEvent.ACTION_UP:
Daniel Sandlere03d1bc2010-11-17 21:36:40 -05001396 mHandler.removeMessages(MSG_RESTORE_SHADOWS);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001397 if (mShowShadows) {
Jim Miller85babff2011-01-11 14:26:03 -08001398 mHandler.sendEmptyMessageDelayed(MSG_RESTORE_SHADOWS,
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001399 v == mNotificationShadow ? 5000 : 500);
1400 }
1401 last = true;
1402 break;
1403 case MotionEvent.ACTION_DOWN:
Daniel Sandlere03d1bc2010-11-17 21:36:40 -05001404 mHandler.removeMessages(MSG_RESTORE_SHADOWS);
Daniel Sandlerb9606992010-11-19 14:47:59 -05001405 setElementShadow(mTouchTarget, false);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001406 break;
1407 }
1408 mTouchTarget.dispatchTouchEvent(ev);
1409 if (last) mTouchTarget = null;
1410 return true;
1411 }
1412
1413 return false;
1414 }
1415 };
Joe Onoratof63b0f42010-09-12 17:03:19 -04001416 }
1417
Daniel Sandlere03d1bc2010-11-17 21:36:40 -05001418 public void refresh() {
Daniel Sandlerb9606992010-11-19 14:47:59 -05001419 for (View element : mShadowsForElements.keySet()) {
1420 setElementShadow(element, mShowShadows);
1421 }
Daniel Sandlere03d1bc2010-11-17 21:36:40 -05001422 }
1423
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001424 public void showAllShadows() {
1425 mShowShadows = true;
Daniel Sandlere03d1bc2010-11-17 21:36:40 -05001426 refresh();
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001427 }
1428
1429 public void hideAllShadows() {
1430 mShowShadows = false;
Daniel Sandlere03d1bc2010-11-17 21:36:40 -05001431 refresh();
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001432 }
1433
1434 // Use View.INVISIBLE for things hidden due to shadowing, and View.GONE for things that are
1435 // disabled (and should not be shadowed or re-shown)
Daniel Sandlerb9606992010-11-19 14:47:59 -05001436 public void setElementShadow(View button, boolean shade) {
1437 View shadow = mShadowsForElements.get(button);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001438 if (shadow != null) {
1439 if (button.getVisibility() != View.GONE) {
1440 shadow.setVisibility(shade ? View.VISIBLE : View.INVISIBLE);
1441 button.setVisibility(shade ? View.INVISIBLE : View.VISIBLE);
1442 }
1443 }
1444 }
Daniel Sandlerb9606992010-11-19 14:47:59 -05001445
1446 // Hide both element and shadow, using default layout animations.
1447 public void hideElement(View button) {
1448 Slog.d(TAG, "hiding: " + button);
1449 View shadow = mShadowsForElements.get(button);
1450 if (shadow != null) {
1451 shadow.setVisibility(View.GONE);
1452 }
1453 button.setVisibility(View.GONE);
1454 }
1455
1456 // Honoring the current shadow state.
1457 public void showElement(View button) {
1458 Slog.d(TAG, "showing: " + button);
1459 View shadow = mShadowsForElements.get(button);
1460 if (shadow != null) {
1461 shadow.setVisibility(mShowShadows ? View.VISIBLE : View.INVISIBLE);
1462 }
1463 button.setVisibility(mShowShadows ? View.INVISIBLE : View.VISIBLE);
1464 }
Daniel Sandlerce70d912010-09-02 11:59:41 -04001465 }
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001466 */
Joe Onoratob62ac122010-09-20 16:16:32 -04001467
1468 public class TouchOutsideListener implements View.OnTouchListener {
1469 private int mMsg;
Joe Onoratoddf680b2010-09-26 13:59:40 -07001470 private StatusBarPanel mPanel;
Joe Onoratob62ac122010-09-20 16:16:32 -04001471
Joe Onoratoddf680b2010-09-26 13:59:40 -07001472 public TouchOutsideListener(int msg, StatusBarPanel panel) {
Joe Onoratob62ac122010-09-20 16:16:32 -04001473 mMsg = msg;
Joe Onoratoddf680b2010-09-26 13:59:40 -07001474 mPanel = panel;
Joe Onoratob62ac122010-09-20 16:16:32 -04001475 }
1476
1477 public boolean onTouch(View v, MotionEvent ev) {
Joe Onoratoddf680b2010-09-26 13:59:40 -07001478 final int action = ev.getAction();
1479 if (action == MotionEvent.ACTION_OUTSIDE
1480 || (action == MotionEvent.ACTION_DOWN
1481 && !mPanel.isInContentArea((int)ev.getX(), (int)ev.getY()))) {
Joe Onoratob62ac122010-09-20 16:16:32 -04001482 mHandler.removeMessages(mMsg);
1483 mHandler.sendEmptyMessage(mMsg);
1484 return true;
1485 }
1486 return false;
1487 }
1488 }
Joe Onorato091e1b82010-09-26 18:04:44 -07001489
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001490 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1491 pw.print("mDisabled=0x");
1492 pw.println(Integer.toHexString(mDisabled));
Joe Onorato933464d2011-01-05 15:53:36 -08001493 pw.println("mNetworkController:");
1494 mNetworkController.dump(fd, pw, args);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001495 }
Joe Onorato808182d2010-07-09 18:52:06 -04001496}
Daniel Sandlerd39e3882010-08-31 14:16:13 -04001497
1498