Home | History | Annotate | Download | only in statusbar
      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