Home | History | Annotate | Download | only in policy
      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.policy;
     17 
     18 import android.content.Context;
     19 import android.content.Intent;
     20 import android.net.ConnectivityManager;
     21 import android.net.NetworkCapabilities;
     22 import android.net.NetworkScoreManager;
     23 import android.net.wifi.WifiManager;
     24 import android.os.Handler;
     25 import android.os.Looper;
     26 import android.os.Message;
     27 import android.os.Messenger;
     28 import android.text.TextUtils;
     29 import android.util.Log;
     30 
     31 import com.android.internal.annotations.VisibleForTesting;
     32 import com.android.internal.util.AsyncChannel;
     33 import com.android.settingslib.wifi.WifiStatusTracker;
     34 import com.android.systemui.R;
     35 import com.android.systemui.statusbar.policy.NetworkController.IconState;
     36 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
     37 
     38 import java.util.Objects;
     39 
     40 
     41 public class WifiSignalController extends
     42         SignalController<WifiSignalController.WifiState, SignalController.IconGroup> {
     43     private final AsyncChannel mWifiChannel;
     44     private final boolean mHasMobileData;
     45     private final WifiStatusTracker mWifiTracker;
     46 
     47     public WifiSignalController(Context context, boolean hasMobileData,
     48             CallbackHandler callbackHandler, NetworkControllerImpl networkController,
     49             WifiManager wifiManager) {
     50         super("WifiSignalController", context, NetworkCapabilities.TRANSPORT_WIFI,
     51                 callbackHandler, networkController);
     52         NetworkScoreManager networkScoreManager =
     53                 context.getSystemService(NetworkScoreManager.class);
     54         ConnectivityManager connectivityManager =
     55                 context.getSystemService(ConnectivityManager.class);
     56         mWifiTracker = new WifiStatusTracker(mContext, wifiManager, networkScoreManager,
     57                 connectivityManager, this::handleStatusUpdated);
     58         mWifiTracker.setListening(true);
     59         mHasMobileData = hasMobileData;
     60         Handler handler = new WifiHandler(Looper.getMainLooper());
     61         mWifiChannel = new AsyncChannel();
     62         Messenger wifiMessenger = wifiManager.getWifiServiceMessenger();
     63         if (wifiMessenger != null) {
     64             mWifiChannel.connect(context, handler, wifiMessenger);
     65         }
     66         // WiFi only has one state.
     67         mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup(
     68                 "Wi-Fi Icons",
     69                 WifiIcons.WIFI_SIGNAL_STRENGTH,
     70                 WifiIcons.QS_WIFI_SIGNAL_STRENGTH,
     71                 AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH,
     72                 WifiIcons.WIFI_NO_NETWORK,
     73                 WifiIcons.QS_WIFI_NO_NETWORK,
     74                 WifiIcons.WIFI_NO_NETWORK,
     75                 WifiIcons.QS_WIFI_NO_NETWORK,
     76                 AccessibilityContentDescriptions.WIFI_NO_CONNECTION
     77                 );
     78     }
     79 
     80     @Override
     81     protected WifiState cleanState() {
     82         return new WifiState();
     83     }
     84 
     85     @Override
     86     public void notifyListeners(SignalCallback callback) {
     87         // only show wifi in the cluster if connected or if wifi-only
     88         boolean wifiVisible = mCurrentState.enabled
     89                 && (mCurrentState.connected || !mHasMobileData);
     90         String wifiDesc = wifiVisible ? mCurrentState.ssid : null;
     91         boolean ssidPresent = wifiVisible && mCurrentState.ssid != null;
     92         String contentDescription = getStringIfExists(getContentDescription());
     93         if (mCurrentState.inetCondition == 0) {
     94             contentDescription += ("," + mContext.getString(R.string.data_connection_no_internet));
     95         }
     96         IconState statusIcon = new IconState(wifiVisible, getCurrentIconId(), contentDescription);
     97         IconState qsIcon = new IconState(mCurrentState.connected, getQsCurrentIconId(),
     98                 contentDescription);
     99         callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
    100                 ssidPresent && mCurrentState.activityIn, ssidPresent && mCurrentState.activityOut,
    101                 wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel);
    102     }
    103 
    104     /**
    105      * Extract wifi state directly from broadcasts about changes in wifi state.
    106      */
    107     public void handleBroadcast(Intent intent) {
    108         mWifiTracker.handleBroadcast(intent);
    109         mCurrentState.enabled = mWifiTracker.enabled;
    110         mCurrentState.connected = mWifiTracker.connected;
    111         mCurrentState.ssid = mWifiTracker.ssid;
    112         mCurrentState.rssi = mWifiTracker.rssi;
    113         mCurrentState.level = mWifiTracker.level;
    114         mCurrentState.statusLabel = mWifiTracker.statusLabel;
    115         notifyListenersIfNecessary();
    116     }
    117 
    118     private void handleStatusUpdated() {
    119         mCurrentState.statusLabel = mWifiTracker.statusLabel;
    120         notifyListenersIfNecessary();
    121     }
    122 
    123     @VisibleForTesting
    124     void setActivity(int wifiActivity) {
    125         mCurrentState.activityIn = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
    126                 || wifiActivity == WifiManager.DATA_ACTIVITY_IN;
    127         mCurrentState.activityOut = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
    128                 || wifiActivity == WifiManager.DATA_ACTIVITY_OUT;
    129         notifyListenersIfNecessary();
    130     }
    131 
    132     /**
    133      * Handler to receive the data activity on wifi.
    134      */
    135     private class WifiHandler extends Handler {
    136         WifiHandler(Looper looper) {
    137             super(looper);
    138         }
    139 
    140         @Override
    141         public void handleMessage(Message msg) {
    142             switch (msg.what) {
    143                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
    144                     if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
    145                         mWifiChannel.sendMessage(Message.obtain(this,
    146                                 AsyncChannel.CMD_CHANNEL_FULL_CONNECTION));
    147                     } else {
    148                         Log.e(mTag, "Failed to connect to wifi");
    149                     }
    150                     break;
    151                 case WifiManager.DATA_ACTIVITY_NOTIFICATION:
    152                     setActivity(msg.arg1);
    153                     break;
    154                 default:
    155                     // Ignore
    156                     break;
    157             }
    158         }
    159     }
    160 
    161     static class WifiState extends SignalController.State {
    162         String ssid;
    163         boolean isTransient;
    164         String statusLabel;
    165 
    166         @Override
    167         public void copyFrom(State s) {
    168             super.copyFrom(s);
    169             WifiState state = (WifiState) s;
    170             ssid = state.ssid;
    171             isTransient = state.isTransient;
    172             statusLabel = state.statusLabel;
    173         }
    174 
    175         @Override
    176         protected void toString(StringBuilder builder) {
    177             super.toString(builder);
    178             builder.append(",ssid=").append(ssid)
    179                 .append(",isTransient=").append(isTransient)
    180                 .append(",statusLabel=").append(statusLabel);
    181         }
    182 
    183         @Override
    184         public boolean equals(Object o) {
    185             if (!super.equals(o)) {
    186                 return false;
    187             }
    188             WifiState other = (WifiState) o;
    189             return Objects.equals(other.ssid, ssid)
    190                     && other.isTransient == isTransient
    191                     && TextUtils.equals(other.statusLabel, statusLabel);
    192         }
    193     }
    194 }
    195