blob: fd044187c4a6d1b91b560c9509aaec51a7cf170c [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;
Joe Onorato857fd9b2011-01-27 15:08:35 -080036import android.inputmethodservice.InputMethodService;
Daniel Sandler9120d552010-07-23 09:11:14 -040037import android.graphics.PixelFormat;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040038import android.graphics.Rect;
Joe Onorato4daaeaf2010-11-17 20:43:12 -080039import android.graphics.drawable.Drawable;
40import android.graphics.drawable.LayerDrawable;
Daniel Sandler9120d552010-07-23 09:11:14 -040041import android.os.Handler;
Joe Onorato808182d2010-07-09 18:52:06 -040042import android.os.IBinder;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040043import android.os.Message;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040044import android.os.RemoteException;
Daniel Sandler10163c62010-12-08 11:51:05 -050045import android.os.ServiceManager;
Joe Onoratoef1e7762010-09-17 18:38:38 -040046import android.text.TextUtils;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040047import android.util.Slog;
Joe Onorato55d2d762010-09-26 13:02:01 -070048import android.view.animation.Animation;
Daniel Sandlerce70d912010-09-02 11:59:41 -040049import android.view.animation.AnimationUtils;
Joe Onorato808182d2010-07-09 18:52:06 -040050import android.view.Gravity;
Daniel Sandler10163c62010-12-08 11:51:05 -050051import android.view.IWindowManager;
52import android.view.KeyEvent;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040053import android.view.LayoutInflater;
Joe Onoratob62ac122010-09-20 16:16:32 -040054import android.view.MotionEvent;
Daniel Sandler8304da42010-10-25 15:53:25 -040055import android.view.VelocityTracker;
Joe Onorato808182d2010-07-09 18:52:06 -040056import android.view.View;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -040057import android.view.ViewConfiguration;
Daniel Sandler9120d552010-07-23 09:11:14 -040058import android.view.ViewGroup;
59import android.view.WindowManager;
60import android.view.WindowManagerImpl;
Joe Onoratoef1e7762010-09-17 18:38:38 -040061import android.widget.FrameLayout;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040062import android.widget.ImageView;
Joe Onorato808182d2010-07-09 18:52:06 -040063import android.widget.LinearLayout;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040064import android.widget.RemoteViews;
65import android.widget.ScrollView;
66import android.widget.TextSwitcher;
Daniel Sandler9120d552010-07-23 09:11:14 -040067import android.widget.TextView;
Joe Onorato808182d2010-07-09 18:52:06 -040068
69import com.android.internal.statusbar.StatusBarIcon;
Joe Onorato808182d2010-07-09 18:52:06 -040070import com.android.internal.statusbar.StatusBarNotification;
71
Joe Onorato808182d2010-07-09 18:52:06 -040072import com.android.systemui.R;
Joe Onoratofd52b182010-11-10 18:00:52 -080073import com.android.systemui.statusbar.*;
74import com.android.systemui.statusbar.policy.BatteryController;
75import com.android.systemui.statusbar.policy.NetworkController;
76import com.android.systemui.recent.RecentApplicationsActivity;
Joe Onorato808182d2010-07-09 18:52:06 -040077
Joe Onoratodc100302011-01-11 17:07:41 -080078public class TabletStatusBar extends StatusBar implements
79 HeightReceiver.OnBarHeightChangedListener {
Daniel Sandlerfb970e92010-08-20 10:57:17 -040080 public static final boolean DEBUG = false;
Joe Onoratofd52b182010-11-10 18:00:52 -080081 public static final String TAG = "TabletStatusBar";
Joe Onorato808182d2010-07-09 18:52:06 -040082
Daniel Sandler0ad460b2010-12-14 12:14:53 -050083 public static final int MAX_NOTIFICATION_ICONS = 5;
satok82beadf2010-12-27 19:03:06 +090084 // IME switcher icon is big and occupy width of two icons
satok51133822011-01-25 15:01:48 +090085 public static final int MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE = MAX_NOTIFICATION_ICONS - 1;
Daniel Sandler0ad460b2010-12-14 12:14:53 -050086
Joe Onoratob62ac122010-09-20 16:16:32 -040087 public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
88 public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -040089 public static final int MSG_OPEN_NOTIFICATION_PEEK = 1002;
90 public static final int MSG_CLOSE_NOTIFICATION_PEEK = 1003;
Jim Miller44c66fe2010-10-20 18:32:52 -070091 public static final int MSG_OPEN_RECENTS_PANEL = 1020;
92 public static final int MSG_CLOSE_RECENTS_PANEL = 1021;
Daniel Sandler0ad460b2010-12-14 12:14:53 -050093 public static final int MSG_SHOW_CHROME = 1030;
94 public static final int MSG_HIDE_CHROME = 1031;
satok82beadf2010-12-27 19:03:06 +090095 public static final int MSG_OPEN_INPUT_METHODS_PANEL = 1040;
96 public static final int MSG_CLOSE_INPUT_METHODS_PANEL = 1041;
Jim Miller44c66fe2010-10-20 18:32:52 -070097
Daniel Sandler10163c62010-12-08 11:51:05 -050098 // Fitts' Law assistance for LatinIME; TODO: replace with a more general approach
99 private static final boolean FAKE_SPACE_BAR = true;
100
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500101 public static final int LIGHTS_ON_DELAY = 5000;
102
Joe Onoratodc100302011-01-11 17:07:41 -0800103 // The height of the bar, as definied by the build. It may be taller if we're plugged
104 // into hdmi.
105 int mNaturalBarHeight = -1;
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500106 int mIconSize = -1;
107 int mIconHPadding = -1;
Daniel Sandler9120d552010-07-23 09:11:14 -0400108
109 H mHandler = new H();
110
Daniel Sandler10163c62010-12-08 11:51:05 -0500111 IWindowManager mWindowManager;
112
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400113 // tracking all current notifications
114 private NotificationData mNotns = new NotificationData();
Jim Miller44c66fe2010-10-20 18:32:52 -0700115
Joe Onoratob62ac122010-09-20 16:16:32 -0400116 TabletStatusBarView mStatusBarView;
Joe Onoratofd52b182010-11-10 18:00:52 -0800117 View mNotificationArea;
118 View mNotificationTrigger;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400119 NotificationIconArea mNotificationIconArea;
Joe Onorato091e1b82010-09-26 18:04:44 -0700120 View mNavigationArea;
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500121
Joe Onorato536c58f2010-11-28 17:52:28 -0800122 ImageView mBackButton;
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500123 View mHomeButton;
Daniel Sandlere02d8082010-10-08 15:13:22 -0400124 View mMenuButton;
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400125 View mRecentButton;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400126
Joe Onoratoec51a822011-01-04 16:33:01 -0800127 ViewGroup mNotificationAndImeArea;
satokcd7cd292010-11-20 15:46:23 +0900128 InputMethodButton mInputMethodSwitchButton;
satok06487a52010-10-29 11:37:18 +0900129
Joe Onoratoddf680b2010-09-26 13:59:40 -0700130 NotificationPanel mNotificationPanel;
Joe Onorato8a576712010-11-15 16:50:34 -0800131 NotificationPeekPanel mNotificationPeekWindow;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400132 ViewGroup mNotificationPeekRow;
133 int mNotificationPeekIndex;
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500134 IBinder mNotificationPeekKey;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400135 LayoutTransition mNotificationPeekScrubLeft, mNotificationPeekScrubRight;
136
137 int mNotificationPeekTapDuration;
138 int mNotificationFlingVelocity;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400139
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400140 ViewGroup mPile;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400141
Joe Onoratodc100302011-01-11 17:07:41 -0800142 HeightReceiver mHeightReceiver;
Joe Onoratofd52b182010-11-10 18:00:52 -0800143 BatteryController mBatteryController;
144 NetworkController mNetworkController;
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400145
Daniel Sandlerce70d912010-09-02 11:59:41 -0400146 View mBarContents;
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500147
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500148 // hide system chrome ("lights out") support
149 View mShadow;
Daniel Sandlerce70d912010-09-02 11:59:41 -0400150
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400151 NotificationIconArea.IconLayout mIconLayout;
152
Joe Onoratoef1e7762010-09-17 18:38:38 -0400153 TabletTicker mTicker;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400154
Daniel Sandler10163c62010-12-08 11:51:05 -0500155 View mFakeSpaceBar;
156 KeyEvent mSpaceBarKeyEvent = null;
157
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400158 // for disabling the status bar
159 int mDisabled = 0;
160
Joe Onorato55d2d762010-09-26 13:02:01 -0700161 boolean mNotificationsOn = true;
Jim Miller44c66fe2010-10-20 18:32:52 -0700162 private RecentAppsPanel mRecentsPanel;
satok82beadf2010-12-27 19:03:06 +0900163 private InputMethodsPanel mInputMethodsPanel;
Joe Onorato55d2d762010-09-26 13:02:01 -0700164
Daniel Sandlerc51451a2010-12-16 19:06:46 -0500165 public Context getContext() { return mContext; }
166
Daniel Sandler9120d552010-07-23 09:11:14 -0400167 protected void addPanelWindows() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400168 final Context context = mContext;
169
Jim Miller44c66fe2010-10-20 18:32:52 -0700170 // Notification Panel
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400171 mNotificationPanel = (NotificationPanel)View.inflate(context,
Joe Onorato755cc742010-11-27 15:45:35 -0800172 R.layout.status_bar_notification_panel, null);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800173 mNotificationPanel.show(false, false);
Joe Onoratob62ac122010-09-20 16:16:32 -0400174 mNotificationPanel.setOnTouchListener(
Joe Onoratoddf680b2010-09-26 13:59:40 -0700175 new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PANEL, mNotificationPanel));
Joe Onoratob62ac122010-09-20 16:16:32 -0400176
Joe Onoratofd52b182010-11-10 18:00:52 -0800177 // the battery and network icons
178 mBatteryController.addIconView((ImageView)mNotificationPanel.findViewById(R.id.battery));
179 mBatteryController.addLabelView(
180 (TextView)mNotificationPanel.findViewById(R.id.battery_text));
Joe Onoratoddbba422010-11-23 15:42:28 -0800181 mNetworkController.addCombinedSignalIconView(
Joe Onorato42f8e132010-11-29 15:52:43 -0800182 (ImageView)mNotificationPanel.findViewById(R.id.network_signal));
183 mNetworkController.addDataTypeIconView(
184 (ImageView)mNotificationPanel.findViewById(R.id.network_type));
Joe Onoratofd52b182010-11-10 18:00:52 -0800185 mNetworkController.addLabelView(
186 (TextView)mNotificationPanel.findViewById(R.id.network_text));
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500187 mNetworkController.addLabelView(
188 (TextView)mBarContents.findViewById(R.id.network_text));
Joe Onoratofd52b182010-11-10 18:00:52 -0800189
Joe Onorato55d2d762010-09-26 13:02:01 -0700190 mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400191
Daniel Sandler9120d552010-07-23 09:11:14 -0400192 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
Daniel Sandleradd26202011-01-20 02:53:43 -0500193 512, // ViewGroup.LayoutParams.MATCH_PARENT,
Joe Onoratocf2b1992010-11-16 21:36:42 -0800194 ViewGroup.LayoutParams.MATCH_PARENT,
Daniel Sandler9120d552010-07-23 09:11:14 -0400195 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
196 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
Jeff Brown46e75292010-11-10 16:53:45 -0800197 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
Joe Onorato7c270fa2010-12-08 17:31:42 -0800198 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
199 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
Daniel Sandler9120d552010-07-23 09:11:14 -0400200 PixelFormat.TRANSLUCENT);
Joe Onoratoea70e632010-09-27 17:59:37 -0700201 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
Daniel Sandler9120d552010-07-23 09:11:14 -0400202 lp.setTitle("NotificationPanel");
Joe Onorato7c270fa2010-12-08 17:31:42 -0800203 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
204 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
205 lp.windowAnimations = com.android.internal.R.style.Animation; // == no animation
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500206// lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
Daniel Sandler9120d552010-07-23 09:11:14 -0400207
208 WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
209
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400210 // Notification preview window
Joe Onorato8a576712010-11-15 16:50:34 -0800211 mNotificationPeekWindow = (NotificationPeekPanel) View.inflate(context,
Joe Onorato755cc742010-11-27 15:45:35 -0800212 R.layout.status_bar_notification_peek, null);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400213 mNotificationPeekRow = (ViewGroup) mNotificationPeekWindow.findViewById(R.id.content);
214 mNotificationPeekWindow.setVisibility(View.GONE);
215 mNotificationPeekWindow.setOnTouchListener(
Joe Onorato5e759462010-11-28 17:43:50 -0800216 new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PEEK, mNotificationPeekWindow));
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400217 mNotificationPeekScrubRight = new LayoutTransition();
Jim Miller85babff2011-01-11 14:26:03 -0800218 mNotificationPeekScrubRight.setAnimator(LayoutTransition.APPEARING,
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400219 ObjectAnimator.ofInt(null, "left", -512, 0));
Jim Miller85babff2011-01-11 14:26:03 -0800220 mNotificationPeekScrubRight.setAnimator(LayoutTransition.DISAPPEARING,
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400221 ObjectAnimator.ofInt(null, "left", -512, 0));
222 mNotificationPeekScrubRight.setDuration(500);
223
224 mNotificationPeekScrubLeft = new LayoutTransition();
Jim Miller85babff2011-01-11 14:26:03 -0800225 mNotificationPeekScrubLeft.setAnimator(LayoutTransition.APPEARING,
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400226 ObjectAnimator.ofInt(null, "left", 512, 0));
Jim Miller85babff2011-01-11 14:26:03 -0800227 mNotificationPeekScrubLeft.setAnimator(LayoutTransition.DISAPPEARING,
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400228 ObjectAnimator.ofInt(null, "left", 512, 0));
229 mNotificationPeekScrubLeft.setDuration(500);
230
231 // XXX: setIgnoreChildren?
232 lp = new WindowManager.LayoutParams(
233 512, // ViewGroup.LayoutParams.WRAP_CONTENT,
234 ViewGroup.LayoutParams.WRAP_CONTENT,
235 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
236 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
Jeff Brown46e75292010-11-10 16:53:45 -0800237 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
238 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400239 PixelFormat.TRANSLUCENT);
240 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
241 lp.setTitle("NotificationPeekWindow");
242 lp.windowAnimations = com.android.internal.R.style.Animation_Toast;
243
244 WindowManagerImpl.getDefault().addView(mNotificationPeekWindow, lp);
245
Jim Miller44c66fe2010-10-20 18:32:52 -0700246 // Recents Panel
Jim Miller85babff2011-01-11 14:26:03 -0800247 mRecentsPanel = (RecentAppsPanel) View.inflate(context,
248 R.layout.status_bar_recent_panel, null);
249 mRecentsPanel.setVisibility(View.GONE);
250 mRecentsPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL,
251 mRecentsPanel));
252 mStatusBarView.setIgnoreChildren(2, mRecentButton, mRecentsPanel);
Jim Miller44c66fe2010-10-20 18:32:52 -0700253
Jim Miller85babff2011-01-11 14:26:03 -0800254 lp = new WindowManager.LayoutParams(
255 ViewGroup.LayoutParams.WRAP_CONTENT,
256 ViewGroup.LayoutParams.WRAP_CONTENT,
257 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
258 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
259 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
260 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
261 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
262 PixelFormat.TRANSLUCENT);
263 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
264 lp.setTitle("RecentsPanel");
265 lp.windowAnimations = R.style.Animation_RecentPanel;
Jim Miller44c66fe2010-10-20 18:32:52 -0700266
Jim Miller85babff2011-01-11 14:26:03 -0800267 WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
268 mRecentsPanel.setBar(this);
satok82beadf2010-12-27 19:03:06 +0900269
270 // Input methods Panel
271 mInputMethodsPanel = (InputMethodsPanel) View.inflate(context,
272 R.layout.status_bar_input_methods_panel, null);
273 mInputMethodsPanel.setVisibility(View.GONE);
274 mInputMethodsPanel.setOnTouchListener(new TouchOutsideListener(
275 MSG_CLOSE_INPUT_METHODS_PANEL, mInputMethodsPanel));
satok913f42d2011-01-17 16:58:10 +0900276 mInputMethodsPanel.setImeSwitchButton(mInputMethodSwitchButton);
satok82beadf2010-12-27 19:03:06 +0900277 mStatusBarView.setIgnoreChildren(3, mInputMethodSwitchButton, mInputMethodsPanel);
278 lp = new WindowManager.LayoutParams(
279 ViewGroup.LayoutParams.WRAP_CONTENT,
280 ViewGroup.LayoutParams.WRAP_CONTENT,
281 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
282 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
283 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
284 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
285 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
286 PixelFormat.TRANSLUCENT);
287 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
288 lp.setTitle("InputMethodsPanel");
289 lp.windowAnimations = R.style.Animation_RecentPanel;
290
291 WindowManagerImpl.getDefault().addView(mInputMethodsPanel, lp);
Daniel Sandler9120d552010-07-23 09:11:14 -0400292 }
Joe Onorato808182d2010-07-09 18:52:06 -0400293
294 @Override
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400295 public void start() {
296 super.start(); // will add the main bar view
Joe Onorato808182d2010-07-09 18:52:06 -0400297 }
298
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500299 @Override
Joe Onoratodc100302011-01-11 17:07:41 -0800300 protected void onConfigurationChanged(Configuration newConfig) {
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500301 loadDimens();
302 }
303
304 protected void loadDimens() {
305 final Resources res = mContext.getResources();
306
Joe Onoratodc100302011-01-11 17:07:41 -0800307 mNaturalBarHeight = res.getDimensionPixelSize(
308 com.android.internal.R.dimen.status_bar_height);
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500309
310 int newIconSize = res.getDimensionPixelSize(
311 com.android.internal.R.dimen.status_bar_icon_size);
312 int newIconHPadding = res.getDimensionPixelSize(
313 R.dimen.status_bar_icon_padding);
314
315 if (newIconHPadding != mIconHPadding || newIconSize != mIconSize) {
316// Slog.d(TAG, "size=" + newIconSize + " padding=" + newIconHPadding);
317 mIconHPadding = newIconHPadding;
318 mIconSize = newIconSize;
319 reloadAllNotificationIcons(); // reload the tray
320 }
321 }
322
Joe Onorato808182d2010-07-09 18:52:06 -0400323 protected View makeStatusBarView() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400324 final Context context = mContext;
Jim Miller85babff2011-01-11 14:26:03 -0800325
Daniel Sandler10163c62010-12-08 11:51:05 -0500326 mWindowManager = IWindowManager.Stub.asInterface(
327 ServiceManager.getService(Context.WINDOW_SERVICE));
Joe Onorato808182d2010-07-09 18:52:06 -0400328
Joe Onoratodc100302011-01-11 17:07:41 -0800329 // This guy will listen for HDMI plugged broadcasts so we can resize the
330 // status bar as appropriate.
331 mHeightReceiver = new HeightReceiver(mContext);
332 mHeightReceiver.registerReceiver();
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500333 loadDimens();
Joe Onorato808182d2010-07-09 18:52:06 -0400334
Joe Onoratob62ac122010-09-20 16:16:32 -0400335 final TabletStatusBarView sb = (TabletStatusBarView)View.inflate(
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400336 context, R.layout.status_bar, null);
Joe Onorato808182d2010-07-09 18:52:06 -0400337 mStatusBarView = sb;
338
Joe Onoratob62ac122010-09-20 16:16:32 -0400339 sb.setHandler(mHandler);
340
Daniel Sandlerce70d912010-09-02 11:59:41 -0400341 mBarContents = sb.findViewById(R.id.bar_contents);
Joe Onoratof63b0f42010-09-12 17:03:19 -0400342
Joe Onoratofd52b182010-11-10 18:00:52 -0800343 // the whole right-hand side of the bar
344 mNotificationArea = sb.findViewById(R.id.notificationArea);
345
Joe Onorato55d2d762010-09-26 13:02:01 -0700346 // the button to open the notification area
Joe Onoratofd52b182010-11-10 18:00:52 -0800347 mNotificationTrigger = sb.findViewById(R.id.notificationTrigger);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400348 mNotificationTrigger.setOnClickListener(mOnClickListener);
Joe Onorato55d2d762010-09-26 13:02:01 -0700349
Joe Onorato808182d2010-07-09 18:52:06 -0400350 // the more notifications icon
351 mNotificationIconArea = (NotificationIconArea)sb.findViewById(R.id.notificationIcons);
352
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400353 // where the icons go
354 mIconLayout = (NotificationIconArea.IconLayout) sb.findViewById(R.id.icons);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400355 mIconLayout.setOnTouchListener(new NotificationIconTouchListener());
356
357 ViewConfiguration vc = ViewConfiguration.get(context);
358 mNotificationPeekTapDuration = vc.getTapTimeout();
359 mNotificationFlingVelocity = 300; // px/s
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400360
Daniel Sandlerc51451a2010-12-16 19:06:46 -0500361 mTicker = new TabletTicker(this);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400362
Joe Onoratofd52b182010-11-10 18:00:52 -0800363 // The icons
364 mBatteryController = new BatteryController(mContext);
365 mBatteryController.addIconView((ImageView)sb.findViewById(R.id.battery));
366 mNetworkController = new NetworkController(mContext);
Joe Onorato42f8e132010-11-29 15:52:43 -0800367 mNetworkController.addCombinedSignalIconView(
368 (ImageView)sb.findViewById(R.id.network_signal));
369 mNetworkController.addDataTypeIconView(
370 (ImageView)sb.findViewById(R.id.network_type));
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400371
Joe Onorato091e1b82010-09-26 18:04:44 -0700372 // The navigation buttons
Joe Onorato6478adc2011-01-27 21:15:01 -0800373 mBackButton = (ImageView)sb.findViewById(R.id.back);
Joe Onorato091e1b82010-09-26 18:04:44 -0700374 mNavigationArea = sb.findViewById(R.id.navigationArea);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500375 mHomeButton = mNavigationArea.findViewById(R.id.home);
Daniel Sandlere02d8082010-10-08 15:13:22 -0400376 mMenuButton = mNavigationArea.findViewById(R.id.menu);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500377 mRecentButton = mNavigationArea.findViewById(R.id.recent_apps);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500378 mRecentButton.setOnClickListener(mOnClickListener);
Joe Onorato091e1b82010-09-26 18:04:44 -0700379
satok06487a52010-10-29 11:37:18 +0900380 // The bar contents buttons
Joe Onoratoec51a822011-01-04 16:33:01 -0800381 mNotificationAndImeArea = (ViewGroup)sb.findViewById(R.id.notificationAndImeArea);
satokcd7cd292010-11-20 15:46:23 +0900382 mInputMethodSwitchButton = (InputMethodButton) sb.findViewById(R.id.imeSwitchButton);
satok82beadf2010-12-27 19:03:06 +0900383 // Overwrite the lister
384 mInputMethodSwitchButton.setOnClickListener(mOnClickListener);
satok06487a52010-10-29 11:37:18 +0900385
Daniel Sandler10163c62010-12-08 11:51:05 -0500386 // for redirecting errant bar taps to the IME
387 mFakeSpaceBar = sb.findViewById(R.id.fake_space_bar);
388
Daniel Sandlerb9606992010-11-19 14:47:59 -0500389 // "shadows" of the status bar features, for lights-out mode
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500390 mShadow = sb.findViewById(R.id.bar_shadow);
391 mShadow.setOnTouchListener(
392 new View.OnTouchListener() {
393 public boolean onTouch(View v, MotionEvent ev) {
394 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
Joe Onorato55bf3802011-01-25 13:42:10 -0800395 try {
396 mBarService.setSystemUiVisibility(View.STATUS_BAR_VISIBLE);
397 } catch (RemoteException ex) {
398 // system process dead
399 }
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500400 }
401 return false;
402 }
403 });
Daniel Sandlerb9606992010-11-19 14:47:59 -0500404
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500405 // tuning parameters
406 final int LIGHTS_GOING_OUT_SYSBAR_DURATION = 600;
407 final int LIGHTS_GOING_OUT_SHADOW_DURATION = 1000;
408 final int LIGHTS_GOING_OUT_SHADOW_DELAY = 500;
409
410 final int LIGHTS_COMING_UP_SYSBAR_DURATION = 200;
411// final int LIGHTS_COMING_UP_SYSBAR_DELAY = 50;
412 final int LIGHTS_COMING_UP_SHADOW_DURATION = 0;
413
414 LayoutTransition xition = new LayoutTransition();
415 xition.setAnimator(LayoutTransition.APPEARING,
416 ObjectAnimator.ofFloat(null, "alpha", 0.5f, 1f));
417 xition.setDuration(LayoutTransition.APPEARING, LIGHTS_COMING_UP_SYSBAR_DURATION);
418 xition.setStartDelay(LayoutTransition.APPEARING, 0);
419 xition.setAnimator(LayoutTransition.DISAPPEARING,
420 ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
421 xition.setDuration(LayoutTransition.DISAPPEARING, LIGHTS_GOING_OUT_SYSBAR_DURATION);
422 xition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
423 ((ViewGroup)sb.findViewById(R.id.bar_contents_holder)).setLayoutTransition(xition);
424
425 xition = new LayoutTransition();
426 xition.setAnimator(LayoutTransition.APPEARING,
427 ObjectAnimator.ofFloat(null, "alpha", 0f, 1f));
428 xition.setDuration(LayoutTransition.APPEARING, LIGHTS_GOING_OUT_SHADOW_DURATION);
429 xition.setStartDelay(LayoutTransition.APPEARING, LIGHTS_GOING_OUT_SHADOW_DELAY);
430 xition.setAnimator(LayoutTransition.DISAPPEARING,
431 ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
432 xition.setDuration(LayoutTransition.DISAPPEARING, LIGHTS_COMING_UP_SHADOW_DURATION);
433 xition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
434 ((ViewGroup)sb.findViewById(R.id.bar_shadow_holder)).setLayoutTransition(xition);
Daniel Sandlerb9606992010-11-19 14:47:59 -0500435
Joe Onorato5dd11692010-09-27 15:34:04 -0700436 // set the initial view visibility
437 setAreThereNotifications();
438
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400439 // Add the windows
440 addPanelWindows();
441
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400442 mPile = (ViewGroup)mNotificationPanel.findViewById(R.id.content);
443 mPile.removeAllViews();
Jim Miller44c66fe2010-10-20 18:32:52 -0700444
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400445 ScrollView scroller = (ScrollView)mPile.getParent();
446 scroller.setFillViewport(true);
447
Joe Onoratodc100302011-01-11 17:07:41 -0800448 mHeightReceiver.addOnBarHeightChangedListener(this);
449
Joe Onorato808182d2010-07-09 18:52:06 -0400450 return sb;
451 }
452
Joe Onoratodc100302011-01-11 17:07:41 -0800453 public int getStatusBarHeight() {
454 return mHeightReceiver.getHeight();
455 }
456
Joe Onorato808182d2010-07-09 18:52:06 -0400457 protected int getStatusBarGravity() {
458 return Gravity.BOTTOM | Gravity.FILL_HORIZONTAL;
459 }
460
Joe Onoratodc100302011-01-11 17:07:41 -0800461 public void onBarHeightChanged(int height) {
462 final WindowManager.LayoutParams lp
463 = (WindowManager.LayoutParams)mStatusBarView.getLayoutParams();
464 if (lp == null) {
465 // haven't been added yet
466 return;
467 }
468 if (lp.height != height) {
469 lp.height = height;
470 final WindowManager wm = WindowManagerImpl.getDefault();
471 wm.updateViewLayout(mStatusBarView, lp);
472 }
473 }
474
Daniel Sandler9120d552010-07-23 09:11:14 -0400475 private class H extends Handler {
Daniel Sandler9120d552010-07-23 09:11:14 -0400476 public void handleMessage(Message m) {
477 switch (m.what) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400478 case MSG_OPEN_NOTIFICATION_PEEK:
479 if (DEBUG) Slog.d(TAG, "opening notification peek window; arg=" + m.arg1);
480 if (m.arg1 >= 0) {
481 final int N = mNotns.size();
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500482 if (mNotificationPeekIndex >= 0 && mNotificationPeekIndex < N) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400483 NotificationData.Entry entry = mNotns.get(N-1-mNotificationPeekIndex);
484 entry.icon.setBackgroundColor(0);
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500485 mNotificationPeekIndex = -1;
486 mNotificationPeekKey = null;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400487 }
488
489 final int peekIndex = m.arg1;
490 if (peekIndex < N) {
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500491 //Slog.d(TAG, "loading peek: " + peekIndex);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400492 NotificationData.Entry entry = mNotns.get(N-1-peekIndex);
493 NotificationData.Entry copy = new NotificationData.Entry(
Jim Miller85babff2011-01-11 14:26:03 -0800494 entry.key,
495 entry.notification,
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400496 entry.icon);
497 inflateViews(copy, mNotificationPeekRow);
498
499 entry.icon.setBackgroundColor(0x20FFFFFF);
500
501// mNotificationPeekRow.setLayoutTransition(
Jim Miller85babff2011-01-11 14:26:03 -0800502// peekIndex < mNotificationPeekIndex
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400503// ? mNotificationPeekScrubLeft
504// : mNotificationPeekScrubRight);
505
506 mNotificationPeekRow.removeAllViews();
507 mNotificationPeekRow.addView(copy.row);
508
509 mNotificationPeekWindow.setVisibility(View.VISIBLE);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800510 mNotificationPanel.show(false, true);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400511
512 mNotificationPeekIndex = peekIndex;
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500513 mNotificationPeekKey = entry.key;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400514 }
515 }
516 break;
517 case MSG_CLOSE_NOTIFICATION_PEEK:
518 if (DEBUG) Slog.d(TAG, "closing notification peek window");
519 mNotificationPeekWindow.setVisibility(View.GONE);
520 mNotificationPeekRow.removeAllViews();
521 final int N = mNotns.size();
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500522 if (mNotificationPeekIndex >= 0 && mNotificationPeekIndex < N) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400523 NotificationData.Entry entry = mNotns.get(N-1-mNotificationPeekIndex);
524 entry.icon.setBackgroundColor(0);
525 }
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500526
527 mNotificationPeekIndex = -1;
528 mNotificationPeekKey = null;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400529 break;
Daniel Sandler9120d552010-07-23 09:11:14 -0400530 case MSG_OPEN_NOTIFICATION_PANEL:
531 if (DEBUG) Slog.d(TAG, "opening notifications panel");
Joe Onorato7c270fa2010-12-08 17:31:42 -0800532 if (!mNotificationPanel.isShowing()) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400533 mNotificationPeekWindow.setVisibility(View.GONE);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800534 mNotificationPanel.show(true, true);
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500535 mNotificationArea.setVisibility(View.GONE);
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800536 mTicker.halt();
Joe Onorato091e1b82010-09-26 18:04:44 -0700537 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400538 break;
539 case MSG_CLOSE_NOTIFICATION_PANEL:
540 if (DEBUG) Slog.d(TAG, "closing notifications panel");
Joe Onorato7c270fa2010-12-08 17:31:42 -0800541 if (mNotificationPanel.isShowing()) {
542 mNotificationPanel.show(false, true);
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500543 mNotificationArea.setVisibility(View.VISIBLE);
Joe Onorato091e1b82010-09-26 18:04:44 -0700544 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400545 break;
Jim Miller44c66fe2010-10-20 18:32:52 -0700546 case MSG_OPEN_RECENTS_PANEL:
547 if (DEBUG) Slog.d(TAG, "opening recents panel");
Jim Miller85babff2011-01-11 14:26:03 -0800548 if (mRecentsPanel != null) {
549 mRecentsPanel.setVisibility(View.VISIBLE);
550 mRecentsPanel.show(true, true);
551 }
Jim Miller44c66fe2010-10-20 18:32:52 -0700552 break;
553 case MSG_CLOSE_RECENTS_PANEL:
554 if (DEBUG) Slog.d(TAG, "closing recents panel");
Jim Miller85babff2011-01-11 14:26:03 -0800555 if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
556 mRecentsPanel.show(false, true);
557 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400558 break;
satok82beadf2010-12-27 19:03:06 +0900559 case MSG_OPEN_INPUT_METHODS_PANEL:
560 if (DEBUG) Slog.d(TAG, "opening input methods panel");
561 if (mInputMethodsPanel != null) mInputMethodsPanel.setVisibility(View.VISIBLE);
562 break;
563 case MSG_CLOSE_INPUT_METHODS_PANEL:
564 if (DEBUG) Slog.d(TAG, "closing input methods panel");
565 if (mInputMethodsPanel != null) mInputMethodsPanel.setVisibility(View.GONE);
566 break;
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500567 case MSG_SHOW_CHROME:
Daniel Sandlere03d1bc2010-11-17 21:36:40 -0500568 if (DEBUG) Slog.d(TAG, "hiding shadows (lights on)");
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500569 mBarContents.setVisibility(View.VISIBLE);
570 mShadow.setVisibility(View.GONE);
Joe Onorato664644d2011-01-23 17:53:23 -0800571 notifyLightsChanged(true);
Daniel Sandler06e66302010-11-05 15:00:06 -0400572 break;
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500573 case MSG_HIDE_CHROME:
Daniel Sandlere03d1bc2010-11-17 21:36:40 -0500574 if (DEBUG) Slog.d(TAG, "showing shadows (lights out)");
Daniel Sandler06e66302010-11-05 15:00:06 -0400575 animateCollapse();
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500576 mBarContents.setVisibility(View.GONE);
577 mShadow.setVisibility(View.VISIBLE);
Joe Onorato664644d2011-01-23 17:53:23 -0800578 notifyLightsChanged(false);
Daniel Sandlere03d1bc2010-11-17 21:36:40 -0500579 break;
Daniel Sandler9120d552010-07-23 09:11:14 -0400580 }
581 }
582 }
Daniel Sandler271ea122010-10-22 14:06:10 -0400583
Joe Onorato664644d2011-01-23 17:53:23 -0800584 private void notifyLightsChanged(boolean shown) {
585 try {
586 Slog.d(TAG, "lights " + (shown?"on":"out"));
587 mWindowManager.statusBarVisibilityChanged(
588 shown ? View.STATUS_BAR_VISIBLE : View.STATUS_BAR_HIDDEN);
589 } catch (RemoteException ex) {
590 }
591 }
592
Joe Onorato808182d2010-07-09 18:52:06 -0400593 public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400594 if (DEBUG) Slog.d(TAG, "addIcon(" + slot + ") -> " + icon);
Joe Onorato808182d2010-07-09 18:52:06 -0400595 }
596
597 public void updateIcon(String slot, int index, int viewIndex,
598 StatusBarIcon old, StatusBarIcon icon) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400599 if (DEBUG) Slog.d(TAG, "updateIcon(" + slot + ") -> " + icon);
Joe Onorato808182d2010-07-09 18:52:06 -0400600 }
601
602 public void removeIcon(String slot, int index, int viewIndex) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400603 if (DEBUG) Slog.d(TAG, "removeIcon(" + slot + ")");
Joe Onorato808182d2010-07-09 18:52:06 -0400604 }
605
606 public void addNotification(IBinder key, StatusBarNotification notification) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400607 if (DEBUG) Slog.d(TAG, "addNotification(" + key + " -> " + notification + ")");
608 addNotificationViews(key, notification);
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400609
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800610 final boolean immersive = isImmersive();
Joe Onoratocf2b1992010-11-16 21:36:42 -0800611 if (false && immersive) {
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400612 // TODO: immersive mode popups for tablet
613 } else if (notification.notification.fullScreenIntent != null) {
614 // not immersive & a full-screen alert should be shown
Joe Onoratof68b5002011-01-16 17:00:34 -0800615 Slog.w(TAG, "Notification has fullScreenIntent and activity is not immersive;"
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400616 + " sending fullScreenIntent");
617 try {
618 notification.notification.fullScreenIntent.send();
619 } catch (PendingIntent.CanceledException e) {
620 }
621 } else {
Joe Onoratoeeed9942011-01-04 17:13:53 -0800622 tick(key, notification, true);
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400623 }
Joe Onorato5dd11692010-09-27 15:34:04 -0700624
625 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400626 }
627
628 public void updateNotification(IBinder key, StatusBarNotification notification) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400629 if (DEBUG) Slog.d(TAG, "updateNotification(" + key + " -> " + notification + ") // TODO");
Jim Miller44c66fe2010-10-20 18:32:52 -0700630
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400631 final NotificationData.Entry oldEntry = mNotns.findByKey(key);
Daniel Sandler379020a2010-07-29 16:20:06 -0400632 if (oldEntry == null) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400633 Slog.w(TAG, "updateNotification for unknown key: " + key);
634 return;
635 }
636
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400637 final StatusBarNotification oldNotification = oldEntry.notification;
638 final RemoteViews oldContentView = oldNotification.notification.contentView;
639
640 final RemoteViews contentView = notification.notification.contentView;
641
Daniel Sandler373a9982010-11-30 12:03:59 -0500642 if (DEBUG) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400643 Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
644 + " ongoing=" + oldNotification.isOngoing()
645 + " expanded=" + oldEntry.expanded
646 + " contentView=" + oldContentView);
647 Slog.d(TAG, "new notification: when=" + notification.notification.when
648 + " ongoing=" + oldNotification.isOngoing()
649 + " contentView=" + contentView);
650 }
651
652 // Can we just reapply the RemoteViews in place? If when didn't change, the order
653 // didn't change.
Joe Onorato80a44402011-01-15 16:22:24 -0800654 boolean contentsUnchanged = oldEntry.expanded != null
655 && contentView != null && oldContentView != null
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400656 && contentView.getPackage() != null
657 && oldContentView.getPackage() != null
658 && oldContentView.getPackage().equals(contentView.getPackage())
Joe Onoratoc9596d62011-01-12 17:03:11 -0800659 && oldContentView.getLayoutId() == contentView.getLayoutId();
Daniel Sandler373a9982010-11-30 12:03:59 -0500660 ViewGroup rowParent = (ViewGroup) oldEntry.row.getParent();
Joe Onorato80a44402011-01-15 16:22:24 -0800661 boolean orderUnchanged = notification.notification.when==oldNotification.notification.when
662 && notification.isOngoing() == oldNotification.isOngoing();
Joe Onoratoc9596d62011-01-12 17:03:11 -0800663 boolean isLastAnyway = rowParent.indexOfChild(oldEntry.row) == rowParent.getChildCount()-1;
664 if (contentsUnchanged && (orderUnchanged || isLastAnyway)) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400665 if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
666 oldEntry.notification = notification;
667 try {
668 // Reapply the RemoteViews
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400669 contentView.reapply(mContext, oldEntry.content);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400670 // update the contentIntent
671 final PendingIntent contentIntent = notification.notification.contentIntent;
672 if (contentIntent != null) {
673 oldEntry.content.setOnClickListener(new NotificationClicker(contentIntent,
674 notification.pkg, notification.tag, notification.id));
Joe Onorato184498c2010-10-08 17:57:18 -0400675 } else {
676 oldEntry.content.setOnClickListener(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400677 }
678 // Update the icon.
679 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
680 notification.notification.icon, notification.notification.iconLevel,
681 notification.notification.number);
682 if (!oldEntry.icon.set(ic)) {
683 handleNotificationError(key, notification, "Couldn't update icon: " + ic);
684 return;
685 }
Joe Onorato80a44402011-01-15 16:22:24 -0800686 // Update the large icon
687 if (notification.notification.largeIcon != null) {
688 oldEntry.largeIcon.setImageBitmap(notification.notification.largeIcon);
689 } else {
690 oldEntry.largeIcon.getLayoutParams().width = 0;
691 oldEntry.largeIcon.setVisibility(View.INVISIBLE);
692 }
Jim Miller85babff2011-01-11 14:26:03 -0800693
Daniel Sandler7ef29b52010-12-16 17:29:50 -0500694 if (key == mNotificationPeekKey) {
695 // must update the peek window
696 Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
697 peekMsg.arg1 = mNotificationPeekIndex;
698 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
699 mHandler.sendMessage(peekMsg);
700 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400701 }
702 catch (RuntimeException e) {
703 // It failed to add cleanly. Log, and remove the view from the panel.
704 Slog.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
705 removeNotificationViews(key);
706 addNotificationViews(key, notification);
707 }
708 } else {
709 if (DEBUG) Slog.d(TAG, "not reusing notification for key: " + key);
710 removeNotificationViews(key);
711 addNotificationViews(key, notification);
712 }
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800713 // fullScreenIntent doesn't happen on updates. You need to clear & repost a new
714 // notification.
715 final boolean immersive = isImmersive();
716 if (false && immersive) {
717 // TODO: immersive mode
718 } else {
Joe Onoratoeeed9942011-01-04 17:13:53 -0800719 tick(key, notification, false);
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800720 }
Joe Onorato5dd11692010-09-27 15:34:04 -0700721
722 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400723 }
724
725 public void removeNotification(IBinder key) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400726 if (DEBUG) Slog.d(TAG, "removeNotification(" + key + ") // TODO");
727 removeNotificationViews(key);
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800728 mTicker.remove(key);
Joe Onorato5dd11692010-09-27 15:34:04 -0700729 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400730 }
731
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500732 public void showClock(boolean show) {
733 View clock = mBarContents.findViewById(R.id.clock);
734 View network_text = mBarContents.findViewById(R.id.network_text);
735 if (clock != null) {
736 clock.setVisibility(show ? View.VISIBLE : View.GONE);
737 }
738 if (network_text != null) {
739 network_text.setVisibility((!show) ? View.VISIBLE : View.GONE);
740 }
741 }
742
Joe Onorato808182d2010-07-09 18:52:06 -0400743 public void disable(int state) {
Joe Onorato091e1b82010-09-26 18:04:44 -0700744 int old = mDisabled;
745 int diff = state ^ old;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400746 mDisabled = state;
747
Joe Onorato091e1b82010-09-26 18:04:44 -0700748 // act accordingly
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500749 if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) {
750 boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0;
Joe Onoratof68b5002011-01-16 17:00:34 -0800751 Slog.i(TAG, "DISABLE_CLOCK: " + (show ? "no" : "yes"));
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500752 showClock(show);
753 }
Daniel Sandler6f6cf3c2010-12-16 12:54:03 -0500754 if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
755 boolean show = (state & StatusBarManager.DISABLE_SYSTEM_INFO) == 0;
Joe Onoratof68b5002011-01-16 17:00:34 -0800756 Slog.i(TAG, "DISABLE_SYSTEM_INFO: " + (show ? "no" : "yes"));
Daniel Sandler6f6cf3c2010-12-16 12:54:03 -0500757 mNotificationTrigger.setVisibility(show ? View.VISIBLE : View.GONE);
758 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400759 if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
760 if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
Joe Onoratof68b5002011-01-16 17:00:34 -0800761 Slog.i(TAG, "DISABLE_EXPAND: yes");
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400762 animateCollapse();
763 }
764 }
765 if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
766 if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
Joe Onoratof68b5002011-01-16 17:00:34 -0800767 Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
Daniel Sandlerb9606992010-11-19 14:47:59 -0500768 // synchronize with current shadow state
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500769 mNotificationIconArea.setVisibility(View.GONE);
Joe Onorato091e1b82010-09-26 18:04:44 -0700770 mTicker.halt();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400771 } else {
Joe Onoratof68b5002011-01-16 17:00:34 -0800772 Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: no");
Daniel Sandlerb9606992010-11-19 14:47:59 -0500773 // synchronize with current shadow state
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500774 mNotificationIconArea.setVisibility(View.VISIBLE);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400775 }
776 } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
Joe Onorato091e1b82010-09-26 18:04:44 -0700777 if ((state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
Joe Onoratoef1e7762010-09-17 18:38:38 -0400778 mTicker.halt();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400779 }
780 }
Joe Onorato091e1b82010-09-26 18:04:44 -0700781 if ((diff & StatusBarManager.DISABLE_NAVIGATION) != 0) {
782 if ((state & StatusBarManager.DISABLE_NAVIGATION) != 0) {
Joe Onoratof68b5002011-01-16 17:00:34 -0800783 Slog.i(TAG, "DISABLE_NAVIGATION: yes");
Joe Onoratofd52b182010-11-10 18:00:52 -0800784 mNavigationArea.setVisibility(View.GONE);
satokb70c82d2010-12-20 17:59:19 +0900785 mInputMethodSwitchButton.setScreenLocked(true);
Joe Onorato091e1b82010-09-26 18:04:44 -0700786 } else {
Joe Onoratof68b5002011-01-16 17:00:34 -0800787 Slog.i(TAG, "DISABLE_NAVIGATION: no");
Joe Onoratofd52b182010-11-10 18:00:52 -0800788 mNavigationArea.setVisibility(View.VISIBLE);
satokb70c82d2010-12-20 17:59:19 +0900789 mInputMethodSwitchButton.setScreenLocked(false);
Joe Onorato091e1b82010-09-26 18:04:44 -0700790 }
791 }
Joe Onorato6478adc2011-01-27 21:15:01 -0800792 if ((diff & StatusBarManager.DISABLE_BACK) != 0) {
793 if ((state & StatusBarManager.DISABLE_BACK) != 0) {
794 Slog.i(TAG, "DISABLE_BACK: yes");
795 mBackButton.setVisibility(View.INVISIBLE);
796 mInputMethodSwitchButton.setScreenLocked(true);
797 } else {
798 Slog.i(TAG, "DISABLE_BACK: no");
799 mBackButton.setVisibility(View.VISIBLE);
800 mInputMethodSwitchButton.setScreenLocked(false);
801 }
802 }
803
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400804 }
805
Joe Onoratoef1e7762010-09-17 18:38:38 -0400806 private boolean hasTicker(Notification n) {
Joe Onorato46439ce2010-11-19 13:56:21 -0800807 return n.tickerView != null || !TextUtils.isEmpty(n.tickerText);
Joe Onoratoef1e7762010-09-17 18:38:38 -0400808 }
809
Joe Onoratoeeed9942011-01-04 17:13:53 -0800810 private void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
Joe Onorato55d2d762010-09-26 13:02:01 -0700811 // Don't show the ticker when the windowshade is open.
Joe Onorato7c270fa2010-12-08 17:31:42 -0800812 if (mNotificationPanel.isShowing()) {
Joe Onorato55d2d762010-09-26 13:02:01 -0700813 return;
814 }
Joe Onoratoeeed9942011-01-04 17:13:53 -0800815 // If they asked for FLAG_ONLY_ALERT_ONCE, then only show this notification
816 // if it's a new notification.
817 if (!firstTime && (n.notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) {
818 return;
819 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400820 // Show the ticker if one is requested. Also don't do this
821 // until status bar window is attached to the window manager,
822 // because... well, what's the point otherwise? And trying to
823 // run a ticker without being attached will crash!
Joe Onoratoef1e7762010-09-17 18:38:38 -0400824 if (hasTicker(n.notification) && mStatusBarView.getWindowToken() != null) {
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400825 if (0 == (mDisabled & (StatusBarManager.DISABLE_NOTIFICATION_ICONS
826 | StatusBarManager.DISABLE_NOTIFICATION_TICKER))) {
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800827 mTicker.add(key, n);
Joe Onoratoec51a822011-01-04 16:33:01 -0800828 mNotificationAndImeArea.setVisibility(View.GONE);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400829 }
830 }
831 }
832
Daniel Sandlerb8027d82010-12-16 19:35:54 -0500833 // called by TabletTicker when it's done with all queued ticks
834 public void doneTicking() {
Joe Onoratoec51a822011-01-04 16:33:01 -0800835 mNotificationAndImeArea.setVisibility(View.VISIBLE);
Daniel Sandlerb8027d82010-12-16 19:35:54 -0500836 }
837
Joe Onorato808182d2010-07-09 18:52:06 -0400838 public void animateExpand() {
Joe Onoratob62ac122010-09-20 16:16:32 -0400839 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
840 mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
Joe Onorato808182d2010-07-09 18:52:06 -0400841 }
842
843 public void animateCollapse() {
Joe Onoratob62ac122010-09-20 16:16:32 -0400844 mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PANEL);
845 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PANEL);
Jim Miller44c66fe2010-10-20 18:32:52 -0700846 mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
847 mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
satok82beadf2010-12-27 19:03:06 +0900848 mHandler.removeMessages(MSG_CLOSE_INPUT_METHODS_PANEL);
849 mHandler.sendEmptyMessage(MSG_CLOSE_INPUT_METHODS_PANEL);
Daniel Sandler9120d552010-07-23 09:11:14 -0400850 }
851
Joe Onoratofd52b182010-11-10 18:00:52 -0800852 // called by StatusBar
Daniel Sandler06e66302010-11-05 15:00:06 -0400853 @Override
Joe Onorato93056472010-09-10 10:30:46 -0400854 public void setLightsOn(boolean on) {
Daniel Sandler59485d742010-12-02 00:11:33 -0500855 // Policy note: if the frontmost activity needs the menu key, we assume it is a legacy app
856 // that can't handle lights-out mode.
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500857 if (mMenuButton.getVisibility() == View.VISIBLE) {
Daniel Sandler59485d742010-12-02 00:11:33 -0500858 on = true;
859 }
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500860 mHandler.removeMessages(MSG_HIDE_CHROME);
861 mHandler.removeMessages(MSG_SHOW_CHROME);
862 mHandler.sendEmptyMessage(on ? MSG_SHOW_CHROME : MSG_HIDE_CHROME);
Joe Onorato93056472010-09-10 10:30:46 -0400863 }
864
Daniel Sandlere02d8082010-10-08 15:13:22 -0400865 public void setMenuKeyVisible(boolean visible) {
866 if (DEBUG) {
867 Slog.d(TAG, (visible?"showing":"hiding") + " the MENU button");
868 }
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500869 mMenuButton.setVisibility(visible ? View.VISIBLE : View.GONE);
Daniel Sandler59485d742010-12-02 00:11:33 -0500870
871 // See above re: lights-out policy for legacy apps.
872 if (visible) setLightsOn(true);
Daniel Sandlere02d8082010-10-08 15:13:22 -0400873 }
874
Joe Onorato857fd9b2011-01-27 15:08:35 -0800875 public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
876 mInputMethodSwitchButton.setImeWindowStatus(token,
877 (vis & InputMethodService.IME_ACTIVE) != 0);
satok51133822011-01-25 15:01:48 +0900878 updateNotificationIcons();
satok913f42d2011-01-17 16:58:10 +0900879 mInputMethodsPanel.setImeToken(token);
Joe Onorato857fd9b2011-01-27 15:08:35 -0800880 int res;
881 switch (backDisposition) {
882 case InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS:
883 res = R.drawable.ic_sysbar_back;
884 break;
885 case InputMethodService.BACK_DISPOSITION_WILL_DISMISS:
886 res = R.drawable.ic_sysbar_back_ime;
887 break;
888 case InputMethodService.BACK_DISPOSITION_DEFAULT:
889 default:
890 if ((vis & InputMethodService.IME_VISIBLE) != 0) {
891 res = R.drawable.ic_sysbar_back_ime;
892 } else {
893 res = R.drawable.ic_sysbar_back;
894 }
895 break;
896 }
897 mBackButton.setImageResource(res);
Daniel Sandler10163c62010-12-08 11:51:05 -0500898 if (FAKE_SPACE_BAR) {
Joe Onorato857fd9b2011-01-27 15:08:35 -0800899 mFakeSpaceBar.setVisibility(((vis & InputMethodService.IME_VISIBLE) != 0)
900 ? View.VISIBLE : View.GONE);
Daniel Sandler10163c62010-12-08 11:51:05 -0500901 }
satok06487a52010-10-29 11:37:18 +0900902 }
903
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800904 private boolean isImmersive() {
905 try {
906 return ActivityManagerNative.getDefault().isTopActivityImmersive();
907 //Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
908 } catch (RemoteException ex) {
909 // the end is nigh
910 return false;
911 }
912 }
Jim Miller85babff2011-01-11 14:26:03 -0800913
Joe Onorato5dd11692010-09-27 15:34:04 -0700914 private void setAreThereNotifications() {
915 final boolean hasClearable = mNotns.hasClearableItems();
Joe Onorato5dd11692010-09-27 15:34:04 -0700916 }
917
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400918 /**
919 * Cancel this notification and tell the status bar service about the failure. Hold no locks.
920 */
921 void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
922 removeNotification(key);
923 try {
924 mBarService.onNotificationError(n.pkg, n.tag, n.id, n.uid, n.initialPid, message);
925 } catch (RemoteException ex) {
926 // The end is nigh.
927 }
928 }
929
Daniel Sandler10163c62010-12-08 11:51:05 -0500930 private void sendKey(KeyEvent key) {
931 try {
932 if (DEBUG) Slog.d(TAG, "injecting key event: " + key);
933 mWindowManager.injectInputEventNoWait(key);
934 } catch (RemoteException ex) {
935 }
936 }
937
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400938 private View.OnClickListener mOnClickListener = new View.OnClickListener() {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400939 public void onClick(View v) {
Joe Onoratofd52b182010-11-10 18:00:52 -0800940 if (v == mNotificationTrigger) {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400941 onClickNotificationTrigger();
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400942 } else if (v == mRecentButton) {
943 onClickRecentButton();
satok82beadf2010-12-27 19:03:06 +0900944 } else if (v == mInputMethodSwitchButton) {
945 onClickInputMethodSwitchButton();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400946 }
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400947 }
948 };
949
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400950 public void onClickNotificationTrigger() {
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500951 if (DEBUG) Slog.d(TAG, "clicked notification icons; disabled=" + mDisabled);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400952 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
Daniel Sandler271ea122010-10-22 14:06:10 -0400953 if (!mNotificationsOn) {
954 mNotificationsOn = true;
Daniel Sandlercf3c7cf2010-10-22 15:30:12 -0400955 mIconLayout.setVisibility(View.VISIBLE); // TODO: animation
Daniel Sandler271ea122010-10-22 14:06:10 -0400956 } else {
Joe Onorato7c270fa2010-12-08 17:31:42 -0800957 int msg = !mNotificationPanel.isShowing()
Daniel Sandler271ea122010-10-22 14:06:10 -0400958 ? MSG_OPEN_NOTIFICATION_PANEL
959 : MSG_CLOSE_NOTIFICATION_PANEL;
960 mHandler.removeMessages(msg);
961 mHandler.sendEmptyMessage(msg);
962 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400963 }
964 }
965
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400966 public void onClickRecentButton() {
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500967 if (DEBUG) Slog.d(TAG, "clicked recent apps; disabled=" + mDisabled);
Jim Miller44c66fe2010-10-20 18:32:52 -0700968 if (mRecentsPanel == null) {
969 Intent intent = new Intent();
970 intent.setClass(mContext, RecentApplicationsActivity.class);
971 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
972 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
973 mContext.startActivity(intent);
974 } else {
975 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
976 int msg = (mRecentsPanel.getVisibility() == View.GONE)
977 ? MSG_OPEN_RECENTS_PANEL
978 : MSG_CLOSE_RECENTS_PANEL;
979 mHandler.removeMessages(msg);
980 mHandler.sendEmptyMessage(msg);
981 }
982 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400983 }
Joe Onorato55d2d762010-09-26 13:02:01 -0700984
satok82beadf2010-12-27 19:03:06 +0900985 public void onClickInputMethodSwitchButton() {
986 if (DEBUG) Slog.d(TAG, "clicked input methods panel; disabled=" + mDisabled);
987 int msg = (mInputMethodsPanel.getVisibility() == View.GONE) ?
988 MSG_OPEN_INPUT_METHODS_PANEL : MSG_CLOSE_INPUT_METHODS_PANEL;
989 mHandler.removeMessages(msg);
990 mHandler.sendEmptyMessage(msg);
991 }
992
Daniel Sandlerc51451a2010-12-16 19:06:46 -0500993 public NotificationClicker makeClicker(PendingIntent intent, String pkg, String tag, int id) {
994 return new NotificationClicker(intent, pkg, tag, id);
995 }
996
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400997 private class NotificationClicker implements View.OnClickListener {
998 private PendingIntent mIntent;
999 private String mPkg;
1000 private String mTag;
1001 private int mId;
1002
1003 NotificationClicker(PendingIntent intent, String pkg, String tag, int id) {
1004 mIntent = intent;
1005 mPkg = pkg;
1006 mTag = tag;
1007 mId = id;
1008 }
1009
1010 public void onClick(View v) {
1011 try {
1012 // The intent we are sending is for the application, which
1013 // won't have permission to immediately start an activity after
1014 // the user switches to home. We know it is safe to do at this
1015 // point, so make sure new activity switches are now allowed.
1016 ActivityManagerNative.getDefault().resumeAppSwitches();
1017 } catch (RemoteException e) {
1018 }
1019
1020 if (mIntent != null) {
1021 int[] pos = new int[2];
1022 v.getLocationOnScreen(pos);
1023 Intent overlay = new Intent();
1024 overlay.setSourceBounds(
1025 new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
1026 try {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001027 mIntent.send(mContext, 0, overlay);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001028 } catch (PendingIntent.CanceledException e) {
1029 // the stack trace isn't very helpful here. Just log the exception message.
1030 Slog.w(TAG, "Sending contentIntent failed: " + e);
1031 }
1032 }
1033
1034 try {
1035 mBarService.onNotificationClick(mPkg, mTag, mId);
1036 } catch (RemoteException ex) {
1037 // system process is dead if we're here.
1038 }
1039
1040 // close the shade if it was open
1041 animateCollapse();
1042
1043 // If this click was on the intruder alert, hide that instead
1044// mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
1045 }
1046 }
1047
1048 StatusBarNotification removeNotificationViews(IBinder key) {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001049 NotificationData.Entry entry = mNotns.remove(key);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001050 if (entry == null) {
1051 Slog.w(TAG, "removeNotification for unknown key: " + key);
1052 return null;
1053 }
1054 // Remove the expanded view.
1055 ViewGroup rowParent = (ViewGroup)entry.row.getParent();
1056 if (rowParent != null) rowParent.removeView(entry.row);
Daniel Sandlera8e5b062010-12-01 13:53:08 -05001057
1058 if (key == mNotificationPeekKey) {
1059 // must close the peek as well, since it's gone
1060 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
1061 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001062 // Remove the icon.
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001063// ViewGroup iconParent = (ViewGroup)entry.icon.getParent();
1064// if (iconParent != null) iconParent.removeView(entry.icon);
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001065 updateNotificationIcons();
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001066
1067 return entry.notification;
1068 }
1069
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001070 private class NotificationIconTouchListener implements View.OnTouchListener {
1071 VelocityTracker mVT;
1072
1073 public NotificationIconTouchListener() {
1074 }
1075
1076 public boolean onTouch(View v, MotionEvent event) {
1077 boolean peeking = mNotificationPeekWindow.getVisibility() != View.GONE;
Joe Onorato7c270fa2010-12-08 17:31:42 -08001078 boolean panelShowing = mNotificationPanel.isShowing();
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001079 if (panelShowing) return false;
1080
1081 switch (event.getAction()) {
1082 case MotionEvent.ACTION_DOWN:
1083 mVT = VelocityTracker.obtain();
1084
1085 // fall through
1086 case MotionEvent.ACTION_OUTSIDE:
1087 case MotionEvent.ACTION_MOVE:
1088 // peek and switch icons if necessary
1089 int numIcons = mIconLayout.getChildCount();
Joe Onorato5e759462010-11-28 17:43:50 -08001090 int peekIndex = (int)((float)event.getX() * numIcons / mIconLayout.getWidth());
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001091 if (peekIndex > numIcons - 1) peekIndex = numIcons - 1;
1092 else if (peekIndex < 0) peekIndex = 0;
1093
1094 if (!peeking || mNotificationPeekIndex != peekIndex) {
1095 if (DEBUG) Slog.d(TAG, "will peek at notification #" + peekIndex);
1096 Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
1097 peekMsg.arg1 = peekIndex;
1098
1099 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
1100
1101 // no delay if we're scrubbing left-right
Joe Onorato5e759462010-11-28 17:43:50 -08001102 mHandler.sendMessage(peekMsg);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001103 }
1104
1105 // check for fling
1106 if (mVT != null) {
1107 mVT.addMovement(event);
1108 mVT.computeCurrentVelocity(1000);
1109 // require a little more oomph once we're already in peekaboo mode
1110 if (!panelShowing && (
1111 (peeking && mVT.getYVelocity() < -mNotificationFlingVelocity*3)
1112 || (mVT.getYVelocity() < -mNotificationFlingVelocity))) {
1113 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
1114 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
1115 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
1116 mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
1117 }
1118 }
1119 return true;
1120 case MotionEvent.ACTION_UP:
1121 case MotionEvent.ACTION_CANCEL:
1122 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
1123 if (peeking) {
Joe Onorato5e759462010-11-28 17:43:50 -08001124 mHandler.sendEmptyMessageDelayed(MSG_CLOSE_NOTIFICATION_PEEK, 5000);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001125 }
1126 mVT.recycle();
1127 mVT = null;
1128 return true;
1129 }
1130 return false;
1131 }
1132 }
1133
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001134 StatusBarIconView addNotificationViews(IBinder key, StatusBarNotification notification) {
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001135 if (DEBUG) {
1136 Slog.d(TAG, "addNotificationViews(key=" + key + ", notification=" + notification);
1137 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001138 // Construct the icon.
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001139 final StatusBarIconView iconView = new StatusBarIconView(mContext,
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001140 notification.pkg + "/0x" + Integer.toHexString(notification.id));
1141 iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
1142
1143 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
1144 notification.notification.icon,
1145 notification.notification.iconLevel,
1146 notification.notification.number);
1147 if (!iconView.set(ic)) {
1148 handleNotificationError(key, notification, "Couldn't attach StatusBarIcon: " + ic);
1149 return null;
1150 }
1151 // Construct the expanded view.
1152 NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001153 if (!inflateViews(entry, mPile)) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001154 handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
1155 + notification);
1156 return null;
1157 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001158
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001159 // Add the icon.
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001160 mNotns.add(entry);
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001161 updateNotificationIcons();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001162
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001163 return iconView;
1164 }
1165
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001166 private void reloadAllNotificationIcons() {
1167 if (mIconLayout == null) return;
1168 mIconLayout.removeAllViews();
1169 updateNotificationIcons();
1170 }
1171
1172 private void updateNotificationIcons() {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001173 // XXX: need to implement a new limited linear layout class
1174 // to avoid removing & readding everything
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001175
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001176 if (mIconLayout == null) return;
1177
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001178 final LinearLayout.LayoutParams params
Joe Onoratodc100302011-01-11 17:07:41 -08001179 = new LinearLayout.LayoutParams(mIconSize + 2*mIconHPadding, mNaturalBarHeight);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001180
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001181 int N = mNotns.size();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001182
1183 if (DEBUG) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001184 Slog.d(TAG, "refreshing icons: " + N + " notifications, mIconLayout=" + mIconLayout);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001185 }
1186
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001187 ArrayList<View> toShow = new ArrayList<View>();
1188
satok82beadf2010-12-27 19:03:06 +09001189 // When IME button is visible, the number of notification icons should be decremented
1190 // to fit the upper limit.
1191 final int maxNotificationIconsCount =
1192 (mInputMethodSwitchButton.getVisibility() != View.GONE) ?
1193 MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE : MAX_NOTIFICATION_ICONS;
1194 for (int i=0; i< maxNotificationIconsCount; i++) {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001195 if (i>=N) break;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001196 toShow.add(mNotns.get(N-i-1).icon);
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001197 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001198
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001199 ArrayList<View> toRemove = new ArrayList<View>();
1200 for (int i=0; i<mIconLayout.getChildCount(); i++) {
1201 View child = mIconLayout.getChildAt(i);
1202 if (!toShow.contains(child)) {
1203 toRemove.add(child);
1204 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001205 }
Daniel Sandler271ea122010-10-22 14:06:10 -04001206
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001207 for (View remove : toRemove) {
1208 mIconLayout.removeView(remove);
1209 }
1210
1211 for (int i=0; i<toShow.size(); i++) {
1212 View v = toShow.get(i);
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001213 v.setPadding(mIconHPadding, 0, mIconHPadding, 0);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001214 if (v.getParent() == null) {
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001215 mIconLayout.addView(v, i, params);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001216 }
1217 }
1218
1219 loadNotificationPanel();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001220 }
1221
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001222 private void loadNotificationPanel() {
1223 int N = mNotns.size();
1224
1225 ArrayList<View> toShow = new ArrayList<View>();
1226
1227 for (int i=0; i<N; i++) {
1228 View row = mNotns.get(N-i-1).row;
1229 toShow.add(row);
1230 }
1231
1232 ArrayList<View> toRemove = new ArrayList<View>();
1233 for (int i=0; i<mPile.getChildCount(); i++) {
1234 View child = mPile.getChildAt(i);
1235 if (!toShow.contains(child)) {
1236 toRemove.add(child);
1237 }
1238 }
1239
1240 for (View remove : toRemove) {
1241 mPile.removeView(remove);
1242 }
1243
1244 for (int i=0; i<toShow.size(); i++) {
1245 View v = toShow.get(i);
1246 if (v.getParent() == null) {
1247 mPile.addView(toShow.get(i));
1248 }
1249 }
Daniel Sandler40c15452011-01-22 01:26:22 -05001250
1251 mNotificationPanel.setNotificationCount(N);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001252 }
1253
Joe Onorato4daaeaf2010-11-17 20:43:12 -08001254 void workAroundBadLayerDrawableOpacity(View v) {
1255 LayerDrawable d = (LayerDrawable)v.getBackground();
Daniel Sandlerf844dc42011-01-24 23:44:47 -05001256 if (d == null) return;
Joe Onorato4daaeaf2010-11-17 20:43:12 -08001257 v.setBackgroundDrawable(null);
1258 d.setOpacity(PixelFormat.TRANSLUCENT);
1259 v.setBackgroundDrawable(d);
1260 }
1261
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001262 private boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) {
1263 StatusBarNotification sbn = entry.notification;
1264 RemoteViews remoteViews = sbn.notification.contentView;
1265 if (remoteViews == null) {
1266 return false;
1267 }
1268
1269 // create the row view
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001270 LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(
1271 Context.LAYOUT_INFLATER_SERVICE);
Joe Onorato755cc742010-11-27 15:45:35 -08001272 View row = inflater.inflate(R.layout.status_bar_notification_row, parent, false);
Joe Onorato4daaeaf2010-11-17 20:43:12 -08001273 workAroundBadLayerDrawableOpacity(row);
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001274 View vetoButton = row.findViewById(R.id.veto);
Joe Onoratoa4a65032010-09-27 15:53:44 -07001275 if (entry.notification.isClearable()) {
1276 final String _pkg = sbn.pkg;
1277 final String _tag = sbn.tag;
1278 final int _id = sbn.id;
Jim Miller44c66fe2010-10-20 18:32:52 -07001279 vetoButton.setOnClickListener(new View.OnClickListener() {
Joe Onoratoa4a65032010-09-27 15:53:44 -07001280 public void onClick(View v) {
1281 try {
1282 mBarService.onNotificationClear(_pkg, _tag, _id);
1283 } catch (RemoteException ex) {
1284 // system process is dead if we're here.
1285 }
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001286 }
Joe Onoratoa4a65032010-09-27 15:53:44 -07001287 });
1288 } else {
Joe Onorato100748e2011-01-07 11:03:54 -08001289 if ((sbn.notification.flags & Notification.FLAG_ONGOING_EVENT) == 0) {
1290 vetoButton.setVisibility(View.INVISIBLE);
1291 } else {
1292 vetoButton.setVisibility(View.GONE);
1293 }
Joe Onoratoa4a65032010-09-27 15:53:44 -07001294 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001295
Joe Onorato561d3852010-11-20 18:09:34 -08001296 // the large icon
1297 ImageView largeIcon = (ImageView)row.findViewById(R.id.large_icon);
1298 if (sbn.notification.largeIcon != null) {
1299 largeIcon.setImageBitmap(sbn.notification.largeIcon);
1300 } else {
1301 largeIcon.getLayoutParams().width = 0;
1302 largeIcon.setVisibility(View.INVISIBLE);
1303 }
1304
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001305 // bind the click event to the content area
1306 ViewGroup content = (ViewGroup)row.findViewById(R.id.content);
1307 // XXX: update to allow controls within notification views
1308 content.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
1309// content.setOnFocusChangeListener(mFocusChangeListener);
1310 PendingIntent contentIntent = sbn.notification.contentIntent;
1311 if (contentIntent != null) {
1312 content.setOnClickListener(new NotificationClicker(contentIntent,
1313 sbn.pkg, sbn.tag, sbn.id));
Joe Onorato184498c2010-10-08 17:57:18 -04001314 } else {
1315 content.setOnClickListener(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001316 }
1317
1318 View expanded = null;
1319 Exception exception = null;
1320 try {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001321 expanded = remoteViews.apply(mContext, content);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001322 }
1323 catch (RuntimeException e) {
1324 exception = e;
1325 }
1326 if (expanded == null) {
Joe Onorato46439ce2010-11-19 13:56:21 -08001327 final String ident = sbn.pkg + "/0x" + Integer.toHexString(sbn.id);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001328 Slog.e(TAG, "couldn't inflate view for notification " + ident, exception);
1329 return false;
1330 } else {
1331 content.addView(expanded);
1332 row.setDrawingCacheEnabled(true);
1333 }
1334
1335 entry.row = row;
1336 entry.content = content;
1337 entry.expanded = expanded;
Joe Onorato80a44402011-01-15 16:22:24 -08001338 entry.largeIcon = largeIcon;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001339
1340 return true;
1341 }
Daniel Sandlerce70d912010-09-02 11:59:41 -04001342
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001343/*
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001344 public class ShadowController {
1345 boolean mShowShadows;
Daniel Sandlerb9606992010-11-19 14:47:59 -05001346 Map<View, View> mShadowsForElements = new IdentityHashMap<View, View>(7);
1347 Map<View, View> mElementsForShadows = new IdentityHashMap<View, View>(7);
1348 LayoutTransition mElementTransition, mShadowTransition;
1349
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001350 View mTouchTarget;
Daniel Sandlerce70d912010-09-02 11:59:41 -04001351
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001352 ShadowController(boolean showShadows) {
1353 mShowShadows = showShadows;
1354 mTouchTarget = null;
Daniel Sandlerb9606992010-11-19 14:47:59 -05001355
1356 mElementTransition = new LayoutTransition();
1357// AnimatorSet s = new AnimatorSet();
1358// s.play(ObjectAnimator.ofInt(null, "top", 48, 0))
1359// .with(ObjectAnimator.ofFloat(null, "scaleY", 0.5f, 1f))
1360// .with(ObjectAnimator.ofFloat(null, "alpha", 0.5f, 1f))
1361// ;
1362 mElementTransition.setAnimator(LayoutTransition.APPEARING, //s);
1363 ObjectAnimator.ofInt(null, "top", 48, 0));
1364 mElementTransition.setDuration(LayoutTransition.APPEARING, 100);
1365 mElementTransition.setStartDelay(LayoutTransition.APPEARING, 0);
1366
1367// s = new AnimatorSet();
1368// s.play(ObjectAnimator.ofInt(null, "top", 0, 48))
1369// .with(ObjectAnimator.ofFloat(null, "scaleY", 1f, 0.5f))
1370// .with(ObjectAnimator.ofFloat(null, "alpha", 1f, 0.5f))
1371// ;
1372 mElementTransition.setAnimator(LayoutTransition.DISAPPEARING, //s);
1373 ObjectAnimator.ofInt(null, "top", 0, 48));
1374 mElementTransition.setDuration(LayoutTransition.DISAPPEARING, 400);
1375
1376 mShadowTransition = new LayoutTransition();
Jim Miller85babff2011-01-11 14:26:03 -08001377 mShadowTransition.setAnimator(LayoutTransition.APPEARING,
Daniel Sandlerb9606992010-11-19 14:47:59 -05001378 ObjectAnimator.ofFloat(null, "alpha", 0f, 1f));
1379 mShadowTransition.setDuration(LayoutTransition.APPEARING, 200);
1380 mShadowTransition.setStartDelay(LayoutTransition.APPEARING, 100);
Jim Miller85babff2011-01-11 14:26:03 -08001381 mShadowTransition.setAnimator(LayoutTransition.DISAPPEARING,
Daniel Sandlerb9606992010-11-19 14:47:59 -05001382 ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
1383 mShadowTransition.setDuration(LayoutTransition.DISAPPEARING, 100);
1384
1385 ViewGroup bar = (ViewGroup) TabletStatusBar.this.mBarContents;
1386 bar.setLayoutTransition(mElementTransition);
1387 ViewGroup nav = (ViewGroup) TabletStatusBar.this.mNavigationArea;
1388 nav.setLayoutTransition(mElementTransition);
1389 ViewGroup shadowGroup = (ViewGroup) bar.findViewById(R.id.shadows);
1390 shadowGroup.setLayoutTransition(mShadowTransition);
1391 }
1392
1393 public void add(View element, View shadow) {
1394 shadow.setOnTouchListener(makeTouchListener());
1395 mShadowsForElements.put(element, shadow);
1396 mElementsForShadows.put(shadow, element);
Joe Onoratof63b0f42010-09-12 17:03:19 -04001397 }
1398
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001399 public boolean getShadowState() {
1400 return mShowShadows;
Joe Onoratof63b0f42010-09-12 17:03:19 -04001401 }
1402
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001403 public View.OnTouchListener makeTouchListener() {
1404 return new View.OnTouchListener() {
1405 public boolean onTouch(View v, MotionEvent ev) {
1406 final int action = ev.getAction();
1407
1408 if (DEBUG) Slog.d(TAG, "ShadowController: v=" + v + ", ev=" + ev);
1409
1410 // currently redirecting events?
1411 if (mTouchTarget == null) {
Daniel Sandlerb9606992010-11-19 14:47:59 -05001412 mTouchTarget = mElementsForShadows.get(v);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001413 }
1414
1415 if (mTouchTarget != null && mTouchTarget.getVisibility() != View.GONE) {
1416 boolean last = false;
1417 switch (action) {
1418 case MotionEvent.ACTION_CANCEL:
1419 case MotionEvent.ACTION_UP:
Daniel Sandlere03d1bc2010-11-17 21:36:40 -05001420 mHandler.removeMessages(MSG_RESTORE_SHADOWS);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001421 if (mShowShadows) {
Jim Miller85babff2011-01-11 14:26:03 -08001422 mHandler.sendEmptyMessageDelayed(MSG_RESTORE_SHADOWS,
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001423 v == mNotificationShadow ? 5000 : 500);
1424 }
1425 last = true;
1426 break;
1427 case MotionEvent.ACTION_DOWN:
Daniel Sandlere03d1bc2010-11-17 21:36:40 -05001428 mHandler.removeMessages(MSG_RESTORE_SHADOWS);
Daniel Sandlerb9606992010-11-19 14:47:59 -05001429 setElementShadow(mTouchTarget, false);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001430 break;
1431 }
1432 mTouchTarget.dispatchTouchEvent(ev);
1433 if (last) mTouchTarget = null;
1434 return true;
1435 }
1436
1437 return false;
1438 }
1439 };
Joe Onoratof63b0f42010-09-12 17:03:19 -04001440 }
1441
Daniel Sandlere03d1bc2010-11-17 21:36:40 -05001442 public void refresh() {
Daniel Sandlerb9606992010-11-19 14:47:59 -05001443 for (View element : mShadowsForElements.keySet()) {
1444 setElementShadow(element, mShowShadows);
1445 }
Daniel Sandlere03d1bc2010-11-17 21:36:40 -05001446 }
1447
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001448 public void showAllShadows() {
1449 mShowShadows = true;
Daniel Sandlere03d1bc2010-11-17 21:36:40 -05001450 refresh();
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001451 }
1452
1453 public void hideAllShadows() {
1454 mShowShadows = false;
Daniel Sandlere03d1bc2010-11-17 21:36:40 -05001455 refresh();
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001456 }
1457
1458 // Use View.INVISIBLE for things hidden due to shadowing, and View.GONE for things that are
1459 // disabled (and should not be shadowed or re-shown)
Daniel Sandlerb9606992010-11-19 14:47:59 -05001460 public void setElementShadow(View button, boolean shade) {
1461 View shadow = mShadowsForElements.get(button);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001462 if (shadow != null) {
1463 if (button.getVisibility() != View.GONE) {
1464 shadow.setVisibility(shade ? View.VISIBLE : View.INVISIBLE);
1465 button.setVisibility(shade ? View.INVISIBLE : View.VISIBLE);
1466 }
1467 }
1468 }
Daniel Sandlerb9606992010-11-19 14:47:59 -05001469
1470 // Hide both element and shadow, using default layout animations.
1471 public void hideElement(View button) {
1472 Slog.d(TAG, "hiding: " + button);
1473 View shadow = mShadowsForElements.get(button);
1474 if (shadow != null) {
1475 shadow.setVisibility(View.GONE);
1476 }
1477 button.setVisibility(View.GONE);
1478 }
1479
1480 // Honoring the current shadow state.
1481 public void showElement(View button) {
1482 Slog.d(TAG, "showing: " + button);
1483 View shadow = mShadowsForElements.get(button);
1484 if (shadow != null) {
1485 shadow.setVisibility(mShowShadows ? View.VISIBLE : View.INVISIBLE);
1486 }
1487 button.setVisibility(mShowShadows ? View.INVISIBLE : View.VISIBLE);
1488 }
Daniel Sandlerce70d912010-09-02 11:59:41 -04001489 }
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001490 */
Joe Onoratob62ac122010-09-20 16:16:32 -04001491
1492 public class TouchOutsideListener implements View.OnTouchListener {
1493 private int mMsg;
Joe Onoratoddf680b2010-09-26 13:59:40 -07001494 private StatusBarPanel mPanel;
Joe Onoratob62ac122010-09-20 16:16:32 -04001495
Joe Onoratoddf680b2010-09-26 13:59:40 -07001496 public TouchOutsideListener(int msg, StatusBarPanel panel) {
Joe Onoratob62ac122010-09-20 16:16:32 -04001497 mMsg = msg;
Joe Onoratoddf680b2010-09-26 13:59:40 -07001498 mPanel = panel;
Joe Onoratob62ac122010-09-20 16:16:32 -04001499 }
1500
1501 public boolean onTouch(View v, MotionEvent ev) {
Joe Onoratoddf680b2010-09-26 13:59:40 -07001502 final int action = ev.getAction();
1503 if (action == MotionEvent.ACTION_OUTSIDE
1504 || (action == MotionEvent.ACTION_DOWN
1505 && !mPanel.isInContentArea((int)ev.getX(), (int)ev.getY()))) {
Joe Onoratob62ac122010-09-20 16:16:32 -04001506 mHandler.removeMessages(mMsg);
1507 mHandler.sendEmptyMessage(mMsg);
1508 return true;
1509 }
1510 return false;
1511 }
1512 }
Joe Onorato091e1b82010-09-26 18:04:44 -07001513
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001514 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1515 pw.print("mDisabled=0x");
1516 pw.println(Integer.toHexString(mDisabled));
Joe Onorato933464d2011-01-05 15:53:36 -08001517 pw.println("mNetworkController:");
1518 mNetworkController.dump(fd, pw, args);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001519 }
Joe Onorato808182d2010-07-09 18:52:06 -04001520}
Daniel Sandlerd39e3882010-08-31 14:16:13 -04001521
1522