BaseStatusBar.java revision ecc395a51053c433e359a6cfd6c23a193ee546c0
1/* 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; 18 19import java.util.ArrayList; 20 21import android.content.Context; 22import android.os.Handler; 23import android.os.IBinder; 24import android.os.Message; 25import android.os.RemoteException; 26import android.os.ServiceManager; 27import android.util.Log; 28import android.util.Slog; 29import android.view.Display; 30import android.view.IWindowManager; 31import android.view.LayoutInflater; 32import android.view.MotionEvent; 33import android.view.View; 34import android.view.ViewGroup.LayoutParams; 35import android.view.WindowManager; 36import android.view.WindowManagerImpl; 37import android.widget.LinearLayout; 38 39import com.android.internal.statusbar.IStatusBarService; 40import com.android.internal.statusbar.StatusBarIcon; 41import com.android.internal.statusbar.StatusBarIconList; 42import com.android.internal.statusbar.StatusBarNotification; 43import com.android.systemui.SystemUI; 44import com.android.systemui.recent.RecentsPanelView; 45import com.android.systemui.recent.RecentTasksLoader; 46import com.android.systemui.recent.TaskDescription; 47import com.android.systemui.statusbar.CommandQueue; 48import com.android.systemui.statusbar.tablet.StatusBarPanel; 49 50import com.android.systemui.R; 51 52public abstract class BaseStatusBar extends SystemUI implements 53 CommandQueue.Callbacks, RecentsPanelView.OnRecentsPanelVisibilityChangedListener { 54 static final String TAG = "StatusBar"; 55 private static final boolean DEBUG = false; 56 57 protected static final int MSG_OPEN_RECENTS_PANEL = 1020; 58 protected static final int MSG_CLOSE_RECENTS_PANEL = 1021; 59 protected static final int MSG_PRELOAD_RECENT_APPS = 1022; 60 protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023; 61 62 protected CommandQueue mCommandQueue; 63 protected IStatusBarService mBarService; 64 protected H mHandler = createHandler(); 65 66 // Recent apps 67 protected RecentsPanelView mRecentsPanel; 68 protected RecentTasksLoader mRecentTasksLoader; 69 70 // UI-specific methods 71 72 /** 73 * Create all windows necessary for the status bar (including navigation, overlay panels, etc) 74 * and add them to the window manager. 75 */ 76 protected abstract void createAndAddWindows(); 77 78 protected Display mDisplay; 79 private IWindowManager mWindowManager; 80 81 82 public IWindowManager getWindowManager() { 83 return mWindowManager; 84 } 85 86 public Display getDisplay() { 87 return mDisplay; 88 } 89 90 public IStatusBarService getStatusBarService() { 91 return mBarService; 92 } 93 94 public void start() { 95 mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) 96 .getDefaultDisplay(); 97 98 mWindowManager = IWindowManager.Stub.asInterface( 99 ServiceManager.getService(Context.WINDOW_SERVICE)); 100 101 mBarService = IStatusBarService.Stub.asInterface( 102 ServiceManager.getService(Context.STATUS_BAR_SERVICE)); 103 104 // Connect in to the status bar manager service 105 StatusBarIconList iconList = new StatusBarIconList(); 106 ArrayList<IBinder> notificationKeys = new ArrayList<IBinder>(); 107 ArrayList<StatusBarNotification> notifications = new ArrayList<StatusBarNotification>(); 108 mCommandQueue = new CommandQueue(this, iconList); 109 110 int[] switches = new int[7]; 111 ArrayList<IBinder> binders = new ArrayList<IBinder>(); 112 try { 113 mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications, 114 switches, binders); 115 } catch (RemoteException ex) { 116 // If the system process isn't there we're doomed anyway. 117 } 118 119 createAndAddWindows(); 120 121 disable(switches[0]); 122 setSystemUiVisibility(switches[1]); 123 topAppWindowChanged(switches[2] != 0); 124 // StatusBarManagerService has a back up of IME token and it's restored here. 125 setImeWindowStatus(binders.get(0), switches[3], switches[4]); 126 setHardKeyboardStatus(switches[5] != 0, switches[6] != 0); 127 128 // Set up the initial icon state 129 int N = iconList.size(); 130 int viewIndex = 0; 131 for (int i=0; i<N; i++) { 132 StatusBarIcon icon = iconList.getIcon(i); 133 if (icon != null) { 134 addIcon(iconList.getSlot(i), i, viewIndex, icon); 135 viewIndex++; 136 } 137 } 138 139 // Set up the initial notification state 140 N = notificationKeys.size(); 141 if (N == notifications.size()) { 142 for (int i=0; i<N; i++) { 143 addNotification(notificationKeys.get(i), notifications.get(i)); 144 } 145 } else { 146 Log.wtf(TAG, "Notification list length mismatch: keys=" + N 147 + " notifications=" + notifications.size()); 148 } 149 150 if (DEBUG) { 151 Slog.d(TAG, String.format( 152 "init: icons=%d disabled=0x%08x lights=0x%08x menu=0x%08x imeButton=0x%08x", 153 iconList.size(), 154 switches[0], 155 switches[1], 156 switches[2], 157 switches[3] 158 )); 159 } 160 } 161 162 protected View updateNotificationVetoButton(View row, StatusBarNotification n) { 163 View vetoButton = row.findViewById(R.id.veto); 164 if (n.isClearable()) { 165 final String _pkg = n.pkg; 166 final String _tag = n.tag; 167 final int _id = n.id; 168 vetoButton.setOnClickListener(new View.OnClickListener() { 169 public void onClick(View v) { 170 try { 171 mBarService.onNotificationClear(_pkg, _tag, _id); 172 } catch (RemoteException ex) { 173 // system process is dead if we're here. 174 } 175 } 176 }); 177 vetoButton.setVisibility(View.VISIBLE); 178 } else { 179 vetoButton.setVisibility(View.GONE); 180 } 181 return vetoButton; 182 } 183 184 public void dismissIntruder() { 185 // pass 186 } 187 188 @Override 189 public void toggleRecentApps() { 190 int msg = (mRecentsPanel.getVisibility() == View.VISIBLE) 191 ? MSG_CLOSE_RECENTS_PANEL : MSG_OPEN_RECENTS_PANEL; 192 mHandler.removeMessages(msg); 193 mHandler.sendEmptyMessage(msg); 194 } 195 196 @Override 197 public void preloadRecentApps() { 198 int msg = MSG_PRELOAD_RECENT_APPS; 199 mHandler.removeMessages(msg); 200 mHandler.sendEmptyMessage(msg); 201 } 202 203 @Override 204 public void cancelPreloadRecentApps() { 205 int msg = MSG_CANCEL_PRELOAD_RECENT_APPS; 206 mHandler.removeMessages(msg); 207 mHandler.sendEmptyMessage(msg); 208 } 209 210 @Override 211 public void onRecentsPanelVisibilityChanged(boolean visible) { 212 } 213 214 protected abstract WindowManager.LayoutParams getRecentsLayoutParams( 215 LayoutParams layoutParams); 216 217 protected void updateRecentsPanel() { 218 // Recents Panel 219 boolean visible = false; 220 ArrayList<TaskDescription> recentTasksList = null; 221 boolean firstScreenful = false; 222 if (mRecentsPanel != null) { 223 visible = mRecentsPanel.isShowing(); 224 WindowManagerImpl.getDefault().removeView(mRecentsPanel); 225 if (visible) { 226 recentTasksList = mRecentsPanel.getRecentTasksList(); 227 firstScreenful = mRecentsPanel.getFirstScreenful(); 228 } 229 } 230 231 // Provide RecentsPanelView with a temporary parent to allow layout params to work. 232 LinearLayout tmpRoot = new LinearLayout(mContext); 233 mRecentsPanel = (RecentsPanelView) LayoutInflater.from(mContext).inflate( 234 R.layout.status_bar_recent_panel, tmpRoot, false); 235 mRecentsPanel.setRecentTasksLoader(mRecentTasksLoader); 236 mRecentTasksLoader.setRecentsPanel(mRecentsPanel); 237 mRecentsPanel.setOnTouchListener( 238 new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL, mRecentsPanel)); 239 mRecentsPanel.setVisibility(View.GONE); 240 241 242 WindowManager.LayoutParams lp = getRecentsLayoutParams(mRecentsPanel.getLayoutParams()); 243 244 WindowManagerImpl.getDefault().addView(mRecentsPanel, lp); 245 mRecentsPanel.setBar(this); 246 if (visible) { 247 mRecentsPanel.show(true, false, recentTasksList, firstScreenful); 248 } 249 250 } 251 252 protected H createHandler() { 253 return new H(); 254 } 255 256 protected class H extends Handler { 257 public void handleMessage(Message m) { 258 switch (m.what) { 259 case MSG_OPEN_RECENTS_PANEL: 260 if (DEBUG) Slog.d(TAG, "opening recents panel"); 261 if (mRecentsPanel != null) { 262 mRecentsPanel.show(true, true); 263 } 264 break; 265 case MSG_CLOSE_RECENTS_PANEL: 266 if (DEBUG) Slog.d(TAG, "closing recents panel"); 267 if (mRecentsPanel != null && mRecentsPanel.isShowing()) { 268 mRecentsPanel.show(false, true); 269 } 270 break; 271 case MSG_PRELOAD_RECENT_APPS: 272 if (DEBUG) Slog.d(TAG, "preloading recents"); 273 mRecentsPanel.preloadRecentTasksList(); 274 break; 275 case MSG_CANCEL_PRELOAD_RECENT_APPS: 276 if (DEBUG) Slog.d(TAG, "cancel preloading recents"); 277 mRecentsPanel.clearRecentTasksList(); 278 break; 279 } 280 } 281 } 282 283 public class TouchOutsideListener implements View.OnTouchListener { 284 private int mMsg; 285 private StatusBarPanel mPanel; 286 287 public TouchOutsideListener(int msg, StatusBarPanel panel) { 288 mMsg = msg; 289 mPanel = panel; 290 } 291 292 public boolean onTouch(View v, MotionEvent ev) { 293 final int action = ev.getAction(); 294 if (action == MotionEvent.ACTION_OUTSIDE 295 || (action == MotionEvent.ACTION_DOWN 296 && !mPanel.isInContentArea((int)ev.getX(), (int)ev.getY()))) { 297 mHandler.removeMessages(mMsg); 298 mHandler.sendEmptyMessage(mMsg); 299 return true; 300 } 301 return false; 302 } 303 } 304} 305