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