CommandQueue.java revision 75199e3ddcf7886c8ee5fbf8b486a8c21335bf14
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 android.os.Handler; 20import android.os.IBinder; 21import android.os.Message; 22import android.util.Slog; 23 24import com.android.internal.statusbar.IStatusBar; 25import com.android.internal.statusbar.StatusBarIcon; 26import com.android.internal.statusbar.StatusBarIconList; 27import com.android.internal.statusbar.StatusBarNotification; 28 29/** 30 * This class takes the functions from IStatusBar that come in on 31 * binder pool threads and posts messages to get them onto the main 32 * thread, and calls onto Callbacks. It also takes care of 33 * coalescing these calls so they don't stack up. For the calls 34 * are coalesced, note that they are all idempotent. 35 */ 36class CommandQueue extends IStatusBar.Stub { 37 private static final String TAG = "StatusBar.CommandQueue"; 38 39 private static final int MSG_MASK = 0xffff0000; 40 private static final int INDEX_MASK = 0x0000ffff; 41 42 private static final int MSG_ICON = 0x00010000; 43 private static final int OP_SET_ICON = 1; 44 private static final int OP_REMOVE_ICON = 2; 45 46 private static final int MSG_ADD_NOTIFICATION = 0x00020000; 47 private static final int MSG_UPDATE_NOTIFICATION = 0x00030000; 48 private static final int MSG_REMOVE_NOTIFICATION = 0x00040000; 49 50 private static final int MSG_DISABLE = 0x00050000; 51 52 private static final int MSG_SET_VISIBILITY = 0x00060000; 53 private static final int OP_EXPAND = 1; 54 private static final int OP_COLLAPSE = 2; 55 56 private StatusBarIconList mList; 57 private Callbacks mCallbacks; 58 private Handler mHandler = new H(); 59 60 private class NotificationQueueEntry { 61 IBinder key; 62 StatusBarNotification notification; 63 } 64 65 /** 66 * These methods are called back on the main thread. 67 */ 68 public interface Callbacks { 69 public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon); 70 public void updateIcon(String slot, int index, int viewIndex, 71 StatusBarIcon old, StatusBarIcon icon); 72 public void removeIcon(String slot, int index, int viewIndex); 73 public void addNotification(IBinder key, StatusBarNotification notification); 74 public void updateNotification(IBinder key, StatusBarNotification notification); 75 public void removeNotification(IBinder key); 76 public void disable(int state); 77 public void animateExpand(); 78 public void animateCollapse(); 79 } 80 81 public CommandQueue(Callbacks callbacks, StatusBarIconList list) { 82 mCallbacks = callbacks; 83 mList = list; 84 } 85 86 public void setIcon(int index, StatusBarIcon icon) { 87 synchronized (mList) { 88 int what = MSG_ICON | index; 89 mHandler.removeMessages(what); 90 mHandler.obtainMessage(what, OP_SET_ICON, 0, icon.clone()).sendToTarget(); 91 } 92 } 93 94 public void removeIcon(int index) { 95 synchronized (mList) { 96 int what = MSG_ICON | index; 97 mHandler.removeMessages(what); 98 mHandler.obtainMessage(what, OP_REMOVE_ICON, 0, null).sendToTarget(); 99 } 100 } 101 102 public void addNotification(IBinder key, StatusBarNotification notification) { 103 synchronized (mList) { 104 NotificationQueueEntry ne = new NotificationQueueEntry(); 105 ne.key = key; 106 ne.notification = notification; 107 mHandler.obtainMessage(MSG_ADD_NOTIFICATION, 0, 0, ne).sendToTarget(); 108 } 109 } 110 111 public void updateNotification(IBinder key, StatusBarNotification notification) { 112 synchronized (mList) { 113 NotificationQueueEntry ne = new NotificationQueueEntry(); 114 ne.key = key; 115 ne.notification = notification; 116 mHandler.obtainMessage(MSG_UPDATE_NOTIFICATION, 0, 0, ne).sendToTarget(); 117 } 118 } 119 120 public void removeNotification(IBinder key) { 121 synchronized (mList) { 122 mHandler.obtainMessage(MSG_REMOVE_NOTIFICATION, 0, 0, key).sendToTarget(); 123 } 124 } 125 126 public void disable(int state) { 127 synchronized (mList) { 128 mHandler.removeMessages(MSG_DISABLE); 129 mHandler.obtainMessage(MSG_DISABLE, state, 0, null).sendToTarget(); 130 } 131 } 132 133 public void animateExpand() { 134 synchronized (mList) { 135 mHandler.removeMessages(MSG_SET_VISIBILITY); 136 mHandler.obtainMessage(MSG_SET_VISIBILITY, OP_EXPAND, 0, null).sendToTarget(); 137 } 138 } 139 140 public void animateCollapse() { 141 synchronized (mList) { 142 mHandler.removeMessages(MSG_SET_VISIBILITY); 143 mHandler.obtainMessage(MSG_SET_VISIBILITY, OP_COLLAPSE, 0, null).sendToTarget(); 144 } 145 } 146 147 private final class H extends Handler { 148 public void handleMessage(Message msg) { 149 final int what = msg.what & MSG_MASK; 150 Slog.d(TAG, "handleMessage what=0x" + Integer.toHexString(what) + " arg1=" + msg.arg1); 151 switch (what) { 152 case MSG_ICON: { 153 final int index = msg.what & INDEX_MASK; 154 final int viewIndex = mList.getViewIndex(index); 155 switch (msg.arg1) { 156 case OP_SET_ICON: { 157 StatusBarIcon icon = (StatusBarIcon)msg.obj; 158 StatusBarIcon old = mList.getIcon(index); 159 if (old == null) { 160 mList.setIcon(index, icon); 161 mCallbacks.addIcon(mList.getSlot(index), index, viewIndex, icon); 162 } else { 163 mList.setIcon(index, icon); 164 mCallbacks.updateIcon(mList.getSlot(index), index, viewIndex, 165 old, icon); 166 } 167 break; 168 } 169 case OP_REMOVE_ICON: 170 mList.removeIcon(index); 171 mCallbacks.removeIcon(mList.getSlot(index), index, viewIndex); 172 break; 173 } 174 break; 175 } 176 case MSG_ADD_NOTIFICATION: { 177 final NotificationQueueEntry ne = (NotificationQueueEntry)msg.obj; 178 mCallbacks.addNotification(ne.key, ne.notification); 179 break; 180 } 181 case MSG_UPDATE_NOTIFICATION: { 182 final NotificationQueueEntry ne = (NotificationQueueEntry)msg.obj; 183 mCallbacks.updateNotification(ne.key, ne.notification); 184 break; 185 } 186 case MSG_REMOVE_NOTIFICATION: { 187 mCallbacks.removeNotification((IBinder)msg.obj); 188 break; 189 } 190 case MSG_DISABLE: 191 mCallbacks.disable(msg.arg1); 192 break; 193 case MSG_SET_VISIBILITY: 194 if (msg.arg1 == OP_EXPAND) { 195 mCallbacks.animateExpand(); 196 } else { 197 mCallbacks.animateCollapse(); 198 } 199 } 200 } 201 } 202} 203 204