blob: 3ace258324ed4272c615155c37b8194143f7e91e [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;
Joe Onoratof3c3c4f2010-10-21 11:09:02 -040022
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -040023import android.animation.LayoutTransition;
24import android.animation.ObjectAnimator;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040025import android.app.ActivityManagerNative;
Daniel Sandler552b1f02011-06-15 01:03:02 -040026import android.app.Dialog;
Daniel Sandler92d33182011-09-11 16:29:05 -040027import android.app.KeyguardManager;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040028import android.app.PendingIntent;
Joe Onoratoef1e7762010-09-17 18:38:38 -040029import android.app.Notification;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040030import android.app.StatusBarManager;
Joe Onorato808182d2010-07-09 18:52:06 -040031import android.content.Context;
32import android.content.Intent;
Daniel Sandlerce6ff642011-02-18 12:51:08 -050033import android.content.SharedPreferences;
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;
Jeff Brownbc68a592011-07-25 12:58:12 -070038import android.graphics.Point;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040039import android.graphics.Rect;
Joe Onorato4daaeaf2010-11-17 20:43:12 -080040import android.graphics.drawable.LayerDrawable;
Daniel Sandler552b1f02011-06-15 01:03:02 -040041import android.provider.Settings;
Daniel Sandler9120d552010-07-23 09:11:14 -040042import android.os.Handler;
Joe Onorato808182d2010-07-09 18:52:06 -040043import android.os.IBinder;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040044import android.os.Message;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040045import android.os.RemoteException;
Daniel Sandler10163c62010-12-08 11:51:05 -050046import android.os.ServiceManager;
Joe Onoratoef1e7762010-09-17 18:38:38 -040047import android.text.TextUtils;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040048import android.util.Slog;
Daniel Sandleraa051d62011-03-01 16:23:57 -050049import android.view.accessibility.AccessibilityEvent;
Joe Onorato07949e92011-05-25 17:35:35 -070050import android.view.Display;
Joe Onorato808182d2010-07-09 18:52:06 -040051import android.view.Gravity;
Daniel Sandler10163c62010-12-08 11:51:05 -050052import android.view.IWindowManager;
53import android.view.KeyEvent;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040054import android.view.LayoutInflater;
Joe Onoratob62ac122010-09-20 16:16:32 -040055import android.view.MotionEvent;
Daniel Sandleraa051d62011-03-01 16:23:57 -050056import android.view.SoundEffectConstants;
Daniel Sandler8304da42010-10-25 15:53:25 -040057import android.view.VelocityTracker;
Joe Onorato808182d2010-07-09 18:52:06 -040058import android.view.View;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -040059import android.view.ViewConfiguration;
Daniel Sandler9120d552010-07-23 09:11:14 -040060import android.view.ViewGroup;
61import android.view.WindowManager;
62import android.view.WindowManagerImpl;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040063import android.widget.ImageView;
Joe Onorato808182d2010-07-09 18:52:06 -040064import android.widget.LinearLayout;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040065import android.widget.RemoteViews;
66import android.widget.ScrollView;
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;
Joe Onoratofce2bf32011-02-01 17:00:29 -080075import com.android.systemui.statusbar.policy.BluetoothController;
Daniel Sandler45c04012011-06-07 15:29:07 -040076import com.android.systemui.statusbar.policy.CompatModeButton;
Daniel Sandlere40451a2011-02-03 14:51:35 -050077import com.android.systemui.statusbar.policy.LocationController;
Joe Onoratofd52b182010-11-10 18:00:52 -080078import com.android.systemui.statusbar.policy.NetworkController;
Daniel Sandlerce6ff642011-02-18 12:51:08 -050079import com.android.systemui.statusbar.policy.Prefs;
Jim Miller9f0f0e02011-05-17 20:06:29 -070080import com.android.systemui.recent.RecentsPanelView;
Joe Onorato808182d2010-07-09 18:52:06 -040081
Joe Onoratodc100302011-01-11 17:07:41 -080082public class TabletStatusBar extends StatusBar implements
Jeff Brown2992ea72011-01-28 22:04:14 -080083 HeightReceiver.OnBarHeightChangedListener,
84 InputMethodsPanel.OnHardKeyboardEnabledChangeListener {
Daniel Sandlerfb970e92010-08-20 10:57:17 -040085 public static final boolean DEBUG = false;
Daniel Sandlere25f8332011-06-15 15:00:10 -040086 public static final boolean DEBUG_COMPAT_HELP = false;
Joe Onoratofd52b182010-11-10 18:00:52 -080087 public static final String TAG = "TabletStatusBar";
Joe Onorato808182d2010-07-09 18:52:06 -040088
Daniel Sandler0ad460b2010-12-14 12:14:53 -050089
Joe Onoratob62ac122010-09-20 16:16:32 -040090 public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
91 public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -040092 public static final int MSG_OPEN_NOTIFICATION_PEEK = 1002;
93 public static final int MSG_CLOSE_NOTIFICATION_PEEK = 1003;
Jim Miller44c66fe2010-10-20 18:32:52 -070094 public static final int MSG_OPEN_RECENTS_PANEL = 1020;
95 public static final int MSG_CLOSE_RECENTS_PANEL = 1021;
Daniel Sandler0ad460b2010-12-14 12:14:53 -050096 public static final int MSG_SHOW_CHROME = 1030;
97 public static final int MSG_HIDE_CHROME = 1031;
satok82beadf2010-12-27 19:03:06 +090098 public static final int MSG_OPEN_INPUT_METHODS_PANEL = 1040;
99 public static final int MSG_CLOSE_INPUT_METHODS_PANEL = 1041;
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400100 public static final int MSG_OPEN_COMPAT_MODE_PANEL = 1050;
101 public static final int MSG_CLOSE_COMPAT_MODE_PANEL = 1051;
Daniel Sandler2ed08d22011-01-30 16:07:28 -0500102 public static final int MSG_STOP_TICKER = 2000;
Jim Miller44c66fe2010-10-20 18:32:52 -0700103
Daniel Sandler3a2fded2011-02-23 11:19:59 -0500104 // Fitts' Law assistance for LatinIME; see policy.EventHole
Daniel Sandler10163c62010-12-08 11:51:05 -0500105 private static final boolean FAKE_SPACE_BAR = true;
106
Daniel Sandler298a2a82011-08-11 16:13:22 -0400107 // Notification "peeking" (flyover preview of individual notifications)
108 final static boolean NOTIFICATION_PEEK_ENABLED = false;
109 final static int NOTIFICATION_PEEK_HOLD_THRESH = 200; // ms
110 final static int NOTIFICATION_PEEK_FADE_DELAY = 3000; // ms
111
Joe Onoratodc100302011-01-11 17:07:41 -0800112 // The height of the bar, as definied by the build. It may be taller if we're plugged
113 // into hdmi.
114 int mNaturalBarHeight = -1;
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500115 int mIconSize = -1;
116 int mIconHPadding = -1;
satok5485ff62011-05-27 19:15:01 +0900117 private int mMaxNotificationIcons = 5;
Daniel Sandler9120d552010-07-23 09:11:14 -0400118
119 H mHandler = new H();
120
Daniel Sandler10163c62010-12-08 11:51:05 -0500121 IWindowManager mWindowManager;
122
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400123 // tracking all current notifications
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500124 private NotificationData mNotificationData = new NotificationData();
Jim Miller44c66fe2010-10-20 18:32:52 -0700125
Joe Onoratob62ac122010-09-20 16:16:32 -0400126 TabletStatusBarView mStatusBarView;
Joe Onoratofd52b182010-11-10 18:00:52 -0800127 View mNotificationArea;
128 View mNotificationTrigger;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400129 NotificationIconArea mNotificationIconArea;
Daniel Sandler21eb86a2011-03-02 11:52:58 -0500130 ViewGroup mNavigationArea;
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500131
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500132 boolean mNotificationDNDMode;
133 NotificationData.Entry mNotificationDNDDummyEntry;
134
Joe Onorato536c58f2010-11-28 17:52:28 -0800135 ImageView mBackButton;
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500136 View mHomeButton;
Daniel Sandlere02d8082010-10-08 15:13:22 -0400137 View mMenuButton;
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400138 View mRecentButton;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400139
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400140 ViewGroup mFeedbackIconArea; // notification icons, IME icon, compat icon
satokcd7cd292010-11-20 15:46:23 +0900141 InputMethodButton mInputMethodSwitchButton;
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400142 CompatModeButton mCompatModeButton;
satok06487a52010-10-29 11:37:18 +0900143
Joe Onoratoddf680b2010-09-26 13:59:40 -0700144 NotificationPanel mNotificationPanel;
Joe Onorato07949e92011-05-25 17:35:35 -0700145 WindowManager.LayoutParams mNotificationPanelParams;
Joe Onorato8a576712010-11-15 16:50:34 -0800146 NotificationPeekPanel mNotificationPeekWindow;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400147 ViewGroup mNotificationPeekRow;
148 int mNotificationPeekIndex;
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500149 IBinder mNotificationPeekKey;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400150 LayoutTransition mNotificationPeekScrubLeft, mNotificationPeekScrubRight;
151
152 int mNotificationPeekTapDuration;
153 int mNotificationFlingVelocity;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400154
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400155 ViewGroup mPile;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400156
Joe Onoratodc100302011-01-11 17:07:41 -0800157 HeightReceiver mHeightReceiver;
Joe Onoratofd52b182010-11-10 18:00:52 -0800158 BatteryController mBatteryController;
Joe Onoratofce2bf32011-02-01 17:00:29 -0800159 BluetoothController mBluetoothController;
Daniel Sandlere40451a2011-02-03 14:51:35 -0500160 LocationController mLocationController;
Joe Onoratofd52b182010-11-10 18:00:52 -0800161 NetworkController mNetworkController;
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400162
Daniel Sandler21eb86a2011-03-02 11:52:58 -0500163 ViewGroup mBarContents;
164 LayoutTransition mBarContentsLayoutTransition;
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500165
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500166 // hide system chrome ("lights out") support
167 View mShadow;
Daniel Sandlerce70d912010-09-02 11:59:41 -0400168
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400169 NotificationIconArea.IconLayout mIconLayout;
170
Joe Onoratoef1e7762010-09-17 18:38:38 -0400171 TabletTicker mTicker;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400172
Daniel Sandler10163c62010-12-08 11:51:05 -0500173 View mFakeSpaceBar;
174 KeyEvent mSpaceBarKeyEvent = null;
175
Dianne Hackborned31bbf2011-06-15 11:16:06 -0700176 View mCompatibilityHelpDialog = null;
177
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400178 // for disabling the status bar
179 int mDisabled = 0;
180
Jim Miller9f0f0e02011-05-17 20:06:29 -0700181 private RecentsPanelView mRecentsPanel;
satok82beadf2010-12-27 19:03:06 +0900182 private InputMethodsPanel mInputMethodsPanel;
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400183 private CompatModePanel mCompatModePanel;
Joe Onorato55d2d762010-09-26 13:02:01 -0700184
Mike Lockwood066c8912011-08-24 10:17:18 -0400185 private int mSystemUiVisibility = 0;
186 // used to notify status bar for suppressing notification LED
187 private boolean mPanelSlightlyVisible;
Daniel Sandler60ee2562011-07-22 12:34:33 -0400188
Daniel Sandlerc51451a2010-12-16 19:06:46 -0500189 public Context getContext() { return mContext; }
190
Daniel Sandler9120d552010-07-23 09:11:14 -0400191 protected void addPanelWindows() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400192 final Context context = mContext;
Joe Onorato07949e92011-05-25 17:35:35 -0700193 final Resources res = mContext.getResources();
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400194
Jim Miller44c66fe2010-10-20 18:32:52 -0700195 // Notification Panel
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400196 mNotificationPanel = (NotificationPanel)View.inflate(context,
Joe Onorato755cc742010-11-27 15:45:35 -0800197 R.layout.status_bar_notification_panel, null);
Daniel Sandler1347c302011-08-01 16:47:53 -0400198 mNotificationPanel.setBar(this);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800199 mNotificationPanel.show(false, false);
Joe Onoratob62ac122010-09-20 16:16:32 -0400200 mNotificationPanel.setOnTouchListener(
Joe Onoratoddf680b2010-09-26 13:59:40 -0700201 new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PANEL, mNotificationPanel));
Joe Onoratob62ac122010-09-20 16:16:32 -0400202
Daniel Sandler2b697352011-07-22 16:23:09 -0400203 // the battery icon
Joe Onoratofd52b182010-11-10 18:00:52 -0800204 mBatteryController.addIconView((ImageView)mNotificationPanel.findViewById(R.id.battery));
205 mBatteryController.addLabelView(
206 (TextView)mNotificationPanel.findViewById(R.id.battery_text));
Daniel Sandler2b697352011-07-22 16:23:09 -0400207
208 // Bt
Joe Onoratofce2bf32011-02-01 17:00:29 -0800209 mBluetoothController.addIconView(
210 (ImageView)mNotificationPanel.findViewById(R.id.bluetooth));
Daniel Sandler2b697352011-07-22 16:23:09 -0400211
212 // network icons: either a combo icon that switches between mobile and data, or distinct
213 // mobile and data icons
214 final ImageView comboRSSI =
215 (ImageView)mNotificationPanel.findViewById(R.id.network_signal);
216 if (comboRSSI != null) {
217 mNetworkController.addCombinedSignalIconView(comboRSSI);
218 }
219 final ImageView mobileRSSI =
220 (ImageView)mNotificationPanel.findViewById(R.id.mobile_signal);
221 if (mobileRSSI != null) {
222 mNetworkController.addPhoneSignalIconView(mobileRSSI);
223 }
224 final ImageView wifiRSSI =
225 (ImageView)mNotificationPanel.findViewById(R.id.wifi_signal);
226 if (wifiRSSI != null) {
227 mNetworkController.addWifiIconView(wifiRSSI);
228 }
229
Joe Onorato42f8e132010-11-29 15:52:43 -0800230 mNetworkController.addDataTypeIconView(
231 (ImageView)mNotificationPanel.findViewById(R.id.network_type));
Joe Onoratofce2bf32011-02-01 17:00:29 -0800232 mNetworkController.addDataDirectionOverlayIconView(
233 (ImageView)mNotificationPanel.findViewById(R.id.network_direction));
Joe Onoratofd52b182010-11-10 18:00:52 -0800234 mNetworkController.addLabelView(
235 (TextView)mNotificationPanel.findViewById(R.id.network_text));
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500236 mNetworkController.addLabelView(
237 (TextView)mBarContents.findViewById(R.id.network_text));
Joe Onoratofd52b182010-11-10 18:00:52 -0800238
Joe Onorato55d2d762010-09-26 13:02:01 -0700239 mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400240
Joe Onorato07949e92011-05-25 17:35:35 -0700241 WindowManager.LayoutParams lp = mNotificationPanelParams = new WindowManager.LayoutParams(
242 res.getDimensionPixelSize(R.dimen.notification_panel_width),
243 getNotificationPanelHeight(),
Daniel Sandler9120d552010-07-23 09:11:14 -0400244 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
245 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
Joe Onorato07949e92011-05-25 17:35:35 -0700246 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
Jeff Brown46e75292010-11-10 16:53:45 -0800247 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
Joe Onorato7c270fa2010-12-08 17:31:42 -0800248 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
249 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
Daniel Sandler9120d552010-07-23 09:11:14 -0400250 PixelFormat.TRANSLUCENT);
Joe Onoratoea70e632010-09-27 17:59:37 -0700251 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
Daniel Sandler9120d552010-07-23 09:11:14 -0400252 lp.setTitle("NotificationPanel");
Joe Onorato7c270fa2010-12-08 17:31:42 -0800253 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
254 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
255 lp.windowAnimations = com.android.internal.R.style.Animation; // == no animation
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500256// lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
Daniel Sandler9120d552010-07-23 09:11:14 -0400257
258 WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
259
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400260 // Notification preview window
Daniel Sandler298a2a82011-08-11 16:13:22 -0400261 if (NOTIFICATION_PEEK_ENABLED) {
262 mNotificationPeekWindow = (NotificationPeekPanel) View.inflate(context,
263 R.layout.status_bar_notification_peek, null);
264 mNotificationPeekWindow.setBar(this);
Daniel Sandler663f0f22011-03-04 16:45:02 -0500265
Daniel Sandler298a2a82011-08-11 16:13:22 -0400266 mNotificationPeekRow = (ViewGroup) mNotificationPeekWindow.findViewById(R.id.content);
267 mNotificationPeekWindow.setVisibility(View.GONE);
268 mNotificationPeekWindow.setOnTouchListener(
269 new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PEEK, mNotificationPeekWindow));
270 mNotificationPeekScrubRight = new LayoutTransition();
271 mNotificationPeekScrubRight.setAnimator(LayoutTransition.APPEARING,
272 ObjectAnimator.ofInt(null, "left", -512, 0));
273 mNotificationPeekScrubRight.setAnimator(LayoutTransition.DISAPPEARING,
274 ObjectAnimator.ofInt(null, "left", -512, 0));
275 mNotificationPeekScrubRight.setDuration(500);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400276
Daniel Sandler298a2a82011-08-11 16:13:22 -0400277 mNotificationPeekScrubLeft = new LayoutTransition();
278 mNotificationPeekScrubLeft.setAnimator(LayoutTransition.APPEARING,
279 ObjectAnimator.ofInt(null, "left", 512, 0));
280 mNotificationPeekScrubLeft.setAnimator(LayoutTransition.DISAPPEARING,
281 ObjectAnimator.ofInt(null, "left", 512, 0));
282 mNotificationPeekScrubLeft.setDuration(500);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400283
Daniel Sandler298a2a82011-08-11 16:13:22 -0400284 // XXX: setIgnoreChildren?
285 lp = new WindowManager.LayoutParams(
286 512, // ViewGroup.LayoutParams.WRAP_CONTENT,
287 ViewGroup.LayoutParams.WRAP_CONTENT,
288 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
289 WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
290 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
291 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
292 PixelFormat.TRANSLUCENT);
293 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
294 lp.y = res.getDimensionPixelOffset(R.dimen.peek_window_y_offset);
295 lp.setTitle("NotificationPeekWindow");
296 lp.windowAnimations = com.android.internal.R.style.Animation_Toast;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400297
Daniel Sandler298a2a82011-08-11 16:13:22 -0400298 WindowManagerImpl.getDefault().addView(mNotificationPeekWindow, lp);
299 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400300
Jim Miller44c66fe2010-10-20 18:32:52 -0700301 // Recents Panel
Jim Miller9f0f0e02011-05-17 20:06:29 -0700302 mRecentsPanel = (RecentsPanelView) View.inflate(context,
Jim Miller85babff2011-01-11 14:26:03 -0800303 R.layout.status_bar_recent_panel, null);
304 mRecentsPanel.setVisibility(View.GONE);
Jeff Sharkey4519a022011-09-07 23:24:53 -0700305 mRecentsPanel.setSystemUiVisibility(View.STATUS_BAR_DISABLE_BACK);
Jim Miller85babff2011-01-11 14:26:03 -0800306 mRecentsPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL,
307 mRecentsPanel));
308 mStatusBarView.setIgnoreChildren(2, mRecentButton, mRecentsPanel);
Jim Miller44c66fe2010-10-20 18:32:52 -0700309
Jim Miller85babff2011-01-11 14:26:03 -0800310 lp = new WindowManager.LayoutParams(
Peter Ng622a9762011-08-29 10:56:53 -0700311 (int) res.getDimension(R.dimen.status_bar_recents_width),
Chet Haase212f6252011-08-12 09:19:10 -0700312 ViewGroup.LayoutParams.MATCH_PARENT,
Jim Miller85babff2011-01-11 14:26:03 -0800313 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
314 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
315 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
316 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
317 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
318 PixelFormat.TRANSLUCENT);
319 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
320 lp.setTitle("RecentsPanel");
321 lp.windowAnimations = R.style.Animation_RecentPanel;
Jim Miller5fda69c2011-02-16 15:17:11 -0800322 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
323 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
Jim Miller44c66fe2010-10-20 18:32:52 -0700324
Jim Miller85babff2011-01-11 14:26:03 -0800325 WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
326 mRecentsPanel.setBar(this);
satok82beadf2010-12-27 19:03:06 +0900327
328 // Input methods Panel
329 mInputMethodsPanel = (InputMethodsPanel) View.inflate(context,
330 R.layout.status_bar_input_methods_panel, null);
Jeff Brown2992ea72011-01-28 22:04:14 -0800331 mInputMethodsPanel.setHardKeyboardEnabledChangeListener(this);
satok82beadf2010-12-27 19:03:06 +0900332 mInputMethodsPanel.setOnTouchListener(new TouchOutsideListener(
333 MSG_CLOSE_INPUT_METHODS_PANEL, mInputMethodsPanel));
satok913f42d2011-01-17 16:58:10 +0900334 mInputMethodsPanel.setImeSwitchButton(mInputMethodSwitchButton);
satok82beadf2010-12-27 19:03:06 +0900335 mStatusBarView.setIgnoreChildren(3, mInputMethodSwitchButton, mInputMethodsPanel);
336 lp = new WindowManager.LayoutParams(
337 ViewGroup.LayoutParams.WRAP_CONTENT,
338 ViewGroup.LayoutParams.WRAP_CONTENT,
339 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
340 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
341 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
342 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
343 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
344 PixelFormat.TRANSLUCENT);
345 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
346 lp.setTitle("InputMethodsPanel");
347 lp.windowAnimations = R.style.Animation_RecentPanel;
348
349 WindowManagerImpl.getDefault().addView(mInputMethodsPanel, lp);
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400350
351 // Compatibility mode selector panel
352 mCompatModePanel = (CompatModePanel) View.inflate(context,
353 R.layout.status_bar_compat_mode_panel, null);
354 mCompatModePanel.setOnTouchListener(new TouchOutsideListener(
355 MSG_CLOSE_COMPAT_MODE_PANEL, mCompatModePanel));
356 mCompatModePanel.setTrigger(mCompatModeButton);
357 mCompatModePanel.setVisibility(View.GONE);
358 mStatusBarView.setIgnoreChildren(4, mCompatModeButton, mCompatModePanel);
359 lp = new WindowManager.LayoutParams(
360 250,
361 ViewGroup.LayoutParams.WRAP_CONTENT,
362 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
363 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
364 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
365 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
366 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
367 PixelFormat.TRANSLUCENT);
368 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
369 lp.setTitle("CompatModePanel");
370 lp.windowAnimations = android.R.style.Animation_Dialog;
371
372 WindowManagerImpl.getDefault().addView(mCompatModePanel, lp);
Daniel Sandler9120d552010-07-23 09:11:14 -0400373 }
Joe Onorato808182d2010-07-09 18:52:06 -0400374
Joe Onorato07949e92011-05-25 17:35:35 -0700375 private int getNotificationPanelHeight() {
376 final Resources res = mContext.getResources();
377 final Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
Jeff Brownbc68a592011-07-25 12:58:12 -0700378 final Point size = new Point();
379 d.getRealSize(size);
380 return Math.max(res.getDimensionPixelSize(R.dimen.notification_panel_min_height), size.y);
Joe Onorato07949e92011-05-25 17:35:35 -0700381 }
382
Joe Onorato808182d2010-07-09 18:52:06 -0400383 @Override
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400384 public void start() {
385 super.start(); // will add the main bar view
Joe Onorato808182d2010-07-09 18:52:06 -0400386 }
387
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500388 @Override
Joe Onoratodc100302011-01-11 17:07:41 -0800389 protected void onConfigurationChanged(Configuration newConfig) {
Jeff Brownbc68a592011-07-25 12:58:12 -0700390 mHeightReceiver.updateHeight(); // display size may have changed
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500391 loadDimens();
Joe Onorato07949e92011-05-25 17:35:35 -0700392 mNotificationPanelParams.height = getNotificationPanelHeight();
393 WindowManagerImpl.getDefault().updateViewLayout(mNotificationPanel,
394 mNotificationPanelParams);
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500395 }
396
397 protected void loadDimens() {
398 final Resources res = mContext.getResources();
399
Joe Onoratodc100302011-01-11 17:07:41 -0800400 mNaturalBarHeight = res.getDimensionPixelSize(
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700401 com.android.internal.R.dimen.system_bar_height);
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500402
403 int newIconSize = res.getDimensionPixelSize(
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700404 com.android.internal.R.dimen.system_bar_icon_size);
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500405 int newIconHPadding = res.getDimensionPixelSize(
406 R.dimen.status_bar_icon_padding);
407
408 if (newIconHPadding != mIconHPadding || newIconSize != mIconSize) {
409// Slog.d(TAG, "size=" + newIconSize + " padding=" + newIconHPadding);
410 mIconHPadding = newIconHPadding;
411 mIconSize = newIconSize;
412 reloadAllNotificationIcons(); // reload the tray
413 }
satok5485ff62011-05-27 19:15:01 +0900414
415 final int numIcons = res.getInteger(R.integer.config_maxNotificationIcons);
416 if (numIcons != mMaxNotificationIcons) {
417 mMaxNotificationIcons = numIcons;
418 if (DEBUG) Slog.d(TAG, "max notification icons: " + mMaxNotificationIcons);
419 reloadAllNotificationIcons();
420 }
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500421 }
422
Joe Onorato808182d2010-07-09 18:52:06 -0400423 protected View makeStatusBarView() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400424 final Context context = mContext;
Jim Miller85babff2011-01-11 14:26:03 -0800425
Daniel Sandler10163c62010-12-08 11:51:05 -0500426 mWindowManager = IWindowManager.Stub.asInterface(
427 ServiceManager.getService(Context.WINDOW_SERVICE));
Joe Onorato808182d2010-07-09 18:52:06 -0400428
Joe Onoratodc100302011-01-11 17:07:41 -0800429 // This guy will listen for HDMI plugged broadcasts so we can resize the
430 // status bar as appropriate.
431 mHeightReceiver = new HeightReceiver(mContext);
432 mHeightReceiver.registerReceiver();
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500433 loadDimens();
Joe Onorato808182d2010-07-09 18:52:06 -0400434
Joe Onoratob62ac122010-09-20 16:16:32 -0400435 final TabletStatusBarView sb = (TabletStatusBarView)View.inflate(
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400436 context, R.layout.status_bar, null);
Joe Onorato808182d2010-07-09 18:52:06 -0400437 mStatusBarView = sb;
438
Joe Onoratob62ac122010-09-20 16:16:32 -0400439 sb.setHandler(mHandler);
440
Chet Haasebc0009d2011-09-08 16:19:50 -0700441 // Sanity-check that someone hasn't set up the config wrong and asked for a navigation bar
442 // on a tablet that has only the system bar
443 if (mContext.getResources().getBoolean(
444 com.android.internal.R.bool.config_showNavigationBar)) {
445 throw new RuntimeException("Tablet device cannot show navigation bar and system bar");
446 }
447
Daniel Sandler21eb86a2011-03-02 11:52:58 -0500448 mBarContents = (ViewGroup) sb.findViewById(R.id.bar_contents);
449 // layout transitions for the status bar's contents
450 mBarContentsLayoutTransition = new LayoutTransition();
451 // add/removal will fade as normal
452 mBarContentsLayoutTransition.setAnimator(LayoutTransition.APPEARING,
453 ObjectAnimator.ofFloat(null, "alpha", 0f, 1f));
454 mBarContentsLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING,
455 ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
456 // no animations for siblings on change: just jump into place please
457 mBarContentsLayoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, null);
458 mBarContentsLayoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, null);
459 // quick like bunny
460 mBarContentsLayoutTransition.setDuration(250 * (DEBUG?10:1));
461 mBarContents.setLayoutTransition(mBarContentsLayoutTransition);
Joe Onoratof63b0f42010-09-12 17:03:19 -0400462
Joe Onoratofd52b182010-11-10 18:00:52 -0800463 // the whole right-hand side of the bar
464 mNotificationArea = sb.findViewById(R.id.notificationArea);
Daniel Sandler298a2a82011-08-11 16:13:22 -0400465 if (!NOTIFICATION_PEEK_ENABLED) {
466 mNotificationArea.setOnTouchListener(new NotificationTriggerTouchListener());
467 }
Joe Onoratofd52b182010-11-10 18:00:52 -0800468
Joe Onorato55d2d762010-09-26 13:02:01 -0700469 // the button to open the notification area
Joe Onoratofd52b182010-11-10 18:00:52 -0800470 mNotificationTrigger = sb.findViewById(R.id.notificationTrigger);
Daniel Sandler298a2a82011-08-11 16:13:22 -0400471 if (NOTIFICATION_PEEK_ENABLED) {
472 mNotificationTrigger.setOnTouchListener(new NotificationTriggerTouchListener());
473 }
Joe Onorato55d2d762010-09-26 13:02:01 -0700474
Joe Onorato808182d2010-07-09 18:52:06 -0400475 // the more notifications icon
476 mNotificationIconArea = (NotificationIconArea)sb.findViewById(R.id.notificationIcons);
477
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400478 // where the icons go
479 mIconLayout = (NotificationIconArea.IconLayout) sb.findViewById(R.id.icons);
Daniel Sandler298a2a82011-08-11 16:13:22 -0400480 if (NOTIFICATION_PEEK_ENABLED) {
481 mIconLayout.setOnTouchListener(new NotificationIconTouchListener());
482 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400483
484 ViewConfiguration vc = ViewConfiguration.get(context);
485 mNotificationPeekTapDuration = vc.getTapTimeout();
486 mNotificationFlingVelocity = 300; // px/s
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400487
Daniel Sandlerc51451a2010-12-16 19:06:46 -0500488 mTicker = new TabletTicker(this);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400489
Joe Onoratofd52b182010-11-10 18:00:52 -0800490 // The icons
Daniel Sandlere40451a2011-02-03 14:51:35 -0500491 mLocationController = new LocationController(mContext); // will post a notification
492
Joe Onoratofd52b182010-11-10 18:00:52 -0800493 mBatteryController = new BatteryController(mContext);
494 mBatteryController.addIconView((ImageView)sb.findViewById(R.id.battery));
Joe Onoratofce2bf32011-02-01 17:00:29 -0800495 mBluetoothController = new BluetoothController(mContext);
496 mBluetoothController.addIconView((ImageView)sb.findViewById(R.id.bluetooth));
Daniel Sandler2b697352011-07-22 16:23:09 -0400497
Joe Onoratofd52b182010-11-10 18:00:52 -0800498 mNetworkController = new NetworkController(mContext);
Christian Robertson2e347422011-08-11 14:01:04 -0700499 final SignalClusterView signalCluster =
500 (SignalClusterView)sb.findViewById(R.id.signal_cluster);
501 mNetworkController.addSignalCluster(signalCluster);
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400502
Joe Onorato091e1b82010-09-26 18:04:44 -0700503 // The navigation buttons
Joe Onorato6478adc2011-01-27 21:15:01 -0800504 mBackButton = (ImageView)sb.findViewById(R.id.back);
Daniel Sandler21eb86a2011-03-02 11:52:58 -0500505 mNavigationArea = (ViewGroup) sb.findViewById(R.id.navigationArea);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500506 mHomeButton = mNavigationArea.findViewById(R.id.home);
Daniel Sandlere02d8082010-10-08 15:13:22 -0400507 mMenuButton = mNavigationArea.findViewById(R.id.menu);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500508 mRecentButton = mNavigationArea.findViewById(R.id.recent_apps);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500509 mRecentButton.setOnClickListener(mOnClickListener);
Daniel Sandler21eb86a2011-03-02 11:52:58 -0500510 mNavigationArea.setLayoutTransition(mBarContentsLayoutTransition);
Daniel Sandler96f48182011-08-17 09:50:35 -0400511 // no multi-touch on the nav buttons
512 mNavigationArea.setMotionEventSplittingEnabled(false);
Joe Onorato091e1b82010-09-26 18:04:44 -0700513
satok06487a52010-10-29 11:37:18 +0900514 // The bar contents buttons
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400515 mFeedbackIconArea = (ViewGroup)sb.findViewById(R.id.feedbackIconArea);
satokcd7cd292010-11-20 15:46:23 +0900516 mInputMethodSwitchButton = (InputMethodButton) sb.findViewById(R.id.imeSwitchButton);
satok82beadf2010-12-27 19:03:06 +0900517 // Overwrite the lister
518 mInputMethodSwitchButton.setOnClickListener(mOnClickListener);
satok06487a52010-10-29 11:37:18 +0900519
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400520 mCompatModeButton = (CompatModeButton) sb.findViewById(R.id.compatModeButton);
521 mCompatModeButton.setOnClickListener(mOnClickListener);
522
Daniel Sandler10163c62010-12-08 11:51:05 -0500523 // for redirecting errant bar taps to the IME
524 mFakeSpaceBar = sb.findViewById(R.id.fake_space_bar);
525
Daniel Sandlerb9606992010-11-19 14:47:59 -0500526 // "shadows" of the status bar features, for lights-out mode
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500527 mShadow = sb.findViewById(R.id.bar_shadow);
528 mShadow.setOnTouchListener(
529 new View.OnTouchListener() {
530 public boolean onTouch(View v, MotionEvent ev) {
531 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
Daniel Sandlerd7201552011-01-28 09:58:02 -0500532 // even though setting the systemUI visibility below will turn these views
533 // on, we need them to come up faster so that they can catch this motion
534 // event
535 mShadow.setVisibility(View.GONE);
536 mBarContents.setVisibility(View.VISIBLE);
537
Joe Onorato55bf3802011-01-25 13:42:10 -0800538 try {
539 mBarService.setSystemUiVisibility(View.STATUS_BAR_VISIBLE);
540 } catch (RemoteException ex) {
541 // system process dead
542 }
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500543 }
544 return false;
545 }
546 });
Daniel Sandlerb9606992010-11-19 14:47:59 -0500547
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500548 // tuning parameters
549 final int LIGHTS_GOING_OUT_SYSBAR_DURATION = 600;
550 final int LIGHTS_GOING_OUT_SHADOW_DURATION = 1000;
551 final int LIGHTS_GOING_OUT_SHADOW_DELAY = 500;
552
553 final int LIGHTS_COMING_UP_SYSBAR_DURATION = 200;
554// final int LIGHTS_COMING_UP_SYSBAR_DELAY = 50;
555 final int LIGHTS_COMING_UP_SHADOW_DURATION = 0;
556
557 LayoutTransition xition = new LayoutTransition();
558 xition.setAnimator(LayoutTransition.APPEARING,
559 ObjectAnimator.ofFloat(null, "alpha", 0.5f, 1f));
560 xition.setDuration(LayoutTransition.APPEARING, LIGHTS_COMING_UP_SYSBAR_DURATION);
561 xition.setStartDelay(LayoutTransition.APPEARING, 0);
562 xition.setAnimator(LayoutTransition.DISAPPEARING,
563 ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
564 xition.setDuration(LayoutTransition.DISAPPEARING, LIGHTS_GOING_OUT_SYSBAR_DURATION);
565 xition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
566 ((ViewGroup)sb.findViewById(R.id.bar_contents_holder)).setLayoutTransition(xition);
567
568 xition = new LayoutTransition();
569 xition.setAnimator(LayoutTransition.APPEARING,
570 ObjectAnimator.ofFloat(null, "alpha", 0f, 1f));
571 xition.setDuration(LayoutTransition.APPEARING, LIGHTS_GOING_OUT_SHADOW_DURATION);
572 xition.setStartDelay(LayoutTransition.APPEARING, LIGHTS_GOING_OUT_SHADOW_DELAY);
573 xition.setAnimator(LayoutTransition.DISAPPEARING,
574 ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
575 xition.setDuration(LayoutTransition.DISAPPEARING, LIGHTS_COMING_UP_SHADOW_DURATION);
576 xition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
577 ((ViewGroup)sb.findViewById(R.id.bar_shadow_holder)).setLayoutTransition(xition);
Daniel Sandlerb9606992010-11-19 14:47:59 -0500578
Joe Onorato5dd11692010-09-27 15:34:04 -0700579 // set the initial view visibility
580 setAreThereNotifications();
581
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400582 // Add the windows
583 addPanelWindows();
584
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400585 mPile = (ViewGroup)mNotificationPanel.findViewById(R.id.content);
586 mPile.removeAllViews();
Jim Miller44c66fe2010-10-20 18:32:52 -0700587
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400588 ScrollView scroller = (ScrollView)mPile.getParent();
589 scroller.setFillViewport(true);
590
Joe Onoratodc100302011-01-11 17:07:41 -0800591 mHeightReceiver.addOnBarHeightChangedListener(this);
592
Joe Onorato808182d2010-07-09 18:52:06 -0400593 return sb;
594 }
595
Joe Onoratodc100302011-01-11 17:07:41 -0800596 public int getStatusBarHeight() {
597 return mHeightReceiver.getHeight();
598 }
599
Joe Onorato808182d2010-07-09 18:52:06 -0400600 protected int getStatusBarGravity() {
601 return Gravity.BOTTOM | Gravity.FILL_HORIZONTAL;
602 }
603
Joe Onoratodc100302011-01-11 17:07:41 -0800604 public void onBarHeightChanged(int height) {
605 final WindowManager.LayoutParams lp
606 = (WindowManager.LayoutParams)mStatusBarView.getLayoutParams();
607 if (lp == null) {
608 // haven't been added yet
609 return;
610 }
611 if (lp.height != height) {
612 lp.height = height;
613 final WindowManager wm = WindowManagerImpl.getDefault();
614 wm.updateViewLayout(mStatusBarView, lp);
615 }
616 }
617
Daniel Sandler9120d552010-07-23 09:11:14 -0400618 private class H extends Handler {
Daniel Sandler9120d552010-07-23 09:11:14 -0400619 public void handleMessage(Message m) {
620 switch (m.what) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400621 case MSG_OPEN_NOTIFICATION_PEEK:
622 if (DEBUG) Slog.d(TAG, "opening notification peek window; arg=" + m.arg1);
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500623
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400624 if (m.arg1 >= 0) {
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500625 final int N = mNotificationData.size();
626
627 if (!mNotificationDNDMode) {
628 if (mNotificationPeekIndex >= 0 && mNotificationPeekIndex < N) {
629 NotificationData.Entry entry = mNotificationData.get(N-1-mNotificationPeekIndex);
630 entry.icon.setBackgroundColor(0);
631 mNotificationPeekIndex = -1;
632 mNotificationPeekKey = null;
633 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400634 }
635
636 final int peekIndex = m.arg1;
637 if (peekIndex < N) {
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500638 //Slog.d(TAG, "loading peek: " + peekIndex);
Jim Miller5fda69c2011-02-16 15:17:11 -0800639 NotificationData.Entry entry =
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500640 mNotificationDNDMode
641 ? mNotificationDNDDummyEntry
642 : mNotificationData.get(N-1-peekIndex);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400643 NotificationData.Entry copy = new NotificationData.Entry(
Jim Miller85babff2011-01-11 14:26:03 -0800644 entry.key,
645 entry.notification,
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400646 entry.icon);
647 inflateViews(copy, mNotificationPeekRow);
648
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500649 if (mNotificationDNDMode) {
650 copy.content.setOnClickListener(new View.OnClickListener() {
651 public void onClick(View v) {
652 SharedPreferences.Editor editor = Prefs.edit(mContext);
653 editor.putBoolean(Prefs.DO_NOT_DISTURB_PREF, false);
654 editor.apply();
655 animateCollapse();
Mike Lockwood066c8912011-08-24 10:17:18 -0400656 visibilityChanged(false);
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500657 }
658 });
659 }
660
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400661 entry.icon.setBackgroundColor(0x20FFFFFF);
662
663// mNotificationPeekRow.setLayoutTransition(
Jim Miller85babff2011-01-11 14:26:03 -0800664// peekIndex < mNotificationPeekIndex
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400665// ? mNotificationPeekScrubLeft
666// : mNotificationPeekScrubRight);
667
668 mNotificationPeekRow.removeAllViews();
669 mNotificationPeekRow.addView(copy.row);
670
671 mNotificationPeekWindow.setVisibility(View.VISIBLE);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800672 mNotificationPanel.show(false, true);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400673
674 mNotificationPeekIndex = peekIndex;
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500675 mNotificationPeekKey = entry.key;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400676 }
677 }
678 break;
679 case MSG_CLOSE_NOTIFICATION_PEEK:
680 if (DEBUG) Slog.d(TAG, "closing notification peek window");
681 mNotificationPeekWindow.setVisibility(View.GONE);
682 mNotificationPeekRow.removeAllViews();
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500683
684 final int N = mNotificationData.size();
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500685 if (mNotificationPeekIndex >= 0 && mNotificationPeekIndex < N) {
Jim Miller5fda69c2011-02-16 15:17:11 -0800686 NotificationData.Entry entry =
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500687 mNotificationDNDMode
688 ? mNotificationDNDDummyEntry
689 : mNotificationData.get(N-1-mNotificationPeekIndex);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400690 entry.icon.setBackgroundColor(0);
691 }
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500692
693 mNotificationPeekIndex = -1;
694 mNotificationPeekKey = null;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400695 break;
Daniel Sandler9120d552010-07-23 09:11:14 -0400696 case MSG_OPEN_NOTIFICATION_PANEL:
697 if (DEBUG) Slog.d(TAG, "opening notifications panel");
Joe Onorato7c270fa2010-12-08 17:31:42 -0800698 if (!mNotificationPanel.isShowing()) {
Daniel Sandler298a2a82011-08-11 16:13:22 -0400699 if (NOTIFICATION_PEEK_ENABLED) {
700 mNotificationPeekWindow.setVisibility(View.GONE);
701 }
Joe Onorato7c270fa2010-12-08 17:31:42 -0800702 mNotificationPanel.show(true, true);
Daniel Sandler21eb86a2011-03-02 11:52:58 -0500703 mNotificationArea.setVisibility(View.INVISIBLE);
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800704 mTicker.halt();
Joe Onorato091e1b82010-09-26 18:04:44 -0700705 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400706 break;
707 case MSG_CLOSE_NOTIFICATION_PANEL:
708 if (DEBUG) Slog.d(TAG, "closing notifications panel");
Joe Onorato7c270fa2010-12-08 17:31:42 -0800709 if (mNotificationPanel.isShowing()) {
710 mNotificationPanel.show(false, true);
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500711 mNotificationArea.setVisibility(View.VISIBLE);
Joe Onorato091e1b82010-09-26 18:04:44 -0700712 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400713 break;
Jim Miller44c66fe2010-10-20 18:32:52 -0700714 case MSG_OPEN_RECENTS_PANEL:
715 if (DEBUG) Slog.d(TAG, "opening recents panel");
Jim Miller85babff2011-01-11 14:26:03 -0800716 if (mRecentsPanel != null) {
717 mRecentsPanel.setVisibility(View.VISIBLE);
718 mRecentsPanel.show(true, true);
719 }
Jim Miller44c66fe2010-10-20 18:32:52 -0700720 break;
721 case MSG_CLOSE_RECENTS_PANEL:
722 if (DEBUG) Slog.d(TAG, "closing recents panel");
Jim Miller85babff2011-01-11 14:26:03 -0800723 if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
724 mRecentsPanel.show(false, true);
725 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400726 break;
satok82beadf2010-12-27 19:03:06 +0900727 case MSG_OPEN_INPUT_METHODS_PANEL:
728 if (DEBUG) Slog.d(TAG, "opening input methods panel");
Tadashi G. Takaokae385f0c2011-02-01 02:57:44 +0900729 if (mInputMethodsPanel != null) mInputMethodsPanel.openPanel();
satok82beadf2010-12-27 19:03:06 +0900730 break;
731 case MSG_CLOSE_INPUT_METHODS_PANEL:
732 if (DEBUG) Slog.d(TAG, "closing input methods panel");
Tadashi G. Takaokae385f0c2011-02-01 02:57:44 +0900733 if (mInputMethodsPanel != null) mInputMethodsPanel.closePanel(false);
satok82beadf2010-12-27 19:03:06 +0900734 break;
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400735 case MSG_OPEN_COMPAT_MODE_PANEL:
736 if (DEBUG) Slog.d(TAG, "opening compat panel");
737 if (mCompatModePanel != null) mCompatModePanel.openPanel();
738 break;
739 case MSG_CLOSE_COMPAT_MODE_PANEL:
740 if (DEBUG) Slog.d(TAG, "closing compat panel");
741 if (mCompatModePanel != null) mCompatModePanel.closePanel();
742 break;
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500743 case MSG_SHOW_CHROME:
Daniel Sandlere03d1bc2010-11-17 21:36:40 -0500744 if (DEBUG) Slog.d(TAG, "hiding shadows (lights on)");
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500745 mBarContents.setVisibility(View.VISIBLE);
746 mShadow.setVisibility(View.GONE);
Daniel Sandler60ee2562011-07-22 12:34:33 -0400747 mSystemUiVisibility &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
748 notifyUiVisibilityChanged();
Daniel Sandler06e66302010-11-05 15:00:06 -0400749 break;
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500750 case MSG_HIDE_CHROME:
Daniel Sandlere03d1bc2010-11-17 21:36:40 -0500751 if (DEBUG) Slog.d(TAG, "showing shadows (lights out)");
Daniel Sandler06e66302010-11-05 15:00:06 -0400752 animateCollapse();
Mike Lockwood066c8912011-08-24 10:17:18 -0400753 visibilityChanged(false);
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500754 mBarContents.setVisibility(View.GONE);
755 mShadow.setVisibility(View.VISIBLE);
Daniel Sandler60ee2562011-07-22 12:34:33 -0400756 mSystemUiVisibility |= View.SYSTEM_UI_FLAG_LOW_PROFILE;
757 notifyUiVisibilityChanged();
Daniel Sandlere03d1bc2010-11-17 21:36:40 -0500758 break;
Daniel Sandler2ed08d22011-01-30 16:07:28 -0500759 case MSG_STOP_TICKER:
760 mTicker.halt();
761 break;
Daniel Sandler9120d552010-07-23 09:11:14 -0400762 }
763 }
764 }
Daniel Sandler271ea122010-10-22 14:06:10 -0400765
Joe Onorato808182d2010-07-09 18:52:06 -0400766 public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400767 if (DEBUG) Slog.d(TAG, "addIcon(" + slot + ") -> " + icon);
Joe Onorato808182d2010-07-09 18:52:06 -0400768 }
769
770 public void updateIcon(String slot, int index, int viewIndex,
771 StatusBarIcon old, StatusBarIcon icon) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400772 if (DEBUG) Slog.d(TAG, "updateIcon(" + slot + ") -> " + icon);
Joe Onorato808182d2010-07-09 18:52:06 -0400773 }
774
775 public void removeIcon(String slot, int index, int viewIndex) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400776 if (DEBUG) Slog.d(TAG, "removeIcon(" + slot + ")");
Joe Onorato808182d2010-07-09 18:52:06 -0400777 }
778
779 public void addNotification(IBinder key, StatusBarNotification notification) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400780 if (DEBUG) Slog.d(TAG, "addNotification(" + key + " -> " + notification + ")");
781 addNotificationViews(key, notification);
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400782
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800783 final boolean immersive = isImmersive();
Joe Onoratocf2b1992010-11-16 21:36:42 -0800784 if (false && immersive) {
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400785 // TODO: immersive mode popups for tablet
786 } else if (notification.notification.fullScreenIntent != null) {
787 // not immersive & a full-screen alert should be shown
Joe Onoratof68b5002011-01-16 17:00:34 -0800788 Slog.w(TAG, "Notification has fullScreenIntent and activity is not immersive;"
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400789 + " sending fullScreenIntent");
790 try {
791 notification.notification.fullScreenIntent.send();
792 } catch (PendingIntent.CanceledException e) {
793 }
794 } else {
Joe Onoratoeeed9942011-01-04 17:13:53 -0800795 tick(key, notification, true);
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400796 }
Joe Onorato5dd11692010-09-27 15:34:04 -0700797
798 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400799 }
800
801 public void updateNotification(IBinder key, StatusBarNotification notification) {
Daniel Sandler282ff9a2011-02-23 10:36:49 -0500802 if (DEBUG) Slog.d(TAG, "updateNotification(" + key + " -> " + notification + ")");
Jim Miller44c66fe2010-10-20 18:32:52 -0700803
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500804 final NotificationData.Entry oldEntry = mNotificationData.findByKey(key);
Daniel Sandler379020a2010-07-29 16:20:06 -0400805 if (oldEntry == null) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400806 Slog.w(TAG, "updateNotification for unknown key: " + key);
807 return;
808 }
809
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400810 final StatusBarNotification oldNotification = oldEntry.notification;
811 final RemoteViews oldContentView = oldNotification.notification.contentView;
812
813 final RemoteViews contentView = notification.notification.contentView;
814
Daniel Sandler373a9982010-11-30 12:03:59 -0500815 if (DEBUG) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400816 Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
817 + " ongoing=" + oldNotification.isOngoing()
818 + " expanded=" + oldEntry.expanded
Daniel Sandler282ff9a2011-02-23 10:36:49 -0500819 + " contentView=" + oldContentView
820 + " rowParent=" + oldEntry.row.getParent());
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400821 Slog.d(TAG, "new notification: when=" + notification.notification.when
822 + " ongoing=" + oldNotification.isOngoing()
823 + " contentView=" + contentView);
824 }
825
826 // Can we just reapply the RemoteViews in place? If when didn't change, the order
827 // didn't change.
Joe Onorato80a44402011-01-15 16:22:24 -0800828 boolean contentsUnchanged = oldEntry.expanded != null
829 && contentView != null && oldContentView != null
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400830 && contentView.getPackage() != null
831 && oldContentView.getPackage() != null
832 && oldContentView.getPackage().equals(contentView.getPackage())
Joe Onoratoc9596d62011-01-12 17:03:11 -0800833 && oldContentView.getLayoutId() == contentView.getLayoutId();
Daniel Sandler373a9982010-11-30 12:03:59 -0500834 ViewGroup rowParent = (ViewGroup) oldEntry.row.getParent();
Joe Onorato80a44402011-01-15 16:22:24 -0800835 boolean orderUnchanged = notification.notification.when==oldNotification.notification.when
Jim Miller5fda69c2011-02-16 15:17:11 -0800836 && notification.priority == oldNotification.priority;
Daniel Sandlera31e4192011-02-02 22:00:28 -0500837 // priority now encompasses isOngoing()
Joe Onoratoc9596d62011-01-12 17:03:11 -0800838 boolean isLastAnyway = rowParent.indexOfChild(oldEntry.row) == rowParent.getChildCount()-1;
839 if (contentsUnchanged && (orderUnchanged || isLastAnyway)) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400840 if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
841 oldEntry.notification = notification;
842 try {
843 // Reapply the RemoteViews
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400844 contentView.reapply(mContext, oldEntry.content);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400845 // update the contentIntent
846 final PendingIntent contentIntent = notification.notification.contentIntent;
847 if (contentIntent != null) {
Jeff Sharkey847fd752011-09-02 17:48:55 -0700848 final View.OnClickListener listener = new NotificationClicker(contentIntent,
849 notification.pkg, notification.tag, notification.id);
850 oldEntry.largeIcon.setOnClickListener(listener);
851 oldEntry.content.setOnClickListener(listener);
Joe Onorato184498c2010-10-08 17:57:18 -0400852 } else {
Jeff Sharkey847fd752011-09-02 17:48:55 -0700853 oldEntry.largeIcon.setOnClickListener(null);
Joe Onorato184498c2010-10-08 17:57:18 -0400854 oldEntry.content.setOnClickListener(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400855 }
856 // Update the icon.
857 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
858 notification.notification.icon, notification.notification.iconLevel,
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700859 notification.notification.number,
860 notification.notification.tickerText);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400861 if (!oldEntry.icon.set(ic)) {
862 handleNotificationError(key, notification, "Couldn't update icon: " + ic);
863 return;
864 }
Joe Onorato80a44402011-01-15 16:22:24 -0800865 // Update the large icon
866 if (notification.notification.largeIcon != null) {
867 oldEntry.largeIcon.setImageBitmap(notification.notification.largeIcon);
868 } else {
869 oldEntry.largeIcon.getLayoutParams().width = 0;
870 oldEntry.largeIcon.setVisibility(View.INVISIBLE);
871 }
Jim Miller85babff2011-01-11 14:26:03 -0800872
Daniel Sandler298a2a82011-08-11 16:13:22 -0400873 if (NOTIFICATION_PEEK_ENABLED && key == mNotificationPeekKey) {
Daniel Sandler7ef29b52010-12-16 17:29:50 -0500874 // must update the peek window
875 Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
876 peekMsg.arg1 = mNotificationPeekIndex;
877 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
878 mHandler.sendMessage(peekMsg);
879 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400880 }
881 catch (RuntimeException e) {
882 // It failed to add cleanly. Log, and remove the view from the panel.
883 Slog.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
884 removeNotificationViews(key);
885 addNotificationViews(key, notification);
886 }
887 } else {
888 if (DEBUG) Slog.d(TAG, "not reusing notification for key: " + key);
889 removeNotificationViews(key);
890 addNotificationViews(key, notification);
891 }
Daniel Sandler2a58af32011-08-26 09:38:24 -0700892
893 // Restart the ticker if it's still running
894 if (notification.notification.tickerText != null
895 && !TextUtils.equals(notification.notification.tickerText,
896 oldEntry.notification.notification.tickerText)) {
Joe Onoratoeeed9942011-01-04 17:13:53 -0800897 tick(key, notification, false);
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800898 }
Joe Onorato5dd11692010-09-27 15:34:04 -0700899
900 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400901 }
902
903 public void removeNotification(IBinder key) {
Daniel Sandler3a2fded2011-02-23 11:19:59 -0500904 if (DEBUG) Slog.d(TAG, "removeNotification(" + key + ")");
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400905 removeNotificationViews(key);
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800906 mTicker.remove(key);
Joe Onorato5dd11692010-09-27 15:34:04 -0700907 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400908 }
909
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500910 public void showClock(boolean show) {
911 View clock = mBarContents.findViewById(R.id.clock);
912 View network_text = mBarContents.findViewById(R.id.network_text);
913 if (clock != null) {
914 clock.setVisibility(show ? View.VISIBLE : View.GONE);
915 }
916 if (network_text != null) {
917 network_text.setVisibility((!show) ? View.VISIBLE : View.GONE);
918 }
919 }
920
Joe Onorato808182d2010-07-09 18:52:06 -0400921 public void disable(int state) {
Joe Onorato091e1b82010-09-26 18:04:44 -0700922 int old = mDisabled;
923 int diff = state ^ old;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400924 mDisabled = state;
925
Joe Onorato091e1b82010-09-26 18:04:44 -0700926 // act accordingly
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500927 if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) {
928 boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0;
Joe Onoratof68b5002011-01-16 17:00:34 -0800929 Slog.i(TAG, "DISABLE_CLOCK: " + (show ? "no" : "yes"));
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500930 showClock(show);
931 }
Daniel Sandler6f6cf3c2010-12-16 12:54:03 -0500932 if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
933 boolean show = (state & StatusBarManager.DISABLE_SYSTEM_INFO) == 0;
Joe Onoratof68b5002011-01-16 17:00:34 -0800934 Slog.i(TAG, "DISABLE_SYSTEM_INFO: " + (show ? "no" : "yes"));
Daniel Sandler6f6cf3c2010-12-16 12:54:03 -0500935 mNotificationTrigger.setVisibility(show ? View.VISIBLE : View.GONE);
936 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400937 if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
938 if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
Joe Onoratof68b5002011-01-16 17:00:34 -0800939 Slog.i(TAG, "DISABLE_EXPAND: yes");
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400940 animateCollapse();
Mike Lockwood066c8912011-08-24 10:17:18 -0400941 visibilityChanged(false);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400942 }
943 }
944 if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500945 mNotificationDNDMode = Prefs.read(mContext)
946 .getBoolean(Prefs.DO_NOT_DISTURB_PREF, Prefs.DO_NOT_DISTURB_DEFAULT);
Daniel Sandler282ff9a2011-02-23 10:36:49 -0500947
948 if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
949 Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: yes" + (mNotificationDNDMode?" (DND)":""));
950 mTicker.halt();
951 } else {
952 Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: no" + (mNotificationDNDMode?" (DND)":""));
953 }
954
955 // refresh icons to show either notifications or the DND message
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500956 reloadAllNotificationIcons();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400957 } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
Joe Onorato091e1b82010-09-26 18:04:44 -0700958 if ((state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
Joe Onoratoef1e7762010-09-17 18:38:38 -0400959 mTicker.halt();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400960 }
961 }
Mike Lockwoode3646dd2011-09-01 12:46:28 -0400962 if ((diff & (StatusBarManager.DISABLE_NAVIGATION | StatusBarManager.DISABLE_BACK)) != 0) {
963 setNavigationVisibility(state &
964 (StatusBarManager.DISABLE_NAVIGATION | StatusBarManager.DISABLE_BACK));
Joe Onorato091e1b82010-09-26 18:04:44 -0700965 }
Mike Lockwoode3646dd2011-09-01 12:46:28 -0400966 }
967
968 private void setNavigationVisibility(int visibility) {
969 boolean disableNavigation = ((visibility & StatusBarManager.DISABLE_NAVIGATION) != 0);
970 boolean disableBack = ((visibility & StatusBarManager.DISABLE_BACK) != 0);
971
972 Slog.i(TAG, "DISABLE_BACK: " + (disableBack ? "yes" : "no"));
973 Slog.i(TAG, "DISABLE_NAVIGATION: " + (disableNavigation ? "yes" : "no"));
974
975 if (disableNavigation && disableBack) {
976 mNavigationArea.setVisibility(View.INVISIBLE);
977 } else {
978 int backVisiblity = (disableBack ? View.INVISIBLE : View.VISIBLE);
979 int navVisibility = (disableNavigation ? View.INVISIBLE : View.VISIBLE);
980
981 mBackButton.setVisibility(backVisiblity);
982 mHomeButton.setVisibility(navVisibility);
983 mRecentButton.setVisibility(navVisibility);
984 // don't change menu button visibility here
985
986 mNavigationArea.setVisibility(View.VISIBLE);
Joe Onorato6478adc2011-01-27 21:15:01 -0800987 }
988
Mike Lockwoode3646dd2011-09-01 12:46:28 -0400989 mInputMethodSwitchButton.setScreenLocked(disableNavigation);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400990 }
991
Joe Onoratoef1e7762010-09-17 18:38:38 -0400992 private boolean hasTicker(Notification n) {
Joe Onorato46439ce2010-11-19 13:56:21 -0800993 return n.tickerView != null || !TextUtils.isEmpty(n.tickerText);
Joe Onoratoef1e7762010-09-17 18:38:38 -0400994 }
995
Joe Onoratoeeed9942011-01-04 17:13:53 -0800996 private void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
Joe Onorato55d2d762010-09-26 13:02:01 -0700997 // Don't show the ticker when the windowshade is open.
Joe Onorato7c270fa2010-12-08 17:31:42 -0800998 if (mNotificationPanel.isShowing()) {
Joe Onorato55d2d762010-09-26 13:02:01 -0700999 return;
1000 }
Joe Onoratoeeed9942011-01-04 17:13:53 -08001001 // If they asked for FLAG_ONLY_ALERT_ONCE, then only show this notification
1002 // if it's a new notification.
1003 if (!firstTime && (n.notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) {
1004 return;
1005 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001006 // Show the ticker if one is requested. Also don't do this
1007 // until status bar window is attached to the window manager,
1008 // because... well, what's the point otherwise? And trying to
1009 // run a ticker without being attached will crash!
Joe Onoratoef1e7762010-09-17 18:38:38 -04001010 if (hasTicker(n.notification) && mStatusBarView.getWindowToken() != null) {
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001011 if (0 == (mDisabled & (StatusBarManager.DISABLE_NOTIFICATION_ICONS
1012 | StatusBarManager.DISABLE_NOTIFICATION_TICKER))) {
Joe Onorato50ec5ec2010-11-28 17:15:26 -08001013 mTicker.add(key, n);
Daniel Sandler3b0543a2011-06-14 11:30:28 -04001014 mFeedbackIconArea.setVisibility(View.GONE);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001015 }
1016 }
1017 }
1018
Daniel Sandlerb8027d82010-12-16 19:35:54 -05001019 // called by TabletTicker when it's done with all queued ticks
1020 public void doneTicking() {
Daniel Sandler3b0543a2011-06-14 11:30:28 -04001021 mFeedbackIconArea.setVisibility(View.VISIBLE);
Daniel Sandlerb8027d82010-12-16 19:35:54 -05001022 }
1023
Joe Onorato808182d2010-07-09 18:52:06 -04001024 public void animateExpand() {
Daniel Sandler298a2a82011-08-11 16:13:22 -04001025 if (NOTIFICATION_PEEK_ENABLED) {
1026 mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PEEK);
1027 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
1028 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
1029 }
Joe Onoratob62ac122010-09-20 16:16:32 -04001030 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
1031 mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
Joe Onorato808182d2010-07-09 18:52:06 -04001032 }
1033
1034 public void animateCollapse() {
Joe Onoratob62ac122010-09-20 16:16:32 -04001035 mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PANEL);
1036 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PANEL);
Jim Miller44c66fe2010-10-20 18:32:52 -07001037 mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
1038 mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
satok82beadf2010-12-27 19:03:06 +09001039 mHandler.removeMessages(MSG_CLOSE_INPUT_METHODS_PANEL);
1040 mHandler.sendEmptyMessage(MSG_CLOSE_INPUT_METHODS_PANEL);
Daniel Sandler3b0543a2011-06-14 11:30:28 -04001041 mHandler.removeMessages(MSG_CLOSE_COMPAT_MODE_PANEL);
1042 mHandler.sendEmptyMessage(MSG_CLOSE_COMPAT_MODE_PANEL);
Daniel Sandler298a2a82011-08-11 16:13:22 -04001043 if (NOTIFICATION_PEEK_ENABLED) {
1044 mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PEEK);
1045 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
1046 }
Daniel Sandler9120d552010-07-23 09:11:14 -04001047 }
1048
Mike Lockwood066c8912011-08-24 10:17:18 -04001049 /**
1050 * The LEDs are turned o)ff when the notification panel is shown, even just a little bit.
1051 * This was added last-minute and is inconsistent with the way the rest of the notifications
1052 * are handled, because the notification isn't really cancelled. The lights are just
1053 * turned off. If any other notifications happen, the lights will turn back on. Steve says
1054 * this is what he wants. (see bug 1131461)
1055 */
1056 void visibilityChanged(boolean visible) {
1057 if (mPanelSlightlyVisible != visible) {
1058 mPanelSlightlyVisible = visible;
1059 try {
1060 mBarService.onPanelRevealed();
1061 } catch (RemoteException ex) {
1062 // Won't fail unless the world has ended.
1063 }
1064 }
1065 }
1066
Daniel Sandler60ee2562011-07-22 12:34:33 -04001067 private void notifyUiVisibilityChanged() {
1068 try {
1069 mWindowManager.statusBarVisibilityChanged(mSystemUiVisibility);
1070 } catch (RemoteException ex) {
1071 }
1072 }
1073
1074 @Override // CommandQueue
1075 public void setSystemUiVisibility(int vis) {
1076 if (vis != mSystemUiVisibility) {
1077 mSystemUiVisibility = vis;
1078
1079 mHandler.removeMessages(MSG_HIDE_CHROME);
1080 mHandler.removeMessages(MSG_SHOW_CHROME);
1081 mHandler.sendEmptyMessage(0 == (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE)
1082 ? MSG_SHOW_CHROME : MSG_HIDE_CHROME);
1083
1084 notifyUiVisibilityChanged();
1085 }
1086 }
1087
Joe Onorato93056472010-09-10 10:30:46 -04001088 public void setLightsOn(boolean on) {
Daniel Sandler59485d742010-12-02 00:11:33 -05001089 // Policy note: if the frontmost activity needs the menu key, we assume it is a legacy app
1090 // that can't handle lights-out mode.
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001091 if (mMenuButton.getVisibility() == View.VISIBLE) {
Daniel Sandler59485d742010-12-02 00:11:33 -05001092 on = true;
1093 }
Daniel Sandler60ee2562011-07-22 12:34:33 -04001094
1095 Slog.v(TAG, "setLightsOn(" + on + ")");
1096 if (on) {
1097 setSystemUiVisibility(mSystemUiVisibility & ~View.SYSTEM_UI_FLAG_LOW_PROFILE);
1098 } else {
1099 setSystemUiVisibility(mSystemUiVisibility | View.SYSTEM_UI_FLAG_LOW_PROFILE);
1100 }
Joe Onorato93056472010-09-10 10:30:46 -04001101 }
1102
Daniel Sandler5c8da942011-06-28 00:29:04 -04001103 public void topAppWindowChanged(boolean showMenu) {
Daniel Sandlere02d8082010-10-08 15:13:22 -04001104 if (DEBUG) {
Daniel Sandler5c8da942011-06-28 00:29:04 -04001105 Slog.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
Daniel Sandlere02d8082010-10-08 15:13:22 -04001106 }
Daniel Sandler5c8da942011-06-28 00:29:04 -04001107 mMenuButton.setVisibility(showMenu ? View.VISIBLE : View.GONE);
Daniel Sandler59485d742010-12-02 00:11:33 -05001108
1109 // See above re: lights-out policy for legacy apps.
Daniel Sandler5c8da942011-06-28 00:29:04 -04001110 if (showMenu) setLightsOn(true);
Daniel Sandler45c04012011-06-07 15:29:07 -04001111
Daniel Sandler3b0543a2011-06-14 11:30:28 -04001112 mCompatModeButton.refresh();
Daniel Sandler552b1f02011-06-15 01:03:02 -04001113 if (mCompatModeButton.getVisibility() == View.VISIBLE) {
Daniel Sandler319d1e32011-08-05 11:34:06 -04001114 if (DEBUG_COMPAT_HELP
1115 || ! Prefs.read(mContext).getBoolean(Prefs.SHOWN_COMPAT_MODE_HELP, false)) {
Daniel Sandler552b1f02011-06-15 01:03:02 -04001116 showCompatibilityHelp();
Daniel Sandler319d1e32011-08-05 11:34:06 -04001117 }
Dianne Hackborned31bbf2011-06-15 11:16:06 -07001118 } else {
1119 hideCompatibilityHelp();
1120 mCompatModePanel.closePanel();
Daniel Sandler552b1f02011-06-15 01:03:02 -04001121 }
1122 }
1123
1124 private void showCompatibilityHelp() {
Dianne Hackborned31bbf2011-06-15 11:16:06 -07001125 if (mCompatibilityHelpDialog != null) {
1126 return;
1127 }
1128
1129 mCompatibilityHelpDialog = View.inflate(mContext, R.layout.compat_mode_help, null);
1130 View button = mCompatibilityHelpDialog.findViewById(R.id.button);
Daniel Sandler552b1f02011-06-15 01:03:02 -04001131
1132 button.setOnClickListener(new View.OnClickListener() {
1133 @Override
1134 public void onClick(View v) {
Dianne Hackborned31bbf2011-06-15 11:16:06 -07001135 hideCompatibilityHelp();
1136 SharedPreferences.Editor editor = Prefs.edit(mContext);
1137 editor.putBoolean(Prefs.SHOWN_COMPAT_MODE_HELP, true);
1138 editor.apply();
Daniel Sandler552b1f02011-06-15 01:03:02 -04001139 }
1140 });
1141
Daniel Sandlerf1dd26b2011-06-20 14:44:35 -04001142 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
Daniel Sandler552b1f02011-06-15 01:03:02 -04001143 ViewGroup.LayoutParams.MATCH_PARENT,
1144 ViewGroup.LayoutParams.MATCH_PARENT,
1145 WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG,
1146 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
1147 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
1148 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
1149 PixelFormat.TRANSLUCENT);
1150 lp.setTitle("CompatibilityModeDialog");
1151 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
1152 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
1153 lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
1154
Dianne Hackborned31bbf2011-06-15 11:16:06 -07001155 WindowManagerImpl.getDefault().addView(mCompatibilityHelpDialog, lp);
Daniel Sandlere02d8082010-10-08 15:13:22 -04001156 }
1157
Dianne Hackborned31bbf2011-06-15 11:16:06 -07001158 private void hideCompatibilityHelp() {
1159 if (mCompatibilityHelpDialog != null) {
1160 WindowManagerImpl.getDefault().removeView(mCompatibilityHelpDialog);
1161 mCompatibilityHelpDialog = null;
1162 }
1163 }
1164
Joe Onorato857fd9b2011-01-27 15:08:35 -08001165 public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
1166 mInputMethodSwitchButton.setImeWindowStatus(token,
1167 (vis & InputMethodService.IME_ACTIVE) != 0);
satok51133822011-01-25 15:01:48 +09001168 updateNotificationIcons();
satok913f42d2011-01-17 16:58:10 +09001169 mInputMethodsPanel.setImeToken(token);
Joe Onorato857fd9b2011-01-27 15:08:35 -08001170 int res;
1171 switch (backDisposition) {
1172 case InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS:
1173 res = R.drawable.ic_sysbar_back;
1174 break;
1175 case InputMethodService.BACK_DISPOSITION_WILL_DISMISS:
1176 res = R.drawable.ic_sysbar_back_ime;
1177 break;
1178 case InputMethodService.BACK_DISPOSITION_DEFAULT:
1179 default:
1180 if ((vis & InputMethodService.IME_VISIBLE) != 0) {
1181 res = R.drawable.ic_sysbar_back_ime;
1182 } else {
1183 res = R.drawable.ic_sysbar_back;
1184 }
1185 break;
1186 }
1187 mBackButton.setImageResource(res);
Daniel Sandler10163c62010-12-08 11:51:05 -05001188 if (FAKE_SPACE_BAR) {
Joe Onorato857fd9b2011-01-27 15:08:35 -08001189 mFakeSpaceBar.setVisibility(((vis & InputMethodService.IME_VISIBLE) != 0)
1190 ? View.VISIBLE : View.GONE);
Daniel Sandler10163c62010-12-08 11:51:05 -05001191 }
satok06487a52010-10-29 11:37:18 +09001192 }
1193
Jeff Brown2992ea72011-01-28 22:04:14 -08001194 @Override
1195 public void setHardKeyboardStatus(boolean available, boolean enabled) {
1196 if (DEBUG) {
1197 Slog.d(TAG, "Set hard keyboard status: available=" + available
1198 + ", enabled=" + enabled);
1199 }
1200 mInputMethodSwitchButton.setHardKeyboardStatus(available);
1201 updateNotificationIcons();
1202 mInputMethodsPanel.setHardKeyboardStatus(available, enabled);
1203 }
1204
1205 @Override
1206 public void onHardKeyboardEnabledChange(boolean enabled) {
1207 try {
1208 mBarService.setHardKeyboardEnabled(enabled);
1209 } catch (RemoteException ex) {
1210 }
1211 }
1212
Joe Onorato50ec5ec2010-11-28 17:15:26 -08001213 private boolean isImmersive() {
1214 try {
1215 return ActivityManagerNative.getDefault().isTopActivityImmersive();
1216 //Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
1217 } catch (RemoteException ex) {
1218 // the end is nigh
1219 return false;
1220 }
1221 }
Jim Miller85babff2011-01-11 14:26:03 -08001222
Joe Onorato5dd11692010-09-27 15:34:04 -07001223 private void setAreThereNotifications() {
Daniel Sandler06a0d4b2011-08-05 00:19:21 -04001224 if (mNotificationPanel != null) {
1225 mNotificationPanel.setClearable(mNotificationData.hasClearableItems());
1226 }
Joe Onorato5dd11692010-09-27 15:34:04 -07001227 }
1228
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001229 /**
1230 * Cancel this notification and tell the status bar service about the failure. Hold no locks.
1231 */
1232 void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
1233 removeNotification(key);
1234 try {
1235 mBarService.onNotificationError(n.pkg, n.tag, n.id, n.uid, n.initialPid, message);
1236 } catch (RemoteException ex) {
1237 // The end is nigh.
1238 }
1239 }
1240
Daniel Sandler10163c62010-12-08 11:51:05 -05001241 private void sendKey(KeyEvent key) {
1242 try {
1243 if (DEBUG) Slog.d(TAG, "injecting key event: " + key);
1244 mWindowManager.injectInputEventNoWait(key);
1245 } catch (RemoteException ex) {
1246 }
1247 }
1248
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001249 private View.OnClickListener mOnClickListener = new View.OnClickListener() {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001250 public void onClick(View v) {
Daniel Sandler130453c2011-08-18 09:41:01 -04001251 if (v == mRecentButton) {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001252 onClickRecentButton();
satok82beadf2010-12-27 19:03:06 +09001253 } else if (v == mInputMethodSwitchButton) {
1254 onClickInputMethodSwitchButton();
Daniel Sandler3b0543a2011-06-14 11:30:28 -04001255 } else if (v == mCompatModeButton) {
1256 onClickCompatModeButton();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001257 }
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001258 }
1259 };
1260
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001261 public void onClickRecentButton() {
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001262 if (DEBUG) Slog.d(TAG, "clicked recent apps; disabled=" + mDisabled);
Michael Jurka3b1fc472011-06-13 10:54:40 -07001263 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
1264 int msg = (mRecentsPanel.getVisibility() == View.GONE)
1265 ? MSG_OPEN_RECENTS_PANEL
1266 : MSG_CLOSE_RECENTS_PANEL;
1267 mHandler.removeMessages(msg);
1268 mHandler.sendEmptyMessage(msg);
Jim Miller44c66fe2010-10-20 18:32:52 -07001269 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001270 }
Joe Onorato55d2d762010-09-26 13:02:01 -07001271
satok82beadf2010-12-27 19:03:06 +09001272 public void onClickInputMethodSwitchButton() {
1273 if (DEBUG) Slog.d(TAG, "clicked input methods panel; disabled=" + mDisabled);
1274 int msg = (mInputMethodsPanel.getVisibility() == View.GONE) ?
1275 MSG_OPEN_INPUT_METHODS_PANEL : MSG_CLOSE_INPUT_METHODS_PANEL;
1276 mHandler.removeMessages(msg);
1277 mHandler.sendEmptyMessage(msg);
1278 }
1279
Daniel Sandler3b0543a2011-06-14 11:30:28 -04001280 public void onClickCompatModeButton() {
1281 int msg = (mCompatModePanel.getVisibility() == View.GONE) ?
1282 MSG_OPEN_COMPAT_MODE_PANEL : MSG_CLOSE_COMPAT_MODE_PANEL;
1283 mHandler.removeMessages(msg);
1284 mHandler.sendEmptyMessage(msg);
1285 }
1286
Daniel Sandlerc51451a2010-12-16 19:06:46 -05001287 public NotificationClicker makeClicker(PendingIntent intent, String pkg, String tag, int id) {
1288 return new NotificationClicker(intent, pkg, tag, id);
1289 }
1290
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001291 private class NotificationClicker implements View.OnClickListener {
1292 private PendingIntent mIntent;
1293 private String mPkg;
1294 private String mTag;
1295 private int mId;
1296
1297 NotificationClicker(PendingIntent intent, String pkg, String tag, int id) {
1298 mIntent = intent;
1299 mPkg = pkg;
1300 mTag = tag;
1301 mId = id;
1302 }
1303
1304 public void onClick(View v) {
1305 try {
1306 // The intent we are sending is for the application, which
1307 // won't have permission to immediately start an activity after
1308 // the user switches to home. We know it is safe to do at this
1309 // point, so make sure new activity switches are now allowed.
1310 ActivityManagerNative.getDefault().resumeAppSwitches();
1311 } catch (RemoteException e) {
1312 }
1313
1314 if (mIntent != null) {
1315 int[] pos = new int[2];
1316 v.getLocationOnScreen(pos);
1317 Intent overlay = new Intent();
1318 overlay.setSourceBounds(
1319 new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
1320 try {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001321 mIntent.send(mContext, 0, overlay);
Daniel Sandler92d33182011-09-11 16:29:05 -04001322
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001323 } catch (PendingIntent.CanceledException e) {
1324 // the stack trace isn't very helpful here. Just log the exception message.
1325 Slog.w(TAG, "Sending contentIntent failed: " + e);
1326 }
Daniel Sandler92d33182011-09-11 16:29:05 -04001327
1328 KeyguardManager kgm =
1329 (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
1330 if (kgm != null) kgm.exitKeyguardSecurely(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001331 }
1332
1333 try {
1334 mBarService.onNotificationClick(mPkg, mTag, mId);
1335 } catch (RemoteException ex) {
1336 // system process is dead if we're here.
1337 }
1338
1339 // close the shade if it was open
1340 animateCollapse();
Mike Lockwood066c8912011-08-24 10:17:18 -04001341 visibilityChanged(false);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001342
1343 // If this click was on the intruder alert, hide that instead
1344// mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
1345 }
1346 }
1347
1348 StatusBarNotification removeNotificationViews(IBinder key) {
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001349 NotificationData.Entry entry = mNotificationData.remove(key);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001350 if (entry == null) {
1351 Slog.w(TAG, "removeNotification for unknown key: " + key);
1352 return null;
1353 }
1354 // Remove the expanded view.
1355 ViewGroup rowParent = (ViewGroup)entry.row.getParent();
1356 if (rowParent != null) rowParent.removeView(entry.row);
Daniel Sandlera8e5b062010-12-01 13:53:08 -05001357
Daniel Sandler298a2a82011-08-11 16:13:22 -04001358 if (NOTIFICATION_PEEK_ENABLED && key == mNotificationPeekKey) {
Daniel Sandlera8e5b062010-12-01 13:53:08 -05001359 // must close the peek as well, since it's gone
1360 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
1361 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001362 // Remove the icon.
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001363// ViewGroup iconParent = (ViewGroup)entry.icon.getParent();
1364// if (iconParent != null) iconParent.removeView(entry.icon);
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001365 updateNotificationIcons();
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001366
1367 return entry.notification;
1368 }
1369
Daniel Sandler56a6d882011-02-23 16:40:33 -05001370 private class NotificationTriggerTouchListener implements View.OnTouchListener {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001371 VelocityTracker mVT;
Daniel Sandler56a6d882011-02-23 16:40:33 -05001372 float mInitialTouchX, mInitialTouchY;
1373 int mTouchSlop;
1374
1375 public NotificationTriggerTouchListener() {
1376 mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
1377 }
1378
Daniel Sandler298a2a82011-08-11 16:13:22 -04001379 private Runnable mHiliteOnR = new Runnable() { public void run() {
1380 mNotificationArea.setBackgroundResource(
1381 com.android.internal.R.drawable.list_selector_pressed_holo_dark);
1382 }};
1383 public void hilite(final boolean on) {
1384 if (on) {
1385 mNotificationArea.postDelayed(mHiliteOnR, 100);
1386 } else {
1387 mNotificationArea.removeCallbacks(mHiliteOnR);
1388 mNotificationArea.setBackgroundDrawable(null);
1389 }
1390 }
1391
Daniel Sandler56a6d882011-02-23 16:40:33 -05001392 public boolean onTouch(View v, MotionEvent event) {
1393// Slog.d(TAG, String.format("touch: (%.1f, %.1f) initial: (%.1f, %.1f)",
1394// event.getX(),
1395// event.getY(),
1396// mInitialTouchX,
1397// mInitialTouchY));
Daniel Sandler130453c2011-08-18 09:41:01 -04001398
1399 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
1400 return true;
1401 }
1402
Daniel Sandler56a6d882011-02-23 16:40:33 -05001403 final int action = event.getAction();
1404 switch (action) {
1405 case MotionEvent.ACTION_DOWN:
1406 mVT = VelocityTracker.obtain();
1407 mInitialTouchX = event.getX();
1408 mInitialTouchY = event.getY();
Daniel Sandler298a2a82011-08-11 16:13:22 -04001409 hilite(true);
Daniel Sandler56a6d882011-02-23 16:40:33 -05001410 // fall through
1411 case MotionEvent.ACTION_OUTSIDE:
1412 case MotionEvent.ACTION_MOVE:
1413 // check for fling
1414 if (mVT != null) {
1415 mVT.addMovement(event);
1416 mVT.computeCurrentVelocity(1000); // pixels per second
1417 // require a little more oomph once we're already in peekaboo mode
1418 if (mVT.getYVelocity() < -mNotificationFlingVelocity) {
1419 animateExpand();
Mike Lockwood066c8912011-08-24 10:17:18 -04001420 visibilityChanged(true);
Daniel Sandler298a2a82011-08-11 16:13:22 -04001421 hilite(false);
Daniel Sandler56a6d882011-02-23 16:40:33 -05001422 mVT.recycle();
1423 mVT = null;
1424 }
1425 }
1426 return true;
1427 case MotionEvent.ACTION_UP:
1428 case MotionEvent.ACTION_CANCEL:
Daniel Sandler298a2a82011-08-11 16:13:22 -04001429 hilite(false);
Daniel Sandler56a6d882011-02-23 16:40:33 -05001430 if (mVT != null) {
1431 if (action == MotionEvent.ACTION_UP
1432 // was this a sloppy tap?
Jim Miller9f0f0e02011-05-17 20:06:29 -07001433 && Math.abs(event.getX() - mInitialTouchX) < mTouchSlop
Daniel Sandler56a6d882011-02-23 16:40:33 -05001434 && Math.abs(event.getY() - mInitialTouchY) < (mTouchSlop / 3)
1435 // dragging off the bottom doesn't count
1436 && (int)event.getY() < v.getBottom()) {
1437 animateExpand();
Mike Lockwood066c8912011-08-24 10:17:18 -04001438 visibilityChanged(true);
Daniel Sandleraa051d62011-03-01 16:23:57 -05001439 v.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
1440 v.playSoundEffect(SoundEffectConstants.CLICK);
Daniel Sandler56a6d882011-02-23 16:40:33 -05001441 }
1442
1443 mVT.recycle();
1444 mVT = null;
1445 return true;
1446 }
1447 }
1448 return false;
1449 }
1450 }
1451
Daniel Sandler663f0f22011-03-04 16:45:02 -05001452 public void resetNotificationPeekFadeTimer() {
1453 if (DEBUG) {
1454 Slog.d(TAG, "setting peek fade timer for " + NOTIFICATION_PEEK_FADE_DELAY
1455 + "ms from now");
1456 }
1457 mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PEEK);
1458 mHandler.sendEmptyMessageDelayed(MSG_CLOSE_NOTIFICATION_PEEK,
1459 NOTIFICATION_PEEK_FADE_DELAY);
1460 }
1461
1462 private class NotificationIconTouchListener implements View.OnTouchListener {
Daniel Sandler56a6d882011-02-23 16:40:33 -05001463 VelocityTracker mVT;
1464 int mPeekIndex;
1465 float mInitialTouchX, mInitialTouchY;
1466 int mTouchSlop;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001467
1468 public NotificationIconTouchListener() {
Daniel Sandler56a6d882011-02-23 16:40:33 -05001469 mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001470 }
1471
1472 public boolean onTouch(View v, MotionEvent event) {
1473 boolean peeking = mNotificationPeekWindow.getVisibility() != View.GONE;
Joe Onorato7c270fa2010-12-08 17:31:42 -08001474 boolean panelShowing = mNotificationPanel.isShowing();
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001475 if (panelShowing) return false;
1476
Daniel Sandler56a6d882011-02-23 16:40:33 -05001477 int numIcons = mIconLayout.getChildCount();
1478 int newPeekIndex = (int)(event.getX() * numIcons / mIconLayout.getWidth());
1479 if (newPeekIndex > numIcons - 1) newPeekIndex = numIcons - 1;
1480 else if (newPeekIndex < 0) newPeekIndex = 0;
1481
1482 final int action = event.getAction();
1483 switch (action) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001484 case MotionEvent.ACTION_DOWN:
1485 mVT = VelocityTracker.obtain();
Daniel Sandler56a6d882011-02-23 16:40:33 -05001486 mInitialTouchX = event.getX();
1487 mInitialTouchY = event.getY();
1488 mPeekIndex = -1;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001489
1490 // fall through
1491 case MotionEvent.ACTION_OUTSIDE:
1492 case MotionEvent.ACTION_MOVE:
1493 // peek and switch icons if necessary
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001494
Daniel Sandler56a6d882011-02-23 16:40:33 -05001495 if (newPeekIndex != mPeekIndex) {
1496 mPeekIndex = newPeekIndex;
1497
1498 if (DEBUG) Slog.d(TAG, "will peek at notification #" + mPeekIndex);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001499 Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
Daniel Sandler56a6d882011-02-23 16:40:33 -05001500 peekMsg.arg1 = mPeekIndex;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001501
1502 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
1503
Daniel Sandler56a6d882011-02-23 16:40:33 -05001504 if (peeking) {
1505 // no delay if we're scrubbing left-right
1506 mHandler.sendMessage(peekMsg);
1507 } else {
1508 // wait for fling
1509 mHandler.sendMessageDelayed(peekMsg, NOTIFICATION_PEEK_HOLD_THRESH);
1510 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001511 }
1512
1513 // check for fling
1514 if (mVT != null) {
1515 mVT.addMovement(event);
Daniel Sandler56a6d882011-02-23 16:40:33 -05001516 mVT.computeCurrentVelocity(1000); // pixels per second
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001517 // require a little more oomph once we're already in peekaboo mode
1518 if (!panelShowing && (
1519 (peeking && mVT.getYVelocity() < -mNotificationFlingVelocity*3)
1520 || (mVT.getYVelocity() < -mNotificationFlingVelocity))) {
1521 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
1522 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
1523 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
1524 mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
1525 }
1526 }
1527 return true;
1528 case MotionEvent.ACTION_UP:
1529 case MotionEvent.ACTION_CANCEL:
1530 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
Daniel Sandleraa051d62011-03-01 16:23:57 -05001531 if (!peeking) {
1532 if (action == MotionEvent.ACTION_UP
1533 // was this a sloppy tap?
Jim Miller9f0f0e02011-05-17 20:06:29 -07001534 && Math.abs(event.getX() - mInitialTouchX) < mTouchSlop
Daniel Sandleraa051d62011-03-01 16:23:57 -05001535 && Math.abs(event.getY() - mInitialTouchY) < (mTouchSlop / 3)
1536 // dragging off the bottom doesn't count
1537 && (int)event.getY() < v.getBottom()) {
1538 Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
1539 peekMsg.arg1 = mPeekIndex;
1540 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
1541 mHandler.sendMessage(peekMsg);
1542
1543 v.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
1544 v.playSoundEffect(SoundEffectConstants.CLICK);
1545
1546 peeking = true; // not technically true yet, but the next line will run
1547 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001548 }
Daniel Sandler56a6d882011-02-23 16:40:33 -05001549
1550 if (peeking) {
Daniel Sandler663f0f22011-03-04 16:45:02 -05001551 resetNotificationPeekFadeTimer();
Daniel Sandler56a6d882011-02-23 16:40:33 -05001552 }
1553
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001554 mVT.recycle();
1555 mVT = null;
1556 return true;
1557 }
1558 return false;
1559 }
1560 }
1561
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001562 StatusBarIconView addNotificationViews(IBinder key, StatusBarNotification notification) {
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001563 if (DEBUG) {
1564 Slog.d(TAG, "addNotificationViews(key=" + key + ", notification=" + notification);
1565 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001566 // Construct the icon.
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001567 final StatusBarIconView iconView = new StatusBarIconView(mContext,
Svetoslav Ganov6179ea32011-06-28 01:12:41 -07001568 notification.pkg + "/0x" + Integer.toHexString(notification.id),
1569 notification.notification);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001570 iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
1571
1572 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
1573 notification.notification.icon,
1574 notification.notification.iconLevel,
Svetoslav Ganov6179ea32011-06-28 01:12:41 -07001575 notification.notification.number,
1576 notification.notification.tickerText);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001577 if (!iconView.set(ic)) {
1578 handleNotificationError(key, notification, "Couldn't attach StatusBarIcon: " + ic);
1579 return null;
1580 }
1581 // Construct the expanded view.
1582 NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001583 if (!inflateViews(entry, mPile)) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001584 handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
1585 + notification);
1586 return null;
1587 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001588
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001589 // Add the icon.
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001590 int pos = mNotificationData.add(entry);
Daniel Sandlera31e4192011-02-02 22:00:28 -05001591 if (DEBUG) {
1592 Slog.d(TAG, "addNotificationViews: added at " + pos);
1593 }
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001594 updateNotificationIcons();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001595
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001596 return iconView;
1597 }
1598
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001599 private void reloadAllNotificationIcons() {
1600 if (mIconLayout == null) return;
1601 mIconLayout.removeAllViews();
1602 updateNotificationIcons();
1603 }
1604
1605 private void updateNotificationIcons() {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001606 // XXX: need to implement a new limited linear layout class
1607 // to avoid removing & readding everything
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001608
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001609 if (mIconLayout == null) return;
1610
Daniel Sandler282ff9a2011-02-23 10:36:49 -05001611 // first, populate the main notification panel
1612 loadNotificationPanel();
1613
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001614 final LinearLayout.LayoutParams params
Joe Onoratodc100302011-01-11 17:07:41 -08001615 = new LinearLayout.LayoutParams(mIconSize + 2*mIconHPadding, mNaturalBarHeight);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001616
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001617 // alternate behavior in DND mode
Daniel Sandler282ff9a2011-02-23 10:36:49 -05001618 if (mNotificationDNDMode) {
1619 if (mIconLayout.getChildCount() == 0) {
Daniel Sandler282ff9a2011-02-23 10:36:49 -05001620 final Notification dndNotification = new Notification.Builder(mContext)
1621 .setContentTitle(mContext.getText(R.string.notifications_off_title))
1622 .setContentText(mContext.getText(R.string.notifications_off_text))
1623 .setSmallIcon(R.drawable.ic_notification_dnd)
1624 .setOngoing(true)
1625 .getNotification();
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001626
Svetoslav Ganov6179ea32011-06-28 01:12:41 -07001627 final StatusBarIconView iconView = new StatusBarIconView(mContext, "_dnd",
1628 dndNotification);
1629 iconView.setImageResource(R.drawable.ic_notification_dnd);
1630 iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
1631 iconView.setPadding(mIconHPadding, 0, mIconHPadding, 0);
1632
Daniel Sandler282ff9a2011-02-23 10:36:49 -05001633 mNotificationDNDDummyEntry = new NotificationData.Entry(
1634 null,
1635 new StatusBarNotification("", 0, "", 0, 0, dndNotification),
1636 iconView);
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001637
Daniel Sandler282ff9a2011-02-23 10:36:49 -05001638 mIconLayout.addView(iconView, params);
1639 }
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001640
1641 return;
Daniel Sandler8e41f312011-08-03 14:05:07 -04001642 } else if (0 != (mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) {
1643 // if icons are disabled but we're not in DND mode, this is probably Setup and we should
1644 // just leave the area totally empty
1645 return;
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001646 }
1647
1648 int N = mNotificationData.size();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001649
1650 if (DEBUG) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001651 Slog.d(TAG, "refreshing icons: " + N + " notifications, mIconLayout=" + mIconLayout);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001652 }
1653
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001654 ArrayList<View> toShow = new ArrayList<View>();
1655
Daniel Sandler3b0543a2011-06-14 11:30:28 -04001656 // Extra Special Icons
1657 // The IME switcher and compatibility mode icons take the place of notifications. You didn't
1658 // need to see all those new emails, did you?
1659 int maxNotificationIconsCount = mMaxNotificationIcons;
1660 if (mInputMethodSwitchButton.getVisibility() != View.GONE) maxNotificationIconsCount --;
1661 if (mCompatModeButton.getVisibility() != View.GONE) maxNotificationIconsCount --;
1662
satok82beadf2010-12-27 19:03:06 +09001663 for (int i=0; i< maxNotificationIconsCount; i++) {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001664 if (i>=N) break;
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001665 toShow.add(mNotificationData.get(N-i-1).icon);
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001666 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001667
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001668 ArrayList<View> toRemove = new ArrayList<View>();
1669 for (int i=0; i<mIconLayout.getChildCount(); i++) {
1670 View child = mIconLayout.getChildAt(i);
1671 if (!toShow.contains(child)) {
1672 toRemove.add(child);
1673 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001674 }
Daniel Sandler271ea122010-10-22 14:06:10 -04001675
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001676 for (View remove : toRemove) {
1677 mIconLayout.removeView(remove);
1678 }
1679
1680 for (int i=0; i<toShow.size(); i++) {
1681 View v = toShow.get(i);
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001682 v.setPadding(mIconHPadding, 0, mIconHPadding, 0);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001683 if (v.getParent() == null) {
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001684 mIconLayout.addView(v, i, params);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001685 }
1686 }
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001687 }
1688
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001689 private void loadNotificationPanel() {
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001690 int N = mNotificationData.size();
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001691
1692 ArrayList<View> toShow = new ArrayList<View>();
1693
1694 for (int i=0; i<N; i++) {
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001695 View row = mNotificationData.get(N-i-1).row;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001696 toShow.add(row);
1697 }
1698
1699 ArrayList<View> toRemove = new ArrayList<View>();
1700 for (int i=0; i<mPile.getChildCount(); i++) {
1701 View child = mPile.getChildAt(i);
1702 if (!toShow.contains(child)) {
1703 toRemove.add(child);
1704 }
1705 }
1706
1707 for (View remove : toRemove) {
1708 mPile.removeView(remove);
1709 }
1710
1711 for (int i=0; i<toShow.size(); i++) {
1712 View v = toShow.get(i);
1713 if (v.getParent() == null) {
Daniel Sandlera31e4192011-02-02 22:00:28 -05001714 mPile.addView(v, N-1-i); // the notification panel has newest at the bottom
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001715 }
1716 }
Daniel Sandler40c15452011-01-22 01:26:22 -05001717
1718 mNotificationPanel.setNotificationCount(N);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001719 }
1720
Joe Onorato4daaeaf2010-11-17 20:43:12 -08001721 void workAroundBadLayerDrawableOpacity(View v) {
1722 LayerDrawable d = (LayerDrawable)v.getBackground();
Daniel Sandlerf844dc42011-01-24 23:44:47 -05001723 if (d == null) return;
Joe Onorato4daaeaf2010-11-17 20:43:12 -08001724 v.setBackgroundDrawable(null);
1725 d.setOpacity(PixelFormat.TRANSLUCENT);
1726 v.setBackgroundDrawable(d);
1727 }
1728
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001729 private boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) {
1730 StatusBarNotification sbn = entry.notification;
1731 RemoteViews remoteViews = sbn.notification.contentView;
1732 if (remoteViews == null) {
1733 return false;
1734 }
1735
1736 // create the row view
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001737 LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(
1738 Context.LAYOUT_INFLATER_SERVICE);
Joe Onorato755cc742010-11-27 15:45:35 -08001739 View row = inflater.inflate(R.layout.status_bar_notification_row, parent, false);
Joe Onorato4daaeaf2010-11-17 20:43:12 -08001740 workAroundBadLayerDrawableOpacity(row);
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001741 View vetoButton = row.findViewById(R.id.veto);
Joe Onoratoa4a65032010-09-27 15:53:44 -07001742 if (entry.notification.isClearable()) {
1743 final String _pkg = sbn.pkg;
1744 final String _tag = sbn.tag;
1745 final int _id = sbn.id;
Jim Miller44c66fe2010-10-20 18:32:52 -07001746 vetoButton.setOnClickListener(new View.OnClickListener() {
Joe Onoratoa4a65032010-09-27 15:53:44 -07001747 public void onClick(View v) {
1748 try {
1749 mBarService.onNotificationClear(_pkg, _tag, _id);
1750 } catch (RemoteException ex) {
1751 // system process is dead if we're here.
1752 }
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001753 }
Joe Onoratoa4a65032010-09-27 15:53:44 -07001754 });
1755 } else {
Joe Onorato100748e2011-01-07 11:03:54 -08001756 if ((sbn.notification.flags & Notification.FLAG_ONGOING_EVENT) == 0) {
1757 vetoButton.setVisibility(View.INVISIBLE);
Svetoslav Ganov6179ea32011-06-28 01:12:41 -07001758 vetoButton.setContentDescription("VETO");
Joe Onorato100748e2011-01-07 11:03:54 -08001759 } else {
1760 vetoButton.setVisibility(View.GONE);
1761 }
Joe Onoratoa4a65032010-09-27 15:53:44 -07001762 }
Svetoslav Ganov6179ea32011-06-28 01:12:41 -07001763 vetoButton.setContentDescription(mContext.getString(
1764 R.string.accessibility_remove_notification));
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001765
Joe Onorato561d3852010-11-20 18:09:34 -08001766 // the large icon
1767 ImageView largeIcon = (ImageView)row.findViewById(R.id.large_icon);
1768 if (sbn.notification.largeIcon != null) {
1769 largeIcon.setImageBitmap(sbn.notification.largeIcon);
Svetoslav Ganov6179ea32011-06-28 01:12:41 -07001770 largeIcon.setContentDescription(sbn.notification.tickerText);
Joe Onorato561d3852010-11-20 18:09:34 -08001771 } else {
1772 largeIcon.getLayoutParams().width = 0;
1773 largeIcon.setVisibility(View.INVISIBLE);
1774 }
Svetoslav Ganov6179ea32011-06-28 01:12:41 -07001775 largeIcon.setContentDescription(sbn.notification.tickerText);
Joe Onorato561d3852010-11-20 18:09:34 -08001776
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001777 // bind the click event to the content area
1778 ViewGroup content = (ViewGroup)row.findViewById(R.id.content);
1779 // XXX: update to allow controls within notification views
1780 content.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
1781// content.setOnFocusChangeListener(mFocusChangeListener);
1782 PendingIntent contentIntent = sbn.notification.contentIntent;
1783 if (contentIntent != null) {
Jeff Sharkey847fd752011-09-02 17:48:55 -07001784 final View.OnClickListener listener = new NotificationClicker(
1785 contentIntent, sbn.pkg, sbn.tag, sbn.id);
1786 largeIcon.setOnClickListener(listener);
1787 content.setOnClickListener(listener);
Joe Onorato184498c2010-10-08 17:57:18 -04001788 } else {
Jeff Sharkey847fd752011-09-02 17:48:55 -07001789 largeIcon.setOnClickListener(null);
Joe Onorato184498c2010-10-08 17:57:18 -04001790 content.setOnClickListener(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001791 }
1792
1793 View expanded = null;
1794 Exception exception = null;
1795 try {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001796 expanded = remoteViews.apply(mContext, content);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001797 }
1798 catch (RuntimeException e) {
1799 exception = e;
1800 }
1801 if (expanded == null) {
Joe Onorato46439ce2010-11-19 13:56:21 -08001802 final String ident = sbn.pkg + "/0x" + Integer.toHexString(sbn.id);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001803 Slog.e(TAG, "couldn't inflate view for notification " + ident, exception);
1804 return false;
1805 } else {
1806 content.addView(expanded);
1807 row.setDrawingCacheEnabled(true);
1808 }
1809
1810 entry.row = row;
1811 entry.content = content;
1812 entry.expanded = expanded;
Joe Onorato80a44402011-01-15 16:22:24 -08001813 entry.largeIcon = largeIcon;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001814
1815 return true;
1816 }
Daniel Sandlerce70d912010-09-02 11:59:41 -04001817
Daniel Sandler06a0d4b2011-08-05 00:19:21 -04001818 public void clearAll() {
1819 try {
1820 mBarService.onClearAllNotifications();
1821 } catch (RemoteException ex) {
1822 // system process is dead if we're here.
1823 }
1824 animateCollapse();
Mike Lockwood066c8912011-08-24 10:17:18 -04001825 visibilityChanged(false);
Daniel Sandler06a0d4b2011-08-05 00:19:21 -04001826 }
1827
Daniel Sandler1d4d30a2011-04-28 12:35:29 -04001828 public void userActivity() {
1829 }
1830
Michael Jurka3b1fc472011-06-13 10:54:40 -07001831 public void toggleRecentApps() {
1832 int msg = (mRecentsPanel.getVisibility() == View.GONE)
1833 ? MSG_OPEN_RECENTS_PANEL : MSG_CLOSE_RECENTS_PANEL;
1834 mHandler.removeMessages(msg);
1835 mHandler.sendEmptyMessage(msg);
1836 }
1837
Joe Onoratob62ac122010-09-20 16:16:32 -04001838 public class TouchOutsideListener implements View.OnTouchListener {
1839 private int mMsg;
Joe Onoratoddf680b2010-09-26 13:59:40 -07001840 private StatusBarPanel mPanel;
Joe Onoratob62ac122010-09-20 16:16:32 -04001841
Joe Onoratoddf680b2010-09-26 13:59:40 -07001842 public TouchOutsideListener(int msg, StatusBarPanel panel) {
Joe Onoratob62ac122010-09-20 16:16:32 -04001843 mMsg = msg;
Joe Onoratoddf680b2010-09-26 13:59:40 -07001844 mPanel = panel;
Joe Onoratob62ac122010-09-20 16:16:32 -04001845 }
1846
1847 public boolean onTouch(View v, MotionEvent ev) {
Joe Onoratoddf680b2010-09-26 13:59:40 -07001848 final int action = ev.getAction();
1849 if (action == MotionEvent.ACTION_OUTSIDE
1850 || (action == MotionEvent.ACTION_DOWN
1851 && !mPanel.isInContentArea((int)ev.getX(), (int)ev.getY()))) {
Joe Onoratob62ac122010-09-20 16:16:32 -04001852 mHandler.removeMessages(mMsg);
1853 mHandler.sendEmptyMessage(mMsg);
1854 return true;
1855 }
1856 return false;
1857 }
1858 }
Joe Onorato091e1b82010-09-26 18:04:44 -07001859
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001860 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1861 pw.print("mDisabled=0x");
1862 pw.println(Integer.toHexString(mDisabled));
Joe Onorato933464d2011-01-05 15:53:36 -08001863 pw.println("mNetworkController:");
1864 mNetworkController.dump(fd, pw, args);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001865 }
Joe Onorato808182d2010-07-09 18:52:06 -04001866}
Daniel Sandlerd39e3882010-08-31 14:16:13 -04001867
1868