blob: d11aba67854c95d155782d8037bbea8a4dc5187c [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;
21
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040022import android.app.ActivityManagerNative;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040023import android.app.PendingIntent;
Joe Onoratoef1e7762010-09-17 18:38:38 -040024import android.app.Notification;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040025import android.app.StatusBarManager;
Joe Onorato808182d2010-07-09 18:52:06 -040026import android.content.Context;
27import android.content.Intent;
28import android.content.res.Resources;
Daniel Sandler9120d552010-07-23 09:11:14 -040029import android.graphics.PixelFormat;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040030import android.graphics.Rect;
Daniel Sandler9120d552010-07-23 09:11:14 -040031import android.os.Handler;
Joe Onorato808182d2010-07-09 18:52:06 -040032import android.os.IBinder;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040033import android.os.Message;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040034import android.os.RemoteException;
Joe Onoratoef1e7762010-09-17 18:38:38 -040035import android.text.TextUtils;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040036import android.util.Slog;
Joe Onorato55d2d762010-09-26 13:02:01 -070037import android.view.animation.Animation;
Daniel Sandlerce70d912010-09-02 11:59:41 -040038import android.view.animation.AnimationUtils;
Joe Onorato808182d2010-07-09 18:52:06 -040039import android.view.Gravity;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040040import android.view.LayoutInflater;
Joe Onoratob62ac122010-09-20 16:16:32 -040041import android.view.MotionEvent;
Joe Onorato808182d2010-07-09 18:52:06 -040042import android.view.View;
Daniel Sandler9120d552010-07-23 09:11:14 -040043import android.view.ViewGroup;
44import android.view.WindowManager;
45import android.view.WindowManagerImpl;
Joe Onoratoef1e7762010-09-17 18:38:38 -040046import android.widget.FrameLayout;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040047import android.widget.ImageView;
Joe Onorato808182d2010-07-09 18:52:06 -040048import android.widget.LinearLayout;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040049import android.widget.RemoteViews;
50import android.widget.ScrollView;
51import android.widget.TextSwitcher;
Daniel Sandler9120d552010-07-23 09:11:14 -040052import android.widget.TextView;
Joe Onorato808182d2010-07-09 18:52:06 -040053
54import com.android.internal.statusbar.StatusBarIcon;
Joe Onorato808182d2010-07-09 18:52:06 -040055import com.android.internal.statusbar.StatusBarNotification;
56
57import com.android.systemui.statusbar.*;
Joe Onorato013cfc12010-09-08 15:23:18 -040058import com.android.systemui.recent.RecentApplicationsActivity;
Joe Onorato808182d2010-07-09 18:52:06 -040059import com.android.systemui.R;
60
61public class TabletStatusBarService extends StatusBarService {
Daniel Sandlerfb970e92010-08-20 10:57:17 -040062 public static final boolean DEBUG = false;
Joe Onoratob62ac122010-09-20 16:16:32 -040063 public static final String TAG = "TabletStatusBarService";
Joe Onorato808182d2010-07-09 18:52:06 -040064
Joe Onoratob62ac122010-09-20 16:16:32 -040065 public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
66 public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
67 public static final int MSG_OPEN_SYSTEM_PANEL = 1010;
68 public static final int MSG_CLOSE_SYSTEM_PANEL = 1011;
69
Daniel Sandlerd39e3882010-08-31 14:16:13 -040070 private static final int MAX_IMAGE_LEVEL = 10000;
71
Joe Onorato808182d2010-07-09 18:52:06 -040072 int mIconSize;
Daniel Sandler9120d552010-07-23 09:11:14 -040073
74 H mHandler = new H();
75
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040076 // tracking all current notifications
77 private NotificationData mNotns = new NotificationData();
78
Joe Onoratob62ac122010-09-20 16:16:32 -040079 TabletStatusBarView mStatusBarView;
Daniel Sandler271ea122010-10-22 14:06:10 -040080 ImageView mNotificationTrigger;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040081 NotificationIconArea mNotificationIconArea;
Joe Onorato55d2d762010-09-26 13:02:01 -070082 View mNotificationButtons;
Joe Onoratob62ac122010-09-20 16:16:32 -040083 View mSystemInfo;
Joe Onorato091e1b82010-09-26 18:04:44 -070084 View mNavigationArea;
Daniel Sandlere02d8082010-10-08 15:13:22 -040085 View mMenuButton;
Joe Onoratof3c3c4f2010-10-21 11:09:02 -040086 View mRecentButton;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040087
Joe Onoratoddf680b2010-09-26 13:59:40 -070088 NotificationPanel mNotificationPanel;
Daniel Sandler6425ef92010-08-11 16:10:19 -040089 SystemPanel mSystemPanel;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040090
Daniel Sandler0f0b11c2010-08-04 15:54:58 -040091 ViewGroup mPile;
92 TextView mClearButton;
Joe Onorato55d2d762010-09-26 13:02:01 -070093 TextView mDoNotDisturbButton;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040094
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -040095 ImageView mBatteryMeter;
96 ImageView mSignalMeter;
Daniel Sandlerd39e3882010-08-31 14:16:13 -040097 ImageView mSignalIcon;
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -040098
Daniel Sandlerce70d912010-09-02 11:59:41 -040099 View mBarContents;
100 View mCurtains;
101
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400102 NotificationIconArea.IconLayout mIconLayout;
103
Joe Onoratoef1e7762010-09-17 18:38:38 -0400104 TabletTicker mTicker;
105 View mTickerView;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400106 boolean mTicking;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400107
108 // for disabling the status bar
109 int mDisabled = 0;
110
Joe Onorato55d2d762010-09-26 13:02:01 -0700111 boolean mNotificationsOn = true;
112
Daniel Sandler9120d552010-07-23 09:11:14 -0400113 protected void addPanelWindows() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400114 final Context context = mContext;
115
116 final Resources res = context.getResources();
Daniel Sandler9120d552010-07-23 09:11:14 -0400117 final int barHeight= res.getDimensionPixelSize(
118 com.android.internal.R.dimen.status_bar_height);
119
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400120 mNotificationPanel = (NotificationPanel)View.inflate(context,
Joe Onoratoddf680b2010-09-26 13:59:40 -0700121 R.layout.sysbar_panel_notifications, null);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400122 mNotificationPanel.setVisibility(View.GONE);
Joe Onoratob62ac122010-09-20 16:16:32 -0400123 mNotificationPanel.setOnTouchListener(
Joe Onoratoddf680b2010-09-26 13:59:40 -0700124 new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PANEL, mNotificationPanel));
Joe Onoratob62ac122010-09-20 16:16:32 -0400125
Joe Onorato55d2d762010-09-26 13:02:01 -0700126 mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400127
Daniel Sandler9120d552010-07-23 09:11:14 -0400128 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400129 400, // ViewGroup.LayoutParams.WRAP_CONTENT,
Daniel Sandler9120d552010-07-23 09:11:14 -0400130 ViewGroup.LayoutParams.WRAP_CONTENT,
131 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
132 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
Daniel Sandler9120d552010-07-23 09:11:14 -0400133 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
134 PixelFormat.TRANSLUCENT);
Joe Onoratoea70e632010-09-27 17:59:37 -0700135 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
Daniel Sandler9120d552010-07-23 09:11:14 -0400136 lp.setTitle("NotificationPanel");
137 lp.windowAnimations = com.android.internal.R.style.Animation_SlidingCard;
138
139 WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
140
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400141 mSystemPanel = (SystemPanel) View.inflate(context, R.layout.sysbar_panel_system, null);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400142 mSystemPanel.setVisibility(View.GONE);
Joe Onoratoddf680b2010-09-26 13:59:40 -0700143 mSystemPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_SYSTEM_PANEL,
144 mSystemPanel));
Joe Onoratob62ac122010-09-20 16:16:32 -0400145
146 mStatusBarView.setIgnoreChildren(1, mSystemInfo, mSystemPanel);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400147
Daniel Sandler9120d552010-07-23 09:11:14 -0400148 lp = new WindowManager.LayoutParams(
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400149 800,
Daniel Sandler6425ef92010-08-11 16:10:19 -0400150 ViewGroup.LayoutParams.WRAP_CONTENT,
Daniel Sandler9120d552010-07-23 09:11:14 -0400151 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
152 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
Daniel Sandler9120d552010-07-23 09:11:14 -0400153 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
154 PixelFormat.TRANSLUCENT);
155 lp.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
156 lp.setTitle("SystemPanel");
157 lp.windowAnimations = com.android.internal.R.style.Animation_SlidingCard;
158
159 WindowManagerImpl.getDefault().addView(mSystemPanel, lp);
Daniel Sandler6425ef92010-08-11 16:10:19 -0400160 mSystemPanel.setBar(this);
Daniel Sandler9120d552010-07-23 09:11:14 -0400161 }
Joe Onorato808182d2010-07-09 18:52:06 -0400162
163 @Override
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400164 public void start() {
165 super.start(); // will add the main bar view
Joe Onorato808182d2010-07-09 18:52:06 -0400166 }
167
168 protected View makeStatusBarView() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400169 final Context context = mContext;
170 final Resources res = context.getResources();
Joe Onorato808182d2010-07-09 18:52:06 -0400171
172 mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
173
Joe Onoratob62ac122010-09-20 16:16:32 -0400174 final TabletStatusBarView sb = (TabletStatusBarView)View.inflate(
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400175 context, R.layout.status_bar, null);
Joe Onorato808182d2010-07-09 18:52:06 -0400176 mStatusBarView = sb;
177
Joe Onoratob62ac122010-09-20 16:16:32 -0400178 sb.setHandler(mHandler);
179
Daniel Sandlerce70d912010-09-02 11:59:41 -0400180 mBarContents = sb.findViewById(R.id.bar_contents);
181 mCurtains = sb.findViewById(R.id.lights_out);
Joe Onoratob62ac122010-09-20 16:16:32 -0400182 mSystemInfo = sb.findViewById(R.id.systemInfo);
Joe Onoratof63b0f42010-09-12 17:03:19 -0400183
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400184 mSystemInfo.setOnClickListener(mOnClickListener);
Joe Onoratob62ac122010-09-20 16:16:32 -0400185 mSystemInfo.setOnLongClickListener(new SetLightsOnListener(false));
Joe Onoratof63b0f42010-09-12 17:03:19 -0400186
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400187 mRecentButton = sb.findViewById(R.id.recent);
188 mRecentButton.setOnClickListener(mOnClickListener);
189
Joe Onoratof63b0f42010-09-12 17:03:19 -0400190 SetLightsOnListener on = new SetLightsOnListener(true);
191 mCurtains.setOnClickListener(on);
192 mCurtains.setOnLongClickListener(on);
Daniel Sandlerce70d912010-09-02 11:59:41 -0400193
Joe Onorato55d2d762010-09-26 13:02:01 -0700194 // the button to open the notification area
Daniel Sandler271ea122010-10-22 14:06:10 -0400195 mNotificationTrigger = (ImageView) sb.findViewById(R.id.notificationTrigger);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400196 mNotificationTrigger.setOnClickListener(mOnClickListener);
Joe Onorato55d2d762010-09-26 13:02:01 -0700197
Joe Onorato808182d2010-07-09 18:52:06 -0400198 // the more notifications icon
199 mNotificationIconArea = (NotificationIconArea)sb.findViewById(R.id.notificationIcons);
200
Joe Onorato55d2d762010-09-26 13:02:01 -0700201 // the clear and dnd buttons
202 mNotificationButtons = sb.findViewById(R.id.notificationButtons);
203 mClearButton = (TextView)mNotificationButtons.findViewById(R.id.clear_all_button);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400204 mClearButton.setOnClickListener(mOnClickListener);
Joe Onorato55d2d762010-09-26 13:02:01 -0700205 mDoNotDisturbButton = (TextView)mNotificationButtons.findViewById(R.id.do_not_disturb);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400206 mDoNotDisturbButton.setOnClickListener(mOnClickListener);
Joe Onorato55d2d762010-09-26 13:02:01 -0700207
208
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400209 // where the icons go
210 mIconLayout = (NotificationIconArea.IconLayout) sb.findViewById(R.id.icons);
211
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400212 mTicker = new TabletTicker(context, (FrameLayout)sb.findViewById(R.id.ticker));
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400213
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400214 // System info (center)
215 mBatteryMeter = (ImageView) sb.findViewById(R.id.battery);
216 mSignalMeter = (ImageView) sb.findViewById(R.id.signal);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400217 mSignalIcon = (ImageView) sb.findViewById(R.id.signal_icon);
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400218
Joe Onorato091e1b82010-09-26 18:04:44 -0700219 // The navigation buttons
220 mNavigationArea = sb.findViewById(R.id.navigationArea);
Daniel Sandlere02d8082010-10-08 15:13:22 -0400221 mMenuButton = mNavigationArea.findViewById(R.id.menu);
Joe Onorato091e1b82010-09-26 18:04:44 -0700222
Joe Onorato5dd11692010-09-27 15:34:04 -0700223 // set the initial view visibility
224 setAreThereNotifications();
Daniel Sandler271ea122010-10-22 14:06:10 -0400225 refreshNotificationTrigger();
Joe Onorato5dd11692010-09-27 15:34:04 -0700226
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400227 // Add the windows
228 addPanelWindows();
229
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400230 mPile = (ViewGroup)mNotificationPanel.findViewById(R.id.content);
231 mPile.removeAllViews();
232
233 ScrollView scroller = (ScrollView)mPile.getParent();
234 scroller.setFillViewport(true);
235
Joe Onorato808182d2010-07-09 18:52:06 -0400236 return sb;
237 }
238
239 protected int getStatusBarGravity() {
240 return Gravity.BOTTOM | Gravity.FILL_HORIZONTAL;
241 }
242
Daniel Sandler9120d552010-07-23 09:11:14 -0400243 private class H extends Handler {
Daniel Sandler9120d552010-07-23 09:11:14 -0400244 public void handleMessage(Message m) {
245 switch (m.what) {
246 case MSG_OPEN_NOTIFICATION_PANEL:
247 if (DEBUG) Slog.d(TAG, "opening notifications panel");
Joe Onorato091e1b82010-09-26 18:04:44 -0700248 if (mNotificationPanel.getVisibility() == View.GONE) {
249 mDoNotDisturbButton.setText(mNotificationsOn
250 ? R.string.status_bar_do_not_disturb_button
251 : R.string.status_bar_please_disturb_button);
252 mNotificationPanel.setVisibility(View.VISIBLE);
253 setViewVisibility(mNotificationIconArea, View.GONE,
254 R.anim.notification_icons_out);
255 setViewVisibility(mNotificationButtons, View.VISIBLE,
256 R.anim.notification_buttons_in);
Daniel Sandler271ea122010-10-22 14:06:10 -0400257 refreshNotificationTrigger();
Joe Onorato091e1b82010-09-26 18:04:44 -0700258 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400259 break;
260 case MSG_CLOSE_NOTIFICATION_PANEL:
261 if (DEBUG) Slog.d(TAG, "closing notifications panel");
Joe Onorato091e1b82010-09-26 18:04:44 -0700262 if (mNotificationPanel.getVisibility() == View.VISIBLE) {
263 mNotificationPanel.setVisibility(View.GONE);
264 setViewVisibility(mNotificationIconArea, View.VISIBLE,
265 R.anim.notification_icons_in);
266 setViewVisibility(mNotificationButtons, View.GONE,
267 R.anim.notification_buttons_out);
Daniel Sandler271ea122010-10-22 14:06:10 -0400268 refreshNotificationTrigger();
Joe Onorato091e1b82010-09-26 18:04:44 -0700269 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400270 break;
271 case MSG_OPEN_SYSTEM_PANEL:
272 if (DEBUG) Slog.d(TAG, "opening system panel");
273 mSystemPanel.setVisibility(View.VISIBLE);
274 break;
275 case MSG_CLOSE_SYSTEM_PANEL:
276 if (DEBUG) Slog.d(TAG, "closing system panel");
277 mSystemPanel.setVisibility(View.GONE);
278 break;
279 }
280 }
281 }
Daniel Sandler271ea122010-10-22 14:06:10 -0400282
283 public void refreshNotificationTrigger() {
Daniel Sandlercf3c7cf2010-10-22 15:30:12 -0400284 if (mNotificationTrigger == null) return;
285
Daniel Sandler271ea122010-10-22 14:06:10 -0400286 int resId;
287 boolean panel = (mNotificationPanel != null
288 && mNotificationPanel.getVisibility() == View.VISIBLE);
289 if (!mNotificationsOn) {
290 resId = R.drawable.ic_sysbar_noti_dnd;
291 } else if (mNotns.size() > 0) {
292 resId = panel ? R.drawable.ic_sysbar_noti_avail_open : R.drawable.ic_sysbar_noti_avail;
293 } else {
294 resId = panel ? R.drawable.ic_sysbar_noti_none_open : R.drawable.ic_sysbar_noti_none;
295 }
296 mNotificationTrigger.setImageResource(resId);
297 }
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400298
Daniel Sandlerd7db7b12010-08-13 16:26:39 -0400299 public void setBatteryMeter(int level, boolean plugged) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400300 if (DEBUG) Slog.d(TAG, "battery=" + level + (plugged ? " - plugged" : " - unplugged"));
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400301 mBatteryMeter.setImageResource(R.drawable.sysbar_batterymini);
302 // adjust percent to permyriad for ClipDrawable's sake
303 mBatteryMeter.setImageLevel(level * (MAX_IMAGE_LEVEL / 100));
Daniel Sandlerd7db7b12010-08-13 16:26:39 -0400304 }
305
Daniel Sandler764b4da2010-08-24 16:24:35 -0400306 public void setSignalMeter(int level, boolean isWifi) {
307 if (DEBUG) Slog.d(TAG, "signal=" + level);
308 if (level < 0) {
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400309 mSignalMeter.setImageDrawable(null);
Daniel Sandler764b4da2010-08-24 16:24:35 -0400310 mSignalMeter.setImageLevel(0);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400311 mSignalIcon.setImageDrawable(null);
Daniel Sandler764b4da2010-08-24 16:24:35 -0400312 } else {
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400313 mSignalMeter.setImageResource(R.drawable.sysbar_wifimini);
314 // adjust to permyriad
315 mSignalMeter.setImageLevel(level * (MAX_IMAGE_LEVEL / 100));
316 mSignalIcon.setImageResource(isWifi ? R.drawable.ic_sysbar_wifi_mini
317 : R.drawable.ic_sysbar_wifi_mini); // XXX
Daniel Sandler764b4da2010-08-24 16:24:35 -0400318 }
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400319 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400320
Joe Onorato808182d2010-07-09 18:52:06 -0400321 public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400322 if (DEBUG) Slog.d(TAG, "addIcon(" + slot + ") -> " + icon);
Joe Onorato808182d2010-07-09 18:52:06 -0400323 }
324
325 public void updateIcon(String slot, int index, int viewIndex,
326 StatusBarIcon old, StatusBarIcon icon) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400327 if (DEBUG) Slog.d(TAG, "updateIcon(" + slot + ") -> " + icon);
Joe Onorato808182d2010-07-09 18:52:06 -0400328 }
329
330 public void removeIcon(String slot, int index, int viewIndex) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400331 if (DEBUG) Slog.d(TAG, "removeIcon(" + slot + ")");
Joe Onorato808182d2010-07-09 18:52:06 -0400332 }
333
334 public void addNotification(IBinder key, StatusBarNotification notification) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400335 if (DEBUG) Slog.d(TAG, "addNotification(" + key + " -> " + notification + ")");
336 addNotificationViews(key, notification);
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400337
338 boolean immersive = false;
339 try {
340 immersive = ActivityManagerNative.getDefault().isTopActivityImmersive();
341 Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
342 } catch (RemoteException ex) {
343 }
344 if (immersive) {
345 // TODO: immersive mode popups for tablet
346 } else if (notification.notification.fullScreenIntent != null) {
347 // not immersive & a full-screen alert should be shown
348 Slog.d(TAG, "Notification has fullScreenIntent and activity is not immersive;"
349 + " sending fullScreenIntent");
350 try {
351 notification.notification.fullScreenIntent.send();
352 } catch (PendingIntent.CanceledException e) {
353 }
354 } else {
Joe Onoratoef1e7762010-09-17 18:38:38 -0400355 tick(notification);
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400356 }
Joe Onorato5dd11692010-09-27 15:34:04 -0700357
358 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400359 }
360
361 public void updateNotification(IBinder key, StatusBarNotification notification) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400362 if (DEBUG) Slog.d(TAG, "updateNotification(" + key + " -> " + notification + ") // TODO");
Daniel Sandler379020a2010-07-29 16:20:06 -0400363
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400364 final NotificationData.Entry oldEntry = mNotns.findByKey(key);
Daniel Sandler379020a2010-07-29 16:20:06 -0400365 if (oldEntry == null) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400366 Slog.w(TAG, "updateNotification for unknown key: " + key);
367 return;
368 }
369
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400370 final StatusBarNotification oldNotification = oldEntry.notification;
371 final RemoteViews oldContentView = oldNotification.notification.contentView;
372
373 final RemoteViews contentView = notification.notification.contentView;
374
375 if (false) {
376 Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
377 + " ongoing=" + oldNotification.isOngoing()
378 + " expanded=" + oldEntry.expanded
379 + " contentView=" + oldContentView);
380 Slog.d(TAG, "new notification: when=" + notification.notification.when
381 + " ongoing=" + oldNotification.isOngoing()
382 + " contentView=" + contentView);
383 }
384
385 // Can we just reapply the RemoteViews in place? If when didn't change, the order
386 // didn't change.
387 if (notification.notification.when == oldNotification.notification.when
388 && notification.isOngoing() == oldNotification.isOngoing()
389 && oldEntry.expanded != null
390 && contentView != null
391 && oldContentView != null
392 && contentView.getPackage() != null
393 && oldContentView.getPackage() != null
394 && oldContentView.getPackage().equals(contentView.getPackage())
395 && oldContentView.getLayoutId() == contentView.getLayoutId()) {
396 if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
397 oldEntry.notification = notification;
398 try {
399 // Reapply the RemoteViews
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400400 contentView.reapply(mContext, oldEntry.content);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400401 // update the contentIntent
402 final PendingIntent contentIntent = notification.notification.contentIntent;
403 if (contentIntent != null) {
404 oldEntry.content.setOnClickListener(new NotificationClicker(contentIntent,
405 notification.pkg, notification.tag, notification.id));
Joe Onorato184498c2010-10-08 17:57:18 -0400406 } else {
407 oldEntry.content.setOnClickListener(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400408 }
409 // Update the icon.
410 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
411 notification.notification.icon, notification.notification.iconLevel,
412 notification.notification.number);
413 if (!oldEntry.icon.set(ic)) {
414 handleNotificationError(key, notification, "Couldn't update icon: " + ic);
415 return;
416 }
417 }
418 catch (RuntimeException e) {
419 // It failed to add cleanly. Log, and remove the view from the panel.
420 Slog.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
421 removeNotificationViews(key);
422 addNotificationViews(key, notification);
423 }
424 } else {
425 if (DEBUG) Slog.d(TAG, "not reusing notification for key: " + key);
426 removeNotificationViews(key);
427 addNotificationViews(key, notification);
428 }
Joe Onoratoef1e7762010-09-17 18:38:38 -0400429 // TODO: ticker; immersive mode
Joe Onorato5dd11692010-09-27 15:34:04 -0700430
431 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400432 }
433
434 public void removeNotification(IBinder key) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400435 if (DEBUG) Slog.d(TAG, "removeNotification(" + key + ") // TODO");
436 removeNotificationViews(key);
Joe Onorato5dd11692010-09-27 15:34:04 -0700437 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400438 }
439
440 public void disable(int state) {
Joe Onorato091e1b82010-09-26 18:04:44 -0700441 int old = mDisabled;
442 int diff = state ^ old;
443 Slog.d(TAG, "disable... old=0x" + Integer.toHexString(old)
444 + " diff=0x" + Integer.toHexString(diff)
445 + " state=0x" + Integer.toHexString(state));
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400446 mDisabled = state;
447
Joe Onorato091e1b82010-09-26 18:04:44 -0700448 // act accordingly
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400449 if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
450 if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
451 Slog.d(TAG, "DISABLE_EXPAND: yes");
452 animateCollapse();
453 }
454 }
455 if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
456 if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
457 Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
Joe Onorato091e1b82010-09-26 18:04:44 -0700458 setViewVisibility(mNotificationTrigger, View.GONE,
459 R.anim.notification_icons_out);
460 setViewVisibility(mNotificationIconArea, View.GONE,
461 R.anim.notification_icons_out);
462 mTicker.halt();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400463 } else {
464 Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: no");
Joe Onorato091e1b82010-09-26 18:04:44 -0700465 setViewVisibility(mNotificationTrigger, View.VISIBLE,
466 R.anim.notification_icons_in);
467 setViewVisibility(mNotificationIconArea, View.VISIBLE,
468 R.anim.notification_icons_in);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400469 }
470 } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
Joe Onorato091e1b82010-09-26 18:04:44 -0700471 if ((state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
Joe Onoratoef1e7762010-09-17 18:38:38 -0400472 mTicker.halt();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400473 }
474 }
Joe Onorato091e1b82010-09-26 18:04:44 -0700475 if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
476 if ((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
477 Slog.d(TAG, "DISABLE_SYSTEM_INFO: yes");
478 setViewVisibility(mSystemInfo, View.GONE, R.anim.navigation_out);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400479 } else {
Joe Onorato091e1b82010-09-26 18:04:44 -0700480 Slog.d(TAG, "DISABLE_SYSTEM_INFO: no");
481 setViewVisibility(mSystemInfo, View.VISIBLE, R.anim.navigation_in);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400482 }
483 }
Joe Onorato091e1b82010-09-26 18:04:44 -0700484 if ((diff & StatusBarManager.DISABLE_NAVIGATION) != 0) {
485 if ((state & StatusBarManager.DISABLE_NAVIGATION) != 0) {
486 Slog.d(TAG, "DISABLE_NAVIGATION: yes");
487 setViewVisibility(mNavigationArea, View.GONE, R.anim.navigation_out);
488 } else {
489 Slog.d(TAG, "DISABLE_NAVIGATION: no");
490 setViewVisibility(mNavigationArea, View.VISIBLE, R.anim.navigation_in);
491 }
492 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400493 }
494
Joe Onoratoef1e7762010-09-17 18:38:38 -0400495 private boolean hasTicker(Notification n) {
496 return !TextUtils.isEmpty(n.tickerText)
497 || !TextUtils.isEmpty(n.tickerTitle)
498 || !TextUtils.isEmpty(n.tickerSubtitle);
499 }
500
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400501 private void tick(StatusBarNotification n) {
Joe Onorato55d2d762010-09-26 13:02:01 -0700502 // Don't show the ticker when the windowshade is open.
503 if (mNotificationPanel.getVisibility() == View.VISIBLE) {
504 return;
505 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400506 // Show the ticker if one is requested. Also don't do this
507 // until status bar window is attached to the window manager,
508 // because... well, what's the point otherwise? And trying to
509 // run a ticker without being attached will crash!
Joe Onoratoef1e7762010-09-17 18:38:38 -0400510 if (hasTicker(n.notification) && mStatusBarView.getWindowToken() != null) {
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400511 if (0 == (mDisabled & (StatusBarManager.DISABLE_NOTIFICATION_ICONS
512 | StatusBarManager.DISABLE_NOTIFICATION_TICKER))) {
Joe Onoratoef1e7762010-09-17 18:38:38 -0400513 mTicker.add(n);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400514 }
515 }
516 }
517
Joe Onorato808182d2010-07-09 18:52:06 -0400518 public void animateExpand() {
Joe Onoratob62ac122010-09-20 16:16:32 -0400519 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
520 mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
Joe Onorato808182d2010-07-09 18:52:06 -0400521 }
522
523 public void animateCollapse() {
Joe Onoratob62ac122010-09-20 16:16:32 -0400524 mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PANEL);
525 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PANEL);
526 mHandler.removeMessages(MSG_CLOSE_SYSTEM_PANEL);
527 mHandler.sendEmptyMessage(MSG_CLOSE_SYSTEM_PANEL);
Daniel Sandler9120d552010-07-23 09:11:14 -0400528 }
529
Joe Onorato93056472010-09-10 10:30:46 -0400530 public void setLightsOn(boolean on) {
Joe Onoratof63b0f42010-09-12 17:03:19 -0400531 if (on) {
Joe Onorato091e1b82010-09-26 18:04:44 -0700532 setViewVisibility(mCurtains, View.GONE, R.anim.lights_out_out);
533 setViewVisibility(mBarContents, View.VISIBLE, R.anim.status_bar_in);
Joe Onoratof63b0f42010-09-12 17:03:19 -0400534 } else {
Joe Onorato93056472010-09-10 10:30:46 -0400535 animateCollapse();
Joe Onorato091e1b82010-09-26 18:04:44 -0700536 setViewVisibility(mCurtains, View.VISIBLE, R.anim.lights_out_in);
537 setViewVisibility(mBarContents, View.GONE, R.anim.status_bar_out);
Joe Onorato93056472010-09-10 10:30:46 -0400538 }
Joe Onorato93056472010-09-10 10:30:46 -0400539 }
540
Daniel Sandlere02d8082010-10-08 15:13:22 -0400541 public void setMenuKeyVisible(boolean visible) {
542 if (DEBUG) {
543 Slog.d(TAG, (visible?"showing":"hiding") + " the MENU button");
544 }
545 setViewVisibility(mMenuButton,
546 visible ? View.VISIBLE : View.INVISIBLE,
547 visible ? R.anim.navigation_in : R.anim.navigation_out);
548 }
549
Joe Onorato5dd11692010-09-27 15:34:04 -0700550 private void setAreThereNotifications() {
551 final boolean hasClearable = mNotns.hasClearableItems();
552
553 //Slog.d(TAG, "setAreThereNotifications hasClerable=" + hasClearable);
554
555 // Show or hide the "Clear all" button. Note that we don't do an animation
556 // if it's not on screen, so that if someone opens the bar right then they
557 // don't see the animation in progress.
558 // (no ongoing notifications are clearable)
559 if (hasClearable) {
560 if (mNotificationButtons.getVisibility() == View.VISIBLE) {
561 setViewVisibility(mClearButton, View.VISIBLE, R.anim.notification_buttons_in);
562 } else {
563 mClearButton.setVisibility(View.VISIBLE);
564 }
565 } else {
566 if (mNotificationButtons.getVisibility() == View.VISIBLE) {
567 setViewVisibility(mClearButton, View.GONE, R.anim.notification_buttons_out);
568 } else {
569 mClearButton.setVisibility(View.GONE);
570 }
571 }
572
573 /*
574 mOngoingTitle.setVisibility(ongoing ? View.VISIBLE : View.GONE);
575 mLatestTitle.setVisibility(latest ? View.VISIBLE : View.GONE);
576
577 if (ongoing || latest) {
578 mNoNotificationsTitle.setVisibility(View.GONE);
579 } else {
580 mNoNotificationsTitle.setVisibility(View.VISIBLE);
581 }
582 */
583 }
584
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400585 /**
586 * Cancel this notification and tell the status bar service about the failure. Hold no locks.
587 */
588 void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
589 removeNotification(key);
590 try {
591 mBarService.onNotificationError(n.pkg, n.tag, n.id, n.uid, n.initialPid, message);
592 } catch (RemoteException ex) {
593 // The end is nigh.
594 }
595 }
596
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400597 private View.OnClickListener mOnClickListener = new View.OnClickListener() {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400598 public void onClick(View v) {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400599 if (v == mClearButton) {
600 onClickClearButton();
601 } else if (v == mDoNotDisturbButton) {
602 onClickDoNotDisturb();
603 } else if (v == mNotificationTrigger) {
604 onClickNotificationTrigger();
605 } else if (v == mSystemInfo) {
606 onClickSystemInfo();
607 } else if (v == mRecentButton) {
608 onClickRecentButton();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400609 }
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400610 }
611 };
612
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400613 void onClickClearButton() {
614 try {
615 mBarService.onClearAllNotifications();
616 } catch (RemoteException ex) {
617 // system process is dead if we're here.
Joe Onorato55d2d762010-09-26 13:02:01 -0700618 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400619 animateCollapse();
Daniel Sandler271ea122010-10-22 14:06:10 -0400620 refreshNotificationTrigger();
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400621 }
622
623 void onClickDoNotDisturb() {
624 mNotificationsOn = !mNotificationsOn;
Daniel Sandlercf3c7cf2010-10-22 15:30:12 -0400625 mIconLayout.setVisibility(mNotificationsOn ? View.VISIBLE : View.INVISIBLE); // TODO: animation
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400626 animateCollapse();
Daniel Sandler271ea122010-10-22 14:06:10 -0400627 refreshNotificationTrigger();
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400628 }
629
630 public void onClickNotificationTrigger() {
631 if (DEBUG) Slog.d(TAG, "clicked notification icons");
632 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
Daniel Sandler271ea122010-10-22 14:06:10 -0400633 if (!mNotificationsOn) {
634 mNotificationsOn = true;
Daniel Sandlercf3c7cf2010-10-22 15:30:12 -0400635 mIconLayout.setVisibility(View.VISIBLE); // TODO: animation
Daniel Sandler271ea122010-10-22 14:06:10 -0400636 refreshNotificationTrigger();
637 } else {
638 int msg = (mNotificationPanel.getVisibility() == View.GONE)
639 ? MSG_OPEN_NOTIFICATION_PANEL
640 : MSG_CLOSE_NOTIFICATION_PANEL;
641 mHandler.removeMessages(msg);
642 mHandler.sendEmptyMessage(msg);
643 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400644 }
645 }
646
647 public void onClickSystemInfo() {
648 if (DEBUG) Slog.d(TAG, "clicked system info");
649 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
650 int msg = (mSystemPanel.getVisibility() == View.GONE)
651 ? MSG_OPEN_SYSTEM_PANEL
652 : MSG_CLOSE_SYSTEM_PANEL;
653 mHandler.removeMessages(msg);
654 mHandler.sendEmptyMessage(msg);
655 }
656 }
657
658 public void onClickRecentButton() {
659 if (DEBUG) Slog.d(TAG, "clicked recent apps");
660 Intent intent = new Intent();
661 intent.setClass(mContext, RecentApplicationsActivity.class);
662 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
663 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
664 mContext.startActivity(intent);
665 }
Joe Onorato55d2d762010-09-26 13:02:01 -0700666
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400667 private class NotificationClicker implements View.OnClickListener {
668 private PendingIntent mIntent;
669 private String mPkg;
670 private String mTag;
671 private int mId;
672
673 NotificationClicker(PendingIntent intent, String pkg, String tag, int id) {
674 mIntent = intent;
675 mPkg = pkg;
676 mTag = tag;
677 mId = id;
678 }
679
680 public void onClick(View v) {
681 try {
682 // The intent we are sending is for the application, which
683 // won't have permission to immediately start an activity after
684 // the user switches to home. We know it is safe to do at this
685 // point, so make sure new activity switches are now allowed.
686 ActivityManagerNative.getDefault().resumeAppSwitches();
687 } catch (RemoteException e) {
688 }
689
690 if (mIntent != null) {
691 int[] pos = new int[2];
692 v.getLocationOnScreen(pos);
693 Intent overlay = new Intent();
694 overlay.setSourceBounds(
695 new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
696 try {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400697 mIntent.send(mContext, 0, overlay);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400698 } catch (PendingIntent.CanceledException e) {
699 // the stack trace isn't very helpful here. Just log the exception message.
700 Slog.w(TAG, "Sending contentIntent failed: " + e);
701 }
702 }
703
704 try {
705 mBarService.onNotificationClick(mPkg, mTag, mId);
706 } catch (RemoteException ex) {
707 // system process is dead if we're here.
708 }
709
710 // close the shade if it was open
711 animateCollapse();
712
713 // If this click was on the intruder alert, hide that instead
714// mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
715 }
716 }
717
718 StatusBarNotification removeNotificationViews(IBinder key) {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400719 NotificationData.Entry entry = mNotns.remove(key);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400720 if (entry == null) {
721 Slog.w(TAG, "removeNotification for unknown key: " + key);
722 return null;
723 }
724 // Remove the expanded view.
725 ViewGroup rowParent = (ViewGroup)entry.row.getParent();
726 if (rowParent != null) rowParent.removeView(entry.row);
727 // Remove the icon.
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400728// ViewGroup iconParent = (ViewGroup)entry.icon.getParent();
729// if (iconParent != null) iconParent.removeView(entry.icon);
730 refreshIcons();
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400731
732 return entry.notification;
733 }
734
735 StatusBarIconView addNotificationViews(IBinder key, StatusBarNotification notification) {
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400736 if (DEBUG) {
737 Slog.d(TAG, "addNotificationViews(key=" + key + ", notification=" + notification);
738 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400739 // Construct the icon.
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400740 final StatusBarIconView iconView = new StatusBarIconView(mContext,
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400741 notification.pkg + "/0x" + Integer.toHexString(notification.id));
742 iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
743
744 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
745 notification.notification.icon,
746 notification.notification.iconLevel,
747 notification.notification.number);
748 if (!iconView.set(ic)) {
749 handleNotificationError(key, notification, "Couldn't attach StatusBarIcon: " + ic);
750 return null;
751 }
752 // Construct the expanded view.
753 NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400754 if (!inflateViews(entry, mPile)) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400755 handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
756 + notification);
757 return null;
758 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400759 // Add the icon.
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400760 mNotns.add(entry);
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400761 refreshIcons();
762
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400763 return iconView;
764 }
765
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400766 private void refreshIcons() {
767 // XXX: need to implement a new limited linear layout class
768 // to avoid removing & readding everything
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400769
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400770 int N = mNotns.size();
771 LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mIconSize, mIconSize);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400772
773 if (DEBUG) {
774 Slog.d(TAG, "refreshing icons (" + N + " notifications, mIconLayout="
775 + mIconLayout + ", mPile=" + mPile);
776 }
777
778 mIconLayout.removeAllViews();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400779 for (int i=0; i<4; i++) {
780 if (i>=N) break;
781 mIconLayout.addView(mNotns.get(N-i-1).icon, i, params);
782 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400783
784 mPile.removeAllViews();
785 for (int i=0; i<N; i++) {
786 mPile.addView(mNotns.get(N-i-1).row);
787 }
Daniel Sandler271ea122010-10-22 14:06:10 -0400788
789 refreshNotificationTrigger();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400790 }
791
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400792 private boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) {
793 StatusBarNotification sbn = entry.notification;
794 RemoteViews remoteViews = sbn.notification.contentView;
795 if (remoteViews == null) {
796 return false;
797 }
798
799 // create the row view
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400800 LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(
801 Context.LAYOUT_INFLATER_SERVICE);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400802 View row = inflater.inflate(R.layout.status_bar_latest_event, parent, false);
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400803 View vetoButton = row.findViewById(R.id.veto);
Joe Onoratoa4a65032010-09-27 15:53:44 -0700804 if (entry.notification.isClearable()) {
805 final String _pkg = sbn.pkg;
806 final String _tag = sbn.tag;
807 final int _id = sbn.id;
808 vetoButton.setOnClickListener(new View.OnClickListener() {
809 public void onClick(View v) {
810 try {
811 mBarService.onNotificationClear(_pkg, _tag, _id);
812 } catch (RemoteException ex) {
813 // system process is dead if we're here.
814 }
815 // animateCollapse();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400816 }
Joe Onoratoa4a65032010-09-27 15:53:44 -0700817 });
818 } else {
819 vetoButton.setVisibility(View.INVISIBLE);
820 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400821
822 // bind the click event to the content area
823 ViewGroup content = (ViewGroup)row.findViewById(R.id.content);
824 // XXX: update to allow controls within notification views
825 content.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
826// content.setOnFocusChangeListener(mFocusChangeListener);
827 PendingIntent contentIntent = sbn.notification.contentIntent;
828 if (contentIntent != null) {
829 content.setOnClickListener(new NotificationClicker(contentIntent,
830 sbn.pkg, sbn.tag, sbn.id));
Joe Onorato184498c2010-10-08 17:57:18 -0400831 } else {
832 content.setOnClickListener(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400833 }
834
835 View expanded = null;
836 Exception exception = null;
837 try {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400838 expanded = remoteViews.apply(mContext, content);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400839 }
840 catch (RuntimeException e) {
841 exception = e;
842 }
843 if (expanded == null) {
844 String ident = sbn.pkg + "/0x" + Integer.toHexString(sbn.id);
845 Slog.e(TAG, "couldn't inflate view for notification " + ident, exception);
846 return false;
847 } else {
848 content.addView(expanded);
849 row.setDrawingCacheEnabled(true);
850 }
851
852 entry.row = row;
853 entry.content = content;
854 entry.expanded = expanded;
855
856 return true;
857 }
Daniel Sandlerce70d912010-09-02 11:59:41 -0400858
Joe Onoratof63b0f42010-09-12 17:03:19 -0400859 public class SetLightsOnListener implements View.OnLongClickListener,
860 View.OnClickListener {
861 private boolean mOn;
Daniel Sandlerce70d912010-09-02 11:59:41 -0400862
Joe Onoratof63b0f42010-09-12 17:03:19 -0400863 SetLightsOnListener(boolean on) {
864 mOn = on;
865 }
866
867 public void onClick(View v) {
868 try {
869 mBarService.setLightsOn(mOn);
870 } catch (RemoteException ex) {
871 // system process
872 }
873 }
874
875 public boolean onLongClick(View v) {
876 try {
877 mBarService.setLightsOn(mOn);
878 } catch (RemoteException ex) {
879 // system process
880 }
881 return true;
882 }
883
Daniel Sandlerce70d912010-09-02 11:59:41 -0400884 }
Joe Onoratob62ac122010-09-20 16:16:32 -0400885
886 public class TouchOutsideListener implements View.OnTouchListener {
887 private int mMsg;
Joe Onoratoddf680b2010-09-26 13:59:40 -0700888 private StatusBarPanel mPanel;
Joe Onoratob62ac122010-09-20 16:16:32 -0400889
Joe Onoratoddf680b2010-09-26 13:59:40 -0700890 public TouchOutsideListener(int msg, StatusBarPanel panel) {
Joe Onoratob62ac122010-09-20 16:16:32 -0400891 mMsg = msg;
Joe Onoratoddf680b2010-09-26 13:59:40 -0700892 mPanel = panel;
Joe Onoratob62ac122010-09-20 16:16:32 -0400893 }
894
895 public boolean onTouch(View v, MotionEvent ev) {
Joe Onoratoddf680b2010-09-26 13:59:40 -0700896 final int action = ev.getAction();
897 if (action == MotionEvent.ACTION_OUTSIDE
898 || (action == MotionEvent.ACTION_DOWN
899 && !mPanel.isInContentArea((int)ev.getX(), (int)ev.getY()))) {
Joe Onoratob62ac122010-09-20 16:16:32 -0400900 mHandler.removeMessages(mMsg);
901 mHandler.sendEmptyMessage(mMsg);
902 return true;
903 }
904 return false;
905 }
906 }
Joe Onorato091e1b82010-09-26 18:04:44 -0700907
908 private void setViewVisibility(View v, int vis, int anim) {
909 if (v.getVisibility() != vis) {
Joe Onorato5dd11692010-09-27 15:34:04 -0700910 //Slog.d(TAG, "setViewVisibility vis=" + (vis == View.VISIBLE) + " v=" + v);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400911 v.setAnimation(AnimationUtils.loadAnimation(mContext, anim));
Joe Onorato091e1b82010-09-26 18:04:44 -0700912 v.setVisibility(vis);
913 }
914 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400915
916
917 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
918 pw.print("mDisabled=0x");
919 pw.println(Integer.toHexString(mDisabled));
920 }
Joe Onorato808182d2010-07-09 18:52:06 -0400921}
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400922
923