1 /* 2 * Copyright (C) 2015 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 package com.android.systemui.statusbar.connectivity; 17 18 import android.os.Handler; 19 import android.os.Looper; 20 import android.os.Message; 21 import android.telephony.SubscriptionInfo; 22 23 import com.android.internal.annotations.VisibleForTesting; 24 import com.android.systemui.dagger.SysUISingleton; 25 import com.android.systemui.dagger.qualifiers.Main; 26 import com.android.systemui.statusbar.connectivity.NetworkController.EmergencyListener; 27 28 import java.io.PrintWriter; 29 import java.text.SimpleDateFormat; 30 import java.util.ArrayList; 31 import java.util.List; 32 33 import javax.inject.Inject; 34 35 /** 36 * Implements network listeners and forwards the calls along onto other listeners but on 37 * the current or specified Looper. 38 */ 39 @SysUISingleton 40 public class CallbackHandler extends Handler implements EmergencyListener, SignalCallback { 41 private static final String TAG = "CallbackHandler"; 42 private static final int MSG_EMERGENCE_CHANGED = 0; 43 private static final int MSG_SUBS_CHANGED = 1; 44 private static final int MSG_NO_SIM_VISIBLE_CHANGED = 2; 45 private static final int MSG_ETHERNET_CHANGED = 3; 46 private static final int MSG_AIRPLANE_MODE_CHANGED = 4; 47 private static final int MSG_MOBILE_DATA_ENABLED_CHANGED = 5; 48 private static final int MSG_ADD_REMOVE_EMERGENCY = 6; 49 private static final int MSG_ADD_REMOVE_SIGNAL = 7; 50 private static final int HISTORY_SIZE = 64; 51 private static final SimpleDateFormat SSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); 52 53 // All the callbacks. 54 private final ArrayList<EmergencyListener> mEmergencyListeners = new ArrayList<>(); 55 private final ArrayList<SignalCallback> mSignalCallbacks = new ArrayList<>(); 56 57 // Save the previous HISTORY_SIZE states for logging. 58 private final String[] mHistory = new String[HISTORY_SIZE]; 59 // Where to copy the next state into. 60 private int mHistoryIndex; 61 private String mLastCallback; 62 63 @Inject 64 @VisibleForTesting CallbackHandler(@ain Looper looper)65 CallbackHandler(@Main Looper looper) { 66 super(looper); 67 } 68 69 @Override 70 @SuppressWarnings("unchecked") handleMessage(Message msg)71 public void handleMessage(Message msg) { 72 switch (msg.what) { 73 case MSG_EMERGENCE_CHANGED: 74 for (EmergencyListener listener : mEmergencyListeners) { 75 listener.setEmergencyCallsOnly(msg.arg1 != 0); 76 } 77 break; 78 case MSG_SUBS_CHANGED: 79 for (SignalCallback signalCluster : mSignalCallbacks) { 80 signalCluster.setSubs((List<SubscriptionInfo>) msg.obj); 81 } 82 break; 83 case MSG_NO_SIM_VISIBLE_CHANGED: 84 for (SignalCallback signalCluster : mSignalCallbacks) { 85 signalCluster.setNoSims(msg.arg1 != 0, msg.arg2 != 0); 86 } 87 break; 88 case MSG_ETHERNET_CHANGED: 89 for (SignalCallback signalCluster : mSignalCallbacks) { 90 signalCluster.setEthernetIndicators((IconState) msg.obj); 91 } 92 break; 93 case MSG_AIRPLANE_MODE_CHANGED: 94 for (SignalCallback signalCluster : mSignalCallbacks) { 95 signalCluster.setIsAirplaneMode((IconState) msg.obj); 96 } 97 break; 98 case MSG_MOBILE_DATA_ENABLED_CHANGED: 99 for (SignalCallback signalCluster : mSignalCallbacks) { 100 signalCluster.setMobileDataEnabled(msg.arg1 != 0); 101 } 102 break; 103 case MSG_ADD_REMOVE_EMERGENCY: 104 if (msg.arg1 != 0) { 105 mEmergencyListeners.add((EmergencyListener) msg.obj); 106 } else { 107 mEmergencyListeners.remove((EmergencyListener) msg.obj); 108 } 109 break; 110 case MSG_ADD_REMOVE_SIGNAL: 111 if (msg.arg1 != 0) { 112 mSignalCallbacks.add((SignalCallback) msg.obj); 113 } else { 114 mSignalCallbacks.remove((SignalCallback) msg.obj); 115 } 116 break; 117 } 118 } 119 120 @Override setWifiIndicators(final WifiIndicators indicators)121 public void setWifiIndicators(final WifiIndicators indicators) { 122 String log = new StringBuilder() 123 .append(SSDF.format(System.currentTimeMillis())).append(",") 124 .append(indicators) 125 .toString(); 126 recordLastCallback(log); 127 post(() -> { 128 for (SignalCallback callback : mSignalCallbacks) { 129 callback.setWifiIndicators(indicators); 130 } 131 }); 132 } 133 134 @Override setMobileDataIndicators(final MobileDataIndicators indicators)135 public void setMobileDataIndicators(final MobileDataIndicators indicators) { 136 String log = new StringBuilder() 137 .append(SSDF.format(System.currentTimeMillis())).append(",") 138 .append(indicators) 139 .toString(); 140 recordLastCallback(log); 141 post(() -> { 142 for (SignalCallback signalCluster : mSignalCallbacks) { 143 signalCluster.setMobileDataIndicators(indicators); 144 } 145 }); 146 } 147 148 @Override setConnectivityStatus(boolean noDefaultNetwork, boolean noValidatedNetwork, boolean noNetworksAvailable)149 public void setConnectivityStatus(boolean noDefaultNetwork, boolean noValidatedNetwork, 150 boolean noNetworksAvailable) { 151 String currentCallback = new StringBuilder() 152 .append("setConnectivityStatus: ") 153 .append("noDefaultNetwork=").append(noDefaultNetwork).append(",") 154 .append("noValidatedNetwork=").append(noValidatedNetwork).append(",") 155 .append("noNetworksAvailable=").append(noNetworksAvailable) 156 .toString(); 157 if (!currentCallback.equals(mLastCallback)) { 158 mLastCallback = currentCallback; 159 String log = new StringBuilder() 160 .append(SSDF.format(System.currentTimeMillis())).append(",") 161 .append(currentCallback).append(",") 162 .toString(); 163 recordLastCallback(log); 164 } 165 post(() -> { 166 for (SignalCallback signalCluster : mSignalCallbacks) { 167 signalCluster.setConnectivityStatus( 168 noDefaultNetwork, noValidatedNetwork, noNetworksAvailable); 169 } 170 }); 171 } 172 173 @Override setCallIndicator(IconState statusIcon, int subId)174 public void setCallIndicator(IconState statusIcon, int subId) { 175 String currentCallback = new StringBuilder() 176 .append("setCallIndicator: ") 177 .append("statusIcon=").append(statusIcon).append(",") 178 .append("subId=").append(subId) 179 .toString(); 180 if (!currentCallback.equals(mLastCallback)) { 181 mLastCallback = currentCallback; 182 String log = new StringBuilder() 183 .append(SSDF.format(System.currentTimeMillis())).append(",") 184 .append(currentCallback).append(",") 185 .toString(); 186 recordLastCallback(log); 187 } 188 post(() -> { 189 for (SignalCallback signalCluster : mSignalCallbacks) { 190 signalCluster.setCallIndicator(statusIcon, subId); 191 } 192 }); 193 } 194 195 @Override setSubs(List<SubscriptionInfo> subs)196 public void setSubs(List<SubscriptionInfo> subs) { 197 String currentCallback = new StringBuilder() 198 .append("setSubs: ") 199 .append("subs=").append(subs == null ? "" : subs.toString()) 200 .toString(); 201 if (!currentCallback.equals(mLastCallback)) { 202 mLastCallback = currentCallback; 203 String log = new StringBuilder() 204 .append(SSDF.format(System.currentTimeMillis())).append(",") 205 .append(currentCallback).append(",") 206 .toString(); 207 recordLastCallback(log); 208 } 209 obtainMessage(MSG_SUBS_CHANGED, subs).sendToTarget(); 210 } 211 212 @Override setNoSims(boolean show, boolean simDetected)213 public void setNoSims(boolean show, boolean simDetected) { 214 obtainMessage(MSG_NO_SIM_VISIBLE_CHANGED, show ? 1 : 0, simDetected ? 1 : 0).sendToTarget(); 215 } 216 217 @Override setMobileDataEnabled(boolean enabled)218 public void setMobileDataEnabled(boolean enabled) { 219 obtainMessage(MSG_MOBILE_DATA_ENABLED_CHANGED, enabled ? 1 : 0, 0).sendToTarget(); 220 } 221 222 @Override setEmergencyCallsOnly(boolean emergencyOnly)223 public void setEmergencyCallsOnly(boolean emergencyOnly) { 224 obtainMessage(MSG_EMERGENCE_CHANGED, emergencyOnly ? 1 : 0, 0).sendToTarget(); 225 } 226 227 @Override setEthernetIndicators(IconState icon)228 public void setEthernetIndicators(IconState icon) { 229 String log = new StringBuilder() 230 .append(SSDF.format(System.currentTimeMillis())).append(",") 231 .append("setEthernetIndicators: ") 232 .append("icon=").append(icon) 233 .toString(); 234 recordLastCallback(log); 235 obtainMessage(MSG_ETHERNET_CHANGED, icon).sendToTarget(); 236 } 237 238 @Override setIsAirplaneMode(IconState icon)239 public void setIsAirplaneMode(IconState icon) { 240 String currentCallback = new StringBuilder() 241 .append("setIsAirplaneMode: ") 242 .append("icon=").append(icon) 243 .toString(); 244 if (!currentCallback.equals(mLastCallback)) { 245 mLastCallback = currentCallback; 246 String log = new StringBuilder() 247 .append(SSDF.format(System.currentTimeMillis())).append(",") 248 .append(currentCallback).append(",") 249 .toString(); 250 recordLastCallback(log); 251 } 252 obtainMessage(MSG_AIRPLANE_MODE_CHANGED, icon).sendToTarget(); 253 } 254 setListening(EmergencyListener listener, boolean listening)255 void setListening(EmergencyListener listener, boolean listening) { 256 obtainMessage(MSG_ADD_REMOVE_EMERGENCY, listening ? 1 : 0, 0, listener).sendToTarget(); 257 } 258 setListening(SignalCallback listener, boolean listening)259 void setListening(SignalCallback listener, boolean listening) { 260 obtainMessage(MSG_ADD_REMOVE_SIGNAL, listening ? 1 : 0, 0, listener).sendToTarget(); 261 } 262 recordLastCallback(String callback)263 protected void recordLastCallback(String callback) { 264 mHistory[mHistoryIndex] = callback; 265 mHistoryIndex = (mHistoryIndex + 1) % HISTORY_SIZE; 266 } 267 268 /** 269 * Dump the Callback logs 270 */ dump(PrintWriter pw)271 public void dump(PrintWriter pw) { 272 pw.println(" - CallbackHandler -----"); 273 int size = 0; 274 for (int i = 0; i < HISTORY_SIZE; i++) { 275 if (mHistory[i] != null) { 276 size++; 277 } 278 } 279 // Print out the previous states in ordered number. 280 for (int i = mHistoryIndex + HISTORY_SIZE - 1; 281 i >= mHistoryIndex + HISTORY_SIZE - size; i--) { 282 pw.println(" Previous Callback(" + (mHistoryIndex + HISTORY_SIZE - i) + "): " 283 + mHistory[i & (HISTORY_SIZE - 1)]); 284 } 285 } 286 287 } 288