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 17 package com.android.systemui.statusbar; 18 19 import android.app.ActivityManager; 20 import android.app.Service; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.res.Resources; 24 import android.graphics.PixelFormat; 25 import android.os.IBinder; 26 import android.os.RemoteException; 27 import android.os.ServiceManager; 28 import android.util.Slog; 29 import android.util.Log; 30 import android.view.Display; 31 import android.view.Gravity; 32 import android.view.View; 33 import android.view.ViewGroup; 34 import android.view.WindowManager; 35 import android.view.WindowManagerImpl; 36 37 import java.util.ArrayList; 38 39 import com.android.internal.statusbar.IStatusBarService; 40 import com.android.internal.statusbar.StatusBarIcon; 41 import com.android.internal.statusbar.StatusBarIconList; 42 import com.android.internal.statusbar.StatusBarNotification; 43 44 import com.android.systemui.SystemUI; 45 import com.android.systemui.R; 46 47 public abstract class StatusBar extends SystemUI implements CommandQueue.Callbacks { 48 static final String TAG = "StatusBar"; 49 private static final boolean SPEW = false; 50 51 protected CommandQueue mCommandQueue; 52 protected IStatusBarService mBarService; 53 54 // Up-call methods 55 protected abstract View makeStatusBarView(); 56 protected abstract int getStatusBarGravity(); 57 public abstract int getStatusBarHeight(); 58 public abstract void animateCollapse(); 59 60 private DoNotDisturb mDoNotDisturb; 61 62 public void start() { 63 // First set up our views and stuff. 64 View sb = makeStatusBarView(); 65 66 // Connect in to the status bar manager service 67 StatusBarIconList iconList = new StatusBarIconList(); 68 ArrayList<IBinder> notificationKeys = new ArrayList<IBinder>(); 69 ArrayList<StatusBarNotification> notifications = new ArrayList<StatusBarNotification>(); 70 mCommandQueue = new CommandQueue(this, iconList); 71 mBarService = IStatusBarService.Stub.asInterface( 72 ServiceManager.getService(Context.STATUS_BAR_SERVICE)); 73 int[] switches = new int[7]; 74 ArrayList<IBinder> binders = new ArrayList<IBinder>(); 75 try { 76 mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications, 77 switches, binders); 78 } catch (RemoteException ex) { 79 // If the system process isn't there we're doomed anyway. 80 } 81 82 disable(switches[0]); 83 setSystemUiVisibility(switches[1]); 84 topAppWindowChanged(switches[2] != 0); 85 // StatusBarManagerService has a back up of IME token and it's restored here. 86 setImeWindowStatus(binders.get(0), switches[3], switches[4]); 87 setHardKeyboardStatus(switches[5] != 0, switches[6] != 0); 88 89 // Set up the initial icon state 90 int N = iconList.size(); 91 int viewIndex = 0; 92 for (int i=0; i<N; i++) { 93 StatusBarIcon icon = iconList.getIcon(i); 94 if (icon != null) { 95 addIcon(iconList.getSlot(i), i, viewIndex, icon); 96 viewIndex++; 97 } 98 } 99 100 // Set up the initial notification state 101 N = notificationKeys.size(); 102 if (N == notifications.size()) { 103 for (int i=0; i<N; i++) { 104 addNotification(notificationKeys.get(i), notifications.get(i)); 105 } 106 } else { 107 Log.wtf(TAG, "Notification list length mismatch: keys=" + N 108 + " notifications=" + notifications.size()); 109 } 110 111 // Put up the view 112 final int height = getStatusBarHeight(); 113 114 final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 115 ViewGroup.LayoutParams.MATCH_PARENT, 116 height, 117 WindowManager.LayoutParams.TYPE_STATUS_BAR, 118 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 119 | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING 120 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, 121 // We use a pixel format of RGB565 for the status bar to save memory bandwidth and 122 // to ensure that the layer can be handled by HWComposer. On some devices the 123 // HWComposer is unable to handle SW-rendered RGBX_8888 layers. 124 PixelFormat.RGB_565); 125 126 // the status bar should be in an overlay if possible 127 final Display defaultDisplay 128 = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) 129 .getDefaultDisplay(); 130 131 // We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags. The status bar occupies 132 // very little screen real-estate and is updated fairly frequently. By using CPU rendering 133 // for the status bar, we prevent the GPU from having to wake up just to do these small 134 // updates, which should help keep power consumption down. 135 136 lp.gravity = getStatusBarGravity(); 137 lp.setTitle("StatusBar"); 138 lp.packageName = mContext.getPackageName(); 139 lp.windowAnimations = R.style.Animation_StatusBar; 140 WindowManagerImpl.getDefault().addView(sb, lp); 141 142 if (SPEW) { 143 Slog.d(TAG, "Added status bar view: gravity=0x" + Integer.toHexString(lp.gravity) 144 + " icons=" + iconList.size() 145 + " disabled=0x" + Integer.toHexString(switches[0]) 146 + " lights=" + switches[1] 147 + " menu=" + switches[2] 148 + " imeButton=" + switches[3] 149 ); 150 } 151 152 mDoNotDisturb = new DoNotDisturb(mContext); 153 } 154 155 protected View updateNotificationVetoButton(View row, StatusBarNotification n) { 156 View vetoButton = row.findViewById(R.id.veto); 157 if (n.isClearable()) { 158 final String _pkg = n.pkg; 159 final String _tag = n.tag; 160 final int _id = n.id; 161 vetoButton.setOnClickListener(new View.OnClickListener() { 162 public void onClick(View v) { 163 try { 164 mBarService.onNotificationClear(_pkg, _tag, _id); 165 } catch (RemoteException ex) { 166 // system process is dead if we're here. 167 } 168 } 169 }); 170 vetoButton.setVisibility(View.VISIBLE); 171 } else { 172 vetoButton.setVisibility(View.GONE); 173 } 174 return vetoButton; 175 } 176 } 177