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