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