blob: 7ac6d63430d6919901d26dcb2b708f57493f6f44 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.policy;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.telephony.SubscriptionInfo;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
/**
* Implements network listeners and forwards the calls along onto other listeners but on
* the current or specified Looper.
*/
public class CallbackHandler extends Handler implements EmergencyListener, SignalCallback {
private static final String TAG = "CallbackHandler";
private static final int MSG_EMERGENCE_CHANGED = 0;
private static final int MSG_SUBS_CHANGED = 1;
private static final int MSG_NO_SIM_VISIBLE_CHANGED = 2;
private static final int MSG_ETHERNET_CHANGED = 3;
private static final int MSG_AIRPLANE_MODE_CHANGED = 4;
private static final int MSG_MOBILE_DATA_ENABLED_CHANGED = 5;
private static final int MSG_ADD_REMOVE_EMERGENCY = 6;
private static final int MSG_ADD_REMOVE_SIGNAL = 7;
private static final int HISTORY_SIZE = 64;
private static final SimpleDateFormat SSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
// All the callbacks.
private final ArrayList<EmergencyListener> mEmergencyListeners = new ArrayList<>();
private final ArrayList<SignalCallback> mSignalCallbacks = new ArrayList<>();
// Save the previous HISTORY_SIZE states for logging.
private final String[] mHistory = new String[HISTORY_SIZE];
// Where to copy the next state into.
private int mHistoryIndex;
private String mLastCallback;
@Inject
@VisibleForTesting
CallbackHandler(@Main Looper looper) {
super(looper);
}
@Override
@SuppressWarnings("unchecked")
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_EMERGENCE_CHANGED:
for (EmergencyListener listener : mEmergencyListeners) {
listener.setEmergencyCallsOnly(msg.arg1 != 0);
}
break;
case MSG_SUBS_CHANGED:
for (SignalCallback signalCluster : mSignalCallbacks) {
signalCluster.setSubs((List<SubscriptionInfo>) msg.obj);
}
break;
case MSG_NO_SIM_VISIBLE_CHANGED:
for (SignalCallback signalCluster : mSignalCallbacks) {
signalCluster.setNoSims(msg.arg1 != 0, msg.arg2 != 0);
}
break;
case MSG_ETHERNET_CHANGED:
for (SignalCallback signalCluster : mSignalCallbacks) {
signalCluster.setEthernetIndicators((IconState) msg.obj);
}
break;
case MSG_AIRPLANE_MODE_CHANGED:
for (SignalCallback signalCluster : mSignalCallbacks) {
signalCluster.setIsAirplaneMode((IconState) msg.obj);
}
break;
case MSG_MOBILE_DATA_ENABLED_CHANGED:
for (SignalCallback signalCluster : mSignalCallbacks) {
signalCluster.setMobileDataEnabled(msg.arg1 != 0);
}
break;
case MSG_ADD_REMOVE_EMERGENCY:
if (msg.arg1 != 0) {
mEmergencyListeners.add((EmergencyListener) msg.obj);
} else {
mEmergencyListeners.remove((EmergencyListener) msg.obj);
}
break;
case MSG_ADD_REMOVE_SIGNAL:
if (msg.arg1 != 0) {
mSignalCallbacks.add((SignalCallback) msg.obj);
} else {
mSignalCallbacks.remove((SignalCallback) msg.obj);
}
break;
}
}
@Override
public void setWifiIndicators(final WifiIndicators indicators) {
String log = new StringBuilder()
.append(SSDF.format(System.currentTimeMillis())).append(",")
.append(indicators)
.toString();
recordLastCallback(log);
post(() -> {
for (SignalCallback callback : mSignalCallbacks) {
callback.setWifiIndicators(indicators);
}
});
}
@Override
public void setMobileDataIndicators(final MobileDataIndicators indicators) {
String log = new StringBuilder()
.append(SSDF.format(System.currentTimeMillis())).append(",")
.append(indicators)
.toString();
recordLastCallback(log);
post(() -> {
for (SignalCallback signalCluster : mSignalCallbacks) {
signalCluster.setMobileDataIndicators(indicators);
}
});
}
@Override
public void setConnectivityStatus(boolean noDefaultNetwork, boolean noValidatedNetwork,
boolean noNetworksAvailable) {
String currentCallback = new StringBuilder()
.append("setConnectivityStatus: ")
.append("noDefaultNetwork=").append(noDefaultNetwork).append(",")
.append("noValidatedNetwork=").append(noValidatedNetwork).append(",")
.append("noNetworksAvailable=").append(noNetworksAvailable)
.toString();
if (!currentCallback.equals(mLastCallback)) {
mLastCallback = currentCallback;
String log = new StringBuilder()
.append(SSDF.format(System.currentTimeMillis())).append(",")
.append(currentCallback).append(",")
.toString();
recordLastCallback(log);
}
post(() -> {
for (SignalCallback signalCluster : mSignalCallbacks) {
signalCluster.setConnectivityStatus(
noDefaultNetwork, noValidatedNetwork, noNetworksAvailable);
}
});
}
@Override
public void setCallIndicator(IconState statusIcon, int subId) {
String currentCallback = new StringBuilder()
.append("setCallIndicator: ")
.append("statusIcon=").append(statusIcon).append(",")
.append("subId=").append(subId)
.toString();
if (!currentCallback.equals(mLastCallback)) {
mLastCallback = currentCallback;
String log = new StringBuilder()
.append(SSDF.format(System.currentTimeMillis())).append(",")
.append(currentCallback).append(",")
.toString();
recordLastCallback(log);
}
post(() -> {
for (SignalCallback signalCluster : mSignalCallbacks) {
signalCluster.setCallIndicator(statusIcon, subId);
}
});
}
@Override
public void setSubs(List<SubscriptionInfo> subs) {
String currentCallback = new StringBuilder()
.append("setSubs: ")
.append("subs=").append(subs == null ? "" : subs.toString())
.toString();
if (!currentCallback.equals(mLastCallback)) {
mLastCallback = currentCallback;
String log = new StringBuilder()
.append(SSDF.format(System.currentTimeMillis())).append(",")
.append(currentCallback).append(",")
.toString();
recordLastCallback(log);
}
obtainMessage(MSG_SUBS_CHANGED, subs).sendToTarget();
}
@Override
public void setNoSims(boolean show, boolean simDetected) {
obtainMessage(MSG_NO_SIM_VISIBLE_CHANGED, show ? 1 : 0, simDetected ? 1 : 0).sendToTarget();
}
@Override
public void setMobileDataEnabled(boolean enabled) {
obtainMessage(MSG_MOBILE_DATA_ENABLED_CHANGED, enabled ? 1 : 0, 0).sendToTarget();
}
@Override
public void setEmergencyCallsOnly(boolean emergencyOnly) {
obtainMessage(MSG_EMERGENCE_CHANGED, emergencyOnly ? 1 : 0, 0).sendToTarget();
}
@Override
public void setEthernetIndicators(IconState icon) {
String log = new StringBuilder()
.append(SSDF.format(System.currentTimeMillis())).append(",")
.append("setEthernetIndicators: ")
.append("icon=").append(icon)
.toString();
recordLastCallback(log);
obtainMessage(MSG_ETHERNET_CHANGED, icon).sendToTarget();;
}
@Override
public void setIsAirplaneMode(IconState icon) {
String currentCallback = new StringBuilder()
.append("setIsAirplaneMode: ")
.append("icon=").append(icon)
.toString();
if (!currentCallback.equals(mLastCallback)) {
mLastCallback = currentCallback;
String log = new StringBuilder()
.append(SSDF.format(System.currentTimeMillis())).append(",")
.append(currentCallback).append(",")
.toString();
recordLastCallback(log);
}
obtainMessage(MSG_AIRPLANE_MODE_CHANGED, icon).sendToTarget();;
}
public void setListening(EmergencyListener listener, boolean listening) {
obtainMessage(MSG_ADD_REMOVE_EMERGENCY, listening ? 1 : 0, 0, listener).sendToTarget();
}
public void setListening(SignalCallback listener, boolean listening) {
obtainMessage(MSG_ADD_REMOVE_SIGNAL, listening ? 1 : 0, 0, listener).sendToTarget();
}
protected void recordLastCallback(String callback) {
mHistory[mHistoryIndex] = callback;
mHistoryIndex = (mHistoryIndex + 1) % HISTORY_SIZE;
}
/**
* Dump the Callback logs
*/
public void dump(PrintWriter pw) {
pw.println(" - CallbackHandler -----");
int size = 0;
for (int i = 0; i < HISTORY_SIZE; i++) {
if (mHistory[i] != null) {
size++;
}
}
// Print out the previous states in ordered number.
for (int i = mHistoryIndex + HISTORY_SIZE - 1;
i >= mHistoryIndex + HISTORY_SIZE - size; i--) {
pw.println(" Previous Callback(" + (mHistoryIndex + HISTORY_SIZE - i) + "): "
+ mHistory[i & (HISTORY_SIZE - 1)]);
}
}
}