1da68f596282e60bee832dff07cc96bf64bd15939Jason Monk/* 2da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * Copyright (C) 2015 The Android Open Source Project 3da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * 4da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * Licensed under the Apache License, Version 2.0 (the "License"); 5da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * you may not use this file except in compliance with the License. 6da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * You may obtain a copy of the License at 7da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * 8da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * http://www.apache.org/licenses/LICENSE-2.0 9da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * 10da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * Unless required by applicable law or agreed to in writing, software 11da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * distributed under the License is distributed on an "AS IS" BASIS, 12da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * See the License for the specific language governing permissions and 14da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * limitations under the License. 15da68f596282e60bee832dff07cc96bf64bd15939Jason Monk */ 16da68f596282e60bee832dff07cc96bf64bd15939Jason Monkpackage com.android.systemui.statusbar.policy; 17da68f596282e60bee832dff07cc96bf64bd15939Jason Monk 18da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.content.Context; 19da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.content.Intent; 20e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikhimport android.net.ConnectivityManager; 21da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.net.NetworkCapabilities; 22e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikhimport android.net.NetworkScoreManager; 23da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.net.wifi.WifiManager; 24da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.os.Handler; 252c403db659db615831d8bd02661f8769c7762241Geoffrey Pitschimport android.os.Looper; 26da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.os.Message; 27da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.os.Messenger; 28e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikhimport android.text.TextUtils; 29da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.util.Log; 30c0d7058b14c24cd07912f5629c26b39b7b4673d5Winson 31da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.internal.annotations.VisibleForTesting; 32da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.internal.util.AsyncChannel; 334cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monkimport com.android.settingslib.wifi.WifiStatusTracker; 349d10a3cf306d34f598216c6354c87c45a059b5b3Sundeep Ghumanimport com.android.systemui.R; 3507b75fe65dcb5b8add8246654c65f95f1191933eJason Monkimport com.android.systemui.statusbar.policy.NetworkController.IconState; 36e06b065f6e0d0f939b8519ccd3699b90aef818e9Jason Monkimport com.android.systemui.statusbar.policy.NetworkController.SignalCallback; 37da68f596282e60bee832dff07cc96bf64bd15939Jason Monk 38da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport java.util.Objects; 39da68f596282e60bee832dff07cc96bf64bd15939Jason Monk 40da68f596282e60bee832dff07cc96bf64bd15939Jason Monk 41da68f596282e60bee832dff07cc96bf64bd15939Jason Monkpublic class WifiSignalController extends 42da68f596282e60bee832dff07cc96bf64bd15939Jason Monk SignalController<WifiSignalController.WifiState, SignalController.IconGroup> { 43da68f596282e60bee832dff07cc96bf64bd15939Jason Monk private final AsyncChannel mWifiChannel; 44da68f596282e60bee832dff07cc96bf64bd15939Jason Monk private final boolean mHasMobileData; 454cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk private final WifiStatusTracker mWifiTracker; 46da68f596282e60bee832dff07cc96bf64bd15939Jason Monk 47da68f596282e60bee832dff07cc96bf64bd15939Jason Monk public WifiSignalController(Context context, boolean hasMobileData, 48c7593b1e1a46bc78a1404b91eabdf5bd5c58b55dAmin Shaikh CallbackHandler callbackHandler, NetworkControllerImpl networkController, 49c7593b1e1a46bc78a1404b91eabdf5bd5c58b55dAmin Shaikh WifiManager wifiManager) { 50da68f596282e60bee832dff07cc96bf64bd15939Jason Monk super("WifiSignalController", context, NetworkCapabilities.TRANSPORT_WIFI, 5107b75fe65dcb5b8add8246654c65f95f1191933eJason Monk callbackHandler, networkController); 52e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh NetworkScoreManager networkScoreManager = 53e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh context.getSystemService(NetworkScoreManager.class); 54e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh ConnectivityManager connectivityManager = 55e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh context.getSystemService(ConnectivityManager.class); 56e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh mWifiTracker = new WifiStatusTracker(mContext, wifiManager, networkScoreManager, 57e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh connectivityManager, this::handleStatusUpdated); 58e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh mWifiTracker.setListening(true); 59da68f596282e60bee832dff07cc96bf64bd15939Jason Monk mHasMobileData = hasMobileData; 602c403db659db615831d8bd02661f8769c7762241Geoffrey Pitsch Handler handler = new WifiHandler(Looper.getMainLooper()); 61da68f596282e60bee832dff07cc96bf64bd15939Jason Monk mWifiChannel = new AsyncChannel(); 62e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh Messenger wifiMessenger = wifiManager.getWifiServiceMessenger(); 63da68f596282e60bee832dff07cc96bf64bd15939Jason Monk if (wifiMessenger != null) { 64da68f596282e60bee832dff07cc96bf64bd15939Jason Monk mWifiChannel.connect(context, handler, wifiMessenger); 65da68f596282e60bee832dff07cc96bf64bd15939Jason Monk } 66da68f596282e60bee832dff07cc96bf64bd15939Jason Monk // WiFi only has one state. 67da68f596282e60bee832dff07cc96bf64bd15939Jason Monk mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup( 68da68f596282e60bee832dff07cc96bf64bd15939Jason Monk "Wi-Fi Icons", 69da68f596282e60bee832dff07cc96bf64bd15939Jason Monk WifiIcons.WIFI_SIGNAL_STRENGTH, 70da68f596282e60bee832dff07cc96bf64bd15939Jason Monk WifiIcons.QS_WIFI_SIGNAL_STRENGTH, 71da68f596282e60bee832dff07cc96bf64bd15939Jason Monk AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH, 72da68f596282e60bee832dff07cc96bf64bd15939Jason Monk WifiIcons.WIFI_NO_NETWORK, 73da68f596282e60bee832dff07cc96bf64bd15939Jason Monk WifiIcons.QS_WIFI_NO_NETWORK, 747e6c83c752e0825320e44bd87661b6422d3a3db6Jason Monk WifiIcons.WIFI_NO_NETWORK, 75da68f596282e60bee832dff07cc96bf64bd15939Jason Monk WifiIcons.QS_WIFI_NO_NETWORK, 76da68f596282e60bee832dff07cc96bf64bd15939Jason Monk AccessibilityContentDescriptions.WIFI_NO_CONNECTION 77da68f596282e60bee832dff07cc96bf64bd15939Jason Monk ); 78da68f596282e60bee832dff07cc96bf64bd15939Jason Monk } 79da68f596282e60bee832dff07cc96bf64bd15939Jason Monk 80da68f596282e60bee832dff07cc96bf64bd15939Jason Monk @Override 81da68f596282e60bee832dff07cc96bf64bd15939Jason Monk protected WifiState cleanState() { 82da68f596282e60bee832dff07cc96bf64bd15939Jason Monk return new WifiState(); 83da68f596282e60bee832dff07cc96bf64bd15939Jason Monk } 84da68f596282e60bee832dff07cc96bf64bd15939Jason Monk 85da68f596282e60bee832dff07cc96bf64bd15939Jason Monk @Override 86e06b065f6e0d0f939b8519ccd3699b90aef818e9Jason Monk public void notifyListeners(SignalCallback callback) { 87da68f596282e60bee832dff07cc96bf64bd15939Jason Monk // only show wifi in the cluster if connected or if wifi-only 887e6c83c752e0825320e44bd87661b6422d3a3db6Jason Monk boolean wifiVisible = mCurrentState.enabled 897e6c83c752e0825320e44bd87661b6422d3a3db6Jason Monk && (mCurrentState.connected || !mHasMobileData); 90da68f596282e60bee832dff07cc96bf64bd15939Jason Monk String wifiDesc = wifiVisible ? mCurrentState.ssid : null; 91da68f596282e60bee832dff07cc96bf64bd15939Jason Monk boolean ssidPresent = wifiVisible && mCurrentState.ssid != null; 92da68f596282e60bee832dff07cc96bf64bd15939Jason Monk String contentDescription = getStringIfExists(getContentDescription()); 9320aef8a2914478a85aa679ec31bf739c7818eb3cJulia Reynolds if (mCurrentState.inetCondition == 0) { 9443ad7fef062e82260532e55879f1b07325b14e3bAmin Shaikh contentDescription += ("," + mContext.getString(R.string.data_connection_no_internet)); 9520aef8a2914478a85aa679ec31bf739c7818eb3cJulia Reynolds } 969d10a3cf306d34f598216c6354c87c45a059b5b3Sundeep Ghuman IconState statusIcon = new IconState(wifiVisible, getCurrentIconId(), contentDescription); 979d10a3cf306d34f598216c6354c87c45a059b5b3Sundeep Ghuman IconState qsIcon = new IconState(mCurrentState.connected, getQsCurrentIconId(), 989d10a3cf306d34f598216c6354c87c45a059b5b3Sundeep Ghuman contentDescription); 99e06b065f6e0d0f939b8519ccd3699b90aef818e9Jason Monk callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon, 10007b75fe65dcb5b8add8246654c65f95f1191933eJason Monk ssidPresent && mCurrentState.activityIn, ssidPresent && mCurrentState.activityOut, 101e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel); 102da68f596282e60bee832dff07cc96bf64bd15939Jason Monk } 103da68f596282e60bee832dff07cc96bf64bd15939Jason Monk 104da68f596282e60bee832dff07cc96bf64bd15939Jason Monk /** 105da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * Extract wifi state directly from broadcasts about changes in wifi state. 106da68f596282e60bee832dff07cc96bf64bd15939Jason Monk */ 107da68f596282e60bee832dff07cc96bf64bd15939Jason Monk public void handleBroadcast(Intent intent) { 1084cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk mWifiTracker.handleBroadcast(intent); 1094cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk mCurrentState.enabled = mWifiTracker.enabled; 1104cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk mCurrentState.connected = mWifiTracker.connected; 1114cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk mCurrentState.ssid = mWifiTracker.ssid; 1124cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk mCurrentState.rssi = mWifiTracker.rssi; 1134cf95aef839701a43c9bde292f5e2d8ca3213509Jason Monk mCurrentState.level = mWifiTracker.level; 114e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh mCurrentState.statusLabel = mWifiTracker.statusLabel; 115e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh notifyListenersIfNecessary(); 116e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh } 117e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh 118e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh private void handleStatusUpdated() { 119e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh mCurrentState.statusLabel = mWifiTracker.statusLabel; 120da68f596282e60bee832dff07cc96bf64bd15939Jason Monk notifyListenersIfNecessary(); 121da68f596282e60bee832dff07cc96bf64bd15939Jason Monk } 122da68f596282e60bee832dff07cc96bf64bd15939Jason Monk 123da68f596282e60bee832dff07cc96bf64bd15939Jason Monk @VisibleForTesting 124da68f596282e60bee832dff07cc96bf64bd15939Jason Monk void setActivity(int wifiActivity) { 125da68f596282e60bee832dff07cc96bf64bd15939Jason Monk mCurrentState.activityIn = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT 126da68f596282e60bee832dff07cc96bf64bd15939Jason Monk || wifiActivity == WifiManager.DATA_ACTIVITY_IN; 127da68f596282e60bee832dff07cc96bf64bd15939Jason Monk mCurrentState.activityOut = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT 128da68f596282e60bee832dff07cc96bf64bd15939Jason Monk || wifiActivity == WifiManager.DATA_ACTIVITY_OUT; 129da68f596282e60bee832dff07cc96bf64bd15939Jason Monk notifyListenersIfNecessary(); 130da68f596282e60bee832dff07cc96bf64bd15939Jason Monk } 131da68f596282e60bee832dff07cc96bf64bd15939Jason Monk 132da68f596282e60bee832dff07cc96bf64bd15939Jason Monk /** 133da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * Handler to receive the data activity on wifi. 134da68f596282e60bee832dff07cc96bf64bd15939Jason Monk */ 135da68f596282e60bee832dff07cc96bf64bd15939Jason Monk private class WifiHandler extends Handler { 1362c403db659db615831d8bd02661f8769c7762241Geoffrey Pitsch WifiHandler(Looper looper) { 1372c403db659db615831d8bd02661f8769c7762241Geoffrey Pitsch super(looper); 1382c403db659db615831d8bd02661f8769c7762241Geoffrey Pitsch } 1392c403db659db615831d8bd02661f8769c7762241Geoffrey Pitsch 140da68f596282e60bee832dff07cc96bf64bd15939Jason Monk @Override 141da68f596282e60bee832dff07cc96bf64bd15939Jason Monk public void handleMessage(Message msg) { 142da68f596282e60bee832dff07cc96bf64bd15939Jason Monk switch (msg.what) { 143da68f596282e60bee832dff07cc96bf64bd15939Jason Monk case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 144da68f596282e60bee832dff07cc96bf64bd15939Jason Monk if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 145da68f596282e60bee832dff07cc96bf64bd15939Jason Monk mWifiChannel.sendMessage(Message.obtain(this, 146da68f596282e60bee832dff07cc96bf64bd15939Jason Monk AsyncChannel.CMD_CHANNEL_FULL_CONNECTION)); 147da68f596282e60bee832dff07cc96bf64bd15939Jason Monk } else { 148da68f596282e60bee832dff07cc96bf64bd15939Jason Monk Log.e(mTag, "Failed to connect to wifi"); 149da68f596282e60bee832dff07cc96bf64bd15939Jason Monk } 150da68f596282e60bee832dff07cc96bf64bd15939Jason Monk break; 151da68f596282e60bee832dff07cc96bf64bd15939Jason Monk case WifiManager.DATA_ACTIVITY_NOTIFICATION: 152da68f596282e60bee832dff07cc96bf64bd15939Jason Monk setActivity(msg.arg1); 153da68f596282e60bee832dff07cc96bf64bd15939Jason Monk break; 154da68f596282e60bee832dff07cc96bf64bd15939Jason Monk default: 155da68f596282e60bee832dff07cc96bf64bd15939Jason Monk // Ignore 156da68f596282e60bee832dff07cc96bf64bd15939Jason Monk break; 157da68f596282e60bee832dff07cc96bf64bd15939Jason Monk } 158da68f596282e60bee832dff07cc96bf64bd15939Jason Monk } 159da68f596282e60bee832dff07cc96bf64bd15939Jason Monk } 160da68f596282e60bee832dff07cc96bf64bd15939Jason Monk 161da68f596282e60bee832dff07cc96bf64bd15939Jason Monk static class WifiState extends SignalController.State { 162da68f596282e60bee832dff07cc96bf64bd15939Jason Monk String ssid; 163110e5f6c169bed3d0312ed5003833bd12d562455Jason Monk boolean isTransient; 164e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh String statusLabel; 165da68f596282e60bee832dff07cc96bf64bd15939Jason Monk 166da68f596282e60bee832dff07cc96bf64bd15939Jason Monk @Override 167da68f596282e60bee832dff07cc96bf64bd15939Jason Monk public void copyFrom(State s) { 168da68f596282e60bee832dff07cc96bf64bd15939Jason Monk super.copyFrom(s); 169da68f596282e60bee832dff07cc96bf64bd15939Jason Monk WifiState state = (WifiState) s; 170da68f596282e60bee832dff07cc96bf64bd15939Jason Monk ssid = state.ssid; 171110e5f6c169bed3d0312ed5003833bd12d562455Jason Monk isTransient = state.isTransient; 172e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh statusLabel = state.statusLabel; 173da68f596282e60bee832dff07cc96bf64bd15939Jason Monk } 174da68f596282e60bee832dff07cc96bf64bd15939Jason Monk 175da68f596282e60bee832dff07cc96bf64bd15939Jason Monk @Override 176da68f596282e60bee832dff07cc96bf64bd15939Jason Monk protected void toString(StringBuilder builder) { 177da68f596282e60bee832dff07cc96bf64bd15939Jason Monk super.toString(builder); 178e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh builder.append(",ssid=").append(ssid) 179e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh .append(",isTransient=").append(isTransient) 180e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh .append(",statusLabel=").append(statusLabel); 181da68f596282e60bee832dff07cc96bf64bd15939Jason Monk } 182da68f596282e60bee832dff07cc96bf64bd15939Jason Monk 183da68f596282e60bee832dff07cc96bf64bd15939Jason Monk @Override 184da68f596282e60bee832dff07cc96bf64bd15939Jason Monk public boolean equals(Object o) { 185e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh if (!super.equals(o)) { 186e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh return false; 187e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh } 188e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh WifiState other = (WifiState) o; 189e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh return Objects.equals(other.ssid, ssid) 190e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh && other.isTransient == isTransient 191e74dbdd364f0ed5ab1b208e9a5643bddfbafb76fAmin Shaikh && TextUtils.equals(other.statusLabel, statusLabel); 192da68f596282e60bee832dff07cc96bf64bd15939Jason Monk } 193da68f596282e60bee832dff07cc96bf64bd15939Jason Monk } 194da68f596282e60bee832dff07cc96bf64bd15939Jason Monk} 195