blob: 09e38ff31434f870d02db2669f13c448549f3027 [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 Sandler92d33182011-09-11 16:29:05 -040026import android.app.KeyguardManager;
Joe Onoratoef1e7762010-09-17 18:38:38 -040027import android.app.Notification;
Michael Jurkab7f43272011-10-27 15:06:38 -070028import android.app.PendingIntent;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040029import android.app.StatusBarManager;
Michael Jurkab7f43272011-10-27 15:06:38 -070030import android.content.BroadcastReceiver;
Joe Onorato808182d2010-07-09 18:52:06 -040031import android.content.Context;
32import android.content.Intent;
Michael Jurkab7f43272011-10-27 15:06:38 -070033import android.content.IntentFilter;
Daniel Sandlerce6ff642011-02-18 12:51:08 -050034import android.content.SharedPreferences;
Adam Powell29ea5252011-11-15 18:59:36 -080035import android.content.pm.ApplicationInfo;
36import android.content.pm.PackageManager.NameNotFoundException;
Daniel Sandler0ad460b2010-12-14 12:14:53 -050037import android.content.res.Configuration;
Joe Onorato808182d2010-07-09 18:52:06 -040038import android.content.res.Resources;
Joe Onorato857fd9b2011-01-27 15:08:35 -080039import android.inputmethodservice.InputMethodService;
Daniel Sandler9120d552010-07-23 09:11:14 -040040import android.graphics.PixelFormat;
Jeff Brownbc68a592011-07-25 12:58:12 -070041import android.graphics.Point;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040042import android.graphics.Rect;
Adam Powell29ea5252011-11-15 18:59:36 -080043import android.graphics.drawable.Drawable;
Joe Onorato4daaeaf2010-11-17 20:43:12 -080044import android.graphics.drawable.LayerDrawable;
Adam Powell29ea5252011-11-15 18:59:36 -080045import android.os.Build;
Daniel Sandler9120d552010-07-23 09:11:14 -040046import android.os.Handler;
Joe Onorato808182d2010-07-09 18:52:06 -040047import android.os.IBinder;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040048import android.os.Message;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040049import android.os.RemoteException;
Daniel Sandler10163c62010-12-08 11:51:05 -050050import android.os.ServiceManager;
Joe Onoratoef1e7762010-09-17 18:38:38 -040051import android.text.TextUtils;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040052import android.util.Slog;
Daniel Sandleraa051d62011-03-01 16:23:57 -050053import android.view.accessibility.AccessibilityEvent;
Joe Onorato07949e92011-05-25 17:35:35 -070054import android.view.Display;
Joe Onorato808182d2010-07-09 18:52:06 -040055import android.view.Gravity;
Daniel Sandler10163c62010-12-08 11:51:05 -050056import android.view.IWindowManager;
57import android.view.KeyEvent;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040058import android.view.LayoutInflater;
Joe Onoratob62ac122010-09-20 16:16:32 -040059import android.view.MotionEvent;
Daniel Sandleraa051d62011-03-01 16:23:57 -050060import android.view.SoundEffectConstants;
Daniel Sandler8304da42010-10-25 15:53:25 -040061import android.view.VelocityTracker;
Joe Onorato808182d2010-07-09 18:52:06 -040062import android.view.View;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -040063import android.view.ViewConfiguration;
Daniel Sandler9120d552010-07-23 09:11:14 -040064import android.view.ViewGroup;
65import android.view.WindowManager;
66import android.view.WindowManagerImpl;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040067import android.widget.ImageView;
Joe Onorato808182d2010-07-09 18:52:06 -040068import android.widget.LinearLayout;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040069import android.widget.RemoteViews;
70import android.widget.ScrollView;
Daniel Sandler9120d552010-07-23 09:11:14 -040071import android.widget.TextView;
Joe Onorato808182d2010-07-09 18:52:06 -040072
73import com.android.internal.statusbar.StatusBarIcon;
Joe Onorato808182d2010-07-09 18:52:06 -040074import com.android.internal.statusbar.StatusBarNotification;
Joe Onorato808182d2010-07-09 18:52:06 -040075import com.android.systemui.R;
Michael Jurkab7f43272011-10-27 15:06:38 -070076import com.android.systemui.recent.RecentTasksLoader;
77import com.android.systemui.recent.RecentsPanelView;
78import com.android.systemui.statusbar.NotificationData;
79import com.android.systemui.statusbar.SignalClusterView;
80import com.android.systemui.statusbar.StatusBar;
81import com.android.systemui.statusbar.StatusBarIconView;
Joe Onoratofd52b182010-11-10 18:00:52 -080082import com.android.systemui.statusbar.policy.BatteryController;
Joe Onoratofce2bf32011-02-01 17:00:29 -080083import com.android.systemui.statusbar.policy.BluetoothController;
Daniel Sandler45c04012011-06-07 15:29:07 -040084import com.android.systemui.statusbar.policy.CompatModeButton;
Daniel Sandlere40451a2011-02-03 14:51:35 -050085import com.android.systemui.statusbar.policy.LocationController;
Joe Onoratofd52b182010-11-10 18:00:52 -080086import com.android.systemui.statusbar.policy.NetworkController;
Daniel Sandlerce6ff642011-02-18 12:51:08 -050087import com.android.systemui.statusbar.policy.Prefs;
Joe Onorato808182d2010-07-09 18:52:06 -040088
Joe Onoratodc100302011-01-11 17:07:41 -080089public class TabletStatusBar extends StatusBar implements
Jeff Brown2992ea72011-01-28 22:04:14 -080090 HeightReceiver.OnBarHeightChangedListener,
Daniel Sandlerea193ce2011-09-23 15:56:52 -040091 InputMethodsPanel.OnHardKeyboardEnabledChangeListener,
92 RecentsPanelView.OnRecentsPanelVisibilityChangedListener {
Daniel Sandlerfb970e92010-08-20 10:57:17 -040093 public static final boolean DEBUG = false;
Daniel Sandlere25f8332011-06-15 15:00:10 -040094 public static final boolean DEBUG_COMPAT_HELP = false;
Joe Onoratofd52b182010-11-10 18:00:52 -080095 public static final String TAG = "TabletStatusBar";
Joe Onorato808182d2010-07-09 18:52:06 -040096
Daniel Sandler0ad460b2010-12-14 12:14:53 -050097
Joe Onoratob62ac122010-09-20 16:16:32 -040098 public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
99 public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400100 public static final int MSG_OPEN_NOTIFICATION_PEEK = 1002;
101 public static final int MSG_CLOSE_NOTIFICATION_PEEK = 1003;
Jim Miller44c66fe2010-10-20 18:32:52 -0700102 public static final int MSG_OPEN_RECENTS_PANEL = 1020;
103 public static final int MSG_CLOSE_RECENTS_PANEL = 1021;
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500104 public static final int MSG_SHOW_CHROME = 1030;
105 public static final int MSG_HIDE_CHROME = 1031;
satok82beadf2010-12-27 19:03:06 +0900106 public static final int MSG_OPEN_INPUT_METHODS_PANEL = 1040;
107 public static final int MSG_CLOSE_INPUT_METHODS_PANEL = 1041;
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400108 public static final int MSG_OPEN_COMPAT_MODE_PANEL = 1050;
109 public static final int MSG_CLOSE_COMPAT_MODE_PANEL = 1051;
Daniel Sandler2ed08d22011-01-30 16:07:28 -0500110 public static final int MSG_STOP_TICKER = 2000;
Jim Miller44c66fe2010-10-20 18:32:52 -0700111
Daniel Sandler3a2fded2011-02-23 11:19:59 -0500112 // Fitts' Law assistance for LatinIME; see policy.EventHole
Daniel Sandler10163c62010-12-08 11:51:05 -0500113 private static final boolean FAKE_SPACE_BAR = true;
114
Daniel Sandler298a2a82011-08-11 16:13:22 -0400115 // Notification "peeking" (flyover preview of individual notifications)
116 final static boolean NOTIFICATION_PEEK_ENABLED = false;
117 final static int NOTIFICATION_PEEK_HOLD_THRESH = 200; // ms
118 final static int NOTIFICATION_PEEK_FADE_DELAY = 3000; // ms
119
Joe Onoratodc100302011-01-11 17:07:41 -0800120 // The height of the bar, as definied by the build. It may be taller if we're plugged
121 // into hdmi.
122 int mNaturalBarHeight = -1;
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500123 int mIconSize = -1;
124 int mIconHPadding = -1;
Andrew Flynn1d9af302012-03-07 15:48:51 -0800125 int mNavIconWidth = -1;
126 int mMenuNavIconWidth = -1;
satok5485ff62011-05-27 19:15:01 +0900127 private int mMaxNotificationIcons = 5;
Daniel Sandler9120d552010-07-23 09:11:14 -0400128
129 H mHandler = new H();
130
Daniel Sandler10163c62010-12-08 11:51:05 -0500131 IWindowManager mWindowManager;
132
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400133 // tracking all current notifications
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500134 private NotificationData mNotificationData = new NotificationData();
Jim Miller44c66fe2010-10-20 18:32:52 -0700135
Joe Onoratob62ac122010-09-20 16:16:32 -0400136 TabletStatusBarView mStatusBarView;
Joe Onoratofd52b182010-11-10 18:00:52 -0800137 View mNotificationArea;
138 View mNotificationTrigger;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400139 NotificationIconArea mNotificationIconArea;
Daniel Sandler21eb86a2011-03-02 11:52:58 -0500140 ViewGroup mNavigationArea;
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500141
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500142 boolean mNotificationDNDMode;
143 NotificationData.Entry mNotificationDNDDummyEntry;
144
Joe Onorato536c58f2010-11-28 17:52:28 -0800145 ImageView mBackButton;
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500146 View mHomeButton;
Daniel Sandlere02d8082010-10-08 15:13:22 -0400147 View mMenuButton;
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400148 View mRecentButton;
Daniel Sandlerea193ce2011-09-23 15:56:52 -0400149 private boolean mAltBackButtonEnabledForIme;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400150
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400151 ViewGroup mFeedbackIconArea; // notification icons, IME icon, compat icon
satokcd7cd292010-11-20 15:46:23 +0900152 InputMethodButton mInputMethodSwitchButton;
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400153 CompatModeButton mCompatModeButton;
satok06487a52010-10-29 11:37:18 +0900154
Joe Onoratoddf680b2010-09-26 13:59:40 -0700155 NotificationPanel mNotificationPanel;
Joe Onorato07949e92011-05-25 17:35:35 -0700156 WindowManager.LayoutParams mNotificationPanelParams;
Joe Onorato8a576712010-11-15 16:50:34 -0800157 NotificationPeekPanel mNotificationPeekWindow;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400158 ViewGroup mNotificationPeekRow;
159 int mNotificationPeekIndex;
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500160 IBinder mNotificationPeekKey;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400161 LayoutTransition mNotificationPeekScrubLeft, mNotificationPeekScrubRight;
162
163 int mNotificationPeekTapDuration;
164 int mNotificationFlingVelocity;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400165
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400166 ViewGroup mPile;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400167
Joe Onoratodc100302011-01-11 17:07:41 -0800168 HeightReceiver mHeightReceiver;
Joe Onoratofd52b182010-11-10 18:00:52 -0800169 BatteryController mBatteryController;
Joe Onoratofce2bf32011-02-01 17:00:29 -0800170 BluetoothController mBluetoothController;
Daniel Sandlere40451a2011-02-03 14:51:35 -0500171 LocationController mLocationController;
Joe Onoratofd52b182010-11-10 18:00:52 -0800172 NetworkController mNetworkController;
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400173
Daniel Sandler21eb86a2011-03-02 11:52:58 -0500174 ViewGroup mBarContents;
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500175
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500176 // hide system chrome ("lights out") support
177 View mShadow;
Daniel Sandlerce70d912010-09-02 11:59:41 -0400178
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400179 NotificationIconArea.IconLayout mIconLayout;
180
Joe Onoratoef1e7762010-09-17 18:38:38 -0400181 TabletTicker mTicker;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400182
Daniel Sandler10163c62010-12-08 11:51:05 -0500183 View mFakeSpaceBar;
184 KeyEvent mSpaceBarKeyEvent = null;
185
Dianne Hackborned31bbf2011-06-15 11:16:06 -0700186 View mCompatibilityHelpDialog = null;
187
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400188 // for disabling the status bar
189 int mDisabled = 0;
190
Jim Miller9f0f0e02011-05-17 20:06:29 -0700191 private RecentsPanelView mRecentsPanel;
Michael Jurkaab48b682011-09-12 15:39:45 -0700192 private RecentTasksLoader mRecentTasksLoader;
satok82beadf2010-12-27 19:03:06 +0900193 private InputMethodsPanel mInputMethodsPanel;
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400194 private CompatModePanel mCompatModePanel;
Joe Onorato55d2d762010-09-26 13:02:01 -0700195
Mike Lockwood066c8912011-08-24 10:17:18 -0400196 private int mSystemUiVisibility = 0;
197 // used to notify status bar for suppressing notification LED
198 private boolean mPanelSlightlyVisible;
Daniel Sandler60ee2562011-07-22 12:34:33 -0400199
Daniel Sandlerea193ce2011-09-23 15:56:52 -0400200 private int mNavigationIconHints = 0;
201
Daniel Sandlerc51451a2010-12-16 19:06:46 -0500202 public Context getContext() { return mContext; }
203
Daniel Sandler9120d552010-07-23 09:11:14 -0400204 protected void addPanelWindows() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400205 final Context context = mContext;
Joe Onorato07949e92011-05-25 17:35:35 -0700206 final Resources res = mContext.getResources();
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400207
Jim Miller44c66fe2010-10-20 18:32:52 -0700208 // Notification Panel
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400209 mNotificationPanel = (NotificationPanel)View.inflate(context,
Joe Onorato755cc742010-11-27 15:45:35 -0800210 R.layout.status_bar_notification_panel, null);
Daniel Sandler1347c302011-08-01 16:47:53 -0400211 mNotificationPanel.setBar(this);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800212 mNotificationPanel.show(false, false);
Joe Onoratob62ac122010-09-20 16:16:32 -0400213 mNotificationPanel.setOnTouchListener(
Joe Onoratoddf680b2010-09-26 13:59:40 -0700214 new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PANEL, mNotificationPanel));
Joe Onoratob62ac122010-09-20 16:16:32 -0400215
Daniel Sandler2b697352011-07-22 16:23:09 -0400216 // the battery icon
Joe Onoratofd52b182010-11-10 18:00:52 -0800217 mBatteryController.addIconView((ImageView)mNotificationPanel.findViewById(R.id.battery));
218 mBatteryController.addLabelView(
219 (TextView)mNotificationPanel.findViewById(R.id.battery_text));
Daniel Sandler2b697352011-07-22 16:23:09 -0400220
221 // Bt
Joe Onoratofce2bf32011-02-01 17:00:29 -0800222 mBluetoothController.addIconView(
223 (ImageView)mNotificationPanel.findViewById(R.id.bluetooth));
Daniel Sandler2b697352011-07-22 16:23:09 -0400224
225 // network icons: either a combo icon that switches between mobile and data, or distinct
226 // mobile and data icons
Daniel Sandler2b697352011-07-22 16:23:09 -0400227 final ImageView mobileRSSI =
228 (ImageView)mNotificationPanel.findViewById(R.id.mobile_signal);
229 if (mobileRSSI != null) {
230 mNetworkController.addPhoneSignalIconView(mobileRSSI);
231 }
232 final ImageView wifiRSSI =
233 (ImageView)mNotificationPanel.findViewById(R.id.wifi_signal);
234 if (wifiRSSI != null) {
235 mNetworkController.addWifiIconView(wifiRSSI);
236 }
Daniel Sandler5962fd52012-01-11 14:57:04 -0500237 mNetworkController.addWifiLabelView(
238 (TextView)mNotificationPanel.findViewById(R.id.wifi_text));
Daniel Sandler2b697352011-07-22 16:23:09 -0400239
Joe Onorato42f8e132010-11-29 15:52:43 -0800240 mNetworkController.addDataTypeIconView(
Daniel Sandler5962fd52012-01-11 14:57:04 -0500241 (ImageView)mNotificationPanel.findViewById(R.id.mobile_type));
242 mNetworkController.addMobileLabelView(
243 (TextView)mNotificationPanel.findViewById(R.id.mobile_text));
244 mNetworkController.addCombinedLabelView(
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500245 (TextView)mBarContents.findViewById(R.id.network_text));
Joe Onoratofd52b182010-11-10 18:00:52 -0800246
Joe Onorato55d2d762010-09-26 13:02:01 -0700247 mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400248
Joe Onorato07949e92011-05-25 17:35:35 -0700249 WindowManager.LayoutParams lp = mNotificationPanelParams = new WindowManager.LayoutParams(
250 res.getDimensionPixelSize(R.dimen.notification_panel_width),
251 getNotificationPanelHeight(),
Daniel Sandler9120d552010-07-23 09:11:14 -0400252 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
253 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
Joe Onorato07949e92011-05-25 17:35:35 -0700254 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
Jeff Brown46e75292010-11-10 16:53:45 -0800255 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
Joe Onorato7c270fa2010-12-08 17:31:42 -0800256 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
257 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
Daniel Sandler9120d552010-07-23 09:11:14 -0400258 PixelFormat.TRANSLUCENT);
Joe Onoratoea70e632010-09-27 17:59:37 -0700259 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
Daniel Sandler9120d552010-07-23 09:11:14 -0400260 lp.setTitle("NotificationPanel");
Joe Onorato7c270fa2010-12-08 17:31:42 -0800261 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
262 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
263 lp.windowAnimations = com.android.internal.R.style.Animation; // == no animation
Daniel Sandler7d9ea8c2011-01-11 10:28:58 -0500264// lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
Daniel Sandler9120d552010-07-23 09:11:14 -0400265
266 WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
267
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400268 // Notification preview window
Daniel Sandler298a2a82011-08-11 16:13:22 -0400269 if (NOTIFICATION_PEEK_ENABLED) {
270 mNotificationPeekWindow = (NotificationPeekPanel) View.inflate(context,
271 R.layout.status_bar_notification_peek, null);
272 mNotificationPeekWindow.setBar(this);
Daniel Sandler663f0f22011-03-04 16:45:02 -0500273
Daniel Sandler298a2a82011-08-11 16:13:22 -0400274 mNotificationPeekRow = (ViewGroup) mNotificationPeekWindow.findViewById(R.id.content);
275 mNotificationPeekWindow.setVisibility(View.GONE);
276 mNotificationPeekWindow.setOnTouchListener(
277 new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PEEK, mNotificationPeekWindow));
278 mNotificationPeekScrubRight = new LayoutTransition();
279 mNotificationPeekScrubRight.setAnimator(LayoutTransition.APPEARING,
280 ObjectAnimator.ofInt(null, "left", -512, 0));
281 mNotificationPeekScrubRight.setAnimator(LayoutTransition.DISAPPEARING,
282 ObjectAnimator.ofInt(null, "left", -512, 0));
283 mNotificationPeekScrubRight.setDuration(500);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400284
Daniel Sandler298a2a82011-08-11 16:13:22 -0400285 mNotificationPeekScrubLeft = new LayoutTransition();
286 mNotificationPeekScrubLeft.setAnimator(LayoutTransition.APPEARING,
287 ObjectAnimator.ofInt(null, "left", 512, 0));
288 mNotificationPeekScrubLeft.setAnimator(LayoutTransition.DISAPPEARING,
289 ObjectAnimator.ofInt(null, "left", 512, 0));
290 mNotificationPeekScrubLeft.setDuration(500);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400291
Daniel Sandler298a2a82011-08-11 16:13:22 -0400292 // XXX: setIgnoreChildren?
293 lp = new WindowManager.LayoutParams(
294 512, // ViewGroup.LayoutParams.WRAP_CONTENT,
295 ViewGroup.LayoutParams.WRAP_CONTENT,
296 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
297 WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
298 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
299 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
300 PixelFormat.TRANSLUCENT);
301 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
302 lp.y = res.getDimensionPixelOffset(R.dimen.peek_window_y_offset);
303 lp.setTitle("NotificationPeekWindow");
304 lp.windowAnimations = com.android.internal.R.style.Animation_Toast;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400305
Daniel Sandler298a2a82011-08-11 16:13:22 -0400306 WindowManagerImpl.getDefault().addView(mNotificationPeekWindow, lp);
307 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400308
Jim Miller44c66fe2010-10-20 18:32:52 -0700309 // Recents Panel
Michael Jurkaab48b682011-09-12 15:39:45 -0700310 mRecentTasksLoader = new RecentTasksLoader(context);
Jim Miller9f0f0e02011-05-17 20:06:29 -0700311 mRecentsPanel = (RecentsPanelView) View.inflate(context,
Jim Miller85babff2011-01-11 14:26:03 -0800312 R.layout.status_bar_recent_panel, null);
313 mRecentsPanel.setVisibility(View.GONE);
314 mRecentsPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL,
315 mRecentsPanel));
Daniel Sandlerea193ce2011-09-23 15:56:52 -0400316 mRecentsPanel.setOnVisibilityChangedListener(this);
Michael Jurkaab48b682011-09-12 15:39:45 -0700317 mRecentsPanel.setRecentTasksLoader(mRecentTasksLoader);
318 mRecentTasksLoader.setRecentsPanel(mRecentsPanel);
Jim Miller44c66fe2010-10-20 18:32:52 -0700319
Jim Miller85babff2011-01-11 14:26:03 -0800320 lp = new WindowManager.LayoutParams(
Peter Ng622a9762011-08-29 10:56:53 -0700321 (int) res.getDimension(R.dimen.status_bar_recents_width),
Chet Haase212f6252011-08-12 09:19:10 -0700322 ViewGroup.LayoutParams.MATCH_PARENT,
Jim Miller85babff2011-01-11 14:26:03 -0800323 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
324 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
325 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
326 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
327 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
328 PixelFormat.TRANSLUCENT);
329 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
330 lp.setTitle("RecentsPanel");
331 lp.windowAnimations = R.style.Animation_RecentPanel;
Jim Miller5fda69c2011-02-16 15:17:11 -0800332 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
333 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
Jim Miller44c66fe2010-10-20 18:32:52 -0700334
Jim Miller85babff2011-01-11 14:26:03 -0800335 WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
336 mRecentsPanel.setBar(this);
Daniel Sandlerea193ce2011-09-23 15:56:52 -0400337 mRecentsPanel.setStatusBarView(mStatusBarView);
satok82beadf2010-12-27 19:03:06 +0900338
339 // Input methods Panel
340 mInputMethodsPanel = (InputMethodsPanel) View.inflate(context,
341 R.layout.status_bar_input_methods_panel, null);
Jeff Brown2992ea72011-01-28 22:04:14 -0800342 mInputMethodsPanel.setHardKeyboardEnabledChangeListener(this);
satok82beadf2010-12-27 19:03:06 +0900343 mInputMethodsPanel.setOnTouchListener(new TouchOutsideListener(
344 MSG_CLOSE_INPUT_METHODS_PANEL, mInputMethodsPanel));
satok913f42d2011-01-17 16:58:10 +0900345 mInputMethodsPanel.setImeSwitchButton(mInputMethodSwitchButton);
Daniel Sandlerea193ce2011-09-23 15:56:52 -0400346 mStatusBarView.setIgnoreChildren(2, mInputMethodSwitchButton, mInputMethodsPanel);
satok82beadf2010-12-27 19:03:06 +0900347 lp = new WindowManager.LayoutParams(
348 ViewGroup.LayoutParams.WRAP_CONTENT,
349 ViewGroup.LayoutParams.WRAP_CONTENT,
350 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
351 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
352 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
353 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
354 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
355 PixelFormat.TRANSLUCENT);
356 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
357 lp.setTitle("InputMethodsPanel");
358 lp.windowAnimations = R.style.Animation_RecentPanel;
359
360 WindowManagerImpl.getDefault().addView(mInputMethodsPanel, lp);
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400361
362 // Compatibility mode selector panel
363 mCompatModePanel = (CompatModePanel) View.inflate(context,
364 R.layout.status_bar_compat_mode_panel, null);
365 mCompatModePanel.setOnTouchListener(new TouchOutsideListener(
366 MSG_CLOSE_COMPAT_MODE_PANEL, mCompatModePanel));
367 mCompatModePanel.setTrigger(mCompatModeButton);
368 mCompatModePanel.setVisibility(View.GONE);
Daniel Sandlerea193ce2011-09-23 15:56:52 -0400369 mStatusBarView.setIgnoreChildren(3, mCompatModeButton, mCompatModePanel);
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400370 lp = new WindowManager.LayoutParams(
371 250,
372 ViewGroup.LayoutParams.WRAP_CONTENT,
373 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
374 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
375 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
376 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
377 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
378 PixelFormat.TRANSLUCENT);
379 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
380 lp.setTitle("CompatModePanel");
381 lp.windowAnimations = android.R.style.Animation_Dialog;
382
383 WindowManagerImpl.getDefault().addView(mCompatModePanel, lp);
Daniel Sandler9120d552010-07-23 09:11:14 -0400384 }
Joe Onorato808182d2010-07-09 18:52:06 -0400385
Joe Onorato07949e92011-05-25 17:35:35 -0700386 private int getNotificationPanelHeight() {
387 final Resources res = mContext.getResources();
388 final Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
Jeff Brownbc68a592011-07-25 12:58:12 -0700389 final Point size = new Point();
390 d.getRealSize(size);
391 return Math.max(res.getDimensionPixelSize(R.dimen.notification_panel_min_height), size.y);
Joe Onorato07949e92011-05-25 17:35:35 -0700392 }
393
Joe Onorato808182d2010-07-09 18:52:06 -0400394 @Override
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400395 public void start() {
396 super.start(); // will add the main bar view
Joe Onorato808182d2010-07-09 18:52:06 -0400397 }
398
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500399 @Override
Joe Onoratodc100302011-01-11 17:07:41 -0800400 protected void onConfigurationChanged(Configuration newConfig) {
Jeff Brownbc68a592011-07-25 12:58:12 -0700401 mHeightReceiver.updateHeight(); // display size may have changed
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500402 loadDimens();
Joe Onorato07949e92011-05-25 17:35:35 -0700403 mNotificationPanelParams.height = getNotificationPanelHeight();
404 WindowManagerImpl.getDefault().updateViewLayout(mNotificationPanel,
405 mNotificationPanelParams);
Michael Jurkaab48b682011-09-12 15:39:45 -0700406 mRecentsPanel.updateValuesFromResources();
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500407 }
408
409 protected void loadDimens() {
410 final Resources res = mContext.getResources();
411
Joe Onoratodc100302011-01-11 17:07:41 -0800412 mNaturalBarHeight = res.getDimensionPixelSize(
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700413 com.android.internal.R.dimen.system_bar_height);
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500414
415 int newIconSize = res.getDimensionPixelSize(
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700416 com.android.internal.R.dimen.system_bar_icon_size);
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500417 int newIconHPadding = res.getDimensionPixelSize(
418 R.dimen.status_bar_icon_padding);
Andrew Flynn1d9af302012-03-07 15:48:51 -0800419 int newNavIconWidth = res.getDimensionPixelSize(R.dimen.navigation_key_width);
420 int newMenuNavIconWidth = res.getDimensionPixelSize(R.dimen.navigation_menu_key_width);
421
422 if (mNavigationArea != null && newNavIconWidth != mNavIconWidth) {
423 mNavIconWidth = newNavIconWidth;
424
425 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
426 mNavIconWidth, ViewGroup.LayoutParams.MATCH_PARENT);
427 mBackButton.setLayoutParams(lp);
428 mHomeButton.setLayoutParams(lp);
429 mRecentButton.setLayoutParams(lp);
430 }
431
432 if (mNavigationArea != null && newMenuNavIconWidth != mMenuNavIconWidth) {
433 mMenuNavIconWidth = newMenuNavIconWidth;
434
435 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
436 mMenuNavIconWidth, ViewGroup.LayoutParams.MATCH_PARENT);
437 mMenuButton.setLayoutParams(lp);
438 }
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500439
440 if (newIconHPadding != mIconHPadding || newIconSize != mIconSize) {
441// Slog.d(TAG, "size=" + newIconSize + " padding=" + newIconHPadding);
442 mIconHPadding = newIconHPadding;
443 mIconSize = newIconSize;
444 reloadAllNotificationIcons(); // reload the tray
445 }
satok5485ff62011-05-27 19:15:01 +0900446
447 final int numIcons = res.getInteger(R.integer.config_maxNotificationIcons);
448 if (numIcons != mMaxNotificationIcons) {
449 mMaxNotificationIcons = numIcons;
450 if (DEBUG) Slog.d(TAG, "max notification icons: " + mMaxNotificationIcons);
451 reloadAllNotificationIcons();
452 }
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500453 }
454
Daniel Sandlerea193ce2011-09-23 15:56:52 -0400455 public View getStatusBarView() {
456 return mStatusBarView;
457 }
458
Joe Onorato808182d2010-07-09 18:52:06 -0400459 protected View makeStatusBarView() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400460 final Context context = mContext;
Jim Miller85babff2011-01-11 14:26:03 -0800461
Daniel Sandler10163c62010-12-08 11:51:05 -0500462 mWindowManager = IWindowManager.Stub.asInterface(
463 ServiceManager.getService(Context.WINDOW_SERVICE));
Joe Onorato808182d2010-07-09 18:52:06 -0400464
Joe Onoratodc100302011-01-11 17:07:41 -0800465 // This guy will listen for HDMI plugged broadcasts so we can resize the
466 // status bar as appropriate.
467 mHeightReceiver = new HeightReceiver(mContext);
468 mHeightReceiver.registerReceiver();
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500469 loadDimens();
Joe Onorato808182d2010-07-09 18:52:06 -0400470
Joe Onoratob62ac122010-09-20 16:16:32 -0400471 final TabletStatusBarView sb = (TabletStatusBarView)View.inflate(
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400472 context, R.layout.status_bar, null);
Joe Onorato808182d2010-07-09 18:52:06 -0400473 mStatusBarView = sb;
474
Joe Onoratob62ac122010-09-20 16:16:32 -0400475 sb.setHandler(mHandler);
476
Daniel Sandler0c4ccff2011-10-19 16:39:14 -0400477 try {
478 // Sanity-check that someone hasn't set up the config wrong and asked for a navigation
479 // bar on a tablet that has only the system bar
480 if (mWindowManager.hasNavigationBar()) {
481 throw new RuntimeException(
482 "Tablet device cannot show navigation bar and system bar");
483 }
484 } catch (RemoteException ex) {
Chet Haasebc0009d2011-09-08 16:19:50 -0700485 }
486
Daniel Sandler21eb86a2011-03-02 11:52:58 -0500487 mBarContents = (ViewGroup) sb.findViewById(R.id.bar_contents);
Joe Onoratof63b0f42010-09-12 17:03:19 -0400488
Joe Onoratofd52b182010-11-10 18:00:52 -0800489 // the whole right-hand side of the bar
490 mNotificationArea = sb.findViewById(R.id.notificationArea);
Daniel Sandler298a2a82011-08-11 16:13:22 -0400491 if (!NOTIFICATION_PEEK_ENABLED) {
492 mNotificationArea.setOnTouchListener(new NotificationTriggerTouchListener());
493 }
Joe Onoratofd52b182010-11-10 18:00:52 -0800494
Joe Onorato55d2d762010-09-26 13:02:01 -0700495 // the button to open the notification area
Joe Onoratofd52b182010-11-10 18:00:52 -0800496 mNotificationTrigger = sb.findViewById(R.id.notificationTrigger);
Daniel Sandler298a2a82011-08-11 16:13:22 -0400497 if (NOTIFICATION_PEEK_ENABLED) {
498 mNotificationTrigger.setOnTouchListener(new NotificationTriggerTouchListener());
499 }
Joe Onorato55d2d762010-09-26 13:02:01 -0700500
Joe Onorato808182d2010-07-09 18:52:06 -0400501 // the more notifications icon
502 mNotificationIconArea = (NotificationIconArea)sb.findViewById(R.id.notificationIcons);
503
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400504 // where the icons go
505 mIconLayout = (NotificationIconArea.IconLayout) sb.findViewById(R.id.icons);
Daniel Sandler298a2a82011-08-11 16:13:22 -0400506 if (NOTIFICATION_PEEK_ENABLED) {
507 mIconLayout.setOnTouchListener(new NotificationIconTouchListener());
508 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400509
510 ViewConfiguration vc = ViewConfiguration.get(context);
511 mNotificationPeekTapDuration = vc.getTapTimeout();
512 mNotificationFlingVelocity = 300; // px/s
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400513
Daniel Sandlerc51451a2010-12-16 19:06:46 -0500514 mTicker = new TabletTicker(this);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400515
Joe Onoratofd52b182010-11-10 18:00:52 -0800516 // The icons
Daniel Sandlere40451a2011-02-03 14:51:35 -0500517 mLocationController = new LocationController(mContext); // will post a notification
518
Joe Onoratofd52b182010-11-10 18:00:52 -0800519 mBatteryController = new BatteryController(mContext);
520 mBatteryController.addIconView((ImageView)sb.findViewById(R.id.battery));
Joe Onoratofce2bf32011-02-01 17:00:29 -0800521 mBluetoothController = new BluetoothController(mContext);
522 mBluetoothController.addIconView((ImageView)sb.findViewById(R.id.bluetooth));
Daniel Sandler2b697352011-07-22 16:23:09 -0400523
Joe Onoratofd52b182010-11-10 18:00:52 -0800524 mNetworkController = new NetworkController(mContext);
Christian Robertson2e347422011-08-11 14:01:04 -0700525 final SignalClusterView signalCluster =
526 (SignalClusterView)sb.findViewById(R.id.signal_cluster);
527 mNetworkController.addSignalCluster(signalCluster);
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400528
Joe Onorato091e1b82010-09-26 18:04:44 -0700529 // The navigation buttons
Joe Onorato6478adc2011-01-27 21:15:01 -0800530 mBackButton = (ImageView)sb.findViewById(R.id.back);
Daniel Sandler21eb86a2011-03-02 11:52:58 -0500531 mNavigationArea = (ViewGroup) sb.findViewById(R.id.navigationArea);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500532 mHomeButton = mNavigationArea.findViewById(R.id.home);
Daniel Sandlere02d8082010-10-08 15:13:22 -0400533 mMenuButton = mNavigationArea.findViewById(R.id.menu);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500534 mRecentButton = mNavigationArea.findViewById(R.id.recent_apps);
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -0500535 mRecentButton.setOnClickListener(mOnClickListener);
Daniel Sandler4f9986e2011-12-02 16:10:37 -0500536
537 LayoutTransition lt = new LayoutTransition();
538 lt.setDuration(250);
539 // don't wait for these transitions; we just want icons to fade in/out, not move around
540 lt.setDuration(LayoutTransition.CHANGE_APPEARING, 0);
541 lt.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 0);
Daniel Sandler5a826602011-12-07 15:16:18 -0500542 lt.addTransitionListener(new LayoutTransition.TransitionListener() {
543 public void endTransition(LayoutTransition transition, ViewGroup container,
544 View view, int transitionType) {
545 // ensure the menu button doesn't stick around on the status bar after it's been
546 // removed
547 mBarContents.invalidate();
548 }
549 public void startTransition(LayoutTransition transition, ViewGroup container,
550 View view, int transitionType) {}
551 });
Daniel Sandler4f9986e2011-12-02 16:10:37 -0500552 mNavigationArea.setLayoutTransition(lt);
Daniel Sandler96f48182011-08-17 09:50:35 -0400553 // no multi-touch on the nav buttons
554 mNavigationArea.setMotionEventSplittingEnabled(false);
Joe Onorato091e1b82010-09-26 18:04:44 -0700555
satok06487a52010-10-29 11:37:18 +0900556 // The bar contents buttons
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400557 mFeedbackIconArea = (ViewGroup)sb.findViewById(R.id.feedbackIconArea);
satokcd7cd292010-11-20 15:46:23 +0900558 mInputMethodSwitchButton = (InputMethodButton) sb.findViewById(R.id.imeSwitchButton);
satok82beadf2010-12-27 19:03:06 +0900559 // Overwrite the lister
560 mInputMethodSwitchButton.setOnClickListener(mOnClickListener);
satok06487a52010-10-29 11:37:18 +0900561
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400562 mCompatModeButton = (CompatModeButton) sb.findViewById(R.id.compatModeButton);
563 mCompatModeButton.setOnClickListener(mOnClickListener);
Dianne Hackborne0f085d2011-11-30 18:41:15 -0800564 mCompatModeButton.setVisibility(View.GONE);
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400565
Daniel Sandler10163c62010-12-08 11:51:05 -0500566 // for redirecting errant bar taps to the IME
567 mFakeSpaceBar = sb.findViewById(R.id.fake_space_bar);
568
Daniel Sandlerb9606992010-11-19 14:47:59 -0500569 // "shadows" of the status bar features, for lights-out mode
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500570 mShadow = sb.findViewById(R.id.bar_shadow);
571 mShadow.setOnTouchListener(
572 new View.OnTouchListener() {
573 public boolean onTouch(View v, MotionEvent ev) {
574 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
Daniel Sandlerd7201552011-01-28 09:58:02 -0500575 // even though setting the systemUI visibility below will turn these views
576 // on, we need them to come up faster so that they can catch this motion
577 // event
578 mShadow.setVisibility(View.GONE);
579 mBarContents.setVisibility(View.VISIBLE);
580
Joe Onorato55bf3802011-01-25 13:42:10 -0800581 try {
582 mBarService.setSystemUiVisibility(View.STATUS_BAR_VISIBLE);
583 } catch (RemoteException ex) {
584 // system process dead
585 }
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500586 }
587 return false;
588 }
589 });
Daniel Sandlerb9606992010-11-19 14:47:59 -0500590
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500591 // tuning parameters
592 final int LIGHTS_GOING_OUT_SYSBAR_DURATION = 600;
593 final int LIGHTS_GOING_OUT_SHADOW_DURATION = 1000;
594 final int LIGHTS_GOING_OUT_SHADOW_DELAY = 500;
595
596 final int LIGHTS_COMING_UP_SYSBAR_DURATION = 200;
597// final int LIGHTS_COMING_UP_SYSBAR_DELAY = 50;
598 final int LIGHTS_COMING_UP_SHADOW_DURATION = 0;
599
600 LayoutTransition xition = new LayoutTransition();
601 xition.setAnimator(LayoutTransition.APPEARING,
602 ObjectAnimator.ofFloat(null, "alpha", 0.5f, 1f));
603 xition.setDuration(LayoutTransition.APPEARING, LIGHTS_COMING_UP_SYSBAR_DURATION);
604 xition.setStartDelay(LayoutTransition.APPEARING, 0);
605 xition.setAnimator(LayoutTransition.DISAPPEARING,
606 ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
607 xition.setDuration(LayoutTransition.DISAPPEARING, LIGHTS_GOING_OUT_SYSBAR_DURATION);
608 xition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
609 ((ViewGroup)sb.findViewById(R.id.bar_contents_holder)).setLayoutTransition(xition);
610
611 xition = new LayoutTransition();
612 xition.setAnimator(LayoutTransition.APPEARING,
613 ObjectAnimator.ofFloat(null, "alpha", 0f, 1f));
614 xition.setDuration(LayoutTransition.APPEARING, LIGHTS_GOING_OUT_SHADOW_DURATION);
615 xition.setStartDelay(LayoutTransition.APPEARING, LIGHTS_GOING_OUT_SHADOW_DELAY);
616 xition.setAnimator(LayoutTransition.DISAPPEARING,
617 ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
618 xition.setDuration(LayoutTransition.DISAPPEARING, LIGHTS_COMING_UP_SHADOW_DURATION);
619 xition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
620 ((ViewGroup)sb.findViewById(R.id.bar_shadow_holder)).setLayoutTransition(xition);
Daniel Sandlerb9606992010-11-19 14:47:59 -0500621
Joe Onorato5dd11692010-09-27 15:34:04 -0700622 // set the initial view visibility
623 setAreThereNotifications();
624
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400625 // Add the windows
626 addPanelWindows();
Michael Jurka412cba82011-10-17 09:05:00 -0700627 mRecentButton.setOnTouchListener(mRecentsPanel);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400628
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400629 mPile = (ViewGroup)mNotificationPanel.findViewById(R.id.content);
630 mPile.removeAllViews();
Jim Miller44c66fe2010-10-20 18:32:52 -0700631
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400632 ScrollView scroller = (ScrollView)mPile.getParent();
633 scroller.setFillViewport(true);
634
Joe Onoratodc100302011-01-11 17:07:41 -0800635 mHeightReceiver.addOnBarHeightChangedListener(this);
636
Michael Jurkab7f43272011-10-27 15:06:38 -0700637 // receive broadcasts
638 IntentFilter filter = new IntentFilter();
639 filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
640 filter.addAction(Intent.ACTION_SCREEN_OFF);
641 context.registerReceiver(mBroadcastReceiver, filter);
642
Joe Onorato808182d2010-07-09 18:52:06 -0400643 return sb;
644 }
645
Joe Onoratodc100302011-01-11 17:07:41 -0800646 public int getStatusBarHeight() {
647 return mHeightReceiver.getHeight();
648 }
649
Joe Onorato808182d2010-07-09 18:52:06 -0400650 protected int getStatusBarGravity() {
651 return Gravity.BOTTOM | Gravity.FILL_HORIZONTAL;
652 }
653
Joe Onoratodc100302011-01-11 17:07:41 -0800654 public void onBarHeightChanged(int height) {
655 final WindowManager.LayoutParams lp
656 = (WindowManager.LayoutParams)mStatusBarView.getLayoutParams();
657 if (lp == null) {
658 // haven't been added yet
659 return;
660 }
661 if (lp.height != height) {
662 lp.height = height;
663 final WindowManager wm = WindowManagerImpl.getDefault();
664 wm.updateViewLayout(mStatusBarView, lp);
665 }
666 }
667
Daniel Sandler9120d552010-07-23 09:11:14 -0400668 private class H extends Handler {
Daniel Sandler9120d552010-07-23 09:11:14 -0400669 public void handleMessage(Message m) {
670 switch (m.what) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400671 case MSG_OPEN_NOTIFICATION_PEEK:
672 if (DEBUG) Slog.d(TAG, "opening notification peek window; arg=" + m.arg1);
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500673
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400674 if (m.arg1 >= 0) {
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500675 final int N = mNotificationData.size();
676
677 if (!mNotificationDNDMode) {
678 if (mNotificationPeekIndex >= 0 && mNotificationPeekIndex < N) {
679 NotificationData.Entry entry = mNotificationData.get(N-1-mNotificationPeekIndex);
680 entry.icon.setBackgroundColor(0);
681 mNotificationPeekIndex = -1;
682 mNotificationPeekKey = null;
683 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400684 }
685
686 final int peekIndex = m.arg1;
687 if (peekIndex < N) {
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500688 //Slog.d(TAG, "loading peek: " + peekIndex);
Jim Miller5fda69c2011-02-16 15:17:11 -0800689 NotificationData.Entry entry =
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500690 mNotificationDNDMode
691 ? mNotificationDNDDummyEntry
692 : mNotificationData.get(N-1-peekIndex);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400693 NotificationData.Entry copy = new NotificationData.Entry(
Jim Miller85babff2011-01-11 14:26:03 -0800694 entry.key,
695 entry.notification,
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400696 entry.icon);
697 inflateViews(copy, mNotificationPeekRow);
698
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500699 if (mNotificationDNDMode) {
700 copy.content.setOnClickListener(new View.OnClickListener() {
701 public void onClick(View v) {
702 SharedPreferences.Editor editor = Prefs.edit(mContext);
703 editor.putBoolean(Prefs.DO_NOT_DISTURB_PREF, false);
704 editor.apply();
705 animateCollapse();
Mike Lockwood066c8912011-08-24 10:17:18 -0400706 visibilityChanged(false);
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500707 }
708 });
709 }
710
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400711 entry.icon.setBackgroundColor(0x20FFFFFF);
712
713// mNotificationPeekRow.setLayoutTransition(
Jim Miller85babff2011-01-11 14:26:03 -0800714// peekIndex < mNotificationPeekIndex
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400715// ? mNotificationPeekScrubLeft
716// : mNotificationPeekScrubRight);
717
718 mNotificationPeekRow.removeAllViews();
719 mNotificationPeekRow.addView(copy.row);
720
721 mNotificationPeekWindow.setVisibility(View.VISIBLE);
Joe Onorato7c270fa2010-12-08 17:31:42 -0800722 mNotificationPanel.show(false, true);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400723
724 mNotificationPeekIndex = peekIndex;
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500725 mNotificationPeekKey = entry.key;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400726 }
727 }
728 break;
729 case MSG_CLOSE_NOTIFICATION_PEEK:
730 if (DEBUG) Slog.d(TAG, "closing notification peek window");
731 mNotificationPeekWindow.setVisibility(View.GONE);
732 mNotificationPeekRow.removeAllViews();
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500733
734 final int N = mNotificationData.size();
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500735 if (mNotificationPeekIndex >= 0 && mNotificationPeekIndex < N) {
Jim Miller5fda69c2011-02-16 15:17:11 -0800736 NotificationData.Entry entry =
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500737 mNotificationDNDMode
738 ? mNotificationDNDDummyEntry
739 : mNotificationData.get(N-1-mNotificationPeekIndex);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400740 entry.icon.setBackgroundColor(0);
741 }
Daniel Sandlera8e5b062010-12-01 13:53:08 -0500742
743 mNotificationPeekIndex = -1;
744 mNotificationPeekKey = null;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400745 break;
Daniel Sandler9120d552010-07-23 09:11:14 -0400746 case MSG_OPEN_NOTIFICATION_PANEL:
747 if (DEBUG) Slog.d(TAG, "opening notifications panel");
Joe Onorato7c270fa2010-12-08 17:31:42 -0800748 if (!mNotificationPanel.isShowing()) {
Daniel Sandler298a2a82011-08-11 16:13:22 -0400749 if (NOTIFICATION_PEEK_ENABLED) {
750 mNotificationPeekWindow.setVisibility(View.GONE);
751 }
Joe Onorato7c270fa2010-12-08 17:31:42 -0800752 mNotificationPanel.show(true, true);
Daniel Sandler21eb86a2011-03-02 11:52:58 -0500753 mNotificationArea.setVisibility(View.INVISIBLE);
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800754 mTicker.halt();
Joe Onorato091e1b82010-09-26 18:04:44 -0700755 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400756 break;
757 case MSG_CLOSE_NOTIFICATION_PANEL:
758 if (DEBUG) Slog.d(TAG, "closing notifications panel");
Joe Onorato7c270fa2010-12-08 17:31:42 -0800759 if (mNotificationPanel.isShowing()) {
760 mNotificationPanel.show(false, true);
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500761 mNotificationArea.setVisibility(View.VISIBLE);
Joe Onorato091e1b82010-09-26 18:04:44 -0700762 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400763 break;
Jim Miller44c66fe2010-10-20 18:32:52 -0700764 case MSG_OPEN_RECENTS_PANEL:
765 if (DEBUG) Slog.d(TAG, "opening recents panel");
Jim Miller85babff2011-01-11 14:26:03 -0800766 if (mRecentsPanel != null) {
Jim Miller85babff2011-01-11 14:26:03 -0800767 mRecentsPanel.show(true, true);
768 }
Jim Miller44c66fe2010-10-20 18:32:52 -0700769 break;
770 case MSG_CLOSE_RECENTS_PANEL:
771 if (DEBUG) Slog.d(TAG, "closing recents panel");
Jim Miller85babff2011-01-11 14:26:03 -0800772 if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
773 mRecentsPanel.show(false, true);
774 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400775 break;
satok82beadf2010-12-27 19:03:06 +0900776 case MSG_OPEN_INPUT_METHODS_PANEL:
777 if (DEBUG) Slog.d(TAG, "opening input methods panel");
Tadashi G. Takaokae385f0c2011-02-01 02:57:44 +0900778 if (mInputMethodsPanel != null) mInputMethodsPanel.openPanel();
satok82beadf2010-12-27 19:03:06 +0900779 break;
780 case MSG_CLOSE_INPUT_METHODS_PANEL:
781 if (DEBUG) Slog.d(TAG, "closing input methods panel");
Tadashi G. Takaokae385f0c2011-02-01 02:57:44 +0900782 if (mInputMethodsPanel != null) mInputMethodsPanel.closePanel(false);
satok82beadf2010-12-27 19:03:06 +0900783 break;
Daniel Sandler3b0543a2011-06-14 11:30:28 -0400784 case MSG_OPEN_COMPAT_MODE_PANEL:
785 if (DEBUG) Slog.d(TAG, "opening compat panel");
786 if (mCompatModePanel != null) mCompatModePanel.openPanel();
787 break;
788 case MSG_CLOSE_COMPAT_MODE_PANEL:
789 if (DEBUG) Slog.d(TAG, "closing compat panel");
790 if (mCompatModePanel != null) mCompatModePanel.closePanel();
791 break;
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500792 case MSG_SHOW_CHROME:
Daniel Sandlere03d1bc2010-11-17 21:36:40 -0500793 if (DEBUG) Slog.d(TAG, "hiding shadows (lights on)");
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500794 mBarContents.setVisibility(View.VISIBLE);
795 mShadow.setVisibility(View.GONE);
Daniel Sandler60ee2562011-07-22 12:34:33 -0400796 mSystemUiVisibility &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
797 notifyUiVisibilityChanged();
Daniel Sandler06e66302010-11-05 15:00:06 -0400798 break;
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500799 case MSG_HIDE_CHROME:
Daniel Sandlere03d1bc2010-11-17 21:36:40 -0500800 if (DEBUG) Slog.d(TAG, "showing shadows (lights out)");
Daniel Sandler06e66302010-11-05 15:00:06 -0400801 animateCollapse();
Mike Lockwood066c8912011-08-24 10:17:18 -0400802 visibilityChanged(false);
Daniel Sandler0ad460b2010-12-14 12:14:53 -0500803 mBarContents.setVisibility(View.GONE);
804 mShadow.setVisibility(View.VISIBLE);
Daniel Sandler60ee2562011-07-22 12:34:33 -0400805 mSystemUiVisibility |= View.SYSTEM_UI_FLAG_LOW_PROFILE;
806 notifyUiVisibilityChanged();
Daniel Sandlere03d1bc2010-11-17 21:36:40 -0500807 break;
Daniel Sandler2ed08d22011-01-30 16:07:28 -0500808 case MSG_STOP_TICKER:
809 mTicker.halt();
810 break;
Daniel Sandler9120d552010-07-23 09:11:14 -0400811 }
812 }
813 }
Daniel Sandler271ea122010-10-22 14:06:10 -0400814
Joe Onorato808182d2010-07-09 18:52:06 -0400815 public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400816 if (DEBUG) Slog.d(TAG, "addIcon(" + slot + ") -> " + icon);
Joe Onorato808182d2010-07-09 18:52:06 -0400817 }
818
819 public void updateIcon(String slot, int index, int viewIndex,
820 StatusBarIcon old, StatusBarIcon icon) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400821 if (DEBUG) Slog.d(TAG, "updateIcon(" + slot + ") -> " + icon);
Joe Onorato808182d2010-07-09 18:52:06 -0400822 }
823
824 public void removeIcon(String slot, int index, int viewIndex) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400825 if (DEBUG) Slog.d(TAG, "removeIcon(" + slot + ")");
Joe Onorato808182d2010-07-09 18:52:06 -0400826 }
827
828 public void addNotification(IBinder key, StatusBarNotification notification) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400829 if (DEBUG) Slog.d(TAG, "addNotification(" + key + " -> " + notification + ")");
830 addNotificationViews(key, notification);
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400831
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800832 final boolean immersive = isImmersive();
Joe Onoratocf2b1992010-11-16 21:36:42 -0800833 if (false && immersive) {
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400834 // TODO: immersive mode popups for tablet
835 } else if (notification.notification.fullScreenIntent != null) {
836 // not immersive & a full-screen alert should be shown
Joe Onoratof68b5002011-01-16 17:00:34 -0800837 Slog.w(TAG, "Notification has fullScreenIntent and activity is not immersive;"
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400838 + " sending fullScreenIntent");
839 try {
840 notification.notification.fullScreenIntent.send();
841 } catch (PendingIntent.CanceledException e) {
842 }
843 } else {
Joe Onoratoeeed9942011-01-04 17:13:53 -0800844 tick(key, notification, true);
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400845 }
Joe Onorato5dd11692010-09-27 15:34:04 -0700846
847 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400848 }
849
850 public void updateNotification(IBinder key, StatusBarNotification notification) {
Daniel Sandler282ff9a2011-02-23 10:36:49 -0500851 if (DEBUG) Slog.d(TAG, "updateNotification(" + key + " -> " + notification + ")");
Jim Miller44c66fe2010-10-20 18:32:52 -0700852
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500853 final NotificationData.Entry oldEntry = mNotificationData.findByKey(key);
Daniel Sandler379020a2010-07-29 16:20:06 -0400854 if (oldEntry == null) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400855 Slog.w(TAG, "updateNotification for unknown key: " + key);
856 return;
857 }
858
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400859 final StatusBarNotification oldNotification = oldEntry.notification;
860 final RemoteViews oldContentView = oldNotification.notification.contentView;
861
862 final RemoteViews contentView = notification.notification.contentView;
863
Daniel Sandler373a9982010-11-30 12:03:59 -0500864 if (DEBUG) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400865 Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
866 + " ongoing=" + oldNotification.isOngoing()
867 + " expanded=" + oldEntry.expanded
Daniel Sandler282ff9a2011-02-23 10:36:49 -0500868 + " contentView=" + oldContentView
869 + " rowParent=" + oldEntry.row.getParent());
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400870 Slog.d(TAG, "new notification: when=" + notification.notification.when
871 + " ongoing=" + oldNotification.isOngoing()
872 + " contentView=" + contentView);
873 }
874
875 // Can we just reapply the RemoteViews in place? If when didn't change, the order
876 // didn't change.
Joe Onorato80a44402011-01-15 16:22:24 -0800877 boolean contentsUnchanged = oldEntry.expanded != null
878 && contentView != null && oldContentView != null
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400879 && contentView.getPackage() != null
880 && oldContentView.getPackage() != null
881 && oldContentView.getPackage().equals(contentView.getPackage())
Joe Onoratoc9596d62011-01-12 17:03:11 -0800882 && oldContentView.getLayoutId() == contentView.getLayoutId();
Daniel Sandler373a9982010-11-30 12:03:59 -0500883 ViewGroup rowParent = (ViewGroup) oldEntry.row.getParent();
Joe Onorato80a44402011-01-15 16:22:24 -0800884 boolean orderUnchanged = notification.notification.when==oldNotification.notification.when
Jim Miller5fda69c2011-02-16 15:17:11 -0800885 && notification.priority == oldNotification.priority;
Daniel Sandlera31e4192011-02-02 22:00:28 -0500886 // priority now encompasses isOngoing()
Winson Chungc57ccf02011-10-13 15:04:59 -0700887 boolean updateTicker = notification.notification.tickerText != null
888 && !TextUtils.equals(notification.notification.tickerText,
889 oldEntry.notification.notification.tickerText);
Joe Onoratoc9596d62011-01-12 17:03:11 -0800890 boolean isLastAnyway = rowParent.indexOfChild(oldEntry.row) == rowParent.getChildCount()-1;
891 if (contentsUnchanged && (orderUnchanged || isLastAnyway)) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400892 if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
893 oldEntry.notification = notification;
894 try {
895 // Reapply the RemoteViews
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400896 contentView.reapply(mContext, oldEntry.content);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400897 // update the contentIntent
898 final PendingIntent contentIntent = notification.notification.contentIntent;
899 if (contentIntent != null) {
Jeff Sharkey847fd752011-09-02 17:48:55 -0700900 final View.OnClickListener listener = new NotificationClicker(contentIntent,
901 notification.pkg, notification.tag, notification.id);
902 oldEntry.largeIcon.setOnClickListener(listener);
903 oldEntry.content.setOnClickListener(listener);
Joe Onorato184498c2010-10-08 17:57:18 -0400904 } else {
Jeff Sharkey847fd752011-09-02 17:48:55 -0700905 oldEntry.largeIcon.setOnClickListener(null);
Joe Onorato184498c2010-10-08 17:57:18 -0400906 oldEntry.content.setOnClickListener(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400907 }
908 // Update the icon.
909 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
910 notification.notification.icon, notification.notification.iconLevel,
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700911 notification.notification.number,
912 notification.notification.tickerText);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400913 if (!oldEntry.icon.set(ic)) {
914 handleNotificationError(key, notification, "Couldn't update icon: " + ic);
915 return;
916 }
Joe Onorato80a44402011-01-15 16:22:24 -0800917 // Update the large icon
918 if (notification.notification.largeIcon != null) {
919 oldEntry.largeIcon.setImageBitmap(notification.notification.largeIcon);
920 } else {
921 oldEntry.largeIcon.getLayoutParams().width = 0;
922 oldEntry.largeIcon.setVisibility(View.INVISIBLE);
923 }
Jim Miller85babff2011-01-11 14:26:03 -0800924
Daniel Sandler298a2a82011-08-11 16:13:22 -0400925 if (NOTIFICATION_PEEK_ENABLED && key == mNotificationPeekKey) {
Daniel Sandler7ef29b52010-12-16 17:29:50 -0500926 // must update the peek window
927 Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
928 peekMsg.arg1 = mNotificationPeekIndex;
929 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
930 mHandler.sendMessage(peekMsg);
931 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400932 }
933 catch (RuntimeException e) {
934 // It failed to add cleanly. Log, and remove the view from the panel.
935 Slog.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
936 removeNotificationViews(key);
937 addNotificationViews(key, notification);
938 }
939 } else {
940 if (DEBUG) Slog.d(TAG, "not reusing notification for key: " + key);
941 removeNotificationViews(key);
942 addNotificationViews(key, notification);
943 }
Daniel Sandler2a58af32011-08-26 09:38:24 -0700944
945 // Restart the ticker if it's still running
Winson Chungc57ccf02011-10-13 15:04:59 -0700946 if (updateTicker) {
947 mTicker.halt();
Joe Onoratoeeed9942011-01-04 17:13:53 -0800948 tick(key, notification, false);
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800949 }
Joe Onorato5dd11692010-09-27 15:34:04 -0700950
951 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400952 }
953
954 public void removeNotification(IBinder key) {
Daniel Sandler3a2fded2011-02-23 11:19:59 -0500955 if (DEBUG) Slog.d(TAG, "removeNotification(" + key + ")");
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400956 removeNotificationViews(key);
Joe Onorato50ec5ec2010-11-28 17:15:26 -0800957 mTicker.remove(key);
Joe Onorato5dd11692010-09-27 15:34:04 -0700958 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400959 }
960
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500961 public void showClock(boolean show) {
962 View clock = mBarContents.findViewById(R.id.clock);
963 View network_text = mBarContents.findViewById(R.id.network_text);
964 if (clock != null) {
965 clock.setVisibility(show ? View.VISIBLE : View.GONE);
966 }
967 if (network_text != null) {
968 network_text.setVisibility((!show) ? View.VISIBLE : View.GONE);
969 }
970 }
971
Joe Onorato808182d2010-07-09 18:52:06 -0400972 public void disable(int state) {
Joe Onorato091e1b82010-09-26 18:04:44 -0700973 int old = mDisabled;
974 int diff = state ^ old;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400975 mDisabled = state;
976
Joe Onorato091e1b82010-09-26 18:04:44 -0700977 // act accordingly
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500978 if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) {
979 boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0;
Joe Onoratof68b5002011-01-16 17:00:34 -0800980 Slog.i(TAG, "DISABLE_CLOCK: " + (show ? "no" : "yes"));
Daniel Sandler3e8f5a22010-12-03 14:52:10 -0500981 showClock(show);
982 }
Daniel Sandler6f6cf3c2010-12-16 12:54:03 -0500983 if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
984 boolean show = (state & StatusBarManager.DISABLE_SYSTEM_INFO) == 0;
Joe Onoratof68b5002011-01-16 17:00:34 -0800985 Slog.i(TAG, "DISABLE_SYSTEM_INFO: " + (show ? "no" : "yes"));
Daniel Sandler6f6cf3c2010-12-16 12:54:03 -0500986 mNotificationTrigger.setVisibility(show ? View.VISIBLE : View.GONE);
987 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400988 if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
989 if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
Joe Onoratof68b5002011-01-16 17:00:34 -0800990 Slog.i(TAG, "DISABLE_EXPAND: yes");
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400991 animateCollapse();
Mike Lockwood066c8912011-08-24 10:17:18 -0400992 visibilityChanged(false);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400993 }
994 }
995 if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
Daniel Sandlerce6ff642011-02-18 12:51:08 -0500996 mNotificationDNDMode = Prefs.read(mContext)
997 .getBoolean(Prefs.DO_NOT_DISTURB_PREF, Prefs.DO_NOT_DISTURB_DEFAULT);
Daniel Sandler282ff9a2011-02-23 10:36:49 -0500998
999 if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
1000 Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: yes" + (mNotificationDNDMode?" (DND)":""));
1001 mTicker.halt();
1002 } else {
1003 Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: no" + (mNotificationDNDMode?" (DND)":""));
1004 }
1005
1006 // refresh icons to show either notifications or the DND message
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001007 reloadAllNotificationIcons();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001008 } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
Joe Onorato091e1b82010-09-26 18:04:44 -07001009 if ((state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
Joe Onoratoef1e7762010-09-17 18:38:38 -04001010 mTicker.halt();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001011 }
1012 }
Daniel Sandlerdba93562011-10-06 16:39:58 -04001013 if ((diff & (StatusBarManager.DISABLE_RECENT
1014 | StatusBarManager.DISABLE_BACK
1015 | StatusBarManager.DISABLE_HOME)) != 0) {
1016 setNavigationVisibility(state);
Michael Jurkab7f43272011-10-27 15:06:38 -07001017
1018 if ((state & StatusBarManager.DISABLE_RECENT) != 0) {
1019 // close recents if it's visible
1020 mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
1021 mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
1022 }
Joe Onorato091e1b82010-09-26 18:04:44 -07001023 }
Mike Lockwoode3646dd2011-09-01 12:46:28 -04001024 }
1025
1026 private void setNavigationVisibility(int visibility) {
Daniel Sandlerdba93562011-10-06 16:39:58 -04001027 boolean disableHome = ((visibility & StatusBarManager.DISABLE_HOME) != 0);
1028 boolean disableRecent = ((visibility & StatusBarManager.DISABLE_RECENT) != 0);
Mike Lockwoode3646dd2011-09-01 12:46:28 -04001029 boolean disableBack = ((visibility & StatusBarManager.DISABLE_BACK) != 0);
1030
Daniel Sandlerdba93562011-10-06 16:39:58 -04001031 mBackButton.setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
1032 mHomeButton.setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
1033 mRecentButton.setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
Mike Lockwoode3646dd2011-09-01 12:46:28 -04001034
Daniel Sandlerdba93562011-10-06 16:39:58 -04001035 mInputMethodSwitchButton.setScreenLocked(
1036 (visibility & StatusBarManager.DISABLE_SYSTEM_INFO) != 0);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001037 }
1038
Joe Onoratoef1e7762010-09-17 18:38:38 -04001039 private boolean hasTicker(Notification n) {
Joe Onorato46439ce2010-11-19 13:56:21 -08001040 return n.tickerView != null || !TextUtils.isEmpty(n.tickerText);
Joe Onoratoef1e7762010-09-17 18:38:38 -04001041 }
1042
Joe Onoratoeeed9942011-01-04 17:13:53 -08001043 private void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
Joe Onorato55d2d762010-09-26 13:02:01 -07001044 // Don't show the ticker when the windowshade is open.
Joe Onorato7c270fa2010-12-08 17:31:42 -08001045 if (mNotificationPanel.isShowing()) {
Joe Onorato55d2d762010-09-26 13:02:01 -07001046 return;
1047 }
Joe Onoratoeeed9942011-01-04 17:13:53 -08001048 // If they asked for FLAG_ONLY_ALERT_ONCE, then only show this notification
1049 // if it's a new notification.
1050 if (!firstTime && (n.notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) {
1051 return;
1052 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001053 // Show the ticker if one is requested. Also don't do this
1054 // until status bar window is attached to the window manager,
1055 // because... well, what's the point otherwise? And trying to
1056 // run a ticker without being attached will crash!
Joe Onoratoef1e7762010-09-17 18:38:38 -04001057 if (hasTicker(n.notification) && mStatusBarView.getWindowToken() != null) {
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001058 if (0 == (mDisabled & (StatusBarManager.DISABLE_NOTIFICATION_ICONS
1059 | StatusBarManager.DISABLE_NOTIFICATION_TICKER))) {
Joe Onorato50ec5ec2010-11-28 17:15:26 -08001060 mTicker.add(key, n);
Daniel Sandler3b0543a2011-06-14 11:30:28 -04001061 mFeedbackIconArea.setVisibility(View.GONE);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001062 }
1063 }
1064 }
1065
Daniel Sandlerb8027d82010-12-16 19:35:54 -05001066 // called by TabletTicker when it's done with all queued ticks
1067 public void doneTicking() {
Daniel Sandler3b0543a2011-06-14 11:30:28 -04001068 mFeedbackIconArea.setVisibility(View.VISIBLE);
Daniel Sandlerb8027d82010-12-16 19:35:54 -05001069 }
1070
Joe Onorato808182d2010-07-09 18:52:06 -04001071 public void animateExpand() {
Daniel Sandler298a2a82011-08-11 16:13:22 -04001072 if (NOTIFICATION_PEEK_ENABLED) {
1073 mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PEEK);
1074 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
1075 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
1076 }
Joe Onoratob62ac122010-09-20 16:16:32 -04001077 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
1078 mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
Joe Onorato808182d2010-07-09 18:52:06 -04001079 }
1080
1081 public void animateCollapse() {
Michael Jurkab7f43272011-10-27 15:06:38 -07001082 animateCollapse(false);
1083 }
1084
1085 private void animateCollapse(boolean excludeRecents) {
Joe Onoratob62ac122010-09-20 16:16:32 -04001086 mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PANEL);
1087 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PANEL);
Michael Jurkab7f43272011-10-27 15:06:38 -07001088 if (!excludeRecents) {
1089 mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
1090 mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
1091 }
satok82beadf2010-12-27 19:03:06 +09001092 mHandler.removeMessages(MSG_CLOSE_INPUT_METHODS_PANEL);
1093 mHandler.sendEmptyMessage(MSG_CLOSE_INPUT_METHODS_PANEL);
Daniel Sandler3b0543a2011-06-14 11:30:28 -04001094 mHandler.removeMessages(MSG_CLOSE_COMPAT_MODE_PANEL);
1095 mHandler.sendEmptyMessage(MSG_CLOSE_COMPAT_MODE_PANEL);
Daniel Sandler298a2a82011-08-11 16:13:22 -04001096 if (NOTIFICATION_PEEK_ENABLED) {
1097 mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PEEK);
1098 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
1099 }
Daniel Sandler9120d552010-07-23 09:11:14 -04001100 }
1101
Mike Lockwood066c8912011-08-24 10:17:18 -04001102 /**
1103 * The LEDs are turned o)ff when the notification panel is shown, even just a little bit.
1104 * This was added last-minute and is inconsistent with the way the rest of the notifications
1105 * are handled, because the notification isn't really cancelled. The lights are just
1106 * turned off. If any other notifications happen, the lights will turn back on. Steve says
1107 * this is what he wants. (see bug 1131461)
1108 */
1109 void visibilityChanged(boolean visible) {
1110 if (mPanelSlightlyVisible != visible) {
1111 mPanelSlightlyVisible = visible;
1112 try {
1113 mBarService.onPanelRevealed();
1114 } catch (RemoteException ex) {
1115 // Won't fail unless the world has ended.
1116 }
1117 }
1118 }
1119
Daniel Sandlerea193ce2011-09-23 15:56:52 -04001120 @Override // CommandQueue
1121 public void setNavigationIconHints(int hints) {
1122 if (hints == mNavigationIconHints) return;
1123
1124 if (DEBUG) {
1125 android.widget.Toast.makeText(mContext,
1126 "Navigation icon hints = " + hints,
1127 500).show();
1128 }
1129
1130 mNavigationIconHints = hints;
1131
1132 mBackButton.setAlpha(
1133 (0 != (hints & StatusBarManager.NAVIGATION_HINT_BACK_NOP)) ? 0.5f : 1.0f);
1134 mHomeButton.setAlpha(
1135 (0 != (hints & StatusBarManager.NAVIGATION_HINT_HOME_NOP)) ? 0.5f : 1.0f);
1136 mRecentButton.setAlpha(
1137 (0 != (hints & StatusBarManager.NAVIGATION_HINT_RECENT_NOP)) ? 0.5f : 1.0f);
1138
1139 mBackButton.setImageResource(
1140 (0 != (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT))
1141 ? R.drawable.ic_sysbar_back_ime
1142 : R.drawable.ic_sysbar_back);
1143 }
1144
Daniel Sandler60ee2562011-07-22 12:34:33 -04001145 private void notifyUiVisibilityChanged() {
1146 try {
1147 mWindowManager.statusBarVisibilityChanged(mSystemUiVisibility);
1148 } catch (RemoteException ex) {
1149 }
1150 }
1151
1152 @Override // CommandQueue
1153 public void setSystemUiVisibility(int vis) {
1154 if (vis != mSystemUiVisibility) {
1155 mSystemUiVisibility = vis;
1156
1157 mHandler.removeMessages(MSG_HIDE_CHROME);
1158 mHandler.removeMessages(MSG_SHOW_CHROME);
1159 mHandler.sendEmptyMessage(0 == (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE)
1160 ? MSG_SHOW_CHROME : MSG_HIDE_CHROME);
1161
1162 notifyUiVisibilityChanged();
1163 }
1164 }
1165
Joe Onorato93056472010-09-10 10:30:46 -04001166 public void setLightsOn(boolean on) {
Daniel Sandler59485d742010-12-02 00:11:33 -05001167 // Policy note: if the frontmost activity needs the menu key, we assume it is a legacy app
1168 // that can't handle lights-out mode.
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001169 if (mMenuButton.getVisibility() == View.VISIBLE) {
Daniel Sandler59485d742010-12-02 00:11:33 -05001170 on = true;
1171 }
Daniel Sandler60ee2562011-07-22 12:34:33 -04001172
1173 Slog.v(TAG, "setLightsOn(" + on + ")");
1174 if (on) {
1175 setSystemUiVisibility(mSystemUiVisibility & ~View.SYSTEM_UI_FLAG_LOW_PROFILE);
1176 } else {
1177 setSystemUiVisibility(mSystemUiVisibility | View.SYSTEM_UI_FLAG_LOW_PROFILE);
1178 }
Joe Onorato93056472010-09-10 10:30:46 -04001179 }
1180
Daniel Sandler5c8da942011-06-28 00:29:04 -04001181 public void topAppWindowChanged(boolean showMenu) {
Daniel Sandlere02d8082010-10-08 15:13:22 -04001182 if (DEBUG) {
Daniel Sandler5c8da942011-06-28 00:29:04 -04001183 Slog.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
Daniel Sandlere02d8082010-10-08 15:13:22 -04001184 }
Daniel Sandler5c8da942011-06-28 00:29:04 -04001185 mMenuButton.setVisibility(showMenu ? View.VISIBLE : View.GONE);
Daniel Sandler59485d742010-12-02 00:11:33 -05001186
1187 // See above re: lights-out policy for legacy apps.
Daniel Sandler5c8da942011-06-28 00:29:04 -04001188 if (showMenu) setLightsOn(true);
Daniel Sandler45c04012011-06-07 15:29:07 -04001189
Daniel Sandler3b0543a2011-06-14 11:30:28 -04001190 mCompatModeButton.refresh();
Daniel Sandler552b1f02011-06-15 01:03:02 -04001191 if (mCompatModeButton.getVisibility() == View.VISIBLE) {
Daniel Sandler319d1e32011-08-05 11:34:06 -04001192 if (DEBUG_COMPAT_HELP
1193 || ! Prefs.read(mContext).getBoolean(Prefs.SHOWN_COMPAT_MODE_HELP, false)) {
Daniel Sandler552b1f02011-06-15 01:03:02 -04001194 showCompatibilityHelp();
Daniel Sandler319d1e32011-08-05 11:34:06 -04001195 }
Dianne Hackborned31bbf2011-06-15 11:16:06 -07001196 } else {
1197 hideCompatibilityHelp();
1198 mCompatModePanel.closePanel();
Daniel Sandler552b1f02011-06-15 01:03:02 -04001199 }
1200 }
1201
1202 private void showCompatibilityHelp() {
Dianne Hackborned31bbf2011-06-15 11:16:06 -07001203 if (mCompatibilityHelpDialog != null) {
1204 return;
1205 }
1206
1207 mCompatibilityHelpDialog = View.inflate(mContext, R.layout.compat_mode_help, null);
1208 View button = mCompatibilityHelpDialog.findViewById(R.id.button);
Daniel Sandler552b1f02011-06-15 01:03:02 -04001209
1210 button.setOnClickListener(new View.OnClickListener() {
1211 @Override
1212 public void onClick(View v) {
Dianne Hackborned31bbf2011-06-15 11:16:06 -07001213 hideCompatibilityHelp();
1214 SharedPreferences.Editor editor = Prefs.edit(mContext);
1215 editor.putBoolean(Prefs.SHOWN_COMPAT_MODE_HELP, true);
1216 editor.apply();
Daniel Sandler552b1f02011-06-15 01:03:02 -04001217 }
1218 });
1219
Daniel Sandlerf1dd26b2011-06-20 14:44:35 -04001220 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
Daniel Sandler552b1f02011-06-15 01:03:02 -04001221 ViewGroup.LayoutParams.MATCH_PARENT,
1222 ViewGroup.LayoutParams.MATCH_PARENT,
1223 WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG,
1224 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
1225 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
1226 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
1227 PixelFormat.TRANSLUCENT);
1228 lp.setTitle("CompatibilityModeDialog");
1229 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
1230 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
1231 lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
1232
Dianne Hackborned31bbf2011-06-15 11:16:06 -07001233 WindowManagerImpl.getDefault().addView(mCompatibilityHelpDialog, lp);
Daniel Sandlere02d8082010-10-08 15:13:22 -04001234 }
1235
Dianne Hackborned31bbf2011-06-15 11:16:06 -07001236 private void hideCompatibilityHelp() {
1237 if (mCompatibilityHelpDialog != null) {
1238 WindowManagerImpl.getDefault().removeView(mCompatibilityHelpDialog);
1239 mCompatibilityHelpDialog = null;
1240 }
1241 }
1242
Joe Onorato857fd9b2011-01-27 15:08:35 -08001243 public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
1244 mInputMethodSwitchButton.setImeWindowStatus(token,
1245 (vis & InputMethodService.IME_ACTIVE) != 0);
satok51133822011-01-25 15:01:48 +09001246 updateNotificationIcons();
satok913f42d2011-01-17 16:58:10 +09001247 mInputMethodsPanel.setImeToken(token);
Daniel Sandlerea193ce2011-09-23 15:56:52 -04001248
1249 boolean altBack = (backDisposition == InputMethodService.BACK_DISPOSITION_WILL_DISMISS)
1250 || ((vis & InputMethodService.IME_VISIBLE) != 0);
1251 mAltBackButtonEnabledForIme = altBack;
1252
1253 mCommandQueue.setNavigationIconHints(
1254 altBack ? (mNavigationIconHints | StatusBarManager.NAVIGATION_HINT_BACK_ALT)
1255 : (mNavigationIconHints & ~StatusBarManager.NAVIGATION_HINT_BACK_ALT));
1256
Daniel Sandler10163c62010-12-08 11:51:05 -05001257 if (FAKE_SPACE_BAR) {
Joe Onorato857fd9b2011-01-27 15:08:35 -08001258 mFakeSpaceBar.setVisibility(((vis & InputMethodService.IME_VISIBLE) != 0)
1259 ? View.VISIBLE : View.GONE);
Daniel Sandler10163c62010-12-08 11:51:05 -05001260 }
satok06487a52010-10-29 11:37:18 +09001261 }
1262
Jeff Brown2992ea72011-01-28 22:04:14 -08001263 @Override
Daniel Sandlerea193ce2011-09-23 15:56:52 -04001264 public void onRecentsPanelVisibilityChanged(boolean visible) {
1265 boolean altBack = visible || mAltBackButtonEnabledForIme;
1266 mCommandQueue.setNavigationIconHints(
1267 altBack ? (mNavigationIconHints | StatusBarManager.NAVIGATION_HINT_BACK_ALT)
1268 : (mNavigationIconHints & ~StatusBarManager.NAVIGATION_HINT_BACK_ALT));
1269 }
1270
1271 @Override
Jeff Brown2992ea72011-01-28 22:04:14 -08001272 public void setHardKeyboardStatus(boolean available, boolean enabled) {
1273 if (DEBUG) {
1274 Slog.d(TAG, "Set hard keyboard status: available=" + available
1275 + ", enabled=" + enabled);
1276 }
1277 mInputMethodSwitchButton.setHardKeyboardStatus(available);
1278 updateNotificationIcons();
1279 mInputMethodsPanel.setHardKeyboardStatus(available, enabled);
1280 }
1281
1282 @Override
1283 public void onHardKeyboardEnabledChange(boolean enabled) {
1284 try {
1285 mBarService.setHardKeyboardEnabled(enabled);
1286 } catch (RemoteException ex) {
1287 }
1288 }
1289
Joe Onorato50ec5ec2010-11-28 17:15:26 -08001290 private boolean isImmersive() {
1291 try {
1292 return ActivityManagerNative.getDefault().isTopActivityImmersive();
1293 //Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
1294 } catch (RemoteException ex) {
1295 // the end is nigh
1296 return false;
1297 }
1298 }
Jim Miller85babff2011-01-11 14:26:03 -08001299
Joe Onorato5dd11692010-09-27 15:34:04 -07001300 private void setAreThereNotifications() {
Daniel Sandler06a0d4b2011-08-05 00:19:21 -04001301 if (mNotificationPanel != null) {
1302 mNotificationPanel.setClearable(mNotificationData.hasClearableItems());
1303 }
Joe Onorato5dd11692010-09-27 15:34:04 -07001304 }
1305
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001306 /**
1307 * Cancel this notification and tell the status bar service about the failure. Hold no locks.
1308 */
1309 void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
1310 removeNotification(key);
1311 try {
1312 mBarService.onNotificationError(n.pkg, n.tag, n.id, n.uid, n.initialPid, message);
1313 } catch (RemoteException ex) {
1314 // The end is nigh.
1315 }
1316 }
1317
Daniel Sandler10163c62010-12-08 11:51:05 -05001318 private void sendKey(KeyEvent key) {
1319 try {
1320 if (DEBUG) Slog.d(TAG, "injecting key event: " + key);
1321 mWindowManager.injectInputEventNoWait(key);
1322 } catch (RemoteException ex) {
1323 }
1324 }
1325
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001326 private View.OnClickListener mOnClickListener = new View.OnClickListener() {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001327 public void onClick(View v) {
Daniel Sandler130453c2011-08-18 09:41:01 -04001328 if (v == mRecentButton) {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001329 onClickRecentButton();
satok82beadf2010-12-27 19:03:06 +09001330 } else if (v == mInputMethodSwitchButton) {
1331 onClickInputMethodSwitchButton();
Daniel Sandler3b0543a2011-06-14 11:30:28 -04001332 } else if (v == mCompatModeButton) {
1333 onClickCompatModeButton();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001334 }
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001335 }
1336 };
1337
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001338 public void onClickRecentButton() {
Daniel Sandlerb6d3dc62010-11-17 16:51:26 -05001339 if (DEBUG) Slog.d(TAG, "clicked recent apps; disabled=" + mDisabled);
Michael Jurka3b1fc472011-06-13 10:54:40 -07001340 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
Michael Jurka5571ab22011-10-27 12:54:39 -07001341 int msg = (mRecentsPanel.getVisibility() == View.VISIBLE)
1342 ? MSG_CLOSE_RECENTS_PANEL : MSG_OPEN_RECENTS_PANEL;
Michael Jurka3b1fc472011-06-13 10:54:40 -07001343 mHandler.removeMessages(msg);
1344 mHandler.sendEmptyMessage(msg);
Jim Miller44c66fe2010-10-20 18:32:52 -07001345 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001346 }
Joe Onorato55d2d762010-09-26 13:02:01 -07001347
satok82beadf2010-12-27 19:03:06 +09001348 public void onClickInputMethodSwitchButton() {
1349 if (DEBUG) Slog.d(TAG, "clicked input methods panel; disabled=" + mDisabled);
1350 int msg = (mInputMethodsPanel.getVisibility() == View.GONE) ?
1351 MSG_OPEN_INPUT_METHODS_PANEL : MSG_CLOSE_INPUT_METHODS_PANEL;
1352 mHandler.removeMessages(msg);
1353 mHandler.sendEmptyMessage(msg);
1354 }
1355
Daniel Sandler3b0543a2011-06-14 11:30:28 -04001356 public void onClickCompatModeButton() {
1357 int msg = (mCompatModePanel.getVisibility() == View.GONE) ?
1358 MSG_OPEN_COMPAT_MODE_PANEL : MSG_CLOSE_COMPAT_MODE_PANEL;
1359 mHandler.removeMessages(msg);
1360 mHandler.sendEmptyMessage(msg);
1361 }
1362
Daniel Sandlerc51451a2010-12-16 19:06:46 -05001363 public NotificationClicker makeClicker(PendingIntent intent, String pkg, String tag, int id) {
1364 return new NotificationClicker(intent, pkg, tag, id);
1365 }
1366
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001367 private class NotificationClicker implements View.OnClickListener {
1368 private PendingIntent mIntent;
1369 private String mPkg;
1370 private String mTag;
1371 private int mId;
1372
1373 NotificationClicker(PendingIntent intent, String pkg, String tag, int id) {
1374 mIntent = intent;
1375 mPkg = pkg;
1376 mTag = tag;
1377 mId = id;
1378 }
1379
1380 public void onClick(View v) {
1381 try {
1382 // The intent we are sending is for the application, which
1383 // won't have permission to immediately start an activity after
1384 // the user switches to home. We know it is safe to do at this
1385 // point, so make sure new activity switches are now allowed.
1386 ActivityManagerNative.getDefault().resumeAppSwitches();
Dianne Hackborn90c52de2011-09-23 12:57:44 -07001387 // Also, notifications can be launched from the lock screen,
1388 // so dismiss the lock screen when the activity starts.
1389 ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001390 } catch (RemoteException e) {
1391 }
1392
1393 if (mIntent != null) {
1394 int[] pos = new int[2];
1395 v.getLocationOnScreen(pos);
1396 Intent overlay = new Intent();
1397 overlay.setSourceBounds(
1398 new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
1399 try {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001400 mIntent.send(mContext, 0, overlay);
Daniel Sandler92d33182011-09-11 16:29:05 -04001401
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001402 } catch (PendingIntent.CanceledException e) {
1403 // the stack trace isn't very helpful here. Just log the exception message.
1404 Slog.w(TAG, "Sending contentIntent failed: " + e);
1405 }
Daniel Sandler92d33182011-09-11 16:29:05 -04001406
1407 KeyguardManager kgm =
1408 (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
1409 if (kgm != null) kgm.exitKeyguardSecurely(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001410 }
1411
1412 try {
1413 mBarService.onNotificationClick(mPkg, mTag, mId);
1414 } catch (RemoteException ex) {
1415 // system process is dead if we're here.
1416 }
1417
1418 // close the shade if it was open
1419 animateCollapse();
Mike Lockwood066c8912011-08-24 10:17:18 -04001420 visibilityChanged(false);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001421
1422 // If this click was on the intruder alert, hide that instead
1423// mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
1424 }
1425 }
1426
1427 StatusBarNotification removeNotificationViews(IBinder key) {
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001428 NotificationData.Entry entry = mNotificationData.remove(key);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001429 if (entry == null) {
1430 Slog.w(TAG, "removeNotification for unknown key: " + key);
1431 return null;
1432 }
1433 // Remove the expanded view.
1434 ViewGroup rowParent = (ViewGroup)entry.row.getParent();
1435 if (rowParent != null) rowParent.removeView(entry.row);
Daniel Sandlera8e5b062010-12-01 13:53:08 -05001436
Daniel Sandler298a2a82011-08-11 16:13:22 -04001437 if (NOTIFICATION_PEEK_ENABLED && key == mNotificationPeekKey) {
Daniel Sandlera8e5b062010-12-01 13:53:08 -05001438 // must close the peek as well, since it's gone
1439 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
1440 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001441 // Remove the icon.
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001442// ViewGroup iconParent = (ViewGroup)entry.icon.getParent();
1443// if (iconParent != null) iconParent.removeView(entry.icon);
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001444 updateNotificationIcons();
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001445
1446 return entry.notification;
1447 }
1448
Daniel Sandler56a6d882011-02-23 16:40:33 -05001449 private class NotificationTriggerTouchListener implements View.OnTouchListener {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001450 VelocityTracker mVT;
Daniel Sandler56a6d882011-02-23 16:40:33 -05001451 float mInitialTouchX, mInitialTouchY;
1452 int mTouchSlop;
1453
1454 public NotificationTriggerTouchListener() {
1455 mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
1456 }
1457
Daniel Sandler298a2a82011-08-11 16:13:22 -04001458 private Runnable mHiliteOnR = new Runnable() { public void run() {
1459 mNotificationArea.setBackgroundResource(
1460 com.android.internal.R.drawable.list_selector_pressed_holo_dark);
1461 }};
1462 public void hilite(final boolean on) {
1463 if (on) {
1464 mNotificationArea.postDelayed(mHiliteOnR, 100);
1465 } else {
1466 mNotificationArea.removeCallbacks(mHiliteOnR);
1467 mNotificationArea.setBackgroundDrawable(null);
1468 }
1469 }
1470
Daniel Sandler56a6d882011-02-23 16:40:33 -05001471 public boolean onTouch(View v, MotionEvent event) {
1472// Slog.d(TAG, String.format("touch: (%.1f, %.1f) initial: (%.1f, %.1f)",
1473// event.getX(),
1474// event.getY(),
1475// mInitialTouchX,
1476// mInitialTouchY));
Daniel Sandler130453c2011-08-18 09:41:01 -04001477
1478 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
1479 return true;
1480 }
1481
Daniel Sandler56a6d882011-02-23 16:40:33 -05001482 final int action = event.getAction();
1483 switch (action) {
1484 case MotionEvent.ACTION_DOWN:
1485 mVT = VelocityTracker.obtain();
1486 mInitialTouchX = event.getX();
1487 mInitialTouchY = event.getY();
Daniel Sandler298a2a82011-08-11 16:13:22 -04001488 hilite(true);
Daniel Sandler56a6d882011-02-23 16:40:33 -05001489 // fall through
1490 case MotionEvent.ACTION_OUTSIDE:
1491 case MotionEvent.ACTION_MOVE:
1492 // check for fling
1493 if (mVT != null) {
1494 mVT.addMovement(event);
1495 mVT.computeCurrentVelocity(1000); // pixels per second
1496 // require a little more oomph once we're already in peekaboo mode
1497 if (mVT.getYVelocity() < -mNotificationFlingVelocity) {
1498 animateExpand();
Mike Lockwood066c8912011-08-24 10:17:18 -04001499 visibilityChanged(true);
Daniel Sandler298a2a82011-08-11 16:13:22 -04001500 hilite(false);
Daniel Sandler56a6d882011-02-23 16:40:33 -05001501 mVT.recycle();
1502 mVT = null;
1503 }
1504 }
1505 return true;
1506 case MotionEvent.ACTION_UP:
1507 case MotionEvent.ACTION_CANCEL:
Daniel Sandler298a2a82011-08-11 16:13:22 -04001508 hilite(false);
Daniel Sandler56a6d882011-02-23 16:40:33 -05001509 if (mVT != null) {
1510 if (action == MotionEvent.ACTION_UP
1511 // was this a sloppy tap?
Jim Miller9f0f0e02011-05-17 20:06:29 -07001512 && Math.abs(event.getX() - mInitialTouchX) < mTouchSlop
Daniel Sandler56a6d882011-02-23 16:40:33 -05001513 && Math.abs(event.getY() - mInitialTouchY) < (mTouchSlop / 3)
1514 // dragging off the bottom doesn't count
1515 && (int)event.getY() < v.getBottom()) {
1516 animateExpand();
Mike Lockwood066c8912011-08-24 10:17:18 -04001517 visibilityChanged(true);
Daniel Sandleraa051d62011-03-01 16:23:57 -05001518 v.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
1519 v.playSoundEffect(SoundEffectConstants.CLICK);
Daniel Sandler56a6d882011-02-23 16:40:33 -05001520 }
1521
1522 mVT.recycle();
1523 mVT = null;
1524 return true;
1525 }
1526 }
1527 return false;
1528 }
1529 }
1530
Daniel Sandler663f0f22011-03-04 16:45:02 -05001531 public void resetNotificationPeekFadeTimer() {
1532 if (DEBUG) {
1533 Slog.d(TAG, "setting peek fade timer for " + NOTIFICATION_PEEK_FADE_DELAY
1534 + "ms from now");
1535 }
1536 mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PEEK);
1537 mHandler.sendEmptyMessageDelayed(MSG_CLOSE_NOTIFICATION_PEEK,
1538 NOTIFICATION_PEEK_FADE_DELAY);
1539 }
1540
1541 private class NotificationIconTouchListener implements View.OnTouchListener {
Daniel Sandler56a6d882011-02-23 16:40:33 -05001542 VelocityTracker mVT;
1543 int mPeekIndex;
1544 float mInitialTouchX, mInitialTouchY;
1545 int mTouchSlop;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001546
1547 public NotificationIconTouchListener() {
Daniel Sandler56a6d882011-02-23 16:40:33 -05001548 mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001549 }
1550
1551 public boolean onTouch(View v, MotionEvent event) {
1552 boolean peeking = mNotificationPeekWindow.getVisibility() != View.GONE;
Joe Onorato7c270fa2010-12-08 17:31:42 -08001553 boolean panelShowing = mNotificationPanel.isShowing();
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001554 if (panelShowing) return false;
1555
Daniel Sandler56a6d882011-02-23 16:40:33 -05001556 int numIcons = mIconLayout.getChildCount();
1557 int newPeekIndex = (int)(event.getX() * numIcons / mIconLayout.getWidth());
1558 if (newPeekIndex > numIcons - 1) newPeekIndex = numIcons - 1;
1559 else if (newPeekIndex < 0) newPeekIndex = 0;
1560
1561 final int action = event.getAction();
1562 switch (action) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001563 case MotionEvent.ACTION_DOWN:
1564 mVT = VelocityTracker.obtain();
Daniel Sandler56a6d882011-02-23 16:40:33 -05001565 mInitialTouchX = event.getX();
1566 mInitialTouchY = event.getY();
1567 mPeekIndex = -1;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001568
1569 // fall through
1570 case MotionEvent.ACTION_OUTSIDE:
1571 case MotionEvent.ACTION_MOVE:
1572 // peek and switch icons if necessary
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001573
Daniel Sandler56a6d882011-02-23 16:40:33 -05001574 if (newPeekIndex != mPeekIndex) {
1575 mPeekIndex = newPeekIndex;
1576
1577 if (DEBUG) Slog.d(TAG, "will peek at notification #" + mPeekIndex);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001578 Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
Daniel Sandler56a6d882011-02-23 16:40:33 -05001579 peekMsg.arg1 = mPeekIndex;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001580
1581 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
1582
Daniel Sandler56a6d882011-02-23 16:40:33 -05001583 if (peeking) {
1584 // no delay if we're scrubbing left-right
1585 mHandler.sendMessage(peekMsg);
1586 } else {
1587 // wait for fling
1588 mHandler.sendMessageDelayed(peekMsg, NOTIFICATION_PEEK_HOLD_THRESH);
1589 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001590 }
1591
1592 // check for fling
1593 if (mVT != null) {
1594 mVT.addMovement(event);
Daniel Sandler56a6d882011-02-23 16:40:33 -05001595 mVT.computeCurrentVelocity(1000); // pixels per second
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001596 // require a little more oomph once we're already in peekaboo mode
1597 if (!panelShowing && (
1598 (peeking && mVT.getYVelocity() < -mNotificationFlingVelocity*3)
1599 || (mVT.getYVelocity() < -mNotificationFlingVelocity))) {
1600 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
1601 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
1602 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
1603 mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
1604 }
1605 }
1606 return true;
1607 case MotionEvent.ACTION_UP:
1608 case MotionEvent.ACTION_CANCEL:
1609 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
Daniel Sandleraa051d62011-03-01 16:23:57 -05001610 if (!peeking) {
1611 if (action == MotionEvent.ACTION_UP
1612 // was this a sloppy tap?
Jim Miller9f0f0e02011-05-17 20:06:29 -07001613 && Math.abs(event.getX() - mInitialTouchX) < mTouchSlop
Daniel Sandleraa051d62011-03-01 16:23:57 -05001614 && Math.abs(event.getY() - mInitialTouchY) < (mTouchSlop / 3)
1615 // dragging off the bottom doesn't count
1616 && (int)event.getY() < v.getBottom()) {
1617 Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
1618 peekMsg.arg1 = mPeekIndex;
1619 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
1620 mHandler.sendMessage(peekMsg);
1621
1622 v.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
1623 v.playSoundEffect(SoundEffectConstants.CLICK);
1624
1625 peeking = true; // not technically true yet, but the next line will run
1626 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001627 }
Daniel Sandler56a6d882011-02-23 16:40:33 -05001628
1629 if (peeking) {
Daniel Sandler663f0f22011-03-04 16:45:02 -05001630 resetNotificationPeekFadeTimer();
Daniel Sandler56a6d882011-02-23 16:40:33 -05001631 }
1632
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001633 mVT.recycle();
1634 mVT = null;
1635 return true;
1636 }
1637 return false;
1638 }
1639 }
1640
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001641 StatusBarIconView addNotificationViews(IBinder key, StatusBarNotification notification) {
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001642 if (DEBUG) {
1643 Slog.d(TAG, "addNotificationViews(key=" + key + ", notification=" + notification);
1644 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001645 // Construct the icon.
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001646 final StatusBarIconView iconView = new StatusBarIconView(mContext,
Svetoslav Ganov6179ea32011-06-28 01:12:41 -07001647 notification.pkg + "/0x" + Integer.toHexString(notification.id),
1648 notification.notification);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001649 iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
1650
1651 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
1652 notification.notification.icon,
1653 notification.notification.iconLevel,
Svetoslav Ganov6179ea32011-06-28 01:12:41 -07001654 notification.notification.number,
1655 notification.notification.tickerText);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001656 if (!iconView.set(ic)) {
1657 handleNotificationError(key, notification, "Couldn't attach StatusBarIcon: " + ic);
1658 return null;
1659 }
1660 // Construct the expanded view.
1661 NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001662 if (!inflateViews(entry, mPile)) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001663 handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
1664 + notification);
1665 return null;
1666 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001667
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001668 // Add the icon.
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001669 int pos = mNotificationData.add(entry);
Daniel Sandlera31e4192011-02-02 22:00:28 -05001670 if (DEBUG) {
1671 Slog.d(TAG, "addNotificationViews: added at " + pos);
1672 }
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001673 updateNotificationIcons();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001674
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001675 return iconView;
1676 }
1677
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001678 private void reloadAllNotificationIcons() {
1679 if (mIconLayout == null) return;
1680 mIconLayout.removeAllViews();
1681 updateNotificationIcons();
1682 }
1683
1684 private void updateNotificationIcons() {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001685 // XXX: need to implement a new limited linear layout class
1686 // to avoid removing & readding everything
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001687
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001688 if (mIconLayout == null) return;
1689
Daniel Sandler282ff9a2011-02-23 10:36:49 -05001690 // first, populate the main notification panel
1691 loadNotificationPanel();
1692
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001693 final LinearLayout.LayoutParams params
Joe Onoratodc100302011-01-11 17:07:41 -08001694 = new LinearLayout.LayoutParams(mIconSize + 2*mIconHPadding, mNaturalBarHeight);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001695
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001696 // alternate behavior in DND mode
Daniel Sandler282ff9a2011-02-23 10:36:49 -05001697 if (mNotificationDNDMode) {
1698 if (mIconLayout.getChildCount() == 0) {
Daniel Sandler282ff9a2011-02-23 10:36:49 -05001699 final Notification dndNotification = new Notification.Builder(mContext)
1700 .setContentTitle(mContext.getText(R.string.notifications_off_title))
1701 .setContentText(mContext.getText(R.string.notifications_off_text))
1702 .setSmallIcon(R.drawable.ic_notification_dnd)
1703 .setOngoing(true)
1704 .getNotification();
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001705
Svetoslav Ganov6179ea32011-06-28 01:12:41 -07001706 final StatusBarIconView iconView = new StatusBarIconView(mContext, "_dnd",
1707 dndNotification);
1708 iconView.setImageResource(R.drawable.ic_notification_dnd);
1709 iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
1710 iconView.setPadding(mIconHPadding, 0, mIconHPadding, 0);
1711
Daniel Sandler282ff9a2011-02-23 10:36:49 -05001712 mNotificationDNDDummyEntry = new NotificationData.Entry(
1713 null,
1714 new StatusBarNotification("", 0, "", 0, 0, dndNotification),
1715 iconView);
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001716
Daniel Sandler282ff9a2011-02-23 10:36:49 -05001717 mIconLayout.addView(iconView, params);
1718 }
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001719
1720 return;
Daniel Sandler8e41f312011-08-03 14:05:07 -04001721 } else if (0 != (mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) {
1722 // if icons are disabled but we're not in DND mode, this is probably Setup and we should
1723 // just leave the area totally empty
1724 return;
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001725 }
1726
1727 int N = mNotificationData.size();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001728
1729 if (DEBUG) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001730 Slog.d(TAG, "refreshing icons: " + N + " notifications, mIconLayout=" + mIconLayout);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001731 }
1732
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001733 ArrayList<View> toShow = new ArrayList<View>();
1734
Daniel Sandler3b0543a2011-06-14 11:30:28 -04001735 // Extra Special Icons
1736 // The IME switcher and compatibility mode icons take the place of notifications. You didn't
1737 // need to see all those new emails, did you?
1738 int maxNotificationIconsCount = mMaxNotificationIcons;
1739 if (mInputMethodSwitchButton.getVisibility() != View.GONE) maxNotificationIconsCount --;
1740 if (mCompatModeButton.getVisibility() != View.GONE) maxNotificationIconsCount --;
1741
satok82beadf2010-12-27 19:03:06 +09001742 for (int i=0; i< maxNotificationIconsCount; i++) {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001743 if (i>=N) break;
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001744 toShow.add(mNotificationData.get(N-i-1).icon);
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001745 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001746
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001747 ArrayList<View> toRemove = new ArrayList<View>();
1748 for (int i=0; i<mIconLayout.getChildCount(); i++) {
1749 View child = mIconLayout.getChildAt(i);
1750 if (!toShow.contains(child)) {
1751 toRemove.add(child);
1752 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001753 }
Daniel Sandler271ea122010-10-22 14:06:10 -04001754
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001755 for (View remove : toRemove) {
1756 mIconLayout.removeView(remove);
1757 }
1758
1759 for (int i=0; i<toShow.size(); i++) {
1760 View v = toShow.get(i);
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001761 v.setPadding(mIconHPadding, 0, mIconHPadding, 0);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001762 if (v.getParent() == null) {
Daniel Sandler0ad460b2010-12-14 12:14:53 -05001763 mIconLayout.addView(v, i, params);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001764 }
1765 }
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001766 }
1767
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001768 private void loadNotificationPanel() {
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001769 int N = mNotificationData.size();
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001770
1771 ArrayList<View> toShow = new ArrayList<View>();
1772
1773 for (int i=0; i<N; i++) {
Daniel Sandlerce6ff642011-02-18 12:51:08 -05001774 View row = mNotificationData.get(N-i-1).row;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001775 toShow.add(row);
1776 }
1777
1778 ArrayList<View> toRemove = new ArrayList<View>();
1779 for (int i=0; i<mPile.getChildCount(); i++) {
1780 View child = mPile.getChildAt(i);
1781 if (!toShow.contains(child)) {
1782 toRemove.add(child);
1783 }
1784 }
1785
1786 for (View remove : toRemove) {
1787 mPile.removeView(remove);
1788 }
1789
1790 for (int i=0; i<toShow.size(); i++) {
1791 View v = toShow.get(i);
1792 if (v.getParent() == null) {
Daniel Sandlera31e4192011-02-02 22:00:28 -05001793 mPile.addView(v, N-1-i); // the notification panel has newest at the bottom
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001794 }
1795 }
Daniel Sandler40c15452011-01-22 01:26:22 -05001796
1797 mNotificationPanel.setNotificationCount(N);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001798 }
1799
Joe Onorato4daaeaf2010-11-17 20:43:12 -08001800 void workAroundBadLayerDrawableOpacity(View v) {
Adam Powell29ea5252011-11-15 18:59:36 -08001801 Drawable bgd = v.getBackground();
1802 if (!(bgd instanceof LayerDrawable)) return;
1803
1804 LayerDrawable d = (LayerDrawable) bgd;
Joe Onorato4daaeaf2010-11-17 20:43:12 -08001805 v.setBackgroundDrawable(null);
1806 d.setOpacity(PixelFormat.TRANSLUCENT);
1807 v.setBackgroundDrawable(d);
1808 }
1809
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001810 private boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) {
1811 StatusBarNotification sbn = entry.notification;
1812 RemoteViews remoteViews = sbn.notification.contentView;
1813 if (remoteViews == null) {
1814 return false;
1815 }
1816
1817 // create the row view
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001818 LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(
1819 Context.LAYOUT_INFLATER_SERVICE);
Joe Onorato755cc742010-11-27 15:45:35 -08001820 View row = inflater.inflate(R.layout.status_bar_notification_row, parent, false);
Joe Onorato4daaeaf2010-11-17 20:43:12 -08001821 workAroundBadLayerDrawableOpacity(row);
Winson Chungc57ccf02011-10-13 15:04:59 -07001822 View vetoButton = updateNotificationVetoButton(row, entry.notification);
Svetoslav Ganov6179ea32011-06-28 01:12:41 -07001823 vetoButton.setContentDescription(mContext.getString(
1824 R.string.accessibility_remove_notification));
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001825
Joe Onorato561d3852010-11-20 18:09:34 -08001826 // the large icon
1827 ImageView largeIcon = (ImageView)row.findViewById(R.id.large_icon);
1828 if (sbn.notification.largeIcon != null) {
1829 largeIcon.setImageBitmap(sbn.notification.largeIcon);
Svetoslav Ganov6179ea32011-06-28 01:12:41 -07001830 largeIcon.setContentDescription(sbn.notification.tickerText);
Joe Onorato561d3852010-11-20 18:09:34 -08001831 } else {
1832 largeIcon.getLayoutParams().width = 0;
1833 largeIcon.setVisibility(View.INVISIBLE);
1834 }
Svetoslav Ganov6179ea32011-06-28 01:12:41 -07001835 largeIcon.setContentDescription(sbn.notification.tickerText);
Joe Onorato561d3852010-11-20 18:09:34 -08001836
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001837 // bind the click event to the content area
1838 ViewGroup content = (ViewGroup)row.findViewById(R.id.content);
1839 // XXX: update to allow controls within notification views
1840 content.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
1841// content.setOnFocusChangeListener(mFocusChangeListener);
1842 PendingIntent contentIntent = sbn.notification.contentIntent;
1843 if (contentIntent != null) {
Jeff Sharkey847fd752011-09-02 17:48:55 -07001844 final View.OnClickListener listener = new NotificationClicker(
1845 contentIntent, sbn.pkg, sbn.tag, sbn.id);
1846 largeIcon.setOnClickListener(listener);
1847 content.setOnClickListener(listener);
Joe Onorato184498c2010-10-08 17:57:18 -04001848 } else {
Jeff Sharkey847fd752011-09-02 17:48:55 -07001849 largeIcon.setOnClickListener(null);
Joe Onorato184498c2010-10-08 17:57:18 -04001850 content.setOnClickListener(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001851 }
1852
1853 View expanded = null;
1854 Exception exception = null;
1855 try {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001856 expanded = remoteViews.apply(mContext, content);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001857 }
1858 catch (RuntimeException e) {
1859 exception = e;
1860 }
1861 if (expanded == null) {
Joe Onorato46439ce2010-11-19 13:56:21 -08001862 final String ident = sbn.pkg + "/0x" + Integer.toHexString(sbn.id);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001863 Slog.e(TAG, "couldn't inflate view for notification " + ident, exception);
1864 return false;
1865 } else {
1866 content.addView(expanded);
1867 row.setDrawingCacheEnabled(true);
1868 }
1869
Adam Powell29ea5252011-11-15 18:59:36 -08001870 applyLegacyRowBackground(sbn, content);
1871
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001872 entry.row = row;
1873 entry.content = content;
1874 entry.expanded = expanded;
Joe Onorato80a44402011-01-15 16:22:24 -08001875 entry.largeIcon = largeIcon;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001876
1877 return true;
1878 }
Daniel Sandlerce70d912010-09-02 11:59:41 -04001879
Adam Powell29ea5252011-11-15 18:59:36 -08001880 void applyLegacyRowBackground(StatusBarNotification sbn, View content) {
1881 if (sbn.notification.contentView.getLayoutId() !=
1882 com.android.internal.R.layout.status_bar_latest_event_content) {
1883 int version = 0;
1884 try {
1885 ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(sbn.pkg, 0);
1886 version = info.targetSdkVersion;
1887 } catch (NameNotFoundException ex) {
1888 Slog.e(TAG, "Failed looking up ApplicationInfo for " + sbn.pkg, ex);
1889 }
Adam Powellad9deec2011-12-05 15:38:51 -08001890 if (version > 0 && version < Build.VERSION_CODES.GINGERBREAD) {
Adam Powell29ea5252011-11-15 18:59:36 -08001891 content.setBackgroundResource(R.drawable.notification_row_legacy_bg);
1892 } else {
1893 content.setBackgroundResource(R.drawable.notification_row_bg);
1894 }
1895 }
1896 }
1897
Daniel Sandler06a0d4b2011-08-05 00:19:21 -04001898 public void clearAll() {
1899 try {
1900 mBarService.onClearAllNotifications();
1901 } catch (RemoteException ex) {
1902 // system process is dead if we're here.
1903 }
1904 animateCollapse();
Mike Lockwood066c8912011-08-24 10:17:18 -04001905 visibilityChanged(false);
Daniel Sandler06a0d4b2011-08-05 00:19:21 -04001906 }
1907
Michael Jurka3b1fc472011-06-13 10:54:40 -07001908 public void toggleRecentApps() {
Michael Jurka412cba82011-10-17 09:05:00 -07001909 int msg = (mRecentsPanel.getVisibility() == View.VISIBLE)
1910 ? MSG_CLOSE_RECENTS_PANEL : MSG_OPEN_RECENTS_PANEL;
Michael Jurka3b1fc472011-06-13 10:54:40 -07001911 mHandler.removeMessages(msg);
1912 mHandler.sendEmptyMessage(msg);
1913 }
1914
Michael Jurkab7f43272011-10-27 15:06:38 -07001915 private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
1916 public void onReceive(Context context, Intent intent) {
1917 String action = intent.getAction();
1918 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
1919 || Intent.ACTION_SCREEN_OFF.equals(action)) {
1920 boolean excludeRecents = false;
1921 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
1922 String reason = intent.getStringExtra("reason");
1923 if (reason != null) {
1924 excludeRecents = reason.equals("recentapps");
1925 }
1926 }
1927 if (Intent.ACTION_SCREEN_OFF.equals(action)) {
1928 // If we're turning the screen off, we want to hide the
1929 // recents panel with no animation
1930 // TODO: hide other things, like the notification tray,
1931 // with no animation as well
1932 mRecentsPanel.show(false, false);
1933 excludeRecents = true;
1934 }
1935 animateCollapse(excludeRecents);
1936 }
1937 }
1938 };
1939
Joe Onoratob62ac122010-09-20 16:16:32 -04001940 public class TouchOutsideListener implements View.OnTouchListener {
1941 private int mMsg;
Joe Onoratoddf680b2010-09-26 13:59:40 -07001942 private StatusBarPanel mPanel;
Joe Onoratob62ac122010-09-20 16:16:32 -04001943
Joe Onoratoddf680b2010-09-26 13:59:40 -07001944 public TouchOutsideListener(int msg, StatusBarPanel panel) {
Joe Onoratob62ac122010-09-20 16:16:32 -04001945 mMsg = msg;
Joe Onoratoddf680b2010-09-26 13:59:40 -07001946 mPanel = panel;
Joe Onoratob62ac122010-09-20 16:16:32 -04001947 }
1948
1949 public boolean onTouch(View v, MotionEvent ev) {
Joe Onoratoddf680b2010-09-26 13:59:40 -07001950 final int action = ev.getAction();
1951 if (action == MotionEvent.ACTION_OUTSIDE
1952 || (action == MotionEvent.ACTION_DOWN
1953 && !mPanel.isInContentArea((int)ev.getX(), (int)ev.getY()))) {
Joe Onoratob62ac122010-09-20 16:16:32 -04001954 mHandler.removeMessages(mMsg);
1955 mHandler.sendEmptyMessage(mMsg);
1956 return true;
1957 }
1958 return false;
1959 }
1960 }
Joe Onorato091e1b82010-09-26 18:04:44 -07001961
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001962 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1963 pw.print("mDisabled=0x");
1964 pw.println(Integer.toHexString(mDisabled));
Joe Onorato933464d2011-01-05 15:53:36 -08001965 pw.println("mNetworkController:");
1966 mNetworkController.dump(fd, pw, args);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001967 }
Joe Onorato808182d2010-07-09 18:52:06 -04001968}
Daniel Sandlerd39e3882010-08-31 14:16:13 -04001969
1970