blob: 0c004aef2a0e5977cc219a0e49e1636ecef02daf [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() {
284 int resId;
285 boolean panel = (mNotificationPanel != null
286 && mNotificationPanel.getVisibility() == View.VISIBLE);
287 if (!mNotificationsOn) {
288 resId = R.drawable.ic_sysbar_noti_dnd;
289 } else if (mNotns.size() > 0) {
290 resId = panel ? R.drawable.ic_sysbar_noti_avail_open : R.drawable.ic_sysbar_noti_avail;
291 } else {
292 resId = panel ? R.drawable.ic_sysbar_noti_none_open : R.drawable.ic_sysbar_noti_none;
293 }
294 mNotificationTrigger.setImageResource(resId);
295 }
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400296
Daniel Sandlerd7db7b12010-08-13 16:26:39 -0400297 public void setBatteryMeter(int level, boolean plugged) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400298 if (DEBUG) Slog.d(TAG, "battery=" + level + (plugged ? " - plugged" : " - unplugged"));
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400299 mBatteryMeter.setImageResource(R.drawable.sysbar_batterymini);
300 // adjust percent to permyriad for ClipDrawable's sake
301 mBatteryMeter.setImageLevel(level * (MAX_IMAGE_LEVEL / 100));
Daniel Sandlerd7db7b12010-08-13 16:26:39 -0400302 }
303
Daniel Sandler764b4da2010-08-24 16:24:35 -0400304 public void setSignalMeter(int level, boolean isWifi) {
305 if (DEBUG) Slog.d(TAG, "signal=" + level);
306 if (level < 0) {
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400307 mSignalMeter.setImageDrawable(null);
Daniel Sandler764b4da2010-08-24 16:24:35 -0400308 mSignalMeter.setImageLevel(0);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400309 mSignalIcon.setImageDrawable(null);
Daniel Sandler764b4da2010-08-24 16:24:35 -0400310 } else {
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400311 mSignalMeter.setImageResource(R.drawable.sysbar_wifimini);
312 // adjust to permyriad
313 mSignalMeter.setImageLevel(level * (MAX_IMAGE_LEVEL / 100));
314 mSignalIcon.setImageResource(isWifi ? R.drawable.ic_sysbar_wifi_mini
315 : R.drawable.ic_sysbar_wifi_mini); // XXX
Daniel Sandler764b4da2010-08-24 16:24:35 -0400316 }
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400317 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400318
Joe Onorato808182d2010-07-09 18:52:06 -0400319 public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400320 if (DEBUG) Slog.d(TAG, "addIcon(" + slot + ") -> " + icon);
Joe Onorato808182d2010-07-09 18:52:06 -0400321 }
322
323 public void updateIcon(String slot, int index, int viewIndex,
324 StatusBarIcon old, StatusBarIcon icon) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400325 if (DEBUG) Slog.d(TAG, "updateIcon(" + slot + ") -> " + icon);
Joe Onorato808182d2010-07-09 18:52:06 -0400326 }
327
328 public void removeIcon(String slot, int index, int viewIndex) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400329 if (DEBUG) Slog.d(TAG, "removeIcon(" + slot + ")");
Joe Onorato808182d2010-07-09 18:52:06 -0400330 }
331
332 public void addNotification(IBinder key, StatusBarNotification notification) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400333 if (DEBUG) Slog.d(TAG, "addNotification(" + key + " -> " + notification + ")");
334 addNotificationViews(key, notification);
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400335
336 boolean immersive = false;
337 try {
338 immersive = ActivityManagerNative.getDefault().isTopActivityImmersive();
339 Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
340 } catch (RemoteException ex) {
341 }
342 if (immersive) {
343 // TODO: immersive mode popups for tablet
344 } else if (notification.notification.fullScreenIntent != null) {
345 // not immersive & a full-screen alert should be shown
346 Slog.d(TAG, "Notification has fullScreenIntent and activity is not immersive;"
347 + " sending fullScreenIntent");
348 try {
349 notification.notification.fullScreenIntent.send();
350 } catch (PendingIntent.CanceledException e) {
351 }
352 } else {
Joe Onoratoef1e7762010-09-17 18:38:38 -0400353 tick(notification);
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400354 }
Joe Onorato5dd11692010-09-27 15:34:04 -0700355
356 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400357 }
358
359 public void updateNotification(IBinder key, StatusBarNotification notification) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400360 if (DEBUG) Slog.d(TAG, "updateNotification(" + key + " -> " + notification + ") // TODO");
Daniel Sandler379020a2010-07-29 16:20:06 -0400361
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400362 final NotificationData.Entry oldEntry = mNotns.findByKey(key);
Daniel Sandler379020a2010-07-29 16:20:06 -0400363 if (oldEntry == null) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400364 Slog.w(TAG, "updateNotification for unknown key: " + key);
365 return;
366 }
367
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400368 final StatusBarNotification oldNotification = oldEntry.notification;
369 final RemoteViews oldContentView = oldNotification.notification.contentView;
370
371 final RemoteViews contentView = notification.notification.contentView;
372
373 if (false) {
374 Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
375 + " ongoing=" + oldNotification.isOngoing()
376 + " expanded=" + oldEntry.expanded
377 + " contentView=" + oldContentView);
378 Slog.d(TAG, "new notification: when=" + notification.notification.when
379 + " ongoing=" + oldNotification.isOngoing()
380 + " contentView=" + contentView);
381 }
382
383 // Can we just reapply the RemoteViews in place? If when didn't change, the order
384 // didn't change.
385 if (notification.notification.when == oldNotification.notification.when
386 && notification.isOngoing() == oldNotification.isOngoing()
387 && oldEntry.expanded != null
388 && contentView != null
389 && oldContentView != null
390 && contentView.getPackage() != null
391 && oldContentView.getPackage() != null
392 && oldContentView.getPackage().equals(contentView.getPackage())
393 && oldContentView.getLayoutId() == contentView.getLayoutId()) {
394 if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
395 oldEntry.notification = notification;
396 try {
397 // Reapply the RemoteViews
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400398 contentView.reapply(mContext, oldEntry.content);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400399 // update the contentIntent
400 final PendingIntent contentIntent = notification.notification.contentIntent;
401 if (contentIntent != null) {
402 oldEntry.content.setOnClickListener(new NotificationClicker(contentIntent,
403 notification.pkg, notification.tag, notification.id));
Joe Onorato184498c2010-10-08 17:57:18 -0400404 } else {
405 oldEntry.content.setOnClickListener(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400406 }
407 // Update the icon.
408 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
409 notification.notification.icon, notification.notification.iconLevel,
410 notification.notification.number);
411 if (!oldEntry.icon.set(ic)) {
412 handleNotificationError(key, notification, "Couldn't update icon: " + ic);
413 return;
414 }
415 }
416 catch (RuntimeException e) {
417 // It failed to add cleanly. Log, and remove the view from the panel.
418 Slog.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
419 removeNotificationViews(key);
420 addNotificationViews(key, notification);
421 }
422 } else {
423 if (DEBUG) Slog.d(TAG, "not reusing notification for key: " + key);
424 removeNotificationViews(key);
425 addNotificationViews(key, notification);
426 }
Joe Onoratoef1e7762010-09-17 18:38:38 -0400427 // TODO: ticker; immersive mode
Joe Onorato5dd11692010-09-27 15:34:04 -0700428
429 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400430 }
431
432 public void removeNotification(IBinder key) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400433 if (DEBUG) Slog.d(TAG, "removeNotification(" + key + ") // TODO");
434 removeNotificationViews(key);
Joe Onorato5dd11692010-09-27 15:34:04 -0700435 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400436 }
437
438 public void disable(int state) {
Joe Onorato091e1b82010-09-26 18:04:44 -0700439 int old = mDisabled;
440 int diff = state ^ old;
441 Slog.d(TAG, "disable... old=0x" + Integer.toHexString(old)
442 + " diff=0x" + Integer.toHexString(diff)
443 + " state=0x" + Integer.toHexString(state));
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400444 mDisabled = state;
445
Joe Onorato091e1b82010-09-26 18:04:44 -0700446 // act accordingly
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400447 if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
448 if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
449 Slog.d(TAG, "DISABLE_EXPAND: yes");
450 animateCollapse();
451 }
452 }
453 if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
454 if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
455 Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
Joe Onorato091e1b82010-09-26 18:04:44 -0700456 setViewVisibility(mNotificationTrigger, View.GONE,
457 R.anim.notification_icons_out);
458 setViewVisibility(mNotificationIconArea, View.GONE,
459 R.anim.notification_icons_out);
460 mTicker.halt();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400461 } else {
462 Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: no");
Joe Onorato091e1b82010-09-26 18:04:44 -0700463 setViewVisibility(mNotificationTrigger, View.VISIBLE,
464 R.anim.notification_icons_in);
465 setViewVisibility(mNotificationIconArea, View.VISIBLE,
466 R.anim.notification_icons_in);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400467 }
468 } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
Joe Onorato091e1b82010-09-26 18:04:44 -0700469 if ((state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
Joe Onoratoef1e7762010-09-17 18:38:38 -0400470 mTicker.halt();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400471 }
472 }
Joe Onorato091e1b82010-09-26 18:04:44 -0700473 if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
474 if ((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
475 Slog.d(TAG, "DISABLE_SYSTEM_INFO: yes");
476 setViewVisibility(mSystemInfo, View.GONE, R.anim.navigation_out);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400477 } else {
Joe Onorato091e1b82010-09-26 18:04:44 -0700478 Slog.d(TAG, "DISABLE_SYSTEM_INFO: no");
479 setViewVisibility(mSystemInfo, View.VISIBLE, R.anim.navigation_in);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400480 }
481 }
Joe Onorato091e1b82010-09-26 18:04:44 -0700482 if ((diff & StatusBarManager.DISABLE_NAVIGATION) != 0) {
483 if ((state & StatusBarManager.DISABLE_NAVIGATION) != 0) {
484 Slog.d(TAG, "DISABLE_NAVIGATION: yes");
485 setViewVisibility(mNavigationArea, View.GONE, R.anim.navigation_out);
486 } else {
487 Slog.d(TAG, "DISABLE_NAVIGATION: no");
488 setViewVisibility(mNavigationArea, View.VISIBLE, R.anim.navigation_in);
489 }
490 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400491 }
492
Joe Onoratoef1e7762010-09-17 18:38:38 -0400493 private boolean hasTicker(Notification n) {
494 return !TextUtils.isEmpty(n.tickerText)
495 || !TextUtils.isEmpty(n.tickerTitle)
496 || !TextUtils.isEmpty(n.tickerSubtitle);
497 }
498
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400499 private void tick(StatusBarNotification n) {
Joe Onorato55d2d762010-09-26 13:02:01 -0700500 // Don't show the ticker when the windowshade is open.
501 if (mNotificationPanel.getVisibility() == View.VISIBLE) {
502 return;
503 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400504 // Show the ticker if one is requested. Also don't do this
505 // until status bar window is attached to the window manager,
506 // because... well, what's the point otherwise? And trying to
507 // run a ticker without being attached will crash!
Joe Onoratoef1e7762010-09-17 18:38:38 -0400508 if (hasTicker(n.notification) && mStatusBarView.getWindowToken() != null) {
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400509 if (0 == (mDisabled & (StatusBarManager.DISABLE_NOTIFICATION_ICONS
510 | StatusBarManager.DISABLE_NOTIFICATION_TICKER))) {
Joe Onoratoef1e7762010-09-17 18:38:38 -0400511 mTicker.add(n);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400512 }
513 }
514 }
515
Joe Onorato808182d2010-07-09 18:52:06 -0400516 public void animateExpand() {
Joe Onoratob62ac122010-09-20 16:16:32 -0400517 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
518 mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
Joe Onorato808182d2010-07-09 18:52:06 -0400519 }
520
521 public void animateCollapse() {
Joe Onoratob62ac122010-09-20 16:16:32 -0400522 mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PANEL);
523 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PANEL);
524 mHandler.removeMessages(MSG_CLOSE_SYSTEM_PANEL);
525 mHandler.sendEmptyMessage(MSG_CLOSE_SYSTEM_PANEL);
Daniel Sandler9120d552010-07-23 09:11:14 -0400526 }
527
Joe Onorato93056472010-09-10 10:30:46 -0400528 public void setLightsOn(boolean on) {
Joe Onoratof63b0f42010-09-12 17:03:19 -0400529 if (on) {
Joe Onorato091e1b82010-09-26 18:04:44 -0700530 setViewVisibility(mCurtains, View.GONE, R.anim.lights_out_out);
531 setViewVisibility(mBarContents, View.VISIBLE, R.anim.status_bar_in);
Joe Onoratof63b0f42010-09-12 17:03:19 -0400532 } else {
Joe Onorato93056472010-09-10 10:30:46 -0400533 animateCollapse();
Joe Onorato091e1b82010-09-26 18:04:44 -0700534 setViewVisibility(mCurtains, View.VISIBLE, R.anim.lights_out_in);
535 setViewVisibility(mBarContents, View.GONE, R.anim.status_bar_out);
Joe Onorato93056472010-09-10 10:30:46 -0400536 }
Joe Onorato93056472010-09-10 10:30:46 -0400537 }
538
Daniel Sandlere02d8082010-10-08 15:13:22 -0400539 public void setMenuKeyVisible(boolean visible) {
540 if (DEBUG) {
541 Slog.d(TAG, (visible?"showing":"hiding") + " the MENU button");
542 }
543 setViewVisibility(mMenuButton,
544 visible ? View.VISIBLE : View.INVISIBLE,
545 visible ? R.anim.navigation_in : R.anim.navigation_out);
546 }
547
Joe Onorato5dd11692010-09-27 15:34:04 -0700548 private void setAreThereNotifications() {
549 final boolean hasClearable = mNotns.hasClearableItems();
550
551 //Slog.d(TAG, "setAreThereNotifications hasClerable=" + hasClearable);
552
553 // Show or hide the "Clear all" button. Note that we don't do an animation
554 // if it's not on screen, so that if someone opens the bar right then they
555 // don't see the animation in progress.
556 // (no ongoing notifications are clearable)
557 if (hasClearable) {
558 if (mNotificationButtons.getVisibility() == View.VISIBLE) {
559 setViewVisibility(mClearButton, View.VISIBLE, R.anim.notification_buttons_in);
560 } else {
561 mClearButton.setVisibility(View.VISIBLE);
562 }
563 } else {
564 if (mNotificationButtons.getVisibility() == View.VISIBLE) {
565 setViewVisibility(mClearButton, View.GONE, R.anim.notification_buttons_out);
566 } else {
567 mClearButton.setVisibility(View.GONE);
568 }
569 }
570
571 /*
572 mOngoingTitle.setVisibility(ongoing ? View.VISIBLE : View.GONE);
573 mLatestTitle.setVisibility(latest ? View.VISIBLE : View.GONE);
574
575 if (ongoing || latest) {
576 mNoNotificationsTitle.setVisibility(View.GONE);
577 } else {
578 mNoNotificationsTitle.setVisibility(View.VISIBLE);
579 }
580 */
581 }
582
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400583 /**
584 * Cancel this notification and tell the status bar service about the failure. Hold no locks.
585 */
586 void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
587 removeNotification(key);
588 try {
589 mBarService.onNotificationError(n.pkg, n.tag, n.id, n.uid, n.initialPid, message);
590 } catch (RemoteException ex) {
591 // The end is nigh.
592 }
593 }
594
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400595 private View.OnClickListener mOnClickListener = new View.OnClickListener() {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400596 public void onClick(View v) {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400597 if (v == mClearButton) {
598 onClickClearButton();
599 } else if (v == mDoNotDisturbButton) {
600 onClickDoNotDisturb();
601 } else if (v == mNotificationTrigger) {
602 onClickNotificationTrigger();
603 } else if (v == mSystemInfo) {
604 onClickSystemInfo();
605 } else if (v == mRecentButton) {
606 onClickRecentButton();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400607 }
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400608 }
609 };
610
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400611 void onClickClearButton() {
612 try {
613 mBarService.onClearAllNotifications();
614 } catch (RemoteException ex) {
615 // system process is dead if we're here.
Joe Onorato55d2d762010-09-26 13:02:01 -0700616 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400617 animateCollapse();
Daniel Sandler271ea122010-10-22 14:06:10 -0400618 refreshNotificationTrigger();
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400619 }
620
621 void onClickDoNotDisturb() {
622 mNotificationsOn = !mNotificationsOn;
Daniel Sandler271ea122010-10-22 14:06:10 -0400623 setViewVisibility(mIconLayout,
624 mNotificationsOn ? View.VISIBLE : View.INVISIBLE,
625 mNotificationsOn ? R.anim.notification_dnd_off : R.anim.notification_dnd_on);
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;
635 setViewVisibility(mIconLayout,
636 View.VISIBLE,
637 R.anim.notification_dnd_off);
638 refreshNotificationTrigger();
639 } else {
640 int msg = (mNotificationPanel.getVisibility() == View.GONE)
641 ? MSG_OPEN_NOTIFICATION_PANEL
642 : MSG_CLOSE_NOTIFICATION_PANEL;
643 mHandler.removeMessages(msg);
644 mHandler.sendEmptyMessage(msg);
645 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400646 }
647 }
648
649 public void onClickSystemInfo() {
650 if (DEBUG) Slog.d(TAG, "clicked system info");
651 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
652 int msg = (mSystemPanel.getVisibility() == View.GONE)
653 ? MSG_OPEN_SYSTEM_PANEL
654 : MSG_CLOSE_SYSTEM_PANEL;
655 mHandler.removeMessages(msg);
656 mHandler.sendEmptyMessage(msg);
657 }
658 }
659
660 public void onClickRecentButton() {
661 if (DEBUG) Slog.d(TAG, "clicked recent apps");
662 Intent intent = new Intent();
663 intent.setClass(mContext, RecentApplicationsActivity.class);
664 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
665 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
666 mContext.startActivity(intent);
667 }
Joe Onorato55d2d762010-09-26 13:02:01 -0700668
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400669 private class NotificationClicker implements View.OnClickListener {
670 private PendingIntent mIntent;
671 private String mPkg;
672 private String mTag;
673 private int mId;
674
675 NotificationClicker(PendingIntent intent, String pkg, String tag, int id) {
676 mIntent = intent;
677 mPkg = pkg;
678 mTag = tag;
679 mId = id;
680 }
681
682 public void onClick(View v) {
683 try {
684 // The intent we are sending is for the application, which
685 // won't have permission to immediately start an activity after
686 // the user switches to home. We know it is safe to do at this
687 // point, so make sure new activity switches are now allowed.
688 ActivityManagerNative.getDefault().resumeAppSwitches();
689 } catch (RemoteException e) {
690 }
691
692 if (mIntent != null) {
693 int[] pos = new int[2];
694 v.getLocationOnScreen(pos);
695 Intent overlay = new Intent();
696 overlay.setSourceBounds(
697 new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
698 try {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400699 mIntent.send(mContext, 0, overlay);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400700 } catch (PendingIntent.CanceledException e) {
701 // the stack trace isn't very helpful here. Just log the exception message.
702 Slog.w(TAG, "Sending contentIntent failed: " + e);
703 }
704 }
705
706 try {
707 mBarService.onNotificationClick(mPkg, mTag, mId);
708 } catch (RemoteException ex) {
709 // system process is dead if we're here.
710 }
711
712 // close the shade if it was open
713 animateCollapse();
714
715 // If this click was on the intruder alert, hide that instead
716// mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
717 }
718 }
719
720 StatusBarNotification removeNotificationViews(IBinder key) {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400721 NotificationData.Entry entry = mNotns.remove(key);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400722 if (entry == null) {
723 Slog.w(TAG, "removeNotification for unknown key: " + key);
724 return null;
725 }
726 // Remove the expanded view.
727 ViewGroup rowParent = (ViewGroup)entry.row.getParent();
728 if (rowParent != null) rowParent.removeView(entry.row);
729 // Remove the icon.
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400730// ViewGroup iconParent = (ViewGroup)entry.icon.getParent();
731// if (iconParent != null) iconParent.removeView(entry.icon);
732 refreshIcons();
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400733
734 return entry.notification;
735 }
736
737 StatusBarIconView addNotificationViews(IBinder key, StatusBarNotification notification) {
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400738 if (DEBUG) {
739 Slog.d(TAG, "addNotificationViews(key=" + key + ", notification=" + notification);
740 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400741 // Construct the icon.
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400742 final StatusBarIconView iconView = new StatusBarIconView(mContext,
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400743 notification.pkg + "/0x" + Integer.toHexString(notification.id));
744 iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
745
746 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
747 notification.notification.icon,
748 notification.notification.iconLevel,
749 notification.notification.number);
750 if (!iconView.set(ic)) {
751 handleNotificationError(key, notification, "Couldn't attach StatusBarIcon: " + ic);
752 return null;
753 }
754 // Construct the expanded view.
755 NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400756 if (!inflateViews(entry, mPile)) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400757 handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
758 + notification);
759 return null;
760 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400761 // Add the icon.
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400762 mNotns.add(entry);
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400763 refreshIcons();
764
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400765 return iconView;
766 }
767
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400768 private void refreshIcons() {
769 // XXX: need to implement a new limited linear layout class
770 // to avoid removing & readding everything
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400771
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400772 int N = mNotns.size();
773 LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mIconSize, mIconSize);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400774
775 if (DEBUG) {
776 Slog.d(TAG, "refreshing icons (" + N + " notifications, mIconLayout="
777 + mIconLayout + ", mPile=" + mPile);
778 }
779
780 mIconLayout.removeAllViews();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400781 for (int i=0; i<4; i++) {
782 if (i>=N) break;
783 mIconLayout.addView(mNotns.get(N-i-1).icon, i, params);
784 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400785
786 mPile.removeAllViews();
787 for (int i=0; i<N; i++) {
788 mPile.addView(mNotns.get(N-i-1).row);
789 }
Daniel Sandler271ea122010-10-22 14:06:10 -0400790
791 refreshNotificationTrigger();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400792 }
793
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400794 private boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) {
795 StatusBarNotification sbn = entry.notification;
796 RemoteViews remoteViews = sbn.notification.contentView;
797 if (remoteViews == null) {
798 return false;
799 }
800
801 // create the row view
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400802 LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(
803 Context.LAYOUT_INFLATER_SERVICE);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400804 View row = inflater.inflate(R.layout.status_bar_latest_event, parent, false);
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400805 View vetoButton = row.findViewById(R.id.veto);
Joe Onoratoa4a65032010-09-27 15:53:44 -0700806 if (entry.notification.isClearable()) {
807 final String _pkg = sbn.pkg;
808 final String _tag = sbn.tag;
809 final int _id = sbn.id;
810 vetoButton.setOnClickListener(new View.OnClickListener() {
811 public void onClick(View v) {
812 try {
813 mBarService.onNotificationClear(_pkg, _tag, _id);
814 } catch (RemoteException ex) {
815 // system process is dead if we're here.
816 }
817 // animateCollapse();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400818 }
Joe Onoratoa4a65032010-09-27 15:53:44 -0700819 });
820 } else {
821 vetoButton.setVisibility(View.INVISIBLE);
822 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400823
824 // bind the click event to the content area
825 ViewGroup content = (ViewGroup)row.findViewById(R.id.content);
826 // XXX: update to allow controls within notification views
827 content.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
828// content.setOnFocusChangeListener(mFocusChangeListener);
829 PendingIntent contentIntent = sbn.notification.contentIntent;
830 if (contentIntent != null) {
831 content.setOnClickListener(new NotificationClicker(contentIntent,
832 sbn.pkg, sbn.tag, sbn.id));
Joe Onorato184498c2010-10-08 17:57:18 -0400833 } else {
834 content.setOnClickListener(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400835 }
836
837 View expanded = null;
838 Exception exception = null;
839 try {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400840 expanded = remoteViews.apply(mContext, content);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400841 }
842 catch (RuntimeException e) {
843 exception = e;
844 }
845 if (expanded == null) {
846 String ident = sbn.pkg + "/0x" + Integer.toHexString(sbn.id);
847 Slog.e(TAG, "couldn't inflate view for notification " + ident, exception);
848 return false;
849 } else {
850 content.addView(expanded);
851 row.setDrawingCacheEnabled(true);
852 }
853
854 entry.row = row;
855 entry.content = content;
856 entry.expanded = expanded;
857
858 return true;
859 }
Daniel Sandlerce70d912010-09-02 11:59:41 -0400860
Joe Onoratof63b0f42010-09-12 17:03:19 -0400861 public class SetLightsOnListener implements View.OnLongClickListener,
862 View.OnClickListener {
863 private boolean mOn;
Daniel Sandlerce70d912010-09-02 11:59:41 -0400864
Joe Onoratof63b0f42010-09-12 17:03:19 -0400865 SetLightsOnListener(boolean on) {
866 mOn = on;
867 }
868
869 public void onClick(View v) {
870 try {
871 mBarService.setLightsOn(mOn);
872 } catch (RemoteException ex) {
873 // system process
874 }
875 }
876
877 public boolean onLongClick(View v) {
878 try {
879 mBarService.setLightsOn(mOn);
880 } catch (RemoteException ex) {
881 // system process
882 }
883 return true;
884 }
885
Daniel Sandlerce70d912010-09-02 11:59:41 -0400886 }
Joe Onoratob62ac122010-09-20 16:16:32 -0400887
888 public class TouchOutsideListener implements View.OnTouchListener {
889 private int mMsg;
Joe Onoratoddf680b2010-09-26 13:59:40 -0700890 private StatusBarPanel mPanel;
Joe Onoratob62ac122010-09-20 16:16:32 -0400891
Joe Onoratoddf680b2010-09-26 13:59:40 -0700892 public TouchOutsideListener(int msg, StatusBarPanel panel) {
Joe Onoratob62ac122010-09-20 16:16:32 -0400893 mMsg = msg;
Joe Onoratoddf680b2010-09-26 13:59:40 -0700894 mPanel = panel;
Joe Onoratob62ac122010-09-20 16:16:32 -0400895 }
896
897 public boolean onTouch(View v, MotionEvent ev) {
Joe Onoratoddf680b2010-09-26 13:59:40 -0700898 final int action = ev.getAction();
899 if (action == MotionEvent.ACTION_OUTSIDE
900 || (action == MotionEvent.ACTION_DOWN
901 && !mPanel.isInContentArea((int)ev.getX(), (int)ev.getY()))) {
Joe Onoratob62ac122010-09-20 16:16:32 -0400902 mHandler.removeMessages(mMsg);
903 mHandler.sendEmptyMessage(mMsg);
904 return true;
905 }
906 return false;
907 }
908 }
Joe Onorato091e1b82010-09-26 18:04:44 -0700909
910 private void setViewVisibility(View v, int vis, int anim) {
911 if (v.getVisibility() != vis) {
Joe Onorato5dd11692010-09-27 15:34:04 -0700912 //Slog.d(TAG, "setViewVisibility vis=" + (vis == View.VISIBLE) + " v=" + v);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400913 v.setAnimation(AnimationUtils.loadAnimation(mContext, anim));
Joe Onorato091e1b82010-09-26 18:04:44 -0700914 v.setVisibility(vis);
915 }
916 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400917
918
919 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
920 pw.print("mDisabled=0x");
921 pw.println(Integer.toHexString(mDisabled));
922 }
Joe Onorato808182d2010-07-09 18:52:06 -0400923}
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400924
925