blob: da44f4313a7dedcc35a6b560c49bcfafe5b2de85 [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 Sandlerdfa08db2010-08-05 16:18:42 -040026import android.app.PendingIntent;
Joe Onoratoef1e7762010-09-17 18:38:38 -040027import android.app.Notification;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040028import android.app.StatusBarManager;
Joe Onorato808182d2010-07-09 18:52:06 -040029import android.content.Context;
30import android.content.Intent;
31import android.content.res.Resources;
Daniel Sandler9120d552010-07-23 09:11:14 -040032import android.graphics.PixelFormat;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040033import android.graphics.Rect;
Daniel Sandler9120d552010-07-23 09:11:14 -040034import android.os.Handler;
Joe Onorato808182d2010-07-09 18:52:06 -040035import android.os.IBinder;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040036import android.os.Message;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040037import android.os.RemoteException;
Joe Onoratoef1e7762010-09-17 18:38:38 -040038import android.text.TextUtils;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040039import android.util.Slog;
Joe Onorato55d2d762010-09-26 13:02:01 -070040import android.view.animation.Animation;
Daniel Sandlerce70d912010-09-02 11:59:41 -040041import android.view.animation.AnimationUtils;
Joe Onorato808182d2010-07-09 18:52:06 -040042import android.view.Gravity;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040043import android.view.LayoutInflater;
Joe Onoratob62ac122010-09-20 16:16:32 -040044import android.view.MotionEvent;
Daniel Sandler8304da42010-10-25 15:53:25 -040045import android.view.VelocityTracker;
Joe Onorato808182d2010-07-09 18:52:06 -040046import android.view.View;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -040047import android.view.ViewConfiguration;
Daniel Sandler9120d552010-07-23 09:11:14 -040048import android.view.ViewGroup;
49import android.view.WindowManager;
50import android.view.WindowManagerImpl;
Joe Onoratoef1e7762010-09-17 18:38:38 -040051import android.widget.FrameLayout;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -040052import android.widget.ImageView;
Joe Onorato808182d2010-07-09 18:52:06 -040053import android.widget.LinearLayout;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040054import android.widget.RemoteViews;
55import android.widget.ScrollView;
56import android.widget.TextSwitcher;
Daniel Sandler9120d552010-07-23 09:11:14 -040057import android.widget.TextView;
Joe Onorato808182d2010-07-09 18:52:06 -040058
59import com.android.internal.statusbar.StatusBarIcon;
Joe Onorato808182d2010-07-09 18:52:06 -040060import com.android.internal.statusbar.StatusBarNotification;
61
62import com.android.systemui.statusbar.*;
Joe Onorato013cfc12010-09-08 15:23:18 -040063import com.android.systemui.recent.RecentApplicationsActivity;
Joe Onorato808182d2010-07-09 18:52:06 -040064import com.android.systemui.R;
65
66public class TabletStatusBarService extends StatusBarService {
Daniel Sandlerfb970e92010-08-20 10:57:17 -040067 public static final boolean DEBUG = false;
Joe Onoratob62ac122010-09-20 16:16:32 -040068 public static final String TAG = "TabletStatusBarService";
Joe Onorato808182d2010-07-09 18:52:06 -040069
Joe Onoratob62ac122010-09-20 16:16:32 -040070 public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
71 public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -040072 public static final int MSG_OPEN_NOTIFICATION_PEEK = 1002;
73 public static final int MSG_CLOSE_NOTIFICATION_PEEK = 1003;
Joe Onoratob62ac122010-09-20 16:16:32 -040074 public static final int MSG_OPEN_SYSTEM_PANEL = 1010;
75 public static final int MSG_CLOSE_SYSTEM_PANEL = 1011;
Jim Miller44c66fe2010-10-20 18:32:52 -070076 public static final int MSG_OPEN_RECENTS_PANEL = 1020;
77 public static final int MSG_CLOSE_RECENTS_PANEL = 1021;
Daniel Sandler06e66302010-11-05 15:00:06 -040078 public static final int MSG_LIGHTS_ON = 1030;
79 public static final int MSG_LIGHTS_OUT = 1031;
Jim Miller44c66fe2010-10-20 18:32:52 -070080
Daniel Sandlerd39e3882010-08-31 14:16:13 -040081 private static final int MAX_IMAGE_LEVEL = 10000;
Jim Miller44c66fe2010-10-20 18:32:52 -070082 private static final boolean USE_2D_RECENTS = true;
Daniel Sandlerd39e3882010-08-31 14:16:13 -040083
Joe Onorato808182d2010-07-09 18:52:06 -040084 int mIconSize;
Daniel Sandler9120d552010-07-23 09:11:14 -040085
86 H mHandler = new H();
87
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040088 // tracking all current notifications
89 private NotificationData mNotns = new NotificationData();
Jim Miller44c66fe2010-10-20 18:32:52 -070090
Joe Onoratob62ac122010-09-20 16:16:32 -040091 TabletStatusBarView mStatusBarView;
Daniel Sandler271ea122010-10-22 14:06:10 -040092 ImageView mNotificationTrigger;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040093 NotificationIconArea mNotificationIconArea;
Joe Onorato55d2d762010-09-26 13:02:01 -070094 View mNotificationButtons;
Joe Onoratob62ac122010-09-20 16:16:32 -040095 View mSystemInfo;
Joe Onorato091e1b82010-09-26 18:04:44 -070096 View mNavigationArea;
Daniel Sandlere02d8082010-10-08 15:13:22 -040097 View mMenuButton;
Joe Onoratof3c3c4f2010-10-21 11:09:02 -040098 View mRecentButton;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -040099
satok06487a52010-10-29 11:37:18 +0900100 InputMethodButton mInputMethodButton;
101
Joe Onoratoddf680b2010-09-26 13:59:40 -0700102 NotificationPanel mNotificationPanel;
Daniel Sandler6425ef92010-08-11 16:10:19 -0400103 SystemPanel mSystemPanel;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400104 NotificationPanel mNotificationPeekWindow;
105 ViewGroup mNotificationPeekRow;
106 int mNotificationPeekIndex;
107 LayoutTransition mNotificationPeekScrubLeft, mNotificationPeekScrubRight;
108
109 int mNotificationPeekTapDuration;
110 int mNotificationFlingVelocity;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400111
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400112 ViewGroup mPile;
113 TextView mClearButton;
Joe Onorato55d2d762010-09-26 13:02:01 -0700114 TextView mDoNotDisturbButton;
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400115
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400116 ImageView mBatteryMeter;
117 ImageView mSignalMeter;
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400118 ImageView mSignalIcon;
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400119
Daniel Sandlerce70d912010-09-02 11:59:41 -0400120 View mBarContents;
121 View mCurtains;
122
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400123 NotificationIconArea.IconLayout mIconLayout;
124
Joe Onoratoef1e7762010-09-17 18:38:38 -0400125 TabletTicker mTicker;
126 View mTickerView;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400127 boolean mTicking;
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400128
129 // for disabling the status bar
130 int mDisabled = 0;
131
Joe Onorato55d2d762010-09-26 13:02:01 -0700132 boolean mNotificationsOn = true;
Jim Miller44c66fe2010-10-20 18:32:52 -0700133 private RecentAppsPanel mRecentsPanel;
Joe Onorato55d2d762010-09-26 13:02:01 -0700134
Daniel Sandler9120d552010-07-23 09:11:14 -0400135 protected void addPanelWindows() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400136 final Context context = mContext;
137
138 final Resources res = context.getResources();
Daniel Sandler9120d552010-07-23 09:11:14 -0400139 final int barHeight= res.getDimensionPixelSize(
140 com.android.internal.R.dimen.status_bar_height);
141
Jim Miller44c66fe2010-10-20 18:32:52 -0700142 // Notification Panel
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400143 mNotificationPanel = (NotificationPanel)View.inflate(context,
Joe Onoratoddf680b2010-09-26 13:59:40 -0700144 R.layout.sysbar_panel_notifications, null);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400145 mNotificationPanel.setVisibility(View.GONE);
Joe Onoratob62ac122010-09-20 16:16:32 -0400146 mNotificationPanel.setOnTouchListener(
Joe Onoratoddf680b2010-09-26 13:59:40 -0700147 new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PANEL, mNotificationPanel));
Joe Onoratob62ac122010-09-20 16:16:32 -0400148
Joe Onorato55d2d762010-09-26 13:02:01 -0700149 mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400150
Daniel Sandler9120d552010-07-23 09:11:14 -0400151 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400152 512, // ViewGroup.LayoutParams.WRAP_CONTENT,
Daniel Sandler9120d552010-07-23 09:11:14 -0400153 ViewGroup.LayoutParams.WRAP_CONTENT,
154 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
155 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
Jeff Brown46e75292010-11-10 16:53:45 -0800156 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
157 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
Daniel Sandler9120d552010-07-23 09:11:14 -0400158 PixelFormat.TRANSLUCENT);
Joe Onoratoea70e632010-09-27 17:59:37 -0700159 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
Daniel Sandler9120d552010-07-23 09:11:14 -0400160 lp.setTitle("NotificationPanel");
161 lp.windowAnimations = com.android.internal.R.style.Animation_SlidingCard;
162
163 WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
164
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400165 // Notification preview window
166 mNotificationPeekWindow = (NotificationPanel) View.inflate(context,
167 R.layout.sysbar_panel_notification_peek, null);
168 mNotificationPeekRow = (ViewGroup) mNotificationPeekWindow.findViewById(R.id.content);
169 mNotificationPeekWindow.setVisibility(View.GONE);
170 mNotificationPeekWindow.setOnTouchListener(
171 new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PANEL, mNotificationPeekWindow));
172 mNotificationPeekScrubRight = new LayoutTransition();
173 mNotificationPeekScrubRight.setAnimator(LayoutTransition.APPEARING,
174 ObjectAnimator.ofInt(null, "left", -512, 0));
175 mNotificationPeekScrubRight.setAnimator(LayoutTransition.DISAPPEARING,
176 ObjectAnimator.ofInt(null, "left", -512, 0));
177 mNotificationPeekScrubRight.setDuration(500);
178
179 mNotificationPeekScrubLeft = new LayoutTransition();
180 mNotificationPeekScrubLeft.setAnimator(LayoutTransition.APPEARING,
181 ObjectAnimator.ofInt(null, "left", 512, 0));
182 mNotificationPeekScrubLeft.setAnimator(LayoutTransition.DISAPPEARING,
183 ObjectAnimator.ofInt(null, "left", 512, 0));
184 mNotificationPeekScrubLeft.setDuration(500);
185
186 // XXX: setIgnoreChildren?
187 lp = new WindowManager.LayoutParams(
188 512, // ViewGroup.LayoutParams.WRAP_CONTENT,
189 ViewGroup.LayoutParams.WRAP_CONTENT,
190 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
191 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
Jeff Brown46e75292010-11-10 16:53:45 -0800192 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
193 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400194 PixelFormat.TRANSLUCENT);
195 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
196 lp.setTitle("NotificationPeekWindow");
197 lp.windowAnimations = com.android.internal.R.style.Animation_Toast;
198
199 WindowManagerImpl.getDefault().addView(mNotificationPeekWindow, lp);
200
Jim Miller44c66fe2010-10-20 18:32:52 -0700201 // System Panel
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400202 mSystemPanel = (SystemPanel) View.inflate(context, R.layout.sysbar_panel_system, null);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400203 mSystemPanel.setVisibility(View.GONE);
Joe Onoratoddf680b2010-09-26 13:59:40 -0700204 mSystemPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_SYSTEM_PANEL,
Jim Miller44c66fe2010-10-20 18:32:52 -0700205 mSystemPanel));
Joe Onoratob62ac122010-09-20 16:16:32 -0400206 mStatusBarView.setIgnoreChildren(1, mSystemInfo, mSystemPanel);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400207
Daniel Sandler9120d552010-07-23 09:11:14 -0400208 lp = new WindowManager.LayoutParams(
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400209 800,
Daniel Sandler6425ef92010-08-11 16:10:19 -0400210 ViewGroup.LayoutParams.WRAP_CONTENT,
Daniel Sandler9120d552010-07-23 09:11:14 -0400211 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
212 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
Jeff Brown46e75292010-11-10 16:53:45 -0800213 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
214 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
Daniel Sandler9120d552010-07-23 09:11:14 -0400215 PixelFormat.TRANSLUCENT);
216 lp.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
217 lp.setTitle("SystemPanel");
218 lp.windowAnimations = com.android.internal.R.style.Animation_SlidingCard;
219
220 WindowManagerImpl.getDefault().addView(mSystemPanel, lp);
Daniel Sandler6425ef92010-08-11 16:10:19 -0400221 mSystemPanel.setBar(this);
Jim Miller44c66fe2010-10-20 18:32:52 -0700222
223
224 // Recents Panel
225 if (USE_2D_RECENTS) {
226 mRecentsPanel = (RecentAppsPanel) View.inflate(context, R.layout.sysbar_panel_recent,
227 null);
228 mRecentsPanel.setVisibility(View.GONE);
229 mRecentsPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL,
230 mRecentsPanel));
231 mStatusBarView.setIgnoreChildren(2, mRecentButton, mRecentsPanel);
232
233 lp = new WindowManager.LayoutParams(
234 ViewGroup.LayoutParams.WRAP_CONTENT,
235 ViewGroup.LayoutParams.WRAP_CONTENT,
236 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
237 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
Jeff Brown46e75292010-11-10 16:53:45 -0800238 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
239 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
Jim Miller44c66fe2010-10-20 18:32:52 -0700240 PixelFormat.TRANSLUCENT);
241 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
242 lp.setTitle("RecentsPanel");
243 lp.windowAnimations = com.android.internal.R.style.Animation_SlidingCard;
244
245 WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
246 mRecentsPanel.setBar(this);
247 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400248 }
Joe Onorato808182d2010-07-09 18:52:06 -0400249
250 @Override
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400251 public void start() {
252 super.start(); // will add the main bar view
Joe Onorato808182d2010-07-09 18:52:06 -0400253 }
254
255 protected View makeStatusBarView() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400256 final Context context = mContext;
257 final Resources res = context.getResources();
Joe Onorato808182d2010-07-09 18:52:06 -0400258
259 mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
260
Joe Onoratob62ac122010-09-20 16:16:32 -0400261 final TabletStatusBarView sb = (TabletStatusBarView)View.inflate(
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400262 context, R.layout.status_bar, null);
Joe Onorato808182d2010-07-09 18:52:06 -0400263 mStatusBarView = sb;
264
Joe Onoratob62ac122010-09-20 16:16:32 -0400265 sb.setHandler(mHandler);
266
Daniel Sandlerce70d912010-09-02 11:59:41 -0400267 mBarContents = sb.findViewById(R.id.bar_contents);
268 mCurtains = sb.findViewById(R.id.lights_out);
Joe Onoratob62ac122010-09-20 16:16:32 -0400269 mSystemInfo = sb.findViewById(R.id.systemInfo);
Jim Miller44c66fe2010-10-20 18:32:52 -0700270 mRecentButton = sb.findViewById(R.id.recent_apps);
Joe Onoratof63b0f42010-09-12 17:03:19 -0400271
Daniel Sandler8304da42010-10-25 15:53:25 -0400272 mSystemInfo.setOnTouchListener(new ClockTouchListener());
Joe Onoratof63b0f42010-09-12 17:03:19 -0400273
Jim Miller44c66fe2010-10-20 18:32:52 -0700274 mRecentButton = sb.findViewById(R.id.recent_apps);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400275 mRecentButton.setOnClickListener(mOnClickListener);
276
Joe Onoratof63b0f42010-09-12 17:03:19 -0400277 SetLightsOnListener on = new SetLightsOnListener(true);
278 mCurtains.setOnClickListener(on);
279 mCurtains.setOnLongClickListener(on);
Daniel Sandlerce70d912010-09-02 11:59:41 -0400280
Joe Onorato55d2d762010-09-26 13:02:01 -0700281 // the button to open the notification area
Daniel Sandler271ea122010-10-22 14:06:10 -0400282 mNotificationTrigger = (ImageView) sb.findViewById(R.id.notificationTrigger);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400283 mNotificationTrigger.setOnClickListener(mOnClickListener);
Joe Onorato55d2d762010-09-26 13:02:01 -0700284
Joe Onorato808182d2010-07-09 18:52:06 -0400285 // the more notifications icon
286 mNotificationIconArea = (NotificationIconArea)sb.findViewById(R.id.notificationIcons);
287
Joe Onorato55d2d762010-09-26 13:02:01 -0700288 // the clear and dnd buttons
289 mNotificationButtons = sb.findViewById(R.id.notificationButtons);
290 mClearButton = (TextView)mNotificationButtons.findViewById(R.id.clear_all_button);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400291 mClearButton.setOnClickListener(mOnClickListener);
Joe Onorato55d2d762010-09-26 13:02:01 -0700292 mDoNotDisturbButton = (TextView)mNotificationButtons.findViewById(R.id.do_not_disturb);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400293 mDoNotDisturbButton.setOnClickListener(mOnClickListener);
Joe Onorato55d2d762010-09-26 13:02:01 -0700294
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400295 // where the icons go
296 mIconLayout = (NotificationIconArea.IconLayout) sb.findViewById(R.id.icons);
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400297 mIconLayout.setOnTouchListener(new NotificationIconTouchListener());
298
299 ViewConfiguration vc = ViewConfiguration.get(context);
300 mNotificationPeekTapDuration = vc.getTapTimeout();
301 mNotificationFlingVelocity = 300; // px/s
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400302
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400303 mTicker = new TabletTicker(context, (FrameLayout)sb.findViewById(R.id.ticker));
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400304
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400305 // System info (center)
306 mBatteryMeter = (ImageView) sb.findViewById(R.id.battery);
307 mSignalMeter = (ImageView) sb.findViewById(R.id.signal);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400308 mSignalIcon = (ImageView) sb.findViewById(R.id.signal_icon);
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400309
Joe Onorato091e1b82010-09-26 18:04:44 -0700310 // The navigation buttons
311 mNavigationArea = sb.findViewById(R.id.navigationArea);
Daniel Sandlere02d8082010-10-08 15:13:22 -0400312 mMenuButton = mNavigationArea.findViewById(R.id.menu);
Joe Onorato091e1b82010-09-26 18:04:44 -0700313
satok06487a52010-10-29 11:37:18 +0900314 // The bar contents buttons
315 mInputMethodButton = (InputMethodButton) mBarContents.findViewById(R.id.imeButton);
316
Joe Onorato5dd11692010-09-27 15:34:04 -0700317 // set the initial view visibility
318 setAreThereNotifications();
Daniel Sandler271ea122010-10-22 14:06:10 -0400319 refreshNotificationTrigger();
Joe Onorato5dd11692010-09-27 15:34:04 -0700320
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400321 // Add the windows
322 addPanelWindows();
323
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400324 mPile = (ViewGroup)mNotificationPanel.findViewById(R.id.content);
325 mPile.removeAllViews();
Jim Miller44c66fe2010-10-20 18:32:52 -0700326
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400327 ScrollView scroller = (ScrollView)mPile.getParent();
328 scroller.setFillViewport(true);
329
Joe Onorato808182d2010-07-09 18:52:06 -0400330 return sb;
331 }
332
333 protected int getStatusBarGravity() {
334 return Gravity.BOTTOM | Gravity.FILL_HORIZONTAL;
335 }
336
Daniel Sandler9120d552010-07-23 09:11:14 -0400337 private class H extends Handler {
Daniel Sandler9120d552010-07-23 09:11:14 -0400338 public void handleMessage(Message m) {
339 switch (m.what) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400340 case MSG_OPEN_NOTIFICATION_PEEK:
341 if (DEBUG) Slog.d(TAG, "opening notification peek window; arg=" + m.arg1);
342 if (m.arg1 >= 0) {
343 final int N = mNotns.size();
344 if (mNotificationPeekIndex < N) {
345 NotificationData.Entry entry = mNotns.get(N-1-mNotificationPeekIndex);
346 entry.icon.setBackgroundColor(0);
347 }
348
349 final int peekIndex = m.arg1;
350 if (peekIndex < N) {
351 Slog.d(TAG, "loading peek: " + peekIndex);
352 NotificationData.Entry entry = mNotns.get(N-1-peekIndex);
353 NotificationData.Entry copy = new NotificationData.Entry(
354 entry.key,
355 entry.notification,
356 entry.icon);
357 inflateViews(copy, mNotificationPeekRow);
358
359 entry.icon.setBackgroundColor(0x20FFFFFF);
360
361// mNotificationPeekRow.setLayoutTransition(
362// peekIndex < mNotificationPeekIndex
363// ? mNotificationPeekScrubLeft
364// : mNotificationPeekScrubRight);
365
366 mNotificationPeekRow.removeAllViews();
367 mNotificationPeekRow.addView(copy.row);
368
369 mNotificationPeekWindow.setVisibility(View.VISIBLE);
370 mNotificationPanel.setVisibility(View.GONE);
371
372 mNotificationPeekIndex = peekIndex;
373 }
374 }
375 break;
376 case MSG_CLOSE_NOTIFICATION_PEEK:
377 if (DEBUG) Slog.d(TAG, "closing notification peek window");
378 mNotificationPeekWindow.setVisibility(View.GONE);
379 mNotificationPeekRow.removeAllViews();
380 final int N = mNotns.size();
381 if (mNotificationPeekIndex < N) {
382 NotificationData.Entry entry = mNotns.get(N-1-mNotificationPeekIndex);
383 entry.icon.setBackgroundColor(0);
384 }
385 break;
Daniel Sandler9120d552010-07-23 09:11:14 -0400386 case MSG_OPEN_NOTIFICATION_PANEL:
387 if (DEBUG) Slog.d(TAG, "opening notifications panel");
Joe Onorato091e1b82010-09-26 18:04:44 -0700388 if (mNotificationPanel.getVisibility() == View.GONE) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400389 mNotificationPeekWindow.setVisibility(View.GONE);
390
Joe Onorato091e1b82010-09-26 18:04:44 -0700391 mDoNotDisturbButton.setText(mNotificationsOn
392 ? R.string.status_bar_do_not_disturb_button
393 : R.string.status_bar_please_disturb_button);
394 mNotificationPanel.setVisibility(View.VISIBLE);
395 setViewVisibility(mNotificationIconArea, View.GONE,
396 R.anim.notification_icons_out);
397 setViewVisibility(mNotificationButtons, View.VISIBLE,
398 R.anim.notification_buttons_in);
Daniel Sandler271ea122010-10-22 14:06:10 -0400399 refreshNotificationTrigger();
Joe Onorato091e1b82010-09-26 18:04:44 -0700400 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400401 break;
402 case MSG_CLOSE_NOTIFICATION_PANEL:
403 if (DEBUG) Slog.d(TAG, "closing notifications panel");
Joe Onorato091e1b82010-09-26 18:04:44 -0700404 if (mNotificationPanel.getVisibility() == View.VISIBLE) {
405 mNotificationPanel.setVisibility(View.GONE);
406 setViewVisibility(mNotificationIconArea, View.VISIBLE,
407 R.anim.notification_icons_in);
408 setViewVisibility(mNotificationButtons, View.GONE,
409 R.anim.notification_buttons_out);
Daniel Sandler271ea122010-10-22 14:06:10 -0400410 refreshNotificationTrigger();
Joe Onorato091e1b82010-09-26 18:04:44 -0700411 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400412 break;
413 case MSG_OPEN_SYSTEM_PANEL:
414 if (DEBUG) Slog.d(TAG, "opening system panel");
415 mSystemPanel.setVisibility(View.VISIBLE);
416 break;
417 case MSG_CLOSE_SYSTEM_PANEL:
418 if (DEBUG) Slog.d(TAG, "closing system panel");
419 mSystemPanel.setVisibility(View.GONE);
Joe Onorato31b26102010-10-27 14:32:28 -0700420 break;
Jim Miller44c66fe2010-10-20 18:32:52 -0700421 case MSG_OPEN_RECENTS_PANEL:
422 if (DEBUG) Slog.d(TAG, "opening recents panel");
423 if (mRecentsPanel != null) mRecentsPanel.setVisibility(View.VISIBLE);
424 break;
425 case MSG_CLOSE_RECENTS_PANEL:
426 if (DEBUG) Slog.d(TAG, "closing recents panel");
427 if (mRecentsPanel != null) mRecentsPanel.setVisibility(View.GONE);
Daniel Sandler9120d552010-07-23 09:11:14 -0400428 break;
Daniel Sandler06e66302010-11-05 15:00:06 -0400429 case MSG_LIGHTS_ON:
430 setViewVisibility(mCurtains, View.GONE, R.anim.lights_out_out);
431 setViewVisibility(mBarContents, View.VISIBLE, R.anim.status_bar_in);
432 break;
433 case MSG_LIGHTS_OUT:
434 animateCollapse();
435 setViewVisibility(mCurtains, View.VISIBLE, R.anim.lights_out_in);
436 setViewVisibility(mBarContents, View.GONE, R.anim.status_bar_out);
437 break;
Daniel Sandler9120d552010-07-23 09:11:14 -0400438 }
439 }
440 }
Daniel Sandler271ea122010-10-22 14:06:10 -0400441
442 public void refreshNotificationTrigger() {
Daniel Sandlercf3c7cf2010-10-22 15:30:12 -0400443 if (mNotificationTrigger == null) return;
444
Daniel Sandler271ea122010-10-22 14:06:10 -0400445 int resId;
446 boolean panel = (mNotificationPanel != null
447 && mNotificationPanel.getVisibility() == View.VISIBLE);
448 if (!mNotificationsOn) {
449 resId = R.drawable.ic_sysbar_noti_dnd;
450 } else if (mNotns.size() > 0) {
451 resId = panel ? R.drawable.ic_sysbar_noti_avail_open : R.drawable.ic_sysbar_noti_avail;
452 } else {
453 resId = panel ? R.drawable.ic_sysbar_noti_none_open : R.drawable.ic_sysbar_noti_none;
454 }
455 mNotificationTrigger.setImageResource(resId);
456 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400457
Daniel Sandlerd7db7b12010-08-13 16:26:39 -0400458 public void setBatteryMeter(int level, boolean plugged) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400459 if (DEBUG) Slog.d(TAG, "battery=" + level + (plugged ? " - plugged" : " - unplugged"));
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400460 mBatteryMeter.setImageResource(R.drawable.sysbar_batterymini);
461 // adjust percent to permyriad for ClipDrawable's sake
462 mBatteryMeter.setImageLevel(level * (MAX_IMAGE_LEVEL / 100));
Daniel Sandlerd7db7b12010-08-13 16:26:39 -0400463 }
464
Daniel Sandler764b4da2010-08-24 16:24:35 -0400465 public void setSignalMeter(int level, boolean isWifi) {
466 if (DEBUG) Slog.d(TAG, "signal=" + level);
467 if (level < 0) {
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400468 mSignalMeter.setImageDrawable(null);
Daniel Sandler764b4da2010-08-24 16:24:35 -0400469 mSignalMeter.setImageLevel(0);
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400470 mSignalIcon.setImageDrawable(null);
Daniel Sandler764b4da2010-08-24 16:24:35 -0400471 } else {
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400472 mSignalMeter.setImageResource(R.drawable.sysbar_wifimini);
473 // adjust to permyriad
474 mSignalMeter.setImageLevel(level * (MAX_IMAGE_LEVEL / 100));
Jim Miller44c66fe2010-10-20 18:32:52 -0700475 mSignalIcon.setImageResource(isWifi ? R.drawable.ic_sysbar_wifi_mini
Daniel Sandlerd39e3882010-08-31 14:16:13 -0400476 : R.drawable.ic_sysbar_wifi_mini); // XXX
Daniel Sandler764b4da2010-08-24 16:24:35 -0400477 }
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400478 }
Daniel Sandler9120d552010-07-23 09:11:14 -0400479
Joe Onorato808182d2010-07-09 18:52:06 -0400480 public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400481 if (DEBUG) Slog.d(TAG, "addIcon(" + slot + ") -> " + icon);
Joe Onorato808182d2010-07-09 18:52:06 -0400482 }
483
484 public void updateIcon(String slot, int index, int viewIndex,
485 StatusBarIcon old, StatusBarIcon icon) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400486 if (DEBUG) Slog.d(TAG, "updateIcon(" + slot + ") -> " + icon);
Joe Onorato808182d2010-07-09 18:52:06 -0400487 }
488
489 public void removeIcon(String slot, int index, int viewIndex) {
Daniel Sandler1e3ed8f2010-08-13 10:12:48 -0400490 if (DEBUG) Slog.d(TAG, "removeIcon(" + slot + ")");
Joe Onorato808182d2010-07-09 18:52:06 -0400491 }
492
493 public void addNotification(IBinder key, StatusBarNotification notification) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400494 if (DEBUG) Slog.d(TAG, "addNotification(" + key + " -> " + notification + ")");
495 addNotificationViews(key, notification);
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400496
497 boolean immersive = false;
498 try {
499 immersive = ActivityManagerNative.getDefault().isTopActivityImmersive();
500 Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
501 } catch (RemoteException ex) {
502 }
503 if (immersive) {
504 // TODO: immersive mode popups for tablet
505 } else if (notification.notification.fullScreenIntent != null) {
506 // not immersive & a full-screen alert should be shown
507 Slog.d(TAG, "Notification has fullScreenIntent and activity is not immersive;"
508 + " sending fullScreenIntent");
509 try {
510 notification.notification.fullScreenIntent.send();
511 } catch (PendingIntent.CanceledException e) {
512 }
513 } else {
Joe Onoratoef1e7762010-09-17 18:38:38 -0400514 tick(notification);
Daniel Sandlerfb970e92010-08-20 10:57:17 -0400515 }
Joe Onorato5dd11692010-09-27 15:34:04 -0700516
517 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400518 }
519
520 public void updateNotification(IBinder key, StatusBarNotification notification) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400521 if (DEBUG) Slog.d(TAG, "updateNotification(" + key + " -> " + notification + ") // TODO");
Jim Miller44c66fe2010-10-20 18:32:52 -0700522
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400523 final NotificationData.Entry oldEntry = mNotns.findByKey(key);
Daniel Sandler379020a2010-07-29 16:20:06 -0400524 if (oldEntry == null) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400525 Slog.w(TAG, "updateNotification for unknown key: " + key);
526 return;
527 }
528
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400529 final StatusBarNotification oldNotification = oldEntry.notification;
530 final RemoteViews oldContentView = oldNotification.notification.contentView;
531
532 final RemoteViews contentView = notification.notification.contentView;
533
534 if (false) {
535 Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
536 + " ongoing=" + oldNotification.isOngoing()
537 + " expanded=" + oldEntry.expanded
538 + " contentView=" + oldContentView);
539 Slog.d(TAG, "new notification: when=" + notification.notification.when
540 + " ongoing=" + oldNotification.isOngoing()
541 + " contentView=" + contentView);
542 }
543
544 // Can we just reapply the RemoteViews in place? If when didn't change, the order
545 // didn't change.
546 if (notification.notification.when == oldNotification.notification.when
547 && notification.isOngoing() == oldNotification.isOngoing()
548 && oldEntry.expanded != null
549 && contentView != null
550 && oldContentView != null
551 && contentView.getPackage() != null
552 && oldContentView.getPackage() != null
553 && oldContentView.getPackage().equals(contentView.getPackage())
554 && oldContentView.getLayoutId() == contentView.getLayoutId()) {
555 if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
556 oldEntry.notification = notification;
557 try {
558 // Reapply the RemoteViews
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400559 contentView.reapply(mContext, oldEntry.content);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400560 // update the contentIntent
561 final PendingIntent contentIntent = notification.notification.contentIntent;
562 if (contentIntent != null) {
563 oldEntry.content.setOnClickListener(new NotificationClicker(contentIntent,
564 notification.pkg, notification.tag, notification.id));
Joe Onorato184498c2010-10-08 17:57:18 -0400565 } else {
566 oldEntry.content.setOnClickListener(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400567 }
568 // Update the icon.
569 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
570 notification.notification.icon, notification.notification.iconLevel,
571 notification.notification.number);
572 if (!oldEntry.icon.set(ic)) {
573 handleNotificationError(key, notification, "Couldn't update icon: " + ic);
574 return;
575 }
576 }
577 catch (RuntimeException e) {
578 // It failed to add cleanly. Log, and remove the view from the panel.
579 Slog.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
580 removeNotificationViews(key);
581 addNotificationViews(key, notification);
582 }
583 } else {
584 if (DEBUG) Slog.d(TAG, "not reusing notification for key: " + key);
585 removeNotificationViews(key);
586 addNotificationViews(key, notification);
587 }
Joe Onoratoef1e7762010-09-17 18:38:38 -0400588 // TODO: ticker; immersive mode
Joe Onorato5dd11692010-09-27 15:34:04 -0700589
590 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400591 }
592
593 public void removeNotification(IBinder key) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400594 if (DEBUG) Slog.d(TAG, "removeNotification(" + key + ") // TODO");
595 removeNotificationViews(key);
Joe Onorato5dd11692010-09-27 15:34:04 -0700596 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400597 }
598
599 public void disable(int state) {
Joe Onorato091e1b82010-09-26 18:04:44 -0700600 int old = mDisabled;
601 int diff = state ^ old;
602 Slog.d(TAG, "disable... old=0x" + Integer.toHexString(old)
603 + " diff=0x" + Integer.toHexString(diff)
604 + " state=0x" + Integer.toHexString(state));
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400605 mDisabled = state;
606
Joe Onorato091e1b82010-09-26 18:04:44 -0700607 // act accordingly
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400608 if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
609 if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
610 Slog.d(TAG, "DISABLE_EXPAND: yes");
611 animateCollapse();
612 }
613 }
614 if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
615 if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
616 Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
Joe Onorato091e1b82010-09-26 18:04:44 -0700617 setViewVisibility(mNotificationTrigger, View.GONE,
618 R.anim.notification_icons_out);
619 setViewVisibility(mNotificationIconArea, View.GONE,
620 R.anim.notification_icons_out);
621 mTicker.halt();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400622 } else {
623 Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: no");
Joe Onorato091e1b82010-09-26 18:04:44 -0700624 setViewVisibility(mNotificationTrigger, View.VISIBLE,
625 R.anim.notification_icons_in);
626 setViewVisibility(mNotificationIconArea, View.VISIBLE,
627 R.anim.notification_icons_in);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400628 }
629 } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
Joe Onorato091e1b82010-09-26 18:04:44 -0700630 if ((state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
Joe Onoratoef1e7762010-09-17 18:38:38 -0400631 mTicker.halt();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400632 }
633 }
Joe Onorato091e1b82010-09-26 18:04:44 -0700634 if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
635 if ((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
636 Slog.d(TAG, "DISABLE_SYSTEM_INFO: yes");
637 setViewVisibility(mSystemInfo, View.GONE, R.anim.navigation_out);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400638 } else {
Joe Onorato091e1b82010-09-26 18:04:44 -0700639 Slog.d(TAG, "DISABLE_SYSTEM_INFO: no");
640 setViewVisibility(mSystemInfo, View.VISIBLE, R.anim.navigation_in);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400641 }
642 }
Joe Onorato091e1b82010-09-26 18:04:44 -0700643 if ((diff & StatusBarManager.DISABLE_NAVIGATION) != 0) {
644 if ((state & StatusBarManager.DISABLE_NAVIGATION) != 0) {
645 Slog.d(TAG, "DISABLE_NAVIGATION: yes");
646 setViewVisibility(mNavigationArea, View.GONE, R.anim.navigation_out);
647 } else {
648 Slog.d(TAG, "DISABLE_NAVIGATION: no");
649 setViewVisibility(mNavigationArea, View.VISIBLE, R.anim.navigation_in);
650 }
651 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400652 }
653
Joe Onoratoef1e7762010-09-17 18:38:38 -0400654 private boolean hasTicker(Notification n) {
655 return !TextUtils.isEmpty(n.tickerText)
656 || !TextUtils.isEmpty(n.tickerTitle)
657 || !TextUtils.isEmpty(n.tickerSubtitle);
658 }
659
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400660 private void tick(StatusBarNotification n) {
Joe Onorato55d2d762010-09-26 13:02:01 -0700661 // Don't show the ticker when the windowshade is open.
662 if (mNotificationPanel.getVisibility() == View.VISIBLE) {
663 return;
664 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400665 // Show the ticker if one is requested. Also don't do this
666 // until status bar window is attached to the window manager,
667 // because... well, what's the point otherwise? And trying to
668 // run a ticker without being attached will crash!
Joe Onoratoef1e7762010-09-17 18:38:38 -0400669 if (hasTicker(n.notification) && mStatusBarView.getWindowToken() != null) {
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400670 if (0 == (mDisabled & (StatusBarManager.DISABLE_NOTIFICATION_ICONS
671 | StatusBarManager.DISABLE_NOTIFICATION_TICKER))) {
Joe Onoratoef1e7762010-09-17 18:38:38 -0400672 mTicker.add(n);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -0400673 }
674 }
675 }
676
Joe Onorato808182d2010-07-09 18:52:06 -0400677 public void animateExpand() {
Joe Onoratob62ac122010-09-20 16:16:32 -0400678 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
679 mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
Joe Onorato808182d2010-07-09 18:52:06 -0400680 }
681
682 public void animateCollapse() {
Joe Onoratob62ac122010-09-20 16:16:32 -0400683 mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PANEL);
684 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PANEL);
685 mHandler.removeMessages(MSG_CLOSE_SYSTEM_PANEL);
686 mHandler.sendEmptyMessage(MSG_CLOSE_SYSTEM_PANEL);
Jim Miller44c66fe2010-10-20 18:32:52 -0700687 mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
688 mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
Daniel Sandler9120d552010-07-23 09:11:14 -0400689 }
690
Daniel Sandler06e66302010-11-05 15:00:06 -0400691 // called by StatusBarService
692 @Override
Joe Onorato93056472010-09-10 10:30:46 -0400693 public void setLightsOn(boolean on) {
Daniel Sandler06e66302010-11-05 15:00:06 -0400694 mHandler.removeMessages(MSG_LIGHTS_OUT);
695 mHandler.removeMessages(MSG_LIGHTS_ON);
696 mHandler.sendEmptyMessage(on ? MSG_LIGHTS_ON : MSG_LIGHTS_OUT);
Joe Onorato93056472010-09-10 10:30:46 -0400697 }
698
Daniel Sandlere02d8082010-10-08 15:13:22 -0400699 public void setMenuKeyVisible(boolean visible) {
700 if (DEBUG) {
701 Slog.d(TAG, (visible?"showing":"hiding") + " the MENU button");
702 }
703 setViewVisibility(mMenuButton,
704 visible ? View.VISIBLE : View.INVISIBLE,
705 visible ? R.anim.navigation_in : R.anim.navigation_out);
706 }
707
satok06487a52010-10-29 11:37:18 +0900708 public void setIMEButtonVisible(boolean visible) {
satok06487a52010-10-29 11:37:18 +0900709 if (DEBUG) {
710 Slog.d(TAG, (visible?"showing":"hiding") + " the IME button");
711 }
712 mInputMethodButton.setIMEButtonVisible(visible);
713 }
714
Joe Onorato5dd11692010-09-27 15:34:04 -0700715 private void setAreThereNotifications() {
716 final boolean hasClearable = mNotns.hasClearableItems();
717
718 //Slog.d(TAG, "setAreThereNotifications hasClerable=" + hasClearable);
719
720 // Show or hide the "Clear all" button. Note that we don't do an animation
721 // if it's not on screen, so that if someone opens the bar right then they
722 // don't see the animation in progress.
723 // (no ongoing notifications are clearable)
724 if (hasClearable) {
725 if (mNotificationButtons.getVisibility() == View.VISIBLE) {
726 setViewVisibility(mClearButton, View.VISIBLE, R.anim.notification_buttons_in);
727 } else {
728 mClearButton.setVisibility(View.VISIBLE);
729 }
730 } else {
731 if (mNotificationButtons.getVisibility() == View.VISIBLE) {
732 setViewVisibility(mClearButton, View.GONE, R.anim.notification_buttons_out);
733 } else {
734 mClearButton.setVisibility(View.GONE);
735 }
736 }
737
738 /*
739 mOngoingTitle.setVisibility(ongoing ? View.VISIBLE : View.GONE);
740 mLatestTitle.setVisibility(latest ? View.VISIBLE : View.GONE);
741
742 if (ongoing || latest) {
743 mNoNotificationsTitle.setVisibility(View.GONE);
744 } else {
745 mNoNotificationsTitle.setVisibility(View.VISIBLE);
746 }
747 */
748 }
749
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400750 /**
751 * Cancel this notification and tell the status bar service about the failure. Hold no locks.
752 */
753 void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
754 removeNotification(key);
755 try {
756 mBarService.onNotificationError(n.pkg, n.tag, n.id, n.uid, n.initialPid, message);
757 } catch (RemoteException ex) {
758 // The end is nigh.
759 }
760 }
761
Daniel Sandler8304da42010-10-25 15:53:25 -0400762 private class ClockTouchListener implements View.OnTouchListener {
Daniel Sandler06e66302010-11-05 15:00:06 -0400763 VelocityTracker mVT = null;
764 int mInitX, mInitY;
Daniel Sandler8304da42010-10-25 15:53:25 -0400765 public boolean onTouch (View v, MotionEvent event) {
Daniel Sandler06e66302010-11-05 15:00:06 -0400766 final int x = (int) event.getX();
767 final int y = (int) event.getY();
Daniel Sandler8304da42010-10-25 15:53:25 -0400768 switch (event.getAction()) {
769 case MotionEvent.ACTION_DOWN:
770 mVT = VelocityTracker.obtain();
Daniel Sandler06e66302010-11-05 15:00:06 -0400771 mInitX = x;
772 mInitY = y;
773 mHandler.sendEmptyMessageDelayed(MSG_LIGHTS_OUT,
774 ViewConfiguration.getLongPressTimeout());
775 break;
Daniel Sandler8304da42010-10-25 15:53:25 -0400776 case MotionEvent.ACTION_OUTSIDE:
777 case MotionEvent.ACTION_MOVE:
Daniel Sandler06e66302010-11-05 15:00:06 -0400778 final Rect r = new Rect();
779 final float radius = mSystemInfo.getHeight() / 2;
780 if (Math.abs(x - mInitX) > radius || Math.abs(y - mInitY) > radius) {
781 mHandler.removeMessages(MSG_LIGHTS_OUT);
782 }
Daniel Sandler8304da42010-10-25 15:53:25 -0400783 if (mVT == null) break;
784 mVT.addMovement(event);
785 mVT.computeCurrentVelocity(1000);
Daniel Sandler8304da42010-10-25 15:53:25 -0400786 if (mVT.getYVelocity() < -200 && mSystemPanel.getVisibility() == View.GONE) {
787 mHandler.removeMessages(MSG_OPEN_SYSTEM_PANEL);
788 mHandler.sendEmptyMessage(MSG_OPEN_SYSTEM_PANEL);
Daniel Sandler06e66302010-11-05 15:00:06 -0400789 } else if (mVT.getYVelocity() > 200) {
790 mHandler.sendEmptyMessage(MSG_LIGHTS_OUT);
Daniel Sandler8304da42010-10-25 15:53:25 -0400791 }
792 return true;
793 case MotionEvent.ACTION_UP:
794 case MotionEvent.ACTION_CANCEL:
795 mVT.recycle();
796 mVT = null;
Daniel Sandler06e66302010-11-05 15:00:06 -0400797 mHandler.removeMessages(MSG_LIGHTS_OUT);
Daniel Sandler8304da42010-10-25 15:53:25 -0400798 return true;
799 }
800 return false;
801 }
802 }
803
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400804 private View.OnClickListener mOnClickListener = new View.OnClickListener() {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400805 public void onClick(View v) {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400806 if (v == mClearButton) {
807 onClickClearButton();
808 } else if (v == mDoNotDisturbButton) {
809 onClickDoNotDisturb();
810 } else if (v == mNotificationTrigger) {
811 onClickNotificationTrigger();
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400812 } else if (v == mRecentButton) {
813 onClickRecentButton();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400814 }
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400815 }
816 };
817
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400818 void onClickClearButton() {
819 try {
820 mBarService.onClearAllNotifications();
821 } catch (RemoteException ex) {
822 // system process is dead if we're here.
Joe Onorato55d2d762010-09-26 13:02:01 -0700823 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400824 animateCollapse();
Daniel Sandler271ea122010-10-22 14:06:10 -0400825 refreshNotificationTrigger();
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400826 }
827
828 void onClickDoNotDisturb() {
829 mNotificationsOn = !mNotificationsOn;
Daniel Sandlercf3c7cf2010-10-22 15:30:12 -0400830 mIconLayout.setVisibility(mNotificationsOn ? View.VISIBLE : View.INVISIBLE); // TODO: animation
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400831 animateCollapse();
Daniel Sandler271ea122010-10-22 14:06:10 -0400832 refreshNotificationTrigger();
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400833 }
834
835 public void onClickNotificationTrigger() {
836 if (DEBUG) Slog.d(TAG, "clicked notification icons");
837 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
Daniel Sandler271ea122010-10-22 14:06:10 -0400838 if (!mNotificationsOn) {
839 mNotificationsOn = true;
Daniel Sandlercf3c7cf2010-10-22 15:30:12 -0400840 mIconLayout.setVisibility(View.VISIBLE); // TODO: animation
Daniel Sandler271ea122010-10-22 14:06:10 -0400841 refreshNotificationTrigger();
842 } else {
Jim Miller44c66fe2010-10-20 18:32:52 -0700843 int msg = (mNotificationPanel.getVisibility() == View.GONE)
Daniel Sandler271ea122010-10-22 14:06:10 -0400844 ? MSG_OPEN_NOTIFICATION_PANEL
845 : MSG_CLOSE_NOTIFICATION_PANEL;
846 mHandler.removeMessages(msg);
847 mHandler.sendEmptyMessage(msg);
848 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400849 }
850 }
851
852 public void onClickSystemInfo() {
853 if (DEBUG) Slog.d(TAG, "clicked system info");
854 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
Jim Miller44c66fe2010-10-20 18:32:52 -0700855 int msg = (mSystemPanel.getVisibility() == View.GONE)
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400856 ? MSG_OPEN_SYSTEM_PANEL
857 : MSG_CLOSE_SYSTEM_PANEL;
858 mHandler.removeMessages(msg);
859 mHandler.sendEmptyMessage(msg);
860 }
861 }
862
863 public void onClickRecentButton() {
864 if (DEBUG) Slog.d(TAG, "clicked recent apps");
Jim Miller44c66fe2010-10-20 18:32:52 -0700865 if (mRecentsPanel == null) {
866 Intent intent = new Intent();
867 intent.setClass(mContext, RecentApplicationsActivity.class);
868 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
869 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
870 mContext.startActivity(intent);
871 } else {
872 if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
873 int msg = (mRecentsPanel.getVisibility() == View.GONE)
874 ? MSG_OPEN_RECENTS_PANEL
875 : MSG_CLOSE_RECENTS_PANEL;
876 mHandler.removeMessages(msg);
877 mHandler.sendEmptyMessage(msg);
878 }
879 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400880 }
Joe Onorato55d2d762010-09-26 13:02:01 -0700881
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400882 private class NotificationClicker implements View.OnClickListener {
883 private PendingIntent mIntent;
884 private String mPkg;
885 private String mTag;
886 private int mId;
887
888 NotificationClicker(PendingIntent intent, String pkg, String tag, int id) {
889 mIntent = intent;
890 mPkg = pkg;
891 mTag = tag;
892 mId = id;
893 }
894
895 public void onClick(View v) {
896 try {
897 // The intent we are sending is for the application, which
898 // won't have permission to immediately start an activity after
899 // the user switches to home. We know it is safe to do at this
900 // point, so make sure new activity switches are now allowed.
901 ActivityManagerNative.getDefault().resumeAppSwitches();
902 } catch (RemoteException e) {
903 }
904
905 if (mIntent != null) {
906 int[] pos = new int[2];
907 v.getLocationOnScreen(pos);
908 Intent overlay = new Intent();
909 overlay.setSourceBounds(
910 new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
911 try {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400912 mIntent.send(mContext, 0, overlay);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400913 } catch (PendingIntent.CanceledException e) {
914 // the stack trace isn't very helpful here. Just log the exception message.
915 Slog.w(TAG, "Sending contentIntent failed: " + e);
916 }
917 }
918
919 try {
920 mBarService.onNotificationClick(mPkg, mTag, mId);
921 } catch (RemoteException ex) {
922 // system process is dead if we're here.
923 }
924
925 // close the shade if it was open
926 animateCollapse();
927
928 // If this click was on the intruder alert, hide that instead
929// mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
930 }
931 }
932
933 StatusBarNotification removeNotificationViews(IBinder key) {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400934 NotificationData.Entry entry = mNotns.remove(key);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400935 if (entry == null) {
936 Slog.w(TAG, "removeNotification for unknown key: " + key);
937 return null;
938 }
939 // Remove the expanded view.
940 ViewGroup rowParent = (ViewGroup)entry.row.getParent();
941 if (rowParent != null) rowParent.removeView(entry.row);
942 // Remove the icon.
Daniel Sandler0f0b11c2010-08-04 15:54:58 -0400943// ViewGroup iconParent = (ViewGroup)entry.icon.getParent();
944// if (iconParent != null) iconParent.removeView(entry.icon);
945 refreshIcons();
Daniel Sandler3eebd1f2010-07-27 08:39:33 -0400946
947 return entry.notification;
948 }
949
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -0400950 private class NotificationIconTouchListener implements View.OnTouchListener {
951 VelocityTracker mVT;
952
953 public NotificationIconTouchListener() {
954 }
955
956 public boolean onTouch(View v, MotionEvent event) {
957 boolean peeking = mNotificationPeekWindow.getVisibility() != View.GONE;
958 boolean panelShowing = mNotificationPanel.getVisibility() != View.GONE;
959 if (panelShowing) return false;
960
961 switch (event.getAction()) {
962 case MotionEvent.ACTION_DOWN:
963 mVT = VelocityTracker.obtain();
964
965 // fall through
966 case MotionEvent.ACTION_OUTSIDE:
967 case MotionEvent.ACTION_MOVE:
968 // peek and switch icons if necessary
969 int numIcons = mIconLayout.getChildCount();
970 int peekIndex =
971 (int)((float)event.getX() * numIcons / mIconLayout.getWidth());
972 if (peekIndex > numIcons - 1) peekIndex = numIcons - 1;
973 else if (peekIndex < 0) peekIndex = 0;
974
975 if (!peeking || mNotificationPeekIndex != peekIndex) {
976 if (DEBUG) Slog.d(TAG, "will peek at notification #" + peekIndex);
977 Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
978 peekMsg.arg1 = peekIndex;
979
980 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
981
982 // no delay if we're scrubbing left-right
983 mHandler.sendMessageDelayed(peekMsg,
984 peeking ? 0 : mNotificationPeekTapDuration);
985 }
986
987 // check for fling
988 if (mVT != null) {
989 mVT.addMovement(event);
990 mVT.computeCurrentVelocity(1000);
991 // require a little more oomph once we're already in peekaboo mode
992 if (!panelShowing && (
993 (peeking && mVT.getYVelocity() < -mNotificationFlingVelocity*3)
994 || (mVT.getYVelocity() < -mNotificationFlingVelocity))) {
995 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
996 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
997 mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
998 mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
999 }
1000 }
1001 return true;
1002 case MotionEvent.ACTION_UP:
1003 case MotionEvent.ACTION_CANCEL:
1004 mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
1005 if (peeking) {
1006 mHandler.sendEmptyMessageDelayed(MSG_CLOSE_NOTIFICATION_PEEK, 250);
1007 }
1008 mVT.recycle();
1009 mVT = null;
1010 return true;
1011 }
1012 return false;
1013 }
1014 }
1015
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001016 StatusBarIconView addNotificationViews(IBinder key, StatusBarNotification notification) {
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001017 if (DEBUG) {
1018 Slog.d(TAG, "addNotificationViews(key=" + key + ", notification=" + notification);
1019 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001020 // Construct the icon.
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001021 final StatusBarIconView iconView = new StatusBarIconView(mContext,
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001022 notification.pkg + "/0x" + Integer.toHexString(notification.id));
1023 iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
1024
1025 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
1026 notification.notification.icon,
1027 notification.notification.iconLevel,
1028 notification.notification.number);
1029 if (!iconView.set(ic)) {
1030 handleNotificationError(key, notification, "Couldn't attach StatusBarIcon: " + ic);
1031 return null;
1032 }
1033 // Construct the expanded view.
1034 NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001035 if (!inflateViews(entry, mPile)) {
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001036 handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
1037 + notification);
1038 return null;
1039 }
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001040
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001041 // Add the icon.
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001042 mNotns.add(entry);
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001043 refreshIcons();
1044
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001045 return iconView;
1046 }
1047
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001048 private void refreshIcons() {
1049 // XXX: need to implement a new limited linear layout class
1050 // to avoid removing & readding everything
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001051
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001052 final int ICON_LIMIT = 4;
1053 final LinearLayout.LayoutParams params
1054 = new LinearLayout.LayoutParams(mIconSize, mIconSize);
1055
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001056 int N = mNotns.size();
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001057
1058 if (DEBUG) {
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001059 Slog.d(TAG, "refreshing icons: " + N + " notifications, mIconLayout=" + mIconLayout);
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001060 }
1061
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001062 ArrayList<View> toShow = new ArrayList<View>();
1063
1064 for (int i=0; i<ICON_LIMIT; i++) {
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001065 if (i>=N) break;
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001066 toShow.add(mNotns.get(N-i-1).icon);
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001067 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001068
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001069 ArrayList<View> toRemove = new ArrayList<View>();
1070 for (int i=0; i<mIconLayout.getChildCount(); i++) {
1071 View child = mIconLayout.getChildAt(i);
1072 if (!toShow.contains(child)) {
1073 toRemove.add(child);
1074 }
Daniel Sandlerdfa08db2010-08-05 16:18:42 -04001075 }
Daniel Sandler271ea122010-10-22 14:06:10 -04001076
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001077 for (View remove : toRemove) {
1078 mIconLayout.removeView(remove);
1079 }
1080
1081 for (int i=0; i<toShow.size(); i++) {
1082 View v = toShow.get(i);
1083 if (v.getParent() == null) {
1084 mIconLayout.addView(toShow.get(i), i, params);
1085 }
1086 }
1087
1088 loadNotificationPanel();
Daniel Sandler271ea122010-10-22 14:06:10 -04001089 refreshNotificationTrigger();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001090 }
1091
Daniel Sandlerb0cc50d2010-10-26 16:55:56 -04001092 private void loadNotificationPanel() {
1093 int N = mNotns.size();
1094
1095 ArrayList<View> toShow = new ArrayList<View>();
1096
1097 for (int i=0; i<N; i++) {
1098 View row = mNotns.get(N-i-1).row;
1099 toShow.add(row);
1100 }
1101
1102 ArrayList<View> toRemove = new ArrayList<View>();
1103 for (int i=0; i<mPile.getChildCount(); i++) {
1104 View child = mPile.getChildAt(i);
1105 if (!toShow.contains(child)) {
1106 toRemove.add(child);
1107 }
1108 }
1109
1110 for (View remove : toRemove) {
1111 mPile.removeView(remove);
1112 }
1113
1114 for (int i=0; i<toShow.size(); i++) {
1115 View v = toShow.get(i);
1116 if (v.getParent() == null) {
1117 mPile.addView(toShow.get(i));
1118 }
1119 }
1120 }
1121
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001122 private boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) {
1123 StatusBarNotification sbn = entry.notification;
1124 RemoteViews remoteViews = sbn.notification.contentView;
1125 if (remoteViews == null) {
1126 return false;
1127 }
1128
1129 // create the row view
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001130 LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(
1131 Context.LAYOUT_INFLATER_SERVICE);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001132 View row = inflater.inflate(R.layout.status_bar_latest_event, parent, false);
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001133 View vetoButton = row.findViewById(R.id.veto);
Joe Onoratoa4a65032010-09-27 15:53:44 -07001134 if (entry.notification.isClearable()) {
1135 final String _pkg = sbn.pkg;
1136 final String _tag = sbn.tag;
1137 final int _id = sbn.id;
Jim Miller44c66fe2010-10-20 18:32:52 -07001138 vetoButton.setOnClickListener(new View.OnClickListener() {
Joe Onoratoa4a65032010-09-27 15:53:44 -07001139 public void onClick(View v) {
1140 try {
1141 mBarService.onNotificationClear(_pkg, _tag, _id);
1142 } catch (RemoteException ex) {
1143 // system process is dead if we're here.
1144 }
1145 // animateCollapse();
Daniel Sandler0f0b11c2010-08-04 15:54:58 -04001146 }
Joe Onoratoa4a65032010-09-27 15:53:44 -07001147 });
1148 } else {
1149 vetoButton.setVisibility(View.INVISIBLE);
1150 }
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001151
1152 // bind the click event to the content area
1153 ViewGroup content = (ViewGroup)row.findViewById(R.id.content);
1154 // XXX: update to allow controls within notification views
1155 content.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
1156// content.setOnFocusChangeListener(mFocusChangeListener);
1157 PendingIntent contentIntent = sbn.notification.contentIntent;
1158 if (contentIntent != null) {
1159 content.setOnClickListener(new NotificationClicker(contentIntent,
1160 sbn.pkg, sbn.tag, sbn.id));
Joe Onorato184498c2010-10-08 17:57:18 -04001161 } else {
1162 content.setOnClickListener(null);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001163 }
1164
1165 View expanded = null;
1166 Exception exception = null;
1167 try {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001168 expanded = remoteViews.apply(mContext, content);
Daniel Sandler3eebd1f2010-07-27 08:39:33 -04001169 }
1170 catch (RuntimeException e) {
1171 exception = e;
1172 }
1173 if (expanded == null) {
1174 String ident = sbn.pkg + "/0x" + Integer.toHexString(sbn.id);
1175 Slog.e(TAG, "couldn't inflate view for notification " + ident, exception);
1176 return false;
1177 } else {
1178 content.addView(expanded);
1179 row.setDrawingCacheEnabled(true);
1180 }
1181
1182 entry.row = row;
1183 entry.content = content;
1184 entry.expanded = expanded;
1185
1186 return true;
1187 }
Daniel Sandlerce70d912010-09-02 11:59:41 -04001188
Joe Onoratof63b0f42010-09-12 17:03:19 -04001189 public class SetLightsOnListener implements View.OnLongClickListener,
1190 View.OnClickListener {
1191 private boolean mOn;
Daniel Sandlerce70d912010-09-02 11:59:41 -04001192
Joe Onoratof63b0f42010-09-12 17:03:19 -04001193 SetLightsOnListener(boolean on) {
1194 mOn = on;
1195 }
1196
1197 public void onClick(View v) {
Daniel Sandler06e66302010-11-05 15:00:06 -04001198 setLightsOn(mOn);
Joe Onoratof63b0f42010-09-12 17:03:19 -04001199 }
1200
1201 public boolean onLongClick(View v) {
Daniel Sandler06e66302010-11-05 15:00:06 -04001202 setLightsOn(mOn);
Joe Onoratof63b0f42010-09-12 17:03:19 -04001203 return true;
1204 }
1205
Daniel Sandlerce70d912010-09-02 11:59:41 -04001206 }
Joe Onoratob62ac122010-09-20 16:16:32 -04001207
1208 public class TouchOutsideListener implements View.OnTouchListener {
1209 private int mMsg;
Joe Onoratoddf680b2010-09-26 13:59:40 -07001210 private StatusBarPanel mPanel;
Joe Onoratob62ac122010-09-20 16:16:32 -04001211
Joe Onoratoddf680b2010-09-26 13:59:40 -07001212 public TouchOutsideListener(int msg, StatusBarPanel panel) {
Joe Onoratob62ac122010-09-20 16:16:32 -04001213 mMsg = msg;
Joe Onoratoddf680b2010-09-26 13:59:40 -07001214 mPanel = panel;
Joe Onoratob62ac122010-09-20 16:16:32 -04001215 }
1216
1217 public boolean onTouch(View v, MotionEvent ev) {
Joe Onoratoddf680b2010-09-26 13:59:40 -07001218 final int action = ev.getAction();
1219 if (action == MotionEvent.ACTION_OUTSIDE
1220 || (action == MotionEvent.ACTION_DOWN
1221 && !mPanel.isInContentArea((int)ev.getX(), (int)ev.getY()))) {
Joe Onoratob62ac122010-09-20 16:16:32 -04001222 mHandler.removeMessages(mMsg);
1223 mHandler.sendEmptyMessage(mMsg);
1224 return true;
1225 }
1226 return false;
1227 }
1228 }
Joe Onorato091e1b82010-09-26 18:04:44 -07001229
1230 private void setViewVisibility(View v, int vis, int anim) {
1231 if (v.getVisibility() != vis) {
Joe Onorato5dd11692010-09-27 15:34:04 -07001232 //Slog.d(TAG, "setViewVisibility vis=" + (vis == View.VISIBLE) + " v=" + v);
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001233 v.setAnimation(AnimationUtils.loadAnimation(mContext, anim));
Joe Onorato091e1b82010-09-26 18:04:44 -07001234 v.setVisibility(vis);
1235 }
1236 }
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04001237
1238
1239 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1240 pw.print("mDisabled=0x");
1241 pw.println(Integer.toHexString(mDisabled));
1242 }
Joe Onorato808182d2010-07-09 18:52:06 -04001243}
Daniel Sandlerd39e3882010-08-31 14:16:13 -04001244
1245