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