blob: e5e576d6b80baf0c3040259feb2a4a8df7510a71 [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.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.NetworkScoreManager;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.AsyncChannel;
import com.android.settingslib.wifi.WifiStatusTracker;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import java.util.Objects;
public class WifiSignalController extends
SignalController<WifiSignalController.WifiState, SignalController.IconGroup> {
private final AsyncChannel mWifiChannel;
private final boolean mHasMobileData;
private final WifiStatusTracker mWifiTracker;
public WifiSignalController(Context context, boolean hasMobileData,
CallbackHandler callbackHandler, NetworkControllerImpl networkController,
WifiManager wifiManager) {
super("WifiSignalController", context, NetworkCapabilities.TRANSPORT_WIFI,
callbackHandler, networkController);
NetworkScoreManager networkScoreManager =
context.getSystemService(NetworkScoreManager.class);
ConnectivityManager connectivityManager =
context.getSystemService(ConnectivityManager.class);
mWifiTracker = new WifiStatusTracker(mContext, wifiManager, networkScoreManager,
connectivityManager, this::handleStatusUpdated);
mWifiTracker.setListening(true);
mHasMobileData = hasMobileData;
Handler handler = new WifiHandler(Looper.getMainLooper());
mWifiChannel = new AsyncChannel();
Messenger wifiMessenger = wifiManager.getWifiServiceMessenger();
if (wifiMessenger != null) {
mWifiChannel.connect(context, handler, wifiMessenger);
}
// WiFi only has one state.
mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup(
"Wi-Fi Icons",
WifiIcons.WIFI_SIGNAL_STRENGTH,
WifiIcons.QS_WIFI_SIGNAL_STRENGTH,
AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH,
WifiIcons.WIFI_NO_NETWORK,
WifiIcons.QS_WIFI_NO_NETWORK,
WifiIcons.WIFI_NO_NETWORK,
WifiIcons.QS_WIFI_NO_NETWORK,
AccessibilityContentDescriptions.WIFI_NO_CONNECTION
);
}
@Override
protected WifiState cleanState() {
return new WifiState();
}
@Override
public void notifyListeners(SignalCallback callback) {
// only show wifi in the cluster if connected or if wifi-only
boolean wifiVisible = mCurrentState.enabled
&& (mCurrentState.connected || !mHasMobileData);
String wifiDesc = wifiVisible ? mCurrentState.ssid : null;
boolean ssidPresent = wifiVisible && mCurrentState.ssid != null;
String contentDescription = getStringIfExists(getContentDescription());
if (mCurrentState.inetCondition == 0) {
contentDescription += ("," + mContext.getString(R.string.data_connection_no_internet));
}
IconState statusIcon = new IconState(wifiVisible, getCurrentIconId(), contentDescription);
IconState qsIcon = new IconState(mCurrentState.connected, getQsCurrentIconId(),
contentDescription);
callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
ssidPresent && mCurrentState.activityIn, ssidPresent && mCurrentState.activityOut,
wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel);
}
/**
* Extract wifi state directly from broadcasts about changes in wifi state.
*/
public void handleBroadcast(Intent intent) {
mWifiTracker.handleBroadcast(intent);
mCurrentState.enabled = mWifiTracker.enabled;
mCurrentState.connected = mWifiTracker.connected;
mCurrentState.ssid = mWifiTracker.ssid;
mCurrentState.rssi = mWifiTracker.rssi;
mCurrentState.level = mWifiTracker.level;
mCurrentState.statusLabel = mWifiTracker.statusLabel;
notifyListenersIfNecessary();
}
private void handleStatusUpdated() {
mCurrentState.statusLabel = mWifiTracker.statusLabel;
notifyListenersIfNecessary();
}
@VisibleForTesting
void setActivity(int wifiActivity) {
mCurrentState.activityIn = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
|| wifiActivity == WifiManager.DATA_ACTIVITY_IN;
mCurrentState.activityOut = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
|| wifiActivity == WifiManager.DATA_ACTIVITY_OUT;
notifyListenersIfNecessary();
}
/**
* Handler to receive the data activity on wifi.
*/
private class WifiHandler extends Handler {
WifiHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
mWifiChannel.sendMessage(Message.obtain(this,
AsyncChannel.CMD_CHANNEL_FULL_CONNECTION));
} else {
Log.e(mTag, "Failed to connect to wifi");
}
break;
case WifiManager.DATA_ACTIVITY_NOTIFICATION:
setActivity(msg.arg1);
break;
default:
// Ignore
break;
}
}
}
static class WifiState extends SignalController.State {
String ssid;
boolean isTransient;
String statusLabel;
@Override
public void copyFrom(State s) {
super.copyFrom(s);
WifiState state = (WifiState) s;
ssid = state.ssid;
isTransient = state.isTransient;
statusLabel = state.statusLabel;
}
@Override
protected void toString(StringBuilder builder) {
super.toString(builder);
builder.append(",ssid=").append(ssid)
.append(",isTransient=").append(isTransient)
.append(",statusLabel=").append(statusLabel);
}
@Override
public boolean equals(Object o) {
if (!super.equals(o)) {
return false;
}
WifiState other = (WifiState) o;
return Objects.equals(other.ssid, ssid)
&& other.isTransient == isTransient
&& TextUtils.equals(other.statusLabel, statusLabel);
}
}
}