Home | History | Annotate | Download | only in wifi
      1 /*
      2  * Copyright (C) 2010 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 
     17 package com.android.server.wifi;
     18 
     19 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
     20 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
     21 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
     22 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
     23 import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
     24 import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
     25 import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
     26 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
     27 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
     28 import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
     29 
     30 import android.Manifest;
     31 import android.app.ActivityManager;
     32 import android.app.AlarmManager;
     33 import android.app.PendingIntent;
     34 import android.bluetooth.BluetoothAdapter;
     35 import android.content.BroadcastReceiver;
     36 import android.content.Context;
     37 import android.content.Intent;
     38 import android.content.IntentFilter;
     39 import android.content.pm.ApplicationInfo;
     40 import android.content.pm.IPackageManager;
     41 import android.content.pm.PackageManager;
     42 import android.database.ContentObserver;
     43 import android.net.ConnectivityManager;
     44 import android.net.DhcpResults;
     45 import android.net.LinkProperties;
     46 import android.net.Network;
     47 import android.net.NetworkAgent;
     48 import android.net.NetworkCapabilities;
     49 import android.net.NetworkFactory;
     50 import android.net.NetworkInfo;
     51 import android.net.NetworkInfo.DetailedState;
     52 import android.net.NetworkMisc;
     53 import android.net.NetworkRequest;
     54 import android.net.NetworkUtils;
     55 import android.net.RouteInfo;
     56 import android.net.StaticIpConfiguration;
     57 import android.net.dhcp.DhcpClient;
     58 import android.net.ip.IpManager;
     59 import android.net.wifi.PasspointManagementObjectDefinition;
     60 import android.net.wifi.RssiPacketCountInfo;
     61 import android.net.wifi.ScanResult;
     62 import android.net.wifi.ScanSettings;
     63 import android.net.wifi.SupplicantState;
     64 import android.net.wifi.WifiChannel;
     65 import android.net.wifi.WifiConfiguration;
     66 import android.net.wifi.WifiConnectionStatistics;
     67 import android.net.wifi.WifiEnterpriseConfig;
     68 import android.net.wifi.WifiInfo;
     69 import android.net.wifi.WifiLinkLayerStats;
     70 import android.net.wifi.WifiManager;
     71 import android.net.wifi.WifiScanner;
     72 import android.net.wifi.WifiSsid;
     73 import android.net.wifi.WpsInfo;
     74 import android.net.wifi.WpsResult;
     75 import android.net.wifi.WpsResult.Status;
     76 import android.net.wifi.p2p.IWifiP2pManager;
     77 import android.os.BatteryStats;
     78 import android.os.Binder;
     79 import android.os.Bundle;
     80 import android.os.IBinder;
     81 import android.os.INetworkManagementService;
     82 import android.os.Looper;
     83 import android.os.Message;
     84 import android.os.Messenger;
     85 import android.os.PowerManager;
     86 import android.os.Process;
     87 import android.os.RemoteException;
     88 import android.os.SystemClock;
     89 import android.os.UserHandle;
     90 import android.os.UserManager;
     91 import android.os.WorkSource;
     92 import android.provider.Settings;
     93 import android.telephony.TelephonyManager;
     94 import android.text.TextUtils;
     95 import android.util.Log;
     96 import android.util.SparseArray;
     97 
     98 import com.android.internal.R;
     99 import com.android.internal.annotations.VisibleForTesting;
    100 import com.android.internal.app.IBatteryStats;
    101 import com.android.internal.util.AsyncChannel;
    102 import com.android.internal.util.MessageUtils;
    103 import com.android.internal.util.Protocol;
    104 import com.android.internal.util.State;
    105 import com.android.internal.util.StateMachine;
    106 import com.android.server.connectivity.KeepalivePacketData;
    107 import com.android.server.wifi.hotspot2.IconEvent;
    108 import com.android.server.wifi.hotspot2.NetworkDetail;
    109 import com.android.server.wifi.hotspot2.Utils;
    110 import com.android.server.wifi.p2p.WifiP2pServiceImpl;
    111 import com.android.server.wifi.util.TelephonyUtil;
    112 
    113 import java.io.BufferedReader;
    114 import java.io.FileDescriptor;
    115 import java.io.FileNotFoundException;
    116 import java.io.FileReader;
    117 import java.io.IOException;
    118 import java.io.PrintWriter;
    119 import java.net.Inet4Address;
    120 import java.net.InetAddress;
    121 import java.util.ArrayList;
    122 import java.util.Arrays;
    123 import java.util.Calendar;
    124 import java.util.HashSet;
    125 import java.util.LinkedList;
    126 import java.util.List;
    127 import java.util.Queue;
    128 import java.util.Random;
    129 import java.util.Set;
    130 import java.util.concurrent.atomic.AtomicBoolean;
    131 import java.util.concurrent.atomic.AtomicInteger;
    132 
    133 /**
    134  * TODO:
    135  * Deprecate WIFI_STATE_UNKNOWN
    136  */
    137 
    138 /**
    139  * Track the state of Wifi connectivity. All event handling is done here,
    140  * and all changes in connectivity state are initiated here.
    141  *
    142  * Wi-Fi now supports three modes of operation: Client, SoftAp and p2p
    143  * In the current implementation, we support concurrent wifi p2p and wifi operation.
    144  * The WifiStateMachine handles SoftAp and Client operations while WifiP2pService
    145  * handles p2p operation.
    146  *
    147  * @hide
    148  */
    149 public class WifiStateMachine extends StateMachine implements WifiNative.WifiRssiEventHandler {
    150 
    151     private static final String NETWORKTYPE = "WIFI";
    152     private static final String NETWORKTYPE_UNTRUSTED = "WIFI_UT";
    153     @VisibleForTesting public static final short NUM_LOG_RECS_NORMAL = 100;
    154     @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE_LOW_MEMORY = 200;
    155     @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE = 3000;
    156     private static boolean DBG = false;
    157     private static boolean USE_PAUSE_SCANS = false;
    158     private static final String TAG = "WifiStateMachine";
    159 
    160     private static final int ONE_HOUR_MILLI = 1000 * 60 * 60;
    161 
    162     private static final String GOOGLE_OUI = "DA-A1-19";
    163 
    164     private int mVerboseLoggingLevel = 0;
    165     /* debug flag, indicating if handling of ASSOCIATION_REJECT ended up blacklisting
    166      * the corresponding BSSID.
    167      */
    168     private boolean didBlackListBSSID = false;
    169 
    170     /**
    171      * Log with error attribute
    172      *
    173      * @param s is string log
    174      */
    175     protected void loge(String s) {
    176         Log.e(getName(), s);
    177     }
    178     protected void logd(String s) {
    179         Log.d(getName(), s);
    180     }
    181     protected void log(String s) {;
    182         Log.d(getName(), s);
    183     }
    184     private WifiLastResortWatchdog mWifiLastResortWatchdog;
    185     private WifiMetrics mWifiMetrics;
    186     private WifiInjector mWifiInjector;
    187     private WifiMonitor mWifiMonitor;
    188     private WifiNative mWifiNative;
    189     private WifiConfigManager mWifiConfigManager;
    190     private WifiConnectivityManager mWifiConnectivityManager;
    191     private WifiQualifiedNetworkSelector mWifiQualifiedNetworkSelector;
    192     private INetworkManagementService mNwService;
    193     private ConnectivityManager mCm;
    194     private BaseWifiLogger mWifiLogger;
    195     private WifiApConfigStore mWifiApConfigStore;
    196     private final boolean mP2pSupported;
    197     private final AtomicBoolean mP2pConnected = new AtomicBoolean(false);
    198     private boolean mTemporarilyDisconnectWifi = false;
    199     private final String mPrimaryDeviceType;
    200     private final Clock mClock;
    201     private final PropertyService mPropertyService;
    202     private final BuildProperties mBuildProperties;
    203     private final WifiCountryCode mCountryCode;
    204 
    205     /* Scan results handling */
    206     private List<ScanDetail> mScanResults = new ArrayList<>();
    207     private final Object mScanResultsLock = new Object();
    208 
    209     // For debug, number of known scan results that were found as part of last scan result event,
    210     // as well the number of scans results returned by the supplicant with that message
    211     private int mNumScanResultsKnown;
    212     private int mNumScanResultsReturned;
    213 
    214     private boolean mScreenOn = false;
    215 
    216     /* Chipset supports background scan */
    217     private final boolean mBackgroundScanSupported;
    218 
    219     private final String mInterfaceName;
    220     /* Tethering interface could be separate from wlan interface */
    221     private String mTetherInterfaceName;
    222 
    223     private int mLastSignalLevel = -1;
    224     private String mLastBssid;
    225     private int mLastNetworkId; // The network Id we successfully joined
    226     private boolean linkDebouncing = false;
    227 
    228     @Override
    229     public void onRssiThresholdBreached(byte curRssi) {
    230         if (DBG) {
    231             Log.e(TAG, "onRssiThresholdBreach event. Cur Rssi = " + curRssi);
    232         }
    233         sendMessage(CMD_RSSI_THRESHOLD_BREACH, curRssi);
    234     }
    235 
    236     public void processRssiThreshold(byte curRssi, int reason) {
    237         if (curRssi == Byte.MAX_VALUE || curRssi == Byte.MIN_VALUE) {
    238             Log.wtf(TAG, "processRssiThreshold: Invalid rssi " + curRssi);
    239             return;
    240         }
    241         for (int i = 0; i < mRssiRanges.length; i++) {
    242             if (curRssi < mRssiRanges[i]) {
    243                 // Assume sorted values(ascending order) for rssi,
    244                 // bounded by high(127) and low(-128) at extremeties
    245                 byte maxRssi = mRssiRanges[i];
    246                 byte minRssi = mRssiRanges[i-1];
    247                 // This value of hw has to be believed as this value is averaged and has breached
    248                 // the rssi thresholds and raised event to host. This would be eggregious if this
    249                 // value is invalid
    250                 mWifiInfo.setRssi((int) curRssi);
    251                 updateCapabilities(getCurrentWifiConfiguration());
    252                 int ret = startRssiMonitoringOffload(maxRssi, minRssi);
    253                 Log.d(TAG, "Re-program RSSI thresholds for " + smToString(reason) +
    254                         ": [" + minRssi + ", " + maxRssi + "], curRssi=" + curRssi + " ret=" + ret);
    255                 break;
    256             }
    257         }
    258     }
    259 
    260     // Testing various network disconnect cases by sending lots of spurious
    261     // disconnect to supplicant
    262     private boolean testNetworkDisconnect = false;
    263 
    264     private boolean mEnableRssiPolling = false;
    265     private int mRssiPollToken = 0;
    266     /* 3 operational states for STA operation: CONNECT_MODE, SCAN_ONLY_MODE, SCAN_ONLY_WIFI_OFF_MODE
    267     * In CONNECT_MODE, the STA can scan and connect to an access point
    268     * In SCAN_ONLY_MODE, the STA can only scan for access points
    269     * In SCAN_ONLY_WIFI_OFF_MODE, the STA can only scan for access points with wifi toggle being off
    270     */
    271     private int mOperationalMode = CONNECT_MODE;
    272     private boolean mIsScanOngoing = false;
    273     private boolean mIsFullScanOngoing = false;
    274     private boolean mSendScanResultsBroadcast = false;
    275 
    276     private final Queue<Message> mBufferedScanMsg = new LinkedList<Message>();
    277     private WorkSource mScanWorkSource = null;
    278     private static final int UNKNOWN_SCAN_SOURCE = -1;
    279     private static final int ADD_OR_UPDATE_SOURCE = -3;
    280     private static final int SET_ALLOW_UNTRUSTED_SOURCE = -4;
    281     private static final int ENABLE_WIFI = -5;
    282     public static final int DFS_RESTRICTED_SCAN_REQUEST = -6;
    283 
    284     private static final int SCAN_REQUEST_BUFFER_MAX_SIZE = 10;
    285     private static final String CUSTOMIZED_SCAN_SETTING = "customized_scan_settings";
    286     private static final String CUSTOMIZED_SCAN_WORKSOURCE = "customized_scan_worksource";
    287     private static final String SCAN_REQUEST_TIME = "scan_request_time";
    288 
    289     /* Tracks if state machine has received any screen state change broadcast yet.
    290      * We can miss one of these at boot.
    291      */
    292     private AtomicBoolean mScreenBroadcastReceived = new AtomicBoolean(false);
    293 
    294     private boolean mBluetoothConnectionActive = false;
    295 
    296     private PowerManager.WakeLock mSuspendWakeLock;
    297 
    298     /**
    299      * Interval in milliseconds between polling for RSSI
    300      * and linkspeed information
    301      */
    302     private static final int POLL_RSSI_INTERVAL_MSECS = 3000;
    303 
    304     /**
    305      * Interval in milliseconds between receiving a disconnect event
    306      * while connected to a good AP, and handling the disconnect proper
    307      */
    308     private static final int LINK_FLAPPING_DEBOUNCE_MSEC = 4000;
    309 
    310     /**
    311      * Delay between supplicant restarts upon failure to establish connection
    312      */
    313     private static final int SUPPLICANT_RESTART_INTERVAL_MSECS = 5000;
    314 
    315     /**
    316      * Number of times we attempt to restart supplicant
    317      */
    318     private static final int SUPPLICANT_RESTART_TRIES = 5;
    319 
    320     private int mSupplicantRestartCount = 0;
    321     /* Tracks sequence number on stop failure message */
    322     private int mSupplicantStopFailureToken = 0;
    323 
    324     /**
    325      * Tether state change notification time out
    326      */
    327     private static final int TETHER_NOTIFICATION_TIME_OUT_MSECS = 5000;
    328 
    329     /* Tracks sequence number on a tether notification time out */
    330     private int mTetherToken = 0;
    331 
    332     /**
    333      * Driver start time out.
    334      */
    335     private static final int DRIVER_START_TIME_OUT_MSECS = 10000;
    336 
    337     /* Tracks sequence number on a driver time out */
    338     private int mDriverStartToken = 0;
    339 
    340     /**
    341      * Don't select new network when previous network selection is
    342      * pending connection for this much time
    343      */
    344     private static final int CONNECT_TIMEOUT_MSEC = 3000;
    345 
    346     /**
    347      * The link properties of the wifi interface.
    348      * Do not modify this directly; use updateLinkProperties instead.
    349      */
    350     private LinkProperties mLinkProperties;
    351 
    352     /* Tracks sequence number on a periodic scan message */
    353     private int mPeriodicScanToken = 0;
    354 
    355     // Wakelock held during wifi start/stop and driver load/unload
    356     private PowerManager.WakeLock mWakeLock;
    357 
    358     private Context mContext;
    359 
    360     private final Object mDhcpResultsLock = new Object();
    361     private DhcpResults mDhcpResults;
    362 
    363     // NOTE: Do not return to clients - use #getWiFiInfoForUid(int)
    364     private final WifiInfo mWifiInfo;
    365     private NetworkInfo mNetworkInfo;
    366     private final NetworkCapabilities mDfltNetworkCapabilities;
    367     private SupplicantStateTracker mSupplicantStateTracker;
    368 
    369     private int mWifiLinkLayerStatsSupported = 4; // Temporary disable
    370 
    371     // Whether the state machine goes thru the Disconnecting->Disconnected->ObtainingIpAddress
    372     private boolean mAutoRoaming = false;
    373 
    374     // Roaming failure count
    375     private int mRoamFailCount = 0;
    376 
    377     // This is the BSSID we are trying to associate to, it can be set to "any"
    378     // if we havent selected a BSSID for joining.
    379     // if we havent selected a BSSID for joining.
    380     // The BSSID we are associated to is found in mWifiInfo
    381     private String mTargetRoamBSSID = "any";
    382     //This one is used to track whta is the current target network ID. This is used for error
    383     // handling during connection setup since many error message from supplicant does not report
    384     // SSID Once connected, it will be set to invalid
    385     private int mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
    386 
    387     private long mLastDriverRoamAttempt = 0;
    388 
    389     private WifiConfiguration targetWificonfiguration = null;
    390 
    391     // Used as debug to indicate which configuration last was saved
    392     private WifiConfiguration lastSavedConfigurationAttempt = null;
    393 
    394     // Used as debug to indicate which configuration last was removed
    395     private WifiConfiguration lastForgetConfigurationAttempt = null;
    396 
    397     //Random used by softAP channel Selection
    398     private static Random mRandom = new Random(Calendar.getInstance().getTimeInMillis());
    399 
    400     boolean isRoaming() {
    401         return mAutoRoaming;
    402     }
    403 
    404     public void autoRoamSetBSSID(int netId, String bssid) {
    405         autoRoamSetBSSID(mWifiConfigManager.getWifiConfiguration(netId), bssid);
    406     }
    407 
    408     public boolean autoRoamSetBSSID(WifiConfiguration config, String bssid) {
    409         boolean ret = true;
    410         if (mTargetRoamBSSID == null) mTargetRoamBSSID = "any";
    411         if (bssid == null) bssid = "any";
    412         if (config == null) return false; // Nothing to do
    413 
    414         if (mTargetRoamBSSID != null
    415                 && bssid.equals(mTargetRoamBSSID) && bssid.equals(config.BSSID)) {
    416             return false; // We didnt change anything
    417         }
    418         if (!mTargetRoamBSSID.equals("any") && bssid.equals("any")) {
    419             // Changing to ANY
    420             if (!mWifiConfigManager.ROAM_ON_ANY) {
    421                 ret = false; // Nothing to do
    422             }
    423         }
    424         if (config.BSSID != null) {
    425             bssid = config.BSSID;
    426             if (DBG) {
    427                 Log.d(TAG, "force BSSID to " + bssid + "due to config");
    428             }
    429         }
    430 
    431         if (DBG) {
    432             logd("autoRoamSetBSSID " + bssid + " key=" + config.configKey());
    433         }
    434         mTargetRoamBSSID = bssid;
    435         mWifiConfigManager.saveWifiConfigBSSID(config, bssid);
    436         return ret;
    437     }
    438 
    439     /**
    440      * set Config's default BSSID (for association purpose)
    441      * @param config config need set BSSID
    442      * @param bssid  default BSSID to assocaite with when connect to this network
    443      * @return false -- does not change the current default BSSID of the configure
    444      *         true -- change the  current default BSSID of the configur
    445      */
    446     private boolean setTargetBssid(WifiConfiguration config, String bssid) {
    447         if (config == null) {
    448             return false;
    449         }
    450 
    451         if (config.BSSID != null) {
    452             bssid = config.BSSID;
    453             if (DBG) {
    454                 Log.d(TAG, "force BSSID to " + bssid + "due to config");
    455             }
    456         }
    457 
    458         if (bssid == null) {
    459             bssid = "any";
    460         }
    461 
    462         String networkSelectionBSSID = config.getNetworkSelectionStatus()
    463                 .getNetworkSelectionBSSID();
    464         if (networkSelectionBSSID != null && networkSelectionBSSID.equals(bssid)) {
    465             if (DBG) {
    466                 Log.d(TAG, "Current preferred BSSID is the same as the target one");
    467             }
    468             return false;
    469         }
    470 
    471         if (DBG) {
    472             Log.d(TAG, "target set to " + config.SSID + ":" + bssid);
    473         }
    474         mTargetRoamBSSID = bssid;
    475         mWifiConfigManager.saveWifiConfigBSSID(config, bssid);
    476         return true;
    477     }
    478     /**
    479      * Save the UID correctly depending on if this is a new or existing network.
    480      * @return true if operation is authorized, false otherwise
    481      */
    482     boolean recordUidIfAuthorized(WifiConfiguration config, int uid, boolean onlyAnnotate) {
    483         if (!mWifiConfigManager.isNetworkConfigured(config)) {
    484             config.creatorUid = uid;
    485             config.creatorName = mContext.getPackageManager().getNameForUid(uid);
    486         } else if (!mWifiConfigManager.canModifyNetwork(uid, config, onlyAnnotate)) {
    487             return false;
    488         }
    489 
    490         config.lastUpdateUid = uid;
    491         config.lastUpdateName = mContext.getPackageManager().getNameForUid(uid);
    492 
    493         return true;
    494 
    495     }
    496 
    497     /**
    498      * Checks to see if user has specified if the apps configuration is connectable.
    499      * If the user hasn't specified we query the user and return true.
    500      *
    501      * @param message The message to be deferred
    502      * @param netId Network id of the configuration to check against
    503      * @param allowOverride If true we won't defer to the user if the uid of the message holds the
    504      *                      CONFIG_OVERRIDE_PERMISSION
    505      * @return True if we are waiting for user feedback or netId is invalid. False otherwise.
    506      */
    507     boolean deferForUserInput(Message message, int netId, boolean allowOverride){
    508         final WifiConfiguration config = mWifiConfigManager.getWifiConfiguration(netId);
    509 
    510         // We can only evaluate saved configurations.
    511         if (config == null) {
    512             logd("deferForUserInput: configuration for netId=" + netId + " not stored");
    513             return true;
    514         }
    515 
    516         switch (config.userApproved) {
    517             case WifiConfiguration.USER_APPROVED:
    518             case WifiConfiguration.USER_BANNED:
    519                 return false;
    520             case WifiConfiguration.USER_PENDING:
    521             default: // USER_UNSPECIFIED
    522                /* the intention was to ask user here; but a dialog box is   *
    523                 * too invasive; so we are going to allow connection for now */
    524                 config.userApproved = WifiConfiguration.USER_APPROVED;
    525                 return false;
    526         }
    527     }
    528 
    529     private final IpManager mIpManager;
    530 
    531     private AlarmManager mAlarmManager;
    532     private PendingIntent mScanIntent;
    533 
    534     /* Tracks current frequency mode */
    535     private AtomicInteger mFrequencyBand = new AtomicInteger(WifiManager.WIFI_FREQUENCY_BAND_AUTO);
    536 
    537     // Channel for sending replies.
    538     private AsyncChannel mReplyChannel = new AsyncChannel();
    539 
    540     private WifiP2pServiceImpl mWifiP2pServiceImpl;
    541 
    542     // Used to initiate a connection with WifiP2pService
    543     private AsyncChannel mWifiP2pChannel;
    544 
    545     private WifiScanner mWifiScanner;
    546 
    547     private int mConnectionRequests = 0;
    548     private WifiNetworkFactory mNetworkFactory;
    549     private UntrustedWifiNetworkFactory mUntrustedNetworkFactory;
    550     private WifiNetworkAgent mNetworkAgent;
    551 
    552     private String[] mWhiteListedSsids = null;
    553 
    554     private byte[] mRssiRanges;
    555 
    556     // Keep track of various statistics, for retrieval by System Apps, i.e. under @SystemApi
    557     // We should really persist that into the networkHistory.txt file, and read it back when
    558     // WifiStateMachine starts up
    559     private WifiConnectionStatistics mWifiConnectionStatistics = new WifiConnectionStatistics();
    560 
    561     // Used to filter out requests we couldn't possibly satisfy.
    562     private final NetworkCapabilities mNetworkCapabilitiesFilter = new NetworkCapabilities();
    563 
    564     // Provide packet filter capabilities to ConnectivityService.
    565     private final NetworkMisc mNetworkMisc = new NetworkMisc();
    566 
    567     /* The base for wifi message types */
    568     static final int BASE = Protocol.BASE_WIFI;
    569     /* Start the supplicant */
    570     static final int CMD_START_SUPPLICANT                               = BASE + 11;
    571     /* Stop the supplicant */
    572     static final int CMD_STOP_SUPPLICANT                                = BASE + 12;
    573     /* Start the driver */
    574     static final int CMD_START_DRIVER                                   = BASE + 13;
    575     /* Stop the driver */
    576     static final int CMD_STOP_DRIVER                                    = BASE + 14;
    577     /* Indicates Static IP succeeded */
    578     static final int CMD_STATIC_IP_SUCCESS                              = BASE + 15;
    579     /* Indicates Static IP failed */
    580     static final int CMD_STATIC_IP_FAILURE                              = BASE + 16;
    581     /* Indicates supplicant stop failed */
    582     static final int CMD_STOP_SUPPLICANT_FAILED                         = BASE + 17;
    583     /* A delayed message sent to start driver when it fail to come up */
    584     static final int CMD_DRIVER_START_TIMED_OUT                         = BASE + 19;
    585 
    586     /* Start the soft access point */
    587     static final int CMD_START_AP                                       = BASE + 21;
    588     /* Indicates soft ap start failed */
    589     static final int CMD_START_AP_FAILURE                               = BASE + 22;
    590     /* Stop the soft access point */
    591     static final int CMD_STOP_AP                                        = BASE + 23;
    592     /* Soft access point teardown is completed. */
    593     static final int CMD_AP_STOPPED                                     = BASE + 24;
    594 
    595     static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE                 = BASE + 31;
    596 
    597     /* Supplicant commands */
    598     /* Is supplicant alive ? */
    599     static final int CMD_PING_SUPPLICANT                                = BASE + 51;
    600     /* Add/update a network configuration */
    601     static final int CMD_ADD_OR_UPDATE_NETWORK                          = BASE + 52;
    602     /* Delete a network */
    603     static final int CMD_REMOVE_NETWORK                                 = BASE + 53;
    604     /* Enable a network. The device will attempt a connection to the given network. */
    605     static final int CMD_ENABLE_NETWORK                                 = BASE + 54;
    606     /* Enable all networks */
    607     static final int CMD_ENABLE_ALL_NETWORKS                            = BASE + 55;
    608     /* Blacklist network. De-prioritizes the given BSSID for connection. */
    609     static final int CMD_BLACKLIST_NETWORK                              = BASE + 56;
    610     /* Clear the blacklist network list */
    611     static final int CMD_CLEAR_BLACKLIST                                = BASE + 57;
    612     /* Save configuration */
    613     static final int CMD_SAVE_CONFIG                                    = BASE + 58;
    614     /* Get configured networks */
    615     static final int CMD_GET_CONFIGURED_NETWORKS                        = BASE + 59;
    616     /* Get available frequencies */
    617     static final int CMD_GET_CAPABILITY_FREQ                            = BASE + 60;
    618     /* Get adaptors */
    619     static final int CMD_GET_SUPPORTED_FEATURES                         = BASE + 61;
    620     /* Get configured networks with real preSharedKey */
    621     static final int CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS             = BASE + 62;
    622     /* Get Link Layer Stats thru HAL */
    623     static final int CMD_GET_LINK_LAYER_STATS                           = BASE + 63;
    624     /* Supplicant commands after driver start*/
    625     /* Initiate a scan */
    626     static final int CMD_START_SCAN                                     = BASE + 71;
    627     /* Set operational mode. CONNECT, SCAN ONLY, SCAN_ONLY with Wi-Fi off mode */
    628     static final int CMD_SET_OPERATIONAL_MODE                           = BASE + 72;
    629     /* Disconnect from a network */
    630     static final int CMD_DISCONNECT                                     = BASE + 73;
    631     /* Reconnect to a network */
    632     static final int CMD_RECONNECT                                      = BASE + 74;
    633     /* Reassociate to a network */
    634     static final int CMD_REASSOCIATE                                    = BASE + 75;
    635     /* Get Connection Statistis */
    636     static final int CMD_GET_CONNECTION_STATISTICS                      = BASE + 76;
    637 
    638     /* Controls suspend mode optimizations
    639      *
    640      * When high perf mode is enabled, suspend mode optimizations are disabled
    641      *
    642      * When high perf mode is disabled, suspend mode optimizations are enabled
    643      *
    644      * Suspend mode optimizations include:
    645      * - packet filtering
    646      * - turn off roaming
    647      * - DTIM wake up settings
    648      */
    649     static final int CMD_SET_HIGH_PERF_MODE                             = BASE + 77;
    650     /* Enables RSSI poll */
    651     static final int CMD_ENABLE_RSSI_POLL                               = BASE + 82;
    652     /* RSSI poll */
    653     static final int CMD_RSSI_POLL                                      = BASE + 83;
    654     /* Enable suspend mode optimizations in the driver */
    655     static final int CMD_SET_SUSPEND_OPT_ENABLED                        = BASE + 86;
    656     /* Delayed NETWORK_DISCONNECT */
    657     static final int CMD_DELAYED_NETWORK_DISCONNECT                     = BASE + 87;
    658     /* When there are no saved networks, we do a periodic scan to notify user of
    659      * an open network */
    660     static final int CMD_NO_NETWORKS_PERIODIC_SCAN                      = BASE + 88;
    661     /* Test network Disconnection NETWORK_DISCONNECT */
    662     static final int CMD_TEST_NETWORK_DISCONNECT                        = BASE + 89;
    663 
    664     private int testNetworkDisconnectCounter = 0;
    665 
    666     /* Set the frequency band */
    667     static final int CMD_SET_FREQUENCY_BAND                             = BASE + 90;
    668     /* Enable TDLS on a specific MAC address */
    669     static final int CMD_ENABLE_TDLS                                    = BASE + 92;
    670     /* DHCP/IP configuration watchdog */
    671     static final int CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER            = BASE + 93;
    672 
    673     /**
    674      * Watchdog for protecting against b/16823537
    675      * Leave time for 4-way handshake to succeed
    676      */
    677     static final int ROAM_GUARD_TIMER_MSEC = 15000;
    678 
    679     int roamWatchdogCount = 0;
    680     /* Roam state watchdog */
    681     static final int CMD_ROAM_WATCHDOG_TIMER                            = BASE + 94;
    682     /* Screen change intent handling */
    683     static final int CMD_SCREEN_STATE_CHANGED                           = BASE + 95;
    684 
    685     /* Disconnecting state watchdog */
    686     static final int CMD_DISCONNECTING_WATCHDOG_TIMER                   = BASE + 96;
    687 
    688     /* Remove a packages associated configrations */
    689     static final int CMD_REMOVE_APP_CONFIGURATIONS                      = BASE + 97;
    690 
    691     /* Disable an ephemeral network */
    692     static final int CMD_DISABLE_EPHEMERAL_NETWORK                      = BASE + 98;
    693 
    694     /* Get matching network */
    695     static final int CMD_GET_MATCHING_CONFIG                            = BASE + 99;
    696 
    697     /* alert from firmware */
    698     static final int CMD_FIRMWARE_ALERT                                 = BASE + 100;
    699 
    700     /* SIM is removed; reset any cached data for it */
    701     static final int CMD_RESET_SIM_NETWORKS                             = BASE + 101;
    702 
    703     /* OSU APIs */
    704     static final int CMD_ADD_PASSPOINT_MO                               = BASE + 102;
    705     static final int CMD_MODIFY_PASSPOINT_MO                            = BASE + 103;
    706     static final int CMD_QUERY_OSU_ICON                                 = BASE + 104;
    707 
    708     /* try to match a provider with current network */
    709     static final int CMD_MATCH_PROVIDER_NETWORK                         = BASE + 105;
    710 
    711     /**
    712      * Make this timer 40 seconds, which is about the normal DHCP timeout.
    713      * In no valid case, the WiFiStateMachine should remain stuck in ObtainingIpAddress
    714      * for more than 30 seconds.
    715      */
    716     static final int OBTAINING_IP_ADDRESS_GUARD_TIMER_MSEC = 40000;
    717 
    718     int obtainingIpWatchdogCount = 0;
    719 
    720     /* Commands from/to the SupplicantStateTracker */
    721     /* Reset the supplicant state tracker */
    722     static final int CMD_RESET_SUPPLICANT_STATE                         = BASE + 111;
    723 
    724     int disconnectingWatchdogCount = 0;
    725     static final int DISCONNECTING_GUARD_TIMER_MSEC = 5000;
    726 
    727     /* P2p commands */
    728     /* We are ok with no response here since we wont do much with it anyway */
    729     public static final int CMD_ENABLE_P2P                              = BASE + 131;
    730     /* In order to shut down supplicant cleanly, we wait till p2p has
    731      * been disabled */
    732     public static final int CMD_DISABLE_P2P_REQ                         = BASE + 132;
    733     public static final int CMD_DISABLE_P2P_RSP                         = BASE + 133;
    734 
    735     public static final int CMD_BOOT_COMPLETED                          = BASE + 134;
    736 
    737     /* We now have a valid IP configuration. */
    738     static final int CMD_IP_CONFIGURATION_SUCCESSFUL                    = BASE + 138;
    739     /* We no longer have a valid IP configuration. */
    740     static final int CMD_IP_CONFIGURATION_LOST                          = BASE + 139;
    741     /* Link configuration (IP address, DNS, ...) changes notified via netlink */
    742     static final int CMD_UPDATE_LINKPROPERTIES                          = BASE + 140;
    743 
    744     /* Supplicant is trying to associate to a given BSSID */
    745     static final int CMD_TARGET_BSSID                                   = BASE + 141;
    746 
    747     /* Reload all networks and reconnect */
    748     static final int CMD_RELOAD_TLS_AND_RECONNECT                       = BASE + 142;
    749 
    750     static final int CMD_AUTO_CONNECT                                   = BASE + 143;
    751 
    752     private static final int NETWORK_STATUS_UNWANTED_DISCONNECT         = 0;
    753     private static final int NETWORK_STATUS_UNWANTED_VALIDATION_FAILED  = 1;
    754     private static final int NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN   = 2;
    755 
    756     static final int CMD_UNWANTED_NETWORK                               = BASE + 144;
    757 
    758     static final int CMD_AUTO_ROAM                                      = BASE + 145;
    759 
    760     static final int CMD_AUTO_SAVE_NETWORK                              = BASE + 146;
    761 
    762     static final int CMD_ASSOCIATED_BSSID                               = BASE + 147;
    763 
    764     static final int CMD_NETWORK_STATUS                                 = BASE + 148;
    765 
    766     /* A layer 3 neighbor on the Wi-Fi link became unreachable. */
    767     static final int CMD_IP_REACHABILITY_LOST                           = BASE + 149;
    768 
    769     /* Remove a packages associated configrations */
    770     static final int CMD_REMOVE_USER_CONFIGURATIONS                     = BASE + 152;
    771 
    772     static final int CMD_ACCEPT_UNVALIDATED                             = BASE + 153;
    773 
    774     /* used to log if PNO was started */
    775     static final int CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION              = BASE + 158;
    776 
    777     /* used to offload sending IP packet */
    778     static final int CMD_START_IP_PACKET_OFFLOAD                        = BASE + 160;
    779 
    780     /* used to stop offload sending IP packet */
    781     static final int CMD_STOP_IP_PACKET_OFFLOAD                         = BASE + 161;
    782 
    783     /* used to start rssi monitoring in hw */
    784     static final int CMD_START_RSSI_MONITORING_OFFLOAD                  = BASE + 162;
    785 
    786     /* used to stop rssi moniroting in hw */
    787     static final int CMD_STOP_RSSI_MONITORING_OFFLOAD                   = BASE + 163;
    788 
    789     /* used to indicated RSSI threshold breach in hw */
    790     static final int CMD_RSSI_THRESHOLD_BREACH                          = BASE + 164;
    791 
    792     /* used to indicate that the foreground user was switched */
    793     static final int CMD_USER_SWITCH                                    = BASE + 165;
    794 
    795     /* Enable/Disable WifiConnectivityManager */
    796     static final int CMD_ENABLE_WIFI_CONNECTIVITY_MANAGER               = BASE + 166;
    797 
    798     /* Enable/Disable AutoJoin when associated */
    799     static final int CMD_ENABLE_AUTOJOIN_WHEN_ASSOCIATED                = BASE + 167;
    800 
    801     /**
    802      * Used to handle messages bounced between WifiStateMachine and IpManager.
    803      */
    804     static final int CMD_IPV4_PROVISIONING_SUCCESS                      = BASE + 200;
    805     static final int CMD_IPV4_PROVISIONING_FAILURE                      = BASE + 201;
    806 
    807     /* Push a new APF program to the HAL */
    808     static final int CMD_INSTALL_PACKET_FILTER                          = BASE + 202;
    809 
    810     /* Enable/disable fallback packet filtering */
    811     static final int CMD_SET_FALLBACK_PACKET_FILTERING                  = BASE + 203;
    812 
    813     /* Enable/disable Neighbor Discovery offload functionality. */
    814     static final int CMD_CONFIG_ND_OFFLOAD                              = BASE + 204;
    815 
    816     // For message logging.
    817     private static final Class[] sMessageClasses = {
    818             AsyncChannel.class, WifiStateMachine.class, DhcpClient.class };
    819     private static final SparseArray<String> sSmToString =
    820             MessageUtils.findMessageNames(sMessageClasses);
    821 
    822 
    823     /* Wifi state machine modes of operation */
    824     /* CONNECT_MODE - connect to any 'known' AP when it becomes available */
    825     public static final int CONNECT_MODE = 1;
    826     /* SCAN_ONLY_MODE - don't connect to any APs; scan, but only while apps hold lock */
    827     public static final int SCAN_ONLY_MODE = 2;
    828     /* SCAN_ONLY_WITH_WIFI_OFF - scan, but don't connect to any APs */
    829     public static final int SCAN_ONLY_WITH_WIFI_OFF_MODE = 3;
    830 
    831     private static final int SUCCESS = 1;
    832     private static final int FAILURE = -1;
    833 
    834     /* Tracks if suspend optimizations need to be disabled by DHCP,
    835      * screen or due to high perf mode.
    836      * When any of them needs to disable it, we keep the suspend optimizations
    837      * disabled
    838      */
    839     private int mSuspendOptNeedsDisabled = 0;
    840 
    841     private static final int SUSPEND_DUE_TO_DHCP = 1;
    842     private static final int SUSPEND_DUE_TO_HIGH_PERF = 1 << 1;
    843     private static final int SUSPEND_DUE_TO_SCREEN = 1 << 2;
    844 
    845     /* Tracks if user has enabled suspend optimizations through settings */
    846     private AtomicBoolean mUserWantsSuspendOpt = new AtomicBoolean(true);
    847 
    848     /**
    849      * Default framework scan interval in milliseconds. This is used in the scenario in which
    850      * wifi chipset does not support background scanning to set up a
    851      * periodic wake up scan so that the device can connect to a new access
    852      * point on the move. {@link Settings.Global#WIFI_FRAMEWORK_SCAN_INTERVAL_MS} can
    853      * override this.
    854      */
    855     private final int mDefaultFrameworkScanIntervalMs;
    856 
    857 
    858     /**
    859      * Scan period for the NO_NETWORKS_PERIIDOC_SCAN_FEATURE
    860      */
    861     private final int mNoNetworksPeriodicScan;
    862 
    863     /**
    864      * Supplicant scan interval in milliseconds.
    865      * Comes from {@link Settings.Global#WIFI_SUPPLICANT_SCAN_INTERVAL_MS} or
    866      * from the default config if the setting is not set
    867      */
    868     private long mSupplicantScanIntervalMs;
    869 
    870     /**
    871      * Minimum time interval between enabling all networks.
    872      * A device can end up repeatedly connecting to a bad network on screen on/off toggle
    873      * due to enabling every time. We add a threshold to avoid this.
    874      */
    875     private static final int MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS = 10 * 60 * 1000; /* 10 minutes */
    876     private long mLastEnableAllNetworksTime;
    877 
    878     int mRunningBeaconCount = 0;
    879 
    880     /* Default parent state */
    881     private State mDefaultState = new DefaultState();
    882     /* Temporary initial state */
    883     private State mInitialState = new InitialState();
    884     /* Driver loaded, waiting for supplicant to start */
    885     private State mSupplicantStartingState = new SupplicantStartingState();
    886     /* Driver loaded and supplicant ready */
    887     private State mSupplicantStartedState = new SupplicantStartedState();
    888     /* Waiting for supplicant to stop and monitor to exit */
    889     private State mSupplicantStoppingState = new SupplicantStoppingState();
    890     /* Driver start issued, waiting for completed event */
    891     private State mDriverStartingState = new DriverStartingState();
    892     /* Driver started */
    893     private State mDriverStartedState = new DriverStartedState();
    894     /* Wait until p2p is disabled
    895      * This is a special state which is entered right after we exit out of DriverStartedState
    896      * before transitioning to another state.
    897      */
    898     private State mWaitForP2pDisableState = new WaitForP2pDisableState();
    899     /* Driver stopping */
    900     private State mDriverStoppingState = new DriverStoppingState();
    901     /* Driver stopped */
    902     private State mDriverStoppedState = new DriverStoppedState();
    903     /* Scan for networks, no connection will be established */
    904     private State mScanModeState = new ScanModeState();
    905     /* Connecting to an access point */
    906     private State mConnectModeState = new ConnectModeState();
    907     /* Connected at 802.11 (L2) level */
    908     private State mL2ConnectedState = new L2ConnectedState();
    909     /* fetching IP after connection to access point (assoc+auth complete) */
    910     private State mObtainingIpState = new ObtainingIpState();
    911     /* Connected with IP addr */
    912     private State mConnectedState = new ConnectedState();
    913     /* Roaming */
    914     private State mRoamingState = new RoamingState();
    915     /* disconnect issued, waiting for network disconnect confirmation */
    916     private State mDisconnectingState = new DisconnectingState();
    917     /* Network is not connected, supplicant assoc+auth is not complete */
    918     private State mDisconnectedState = new DisconnectedState();
    919     /* Waiting for WPS to be completed*/
    920     private State mWpsRunningState = new WpsRunningState();
    921     /* Soft ap state */
    922     private State mSoftApState = new SoftApState();
    923 
    924     public static class SimAuthRequestData {
    925         int networkId;
    926         int protocol;
    927         String ssid;
    928         // EAP-SIM: data[] contains the 3 rand, one for each of the 3 challenges
    929         // EAP-AKA/AKA': data[] contains rand & authn couple for the single challenge
    930         String[] data;
    931     }
    932 
    933     /**
    934      * One of  {@link WifiManager#WIFI_STATE_DISABLED},
    935      * {@link WifiManager#WIFI_STATE_DISABLING},
    936      * {@link WifiManager#WIFI_STATE_ENABLED},
    937      * {@link WifiManager#WIFI_STATE_ENABLING},
    938      * {@link WifiManager#WIFI_STATE_UNKNOWN}
    939      */
    940     private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_DISABLED);
    941 
    942     /**
    943      * One of  {@link WifiManager#WIFI_AP_STATE_DISABLED},
    944      * {@link WifiManager#WIFI_AP_STATE_DISABLING},
    945      * {@link WifiManager#WIFI_AP_STATE_ENABLED},
    946      * {@link WifiManager#WIFI_AP_STATE_ENABLING},
    947      * {@link WifiManager#WIFI_AP_STATE_FAILED}
    948      */
    949     private final AtomicInteger mWifiApState = new AtomicInteger(WIFI_AP_STATE_DISABLED);
    950 
    951     private static final int SCAN_REQUEST = 0;
    952 
    953     /**
    954      * Work source to use to blame usage on the WiFi service
    955      */
    956     public static final WorkSource WIFI_WORK_SOURCE = new WorkSource(Process.WIFI_UID);
    957 
    958     /**
    959      * Keep track of whether WIFI is running.
    960      */
    961     private boolean mIsRunning = false;
    962 
    963     /**
    964      * Keep track of whether we last told the battery stats we had started.
    965      */
    966     private boolean mReportedRunning = false;
    967 
    968     /**
    969      * Most recently set source of starting WIFI.
    970      */
    971     private final WorkSource mRunningWifiUids = new WorkSource();
    972 
    973     /**
    974      * The last reported UIDs that were responsible for starting WIFI.
    975      */
    976     private final WorkSource mLastRunningWifiUids = new WorkSource();
    977 
    978     private final IBatteryStats mBatteryStats;
    979 
    980     private final String mTcpBufferSizes;
    981 
    982     // Used for debug and stats gathering
    983     private static int sScanAlarmIntentCount = 0;
    984 
    985     private static final int sFrameworkMinScanIntervalSaneValue = 10000;
    986 
    987     private long mGScanStartTimeMilli;
    988     private long mGScanPeriodMilli;
    989 
    990     private FrameworkFacade mFacade;
    991 
    992     private final BackupManagerProxy mBackupManagerProxy;
    993 
    994     private int mSystemUiUid = -1;
    995 
    996     public WifiStateMachine(Context context, FrameworkFacade facade, Looper looper,
    997                             UserManager userManager, WifiInjector wifiInjector,
    998                             BackupManagerProxy backupManagerProxy,
    999                             WifiCountryCode countryCode) {
   1000         super("WifiStateMachine", looper);
   1001         mWifiInjector = wifiInjector;
   1002         mWifiMetrics = mWifiInjector.getWifiMetrics();
   1003         mWifiLastResortWatchdog = wifiInjector.getWifiLastResortWatchdog();
   1004         mClock = wifiInjector.getClock();
   1005         mPropertyService = wifiInjector.getPropertyService();
   1006         mBuildProperties = wifiInjector.getBuildProperties();
   1007         mContext = context;
   1008         mFacade = facade;
   1009         mWifiNative = WifiNative.getWlanNativeInterface();
   1010         mBackupManagerProxy = backupManagerProxy;
   1011 
   1012         // TODO refactor WifiNative use of context out into it's own class
   1013         mWifiNative.initContext(mContext);
   1014         mInterfaceName = mWifiNative.getInterfaceName();
   1015         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
   1016         mBatteryStats = IBatteryStats.Stub.asInterface(mFacade.getService(
   1017                 BatteryStats.SERVICE_NAME));
   1018 
   1019         IBinder b = mFacade.getService(Context.NETWORKMANAGEMENT_SERVICE);
   1020         mNwService = INetworkManagementService.Stub.asInterface(b);
   1021 
   1022         mP2pSupported = mContext.getPackageManager().hasSystemFeature(
   1023                 PackageManager.FEATURE_WIFI_DIRECT);
   1024 
   1025         mWifiConfigManager = mFacade.makeWifiConfigManager(context, mWifiNative, facade,
   1026                 mWifiInjector.getClock(), userManager, mWifiInjector.getKeyStore());
   1027 
   1028         mWifiMonitor = WifiMonitor.getInstance();
   1029 
   1030         boolean enableFirmwareLogs = mContext.getResources().getBoolean(
   1031                 R.bool.config_wifi_enable_wifi_firmware_debugging);
   1032 
   1033         if (enableFirmwareLogs) {
   1034             mWifiLogger = facade.makeRealLogger(mContext, this, mWifiNative, mBuildProperties);
   1035         } else {
   1036             mWifiLogger = facade.makeBaseLogger();
   1037         }
   1038 
   1039         mWifiInfo = new WifiInfo();
   1040         mWifiQualifiedNetworkSelector = new WifiQualifiedNetworkSelector(mWifiConfigManager,
   1041                 mContext, mWifiInfo, mWifiInjector.getClock());
   1042         mSupplicantStateTracker = mFacade.makeSupplicantStateTracker(
   1043                 context, mWifiConfigManager, getHandler());
   1044 
   1045         mLinkProperties = new LinkProperties();
   1046 
   1047         IBinder s1 = mFacade.getService(Context.WIFI_P2P_SERVICE);
   1048         mWifiP2pServiceImpl = (WifiP2pServiceImpl) IWifiP2pManager.Stub.asInterface(s1);
   1049 
   1050         mNetworkInfo.setIsAvailable(false);
   1051         mLastBssid = null;
   1052         mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
   1053         mLastSignalLevel = -1;
   1054 
   1055         mIpManager = mFacade.makeIpManager(mContext, mInterfaceName, new IpManagerCallback());
   1056         mIpManager.setMulticastFilter(true);
   1057 
   1058         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
   1059 
   1060         // Make sure the interval is not configured less than 10 seconds
   1061         int period = mContext.getResources().getInteger(
   1062                 R.integer.config_wifi_framework_scan_interval);
   1063         if (period < sFrameworkMinScanIntervalSaneValue) {
   1064             period = sFrameworkMinScanIntervalSaneValue;
   1065         }
   1066         mDefaultFrameworkScanIntervalMs = period;
   1067 
   1068         mNoNetworksPeriodicScan = mContext.getResources().getInteger(
   1069                 R.integer.config_wifi_no_network_periodic_scan_interval);
   1070 
   1071         mBackgroundScanSupported = mContext.getResources().getBoolean(
   1072                 R.bool.config_wifi_background_scan_support);
   1073 
   1074         mPrimaryDeviceType = mContext.getResources().getString(
   1075                 R.string.config_wifi_p2p_device_type);
   1076 
   1077         mCountryCode = countryCode;
   1078 
   1079         mUserWantsSuspendOpt.set(mFacade.getIntegerSetting(mContext,
   1080                 Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
   1081 
   1082         mNetworkCapabilitiesFilter.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
   1083         mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
   1084         mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
   1085         mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
   1086         mNetworkCapabilitiesFilter.setLinkUpstreamBandwidthKbps(1024 * 1024);
   1087         mNetworkCapabilitiesFilter.setLinkDownstreamBandwidthKbps(1024 * 1024);
   1088         // TODO - needs to be a bit more dynamic
   1089         mDfltNetworkCapabilities = new NetworkCapabilities(mNetworkCapabilitiesFilter);
   1090 
   1091         IntentFilter filter = new IntentFilter();
   1092         filter.addAction(Intent.ACTION_SCREEN_ON);
   1093         filter.addAction(Intent.ACTION_SCREEN_OFF);
   1094         mContext.registerReceiver(
   1095                 new BroadcastReceiver() {
   1096                     @Override
   1097                     public void onReceive(Context context, Intent intent) {
   1098                         String action = intent.getAction();
   1099 
   1100                         if (action.equals(Intent.ACTION_SCREEN_ON)) {
   1101                             sendMessage(CMD_SCREEN_STATE_CHANGED, 1);
   1102                         } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
   1103                             sendMessage(CMD_SCREEN_STATE_CHANGED, 0);
   1104                         }
   1105                     }
   1106                 }, filter);
   1107 
   1108         mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
   1109                         Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED), false,
   1110                 new ContentObserver(getHandler()) {
   1111                     @Override
   1112                     public void onChange(boolean selfChange) {
   1113                         mUserWantsSuspendOpt.set(mFacade.getIntegerSetting(mContext,
   1114                                 Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
   1115                     }
   1116                 });
   1117 
   1118         mContext.registerReceiver(
   1119                 new BroadcastReceiver() {
   1120                     @Override
   1121                     public void onReceive(Context context, Intent intent) {
   1122                         sendMessage(CMD_BOOT_COMPLETED);
   1123                     }
   1124                 },
   1125                 new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
   1126 
   1127         PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
   1128         mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getName());
   1129 
   1130         mSuspendWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WifiSuspend");
   1131         mSuspendWakeLock.setReferenceCounted(false);
   1132 
   1133         mTcpBufferSizes = mContext.getResources().getString(
   1134                 com.android.internal.R.string.config_wifi_tcp_buffers);
   1135 
   1136         // CHECKSTYLE:OFF IndentationCheck
   1137         addState(mDefaultState);
   1138             addState(mInitialState, mDefaultState);
   1139             addState(mSupplicantStartingState, mDefaultState);
   1140             addState(mSupplicantStartedState, mDefaultState);
   1141                 addState(mDriverStartingState, mSupplicantStartedState);
   1142                 addState(mDriverStartedState, mSupplicantStartedState);
   1143                     addState(mScanModeState, mDriverStartedState);
   1144                     addState(mConnectModeState, mDriverStartedState);
   1145                         addState(mL2ConnectedState, mConnectModeState);
   1146                             addState(mObtainingIpState, mL2ConnectedState);
   1147                             addState(mConnectedState, mL2ConnectedState);
   1148                             addState(mRoamingState, mL2ConnectedState);
   1149                         addState(mDisconnectingState, mConnectModeState);
   1150                         addState(mDisconnectedState, mConnectModeState);
   1151                         addState(mWpsRunningState, mConnectModeState);
   1152                 addState(mWaitForP2pDisableState, mSupplicantStartedState);
   1153                 addState(mDriverStoppingState, mSupplicantStartedState);
   1154                 addState(mDriverStoppedState, mSupplicantStartedState);
   1155             addState(mSupplicantStoppingState, mDefaultState);
   1156             addState(mSoftApState, mDefaultState);
   1157         // CHECKSTYLE:ON IndentationCheck
   1158 
   1159         setInitialState(mInitialState);
   1160 
   1161         setLogRecSize(NUM_LOG_RECS_NORMAL);
   1162         setLogOnlyTransitions(false);
   1163 
   1164         //start the state machine
   1165         start();
   1166 
   1167         mWifiMonitor.registerHandler(mInterfaceName, CMD_TARGET_BSSID, getHandler());
   1168         mWifiMonitor.registerHandler(mInterfaceName, CMD_ASSOCIATED_BSSID, getHandler());
   1169         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ANQP_DONE_EVENT, getHandler());
   1170         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATION_REJECTION_EVENT,
   1171                 getHandler());
   1172         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
   1173                 getHandler());
   1174         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.DRIVER_HUNG_EVENT, getHandler());
   1175         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.GAS_QUERY_DONE_EVENT, getHandler());
   1176         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.GAS_QUERY_START_EVENT,
   1177                 getHandler());
   1178         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.HS20_REMEDIATION_EVENT,
   1179                 getHandler());
   1180         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_CONNECTION_EVENT,
   1181                 getHandler());
   1182         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_DISCONNECTION_EVENT,
   1183                 getHandler());
   1184         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.RX_HS20_ANQP_ICON_EVENT,
   1185                 getHandler());
   1186         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SCAN_FAILED_EVENT, getHandler());
   1187         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SCAN_RESULTS_EVENT, getHandler());
   1188         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SSID_REENABLED, getHandler());
   1189         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SSID_TEMP_DISABLED, getHandler());
   1190         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_CONNECTION_EVENT, getHandler());
   1191         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_DISCONNECTION_EVENT,
   1192                 getHandler());
   1193         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT,
   1194                 getHandler());
   1195         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_REQUEST_IDENTITY, getHandler());
   1196         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_REQUEST_SIM_AUTH, getHandler());
   1197         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_FAIL_EVENT, getHandler());
   1198         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_OVERLAP_EVENT, getHandler());
   1199         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_SUCCESS_EVENT, getHandler());
   1200         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_TIMEOUT_EVENT, getHandler());
   1201 
   1202         final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
   1203         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   1204         intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED);
   1205         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   1206 
   1207         try {
   1208             mSystemUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui",
   1209                     PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
   1210         } catch (PackageManager.NameNotFoundException e) {
   1211             loge("Unable to resolve SystemUI's UID.");
   1212         }
   1213 
   1214         mVerboseLoggingLevel = mFacade.getIntegerSetting(
   1215                 mContext, Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0);
   1216         updateLoggingLevel();
   1217     }
   1218 
   1219     class IpManagerCallback extends IpManager.Callback {
   1220         @Override
   1221         public void onPreDhcpAction() {
   1222             sendMessage(DhcpClient.CMD_PRE_DHCP_ACTION);
   1223         }
   1224 
   1225         @Override
   1226         public void onPostDhcpAction() {
   1227             sendMessage(DhcpClient.CMD_POST_DHCP_ACTION);
   1228         }
   1229 
   1230         @Override
   1231         public void onNewDhcpResults(DhcpResults dhcpResults) {
   1232             if (dhcpResults != null) {
   1233                 sendMessage(CMD_IPV4_PROVISIONING_SUCCESS, dhcpResults);
   1234             } else {
   1235                 sendMessage(CMD_IPV4_PROVISIONING_FAILURE);
   1236                 mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(getTargetSsid(),
   1237                         mTargetRoamBSSID,
   1238                         WifiLastResortWatchdog.FAILURE_CODE_DHCP);
   1239             }
   1240         }
   1241 
   1242         @Override
   1243         public void onProvisioningSuccess(LinkProperties newLp) {
   1244             sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp);
   1245             sendMessage(CMD_IP_CONFIGURATION_SUCCESSFUL);
   1246         }
   1247 
   1248         @Override
   1249         public void onProvisioningFailure(LinkProperties newLp) {
   1250             sendMessage(CMD_IP_CONFIGURATION_LOST);
   1251         }
   1252 
   1253         @Override
   1254         public void onLinkPropertiesChange(LinkProperties newLp) {
   1255             sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp);
   1256         }
   1257 
   1258         @Override
   1259         public void onReachabilityLost(String logMsg) {
   1260             sendMessage(CMD_IP_REACHABILITY_LOST, logMsg);
   1261         }
   1262 
   1263         @Override
   1264         public void installPacketFilter(byte[] filter) {
   1265             sendMessage(CMD_INSTALL_PACKET_FILTER, filter);
   1266         }
   1267 
   1268         @Override
   1269         public void setFallbackMulticastFilter(boolean enabled) {
   1270             sendMessage(CMD_SET_FALLBACK_PACKET_FILTERING, enabled);
   1271         }
   1272 
   1273         @Override
   1274         public void setNeighborDiscoveryOffload(boolean enabled) {
   1275             sendMessage(CMD_CONFIG_ND_OFFLOAD, (enabled ? 1 : 0));
   1276         }
   1277     }
   1278 
   1279     private void stopIpManager() {
   1280         /* Restore power save and suspend optimizations */
   1281         handlePostDhcpSetup();
   1282         mIpManager.stop();
   1283     }
   1284 
   1285     PendingIntent getPrivateBroadcast(String action, int requestCode) {
   1286         Intent intent = new Intent(action, null);
   1287         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   1288         intent.setPackage("android");
   1289         return mFacade.getBroadcast(mContext, requestCode, intent, 0);
   1290     }
   1291 
   1292     int getVerboseLoggingLevel() {
   1293         return mVerboseLoggingLevel;
   1294     }
   1295 
   1296     void enableVerboseLogging(int verbose) {
   1297         if (mVerboseLoggingLevel == verbose) {
   1298             // We are already at the desired verbosity, avoid resetting StateMachine log records by
   1299             // returning here until underlying bug is fixed (b/28027593)
   1300             return;
   1301         }
   1302         mVerboseLoggingLevel = verbose;
   1303         mFacade.setIntegerSetting(
   1304                 mContext, Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, verbose);
   1305         updateLoggingLevel();
   1306     }
   1307 
   1308     /**
   1309      * Set wpa_supplicant log level using |mVerboseLoggingLevel| flag.
   1310      */
   1311     void setSupplicantLogLevel() {
   1312         if (mVerboseLoggingLevel > 0) {
   1313             mWifiNative.setSupplicantLogLevel("DEBUG");
   1314         } else {
   1315             mWifiNative.setSupplicantLogLevel("INFO");
   1316         }
   1317     }
   1318 
   1319     void updateLoggingLevel() {
   1320         if (mVerboseLoggingLevel > 0) {
   1321             DBG = true;
   1322             setLogRecSize(ActivityManager.isLowRamDeviceStatic()
   1323                     ? NUM_LOG_RECS_VERBOSE_LOW_MEMORY : NUM_LOG_RECS_VERBOSE);
   1324         } else {
   1325             DBG = false;
   1326             setLogRecSize(NUM_LOG_RECS_NORMAL);
   1327         }
   1328         configureVerboseHalLogging(mVerboseLoggingLevel > 0);
   1329         setSupplicantLogLevel();
   1330         mCountryCode.enableVerboseLogging(mVerboseLoggingLevel);
   1331         mWifiLogger.startLogging(DBG);
   1332         mWifiMonitor.enableVerboseLogging(mVerboseLoggingLevel);
   1333         mWifiNative.enableVerboseLogging(mVerboseLoggingLevel);
   1334         mWifiConfigManager.enableVerboseLogging(mVerboseLoggingLevel);
   1335         mSupplicantStateTracker.enableVerboseLogging(mVerboseLoggingLevel);
   1336         mWifiQualifiedNetworkSelector.enableVerboseLogging(mVerboseLoggingLevel);
   1337         if (mWifiConnectivityManager != null) {
   1338             mWifiConnectivityManager.enableVerboseLogging(mVerboseLoggingLevel);
   1339         }
   1340     }
   1341 
   1342     private static final String SYSTEM_PROPERTY_LOG_CONTROL_WIFIHAL = "log.tag.WifiHAL";
   1343     private static final String LOGD_LEVEL_DEBUG = "D";
   1344     private static final String LOGD_LEVEL_VERBOSE = "V";
   1345     private void configureVerboseHalLogging(boolean enableVerbose) {
   1346         if (mBuildProperties.isUserBuild()) {  // Verbose HAL logging not supported on user builds.
   1347             return;
   1348         }
   1349         mPropertyService.set(SYSTEM_PROPERTY_LOG_CONTROL_WIFIHAL,
   1350                 enableVerbose ? LOGD_LEVEL_VERBOSE : LOGD_LEVEL_DEBUG);
   1351     }
   1352 
   1353     long mLastScanPermissionUpdate = 0;
   1354     boolean mConnectedModeGScanOffloadStarted = false;
   1355     // Don't do a G-scan enable/re-enable cycle more than once within 20seconds
   1356     // The function updateAssociatedScanPermission() can be called quite frequently, hence
   1357     // we want to throttle the GScan Stop->Start transition
   1358     static final long SCAN_PERMISSION_UPDATE_THROTTLE_MILLI = 20000;
   1359     void updateAssociatedScanPermission() {
   1360     }
   1361 
   1362     private int mAggressiveHandover = 0;
   1363 
   1364     int getAggressiveHandover() {
   1365         return mAggressiveHandover;
   1366     }
   1367 
   1368     void enableAggressiveHandover(int enabled) {
   1369         mAggressiveHandover = enabled;
   1370     }
   1371 
   1372     public void clearANQPCache() {
   1373         mWifiConfigManager.trimANQPCache(true);
   1374     }
   1375 
   1376     public void setAllowScansWithTraffic(int enabled) {
   1377         mWifiConfigManager.mAlwaysEnableScansWhileAssociated.set(enabled);
   1378     }
   1379 
   1380     public int getAllowScansWithTraffic() {
   1381         return mWifiConfigManager.mAlwaysEnableScansWhileAssociated.get();
   1382     }
   1383 
   1384     /*
   1385      * Dynamically turn on/off if switching networks while connected is allowd.
   1386      */
   1387     public boolean setEnableAutoJoinWhenAssociated(boolean enabled) {
   1388         sendMessage(CMD_ENABLE_AUTOJOIN_WHEN_ASSOCIATED, enabled ? 1 : 0);
   1389         return true;
   1390     }
   1391 
   1392     public boolean getEnableAutoJoinWhenAssociated() {
   1393         return mWifiConfigManager.getEnableAutoJoinWhenAssociated();
   1394     }
   1395 
   1396     private boolean setRandomMacOui() {
   1397         String oui = mContext.getResources().getString(R.string.config_wifi_random_mac_oui);
   1398         if (TextUtils.isEmpty(oui)) {
   1399             oui = GOOGLE_OUI;
   1400         }
   1401         String[] ouiParts = oui.split("-");
   1402         byte[] ouiBytes = new byte[3];
   1403         ouiBytes[0] = (byte) (Integer.parseInt(ouiParts[0], 16) & 0xFF);
   1404         ouiBytes[1] = (byte) (Integer.parseInt(ouiParts[1], 16) & 0xFF);
   1405         ouiBytes[2] = (byte) (Integer.parseInt(ouiParts[2], 16) & 0xFF);
   1406 
   1407         logd("Setting OUI to " + oui);
   1408         return mWifiNative.setScanningMacOui(ouiBytes);
   1409     }
   1410 
   1411     /**
   1412      * ******************************************************
   1413      * Methods exposed for public use
   1414      * ******************************************************
   1415      */
   1416 
   1417     public Messenger getMessenger() {
   1418         return new Messenger(getHandler());
   1419     }
   1420 
   1421     /**
   1422      * TODO: doc
   1423      */
   1424     public boolean syncPingSupplicant(AsyncChannel channel) {
   1425         Message resultMsg = channel.sendMessageSynchronously(CMD_PING_SUPPLICANT);
   1426         boolean result = (resultMsg.arg1 != FAILURE);
   1427         resultMsg.recycle();
   1428         return result;
   1429     }
   1430 
   1431     /**
   1432      * Initiate a wifi scan. If workSource is not null, blame is given to it, otherwise blame is
   1433      * given to callingUid.
   1434      *
   1435      * @param callingUid The uid initiating the wifi scan. Blame will be given here unless
   1436      *                   workSource is specified.
   1437      * @param workSource If not null, blame is given to workSource.
   1438      * @param settings   Scan settings, see {@link ScanSettings}.
   1439      */
   1440     public void startScan(int callingUid, int scanCounter,
   1441                           ScanSettings settings, WorkSource workSource) {
   1442         Bundle bundle = new Bundle();
   1443         bundle.putParcelable(CUSTOMIZED_SCAN_SETTING, settings);
   1444         bundle.putParcelable(CUSTOMIZED_SCAN_WORKSOURCE, workSource);
   1445         bundle.putLong(SCAN_REQUEST_TIME, System.currentTimeMillis());
   1446         sendMessage(CMD_START_SCAN, callingUid, scanCounter, bundle);
   1447     }
   1448 
   1449     // called from BroadcastListener
   1450 
   1451     /**
   1452      * Start reading new scan data
   1453      * Data comes in as:
   1454      * "scancount=5\n"
   1455      * "nextcount=5\n"
   1456      * "apcount=3\n"
   1457      * "trunc\n" (optional)
   1458      * "bssid=...\n"
   1459      * "ssid=...\n"
   1460      * "freq=...\n" (in Mhz)
   1461      * "level=...\n"
   1462      * "dist=...\n" (in cm)
   1463      * "distsd=...\n" (standard deviation, in cm)
   1464      * "===="
   1465      * "bssid=...\n"
   1466      * etc
   1467      * "===="
   1468      * "bssid=...\n"
   1469      * etc
   1470      * "%%%%"
   1471      * "apcount=2\n"
   1472      * "bssid=...\n"
   1473      * etc
   1474      * "%%%%
   1475      * etc
   1476      * "----"
   1477      */
   1478     private final static boolean DEBUG_PARSE = false;
   1479 
   1480     private long mDisconnectedTimeStamp = 0;
   1481 
   1482     public long getDisconnectedTimeMilli() {
   1483         if (getCurrentState() == mDisconnectedState
   1484                 && mDisconnectedTimeStamp != 0) {
   1485             long now_ms = System.currentTimeMillis();
   1486             return now_ms - mDisconnectedTimeStamp;
   1487         }
   1488         return 0;
   1489     }
   1490 
   1491     // Last connect attempt is used to prevent scan requests:
   1492     //  - for a period of 10 seconds after attempting to connect
   1493     private long lastConnectAttemptTimestamp = 0;
   1494     private Set<Integer> lastScanFreqs = null;
   1495 
   1496     // For debugging, keep track of last message status handling
   1497     // TODO, find an equivalent mechanism as part of parent class
   1498     private static int MESSAGE_HANDLING_STATUS_PROCESSED = 2;
   1499     private static int MESSAGE_HANDLING_STATUS_OK = 1;
   1500     private static int MESSAGE_HANDLING_STATUS_UNKNOWN = 0;
   1501     private static int MESSAGE_HANDLING_STATUS_REFUSED = -1;
   1502     private static int MESSAGE_HANDLING_STATUS_FAIL = -2;
   1503     private static int MESSAGE_HANDLING_STATUS_OBSOLETE = -3;
   1504     private static int MESSAGE_HANDLING_STATUS_DEFERRED = -4;
   1505     private static int MESSAGE_HANDLING_STATUS_DISCARD = -5;
   1506     private static int MESSAGE_HANDLING_STATUS_LOOPED = -6;
   1507     private static int MESSAGE_HANDLING_STATUS_HANDLING_ERROR = -7;
   1508 
   1509     private int messageHandlingStatus = 0;
   1510 
   1511     //TODO: this is used only to track connection attempts, however the link state and packet per
   1512     //TODO: second logic should be folded into that
   1513     private boolean checkOrDeferScanAllowed(Message msg) {
   1514         long now = System.currentTimeMillis();
   1515         if (lastConnectAttemptTimestamp != 0 && (now - lastConnectAttemptTimestamp) < 10000) {
   1516             Message dmsg = Message.obtain(msg);
   1517             sendMessageDelayed(dmsg, 11000 - (now - lastConnectAttemptTimestamp));
   1518             return false;
   1519         }
   1520         return true;
   1521     }
   1522 
   1523     private int mOnTime = 0;
   1524     private int mTxTime = 0;
   1525     private int mRxTime = 0;
   1526 
   1527     private int mOnTimeScreenStateChange = 0;
   1528     private long lastOntimeReportTimeStamp = 0;
   1529     private long lastScreenStateChangeTimeStamp = 0;
   1530     private int mOnTimeLastReport = 0;
   1531     private int mTxTimeLastReport = 0;
   1532     private int mRxTimeLastReport = 0;
   1533 
   1534     private long lastLinkLayerStatsUpdate = 0;
   1535 
   1536     String reportOnTime() {
   1537         long now = System.currentTimeMillis();
   1538         StringBuilder sb = new StringBuilder();
   1539         // Report stats since last report
   1540         int on = mOnTime - mOnTimeLastReport;
   1541         mOnTimeLastReport = mOnTime;
   1542         int tx = mTxTime - mTxTimeLastReport;
   1543         mTxTimeLastReport = mTxTime;
   1544         int rx = mRxTime - mRxTimeLastReport;
   1545         mRxTimeLastReport = mRxTime;
   1546         int period = (int) (now - lastOntimeReportTimeStamp);
   1547         lastOntimeReportTimeStamp = now;
   1548         sb.append(String.format("[on:%d tx:%d rx:%d period:%d]", on, tx, rx, period));
   1549         // Report stats since Screen State Changed
   1550         on = mOnTime - mOnTimeScreenStateChange;
   1551         period = (int) (now - lastScreenStateChangeTimeStamp);
   1552         sb.append(String.format(" from screen [on:%d period:%d]", on, period));
   1553         return sb.toString();
   1554     }
   1555 
   1556     WifiLinkLayerStats getWifiLinkLayerStats(boolean dbg) {
   1557         WifiLinkLayerStats stats = null;
   1558         if (mWifiLinkLayerStatsSupported > 0) {
   1559             String name = "wlan0";
   1560             stats = mWifiNative.getWifiLinkLayerStats(name);
   1561             if (name != null && stats == null && mWifiLinkLayerStatsSupported > 0) {
   1562                 mWifiLinkLayerStatsSupported -= 1;
   1563             } else if (stats != null) {
   1564                 lastLinkLayerStatsUpdate = System.currentTimeMillis();
   1565                 mOnTime = stats.on_time;
   1566                 mTxTime = stats.tx_time;
   1567                 mRxTime = stats.rx_time;
   1568                 mRunningBeaconCount = stats.beacon_rx;
   1569             }
   1570         }
   1571         if (stats == null || mWifiLinkLayerStatsSupported <= 0) {
   1572             long mTxPkts = mFacade.getTxPackets(mInterfaceName);
   1573             long mRxPkts = mFacade.getRxPackets(mInterfaceName);
   1574             mWifiInfo.updatePacketRates(mTxPkts, mRxPkts);
   1575         } else {
   1576             mWifiInfo.updatePacketRates(stats);
   1577         }
   1578         return stats;
   1579     }
   1580 
   1581     int startWifiIPPacketOffload(int slot, KeepalivePacketData packetData, int intervalSeconds) {
   1582         int ret = mWifiNative.startSendingOffloadedPacket(slot, packetData, intervalSeconds * 1000);
   1583         if (ret != 0) {
   1584             loge("startWifiIPPacketOffload(" + slot + ", " + intervalSeconds +
   1585                     "): hardware error " + ret);
   1586             return ConnectivityManager.PacketKeepalive.ERROR_HARDWARE_ERROR;
   1587         } else {
   1588             return ConnectivityManager.PacketKeepalive.SUCCESS;
   1589         }
   1590     }
   1591 
   1592     int stopWifiIPPacketOffload(int slot) {
   1593         int ret = mWifiNative.stopSendingOffloadedPacket(slot);
   1594         if (ret != 0) {
   1595             loge("stopWifiIPPacketOffload(" + slot + "): hardware error " + ret);
   1596             return ConnectivityManager.PacketKeepalive.ERROR_HARDWARE_ERROR;
   1597         } else {
   1598             return ConnectivityManager.PacketKeepalive.SUCCESS;
   1599         }
   1600     }
   1601 
   1602     int startRssiMonitoringOffload(byte maxRssi, byte minRssi) {
   1603         return mWifiNative.startRssiMonitoring(maxRssi, minRssi, WifiStateMachine.this);
   1604     }
   1605 
   1606     int stopRssiMonitoringOffload() {
   1607         return mWifiNative.stopRssiMonitoring();
   1608     }
   1609 
   1610     private void handleScanRequest(Message message) {
   1611         ScanSettings settings = null;
   1612         WorkSource workSource = null;
   1613 
   1614         // unbundle parameters
   1615         Bundle bundle = (Bundle) message.obj;
   1616 
   1617         if (bundle != null) {
   1618             settings = bundle.getParcelable(CUSTOMIZED_SCAN_SETTING);
   1619             workSource = bundle.getParcelable(CUSTOMIZED_SCAN_WORKSOURCE);
   1620         }
   1621 
   1622         Set<Integer> freqs = null;
   1623         if (settings != null && settings.channelSet != null) {
   1624             freqs = new HashSet<Integer>();
   1625             for (WifiChannel channel : settings.channelSet) {
   1626                 freqs.add(channel.freqMHz);
   1627             }
   1628         }
   1629 
   1630         // Retrieve the list of hidden networkId's to scan for.
   1631         Set<Integer> hiddenNetworkIds = mWifiConfigManager.getHiddenConfiguredNetworkIds();
   1632 
   1633         // call wifi native to start the scan
   1634         if (startScanNative(freqs, hiddenNetworkIds, workSource)) {
   1635             // a full scan covers everything, clearing scan request buffer
   1636             if (freqs == null)
   1637                 mBufferedScanMsg.clear();
   1638             messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK;
   1639             if (workSource != null) {
   1640                 // External worksource was passed along the scan request,
   1641                 // hence always send a broadcast
   1642                 mSendScanResultsBroadcast = true;
   1643             }
   1644             return;
   1645         }
   1646 
   1647         // if reach here, scan request is rejected
   1648 
   1649         if (!mIsScanOngoing) {
   1650             // if rejection is NOT due to ongoing scan (e.g. bad scan parameters),
   1651 
   1652             // discard this request and pop up the next one
   1653             if (mBufferedScanMsg.size() > 0) {
   1654                 sendMessage(mBufferedScanMsg.remove());
   1655             }
   1656             messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
   1657         } else if (!mIsFullScanOngoing) {
   1658             // if rejection is due to an ongoing scan, and the ongoing one is NOT a full scan,
   1659             // buffer the scan request to make sure specified channels will be scanned eventually
   1660             if (freqs == null)
   1661                 mBufferedScanMsg.clear();
   1662             if (mBufferedScanMsg.size() < SCAN_REQUEST_BUFFER_MAX_SIZE) {
   1663                 Message msg = obtainMessage(CMD_START_SCAN,
   1664                         message.arg1, message.arg2, bundle);
   1665                 mBufferedScanMsg.add(msg);
   1666             } else {
   1667                 // if too many requests in buffer, combine them into a single full scan
   1668                 bundle = new Bundle();
   1669                 bundle.putParcelable(CUSTOMIZED_SCAN_SETTING, null);
   1670                 bundle.putParcelable(CUSTOMIZED_SCAN_WORKSOURCE, workSource);
   1671                 Message msg = obtainMessage(CMD_START_SCAN, message.arg1, message.arg2, bundle);
   1672                 mBufferedScanMsg.clear();
   1673                 mBufferedScanMsg.add(msg);
   1674             }
   1675             messageHandlingStatus = MESSAGE_HANDLING_STATUS_LOOPED;
   1676         } else {
   1677             // mIsScanOngoing and mIsFullScanOngoing
   1678             messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL;
   1679         }
   1680     }
   1681 
   1682 
   1683     // TODO this is a temporary measure to bridge between WifiScanner and WifiStateMachine until
   1684     // scan functionality is refactored out of WifiStateMachine.
   1685     /**
   1686      * return true iff scan request is accepted
   1687      */
   1688     private boolean startScanNative(final Set<Integer> freqs, Set<Integer> hiddenNetworkIds,
   1689             WorkSource workSource) {
   1690         WifiScanner.ScanSettings settings = new WifiScanner.ScanSettings();
   1691         if (freqs == null) {
   1692             settings.band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS;
   1693         } else {
   1694             settings.band = WifiScanner.WIFI_BAND_UNSPECIFIED;
   1695             int index = 0;
   1696             settings.channels = new WifiScanner.ChannelSpec[freqs.size()];
   1697             for (Integer freq : freqs) {
   1698                 settings.channels[index++] = new WifiScanner.ChannelSpec(freq);
   1699             }
   1700         }
   1701         settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
   1702                 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;
   1703         if (hiddenNetworkIds != null && hiddenNetworkIds.size() > 0) {
   1704             int i = 0;
   1705             settings.hiddenNetworkIds = new int[hiddenNetworkIds.size()];
   1706             for (Integer netId : hiddenNetworkIds) {
   1707                 settings.hiddenNetworkIds[i++] = netId;
   1708             }
   1709         }
   1710         WifiScanner.ScanListener nativeScanListener = new WifiScanner.ScanListener() {
   1711                 // ignore all events since WifiStateMachine is registered for the supplicant events
   1712                 public void onSuccess() {
   1713                 }
   1714                 public void onFailure(int reason, String description) {
   1715                     mIsScanOngoing = false;
   1716                     mIsFullScanOngoing = false;
   1717                 }
   1718                 public void onResults(WifiScanner.ScanData[] results) {
   1719                 }
   1720                 public void onFullResult(ScanResult fullScanResult) {
   1721                 }
   1722                 public void onPeriodChanged(int periodInMs) {
   1723                 }
   1724             };
   1725         mWifiScanner.startScan(settings, nativeScanListener, workSource);
   1726         mIsScanOngoing = true;
   1727         mIsFullScanOngoing = (freqs == null);
   1728         lastScanFreqs = freqs;
   1729         return true;
   1730     }
   1731 
   1732     /**
   1733      * TODO: doc
   1734      */
   1735     public void setSupplicantRunning(boolean enable) {
   1736         if (enable) {
   1737             sendMessage(CMD_START_SUPPLICANT);
   1738         } else {
   1739             sendMessage(CMD_STOP_SUPPLICANT);
   1740         }
   1741     }
   1742 
   1743     /**
   1744      * TODO: doc
   1745      */
   1746     public void setHostApRunning(WifiConfiguration wifiConfig, boolean enable) {
   1747         if (enable) {
   1748             sendMessage(CMD_START_AP, wifiConfig);
   1749         } else {
   1750             sendMessage(CMD_STOP_AP);
   1751         }
   1752     }
   1753 
   1754     public void setWifiApConfiguration(WifiConfiguration config) {
   1755         mWifiApConfigStore.setApConfiguration(config);
   1756     }
   1757 
   1758     public WifiConfiguration syncGetWifiApConfiguration() {
   1759         return mWifiApConfigStore.getApConfiguration();
   1760     }
   1761 
   1762     /**
   1763      * TODO: doc
   1764      */
   1765     public int syncGetWifiState() {
   1766         return mWifiState.get();
   1767     }
   1768 
   1769     /**
   1770      * TODO: doc
   1771      */
   1772     public String syncGetWifiStateByName() {
   1773         switch (mWifiState.get()) {
   1774             case WIFI_STATE_DISABLING:
   1775                 return "disabling";
   1776             case WIFI_STATE_DISABLED:
   1777                 return "disabled";
   1778             case WIFI_STATE_ENABLING:
   1779                 return "enabling";
   1780             case WIFI_STATE_ENABLED:
   1781                 return "enabled";
   1782             case WIFI_STATE_UNKNOWN:
   1783                 return "unknown state";
   1784             default:
   1785                 return "[invalid state]";
   1786         }
   1787     }
   1788 
   1789     /**
   1790      * TODO: doc
   1791      */
   1792     public int syncGetWifiApState() {
   1793         return mWifiApState.get();
   1794     }
   1795 
   1796     /**
   1797      * TODO: doc
   1798      */
   1799     public String syncGetWifiApStateByName() {
   1800         switch (mWifiApState.get()) {
   1801             case WIFI_AP_STATE_DISABLING:
   1802                 return "disabling";
   1803             case WIFI_AP_STATE_DISABLED:
   1804                 return "disabled";
   1805             case WIFI_AP_STATE_ENABLING:
   1806                 return "enabling";
   1807             case WIFI_AP_STATE_ENABLED:
   1808                 return "enabled";
   1809             case WIFI_AP_STATE_FAILED:
   1810                 return "failed";
   1811             default:
   1812                 return "[invalid state]";
   1813         }
   1814     }
   1815 
   1816     public boolean isConnected() {
   1817         return getCurrentState() == mConnectedState;
   1818     }
   1819 
   1820     public boolean isDisconnected() {
   1821         return getCurrentState() == mDisconnectedState;
   1822     }
   1823 
   1824     public boolean isSupplicantTransientState() {
   1825         SupplicantState SupplicantState = mWifiInfo.getSupplicantState();
   1826         if (SupplicantState == SupplicantState.ASSOCIATING
   1827                 || SupplicantState == SupplicantState.AUTHENTICATING
   1828                 || SupplicantState == SupplicantState.FOUR_WAY_HANDSHAKE
   1829                 || SupplicantState == SupplicantState.GROUP_HANDSHAKE) {
   1830 
   1831             if (DBG) {
   1832                 Log.d(TAG, "Supplicant is under transient state: " + SupplicantState);
   1833             }
   1834             return true;
   1835         } else {
   1836             if (DBG) {
   1837                 Log.d(TAG, "Supplicant is under steady state: " + SupplicantState);
   1838             }
   1839         }
   1840 
   1841         return false;
   1842     }
   1843 
   1844     public boolean isLinkDebouncing() {
   1845         return linkDebouncing;
   1846     }
   1847 
   1848     /**
   1849      * Get status information for the current connection, if any.
   1850      *
   1851      * @return a {@link WifiInfo} object containing information about the current connection
   1852      */
   1853     public WifiInfo syncRequestConnectionInfo() {
   1854         return getWiFiInfoForUid(Binder.getCallingUid());
   1855     }
   1856 
   1857     public WifiInfo getWifiInfo() {
   1858         return mWifiInfo;
   1859     }
   1860 
   1861     public DhcpResults syncGetDhcpResults() {
   1862         synchronized (mDhcpResultsLock) {
   1863             return new DhcpResults(mDhcpResults);
   1864         }
   1865     }
   1866 
   1867     /**
   1868      * TODO: doc
   1869      */
   1870     public void setDriverStart(boolean enable) {
   1871         if (enable) {
   1872             sendMessage(CMD_START_DRIVER);
   1873         } else {
   1874             sendMessage(CMD_STOP_DRIVER);
   1875         }
   1876     }
   1877 
   1878     /**
   1879      * TODO: doc
   1880      */
   1881     public void setOperationalMode(int mode) {
   1882         if (DBG) log("setting operational mode to " + String.valueOf(mode));
   1883         sendMessage(CMD_SET_OPERATIONAL_MODE, mode, 0);
   1884     }
   1885 
   1886     /**
   1887      * Allow tests to confirm the operational mode for WSM.
   1888      */
   1889     @VisibleForTesting
   1890     protected int getOperationalModeForTest() {
   1891         return mOperationalMode;
   1892     }
   1893 
   1894     /**
   1895      * TODO: doc
   1896      */
   1897     public List<ScanResult> syncGetScanResultsList() {
   1898         synchronized (mScanResultsLock) {
   1899             List<ScanResult> scanList = new ArrayList<ScanResult>();
   1900             for (ScanDetail result : mScanResults) {
   1901                 scanList.add(new ScanResult(result.getScanResult()));
   1902             }
   1903             return scanList;
   1904         }
   1905     }
   1906 
   1907     public int syncAddPasspointManagementObject(AsyncChannel channel, String managementObject) {
   1908         Message resultMsg =
   1909                 channel.sendMessageSynchronously(CMD_ADD_PASSPOINT_MO, managementObject);
   1910         int result = resultMsg.arg1;
   1911         resultMsg.recycle();
   1912         return result;
   1913     }
   1914 
   1915     public int syncModifyPasspointManagementObject(AsyncChannel channel, String fqdn,
   1916                                                    List<PasspointManagementObjectDefinition>
   1917                                                            managementObjectDefinitions) {
   1918         Bundle bundle = new Bundle();
   1919         bundle.putString("FQDN", fqdn);
   1920         bundle.putParcelableList("MOS", managementObjectDefinitions);
   1921         Message resultMsg = channel.sendMessageSynchronously(CMD_MODIFY_PASSPOINT_MO, bundle);
   1922         int result = resultMsg.arg1;
   1923         resultMsg.recycle();
   1924         return result;
   1925     }
   1926 
   1927     public boolean syncQueryPasspointIcon(AsyncChannel channel, long bssid, String fileName) {
   1928         Bundle bundle = new Bundle();
   1929         bundle.putLong("BSSID", bssid);
   1930         bundle.putString("FILENAME", fileName);
   1931         Message resultMsg = channel.sendMessageSynchronously(CMD_QUERY_OSU_ICON, bundle);
   1932         int result = resultMsg.arg1;
   1933         resultMsg.recycle();
   1934         return result == 1;
   1935     }
   1936 
   1937     public int matchProviderWithCurrentNetwork(AsyncChannel channel, String fqdn) {
   1938         Message resultMsg = channel.sendMessageSynchronously(CMD_MATCH_PROVIDER_NETWORK, fqdn);
   1939         int result = resultMsg.arg1;
   1940         resultMsg.recycle();
   1941         return result;
   1942     }
   1943 
   1944     /**
   1945      * Deauthenticate and set the re-authentication hold off time for the current network
   1946      * @param holdoff hold off time in milliseconds
   1947      * @param ess set if the hold off pertains to an ESS rather than a BSS
   1948      */
   1949     public void deauthenticateNetwork(AsyncChannel channel, long holdoff, boolean ess) {
   1950         // TODO: This needs an implementation
   1951     }
   1952 
   1953     public void disableEphemeralNetwork(String SSID) {
   1954         if (SSID != null) {
   1955             sendMessage(CMD_DISABLE_EPHEMERAL_NETWORK, SSID);
   1956         }
   1957     }
   1958 
   1959     /**
   1960      * Disconnect from Access Point
   1961      */
   1962     public void disconnectCommand() {
   1963         sendMessage(CMD_DISCONNECT);
   1964     }
   1965 
   1966     public void disconnectCommand(int uid, int reason) {
   1967         sendMessage(CMD_DISCONNECT, uid, reason);
   1968     }
   1969 
   1970     /**
   1971      * Initiate a reconnection to AP
   1972      */
   1973     public void reconnectCommand() {
   1974         sendMessage(CMD_RECONNECT);
   1975     }
   1976 
   1977     /**
   1978      * Initiate a re-association to AP
   1979      */
   1980     public void reassociateCommand() {
   1981         sendMessage(CMD_REASSOCIATE);
   1982     }
   1983 
   1984     /**
   1985      * Reload networks and then reconnect; helps load correct data for TLS networks
   1986      */
   1987 
   1988     public void reloadTlsNetworksAndReconnect() {
   1989         sendMessage(CMD_RELOAD_TLS_AND_RECONNECT);
   1990     }
   1991 
   1992     /**
   1993      * Add a network synchronously
   1994      *
   1995      * @return network id of the new network
   1996      */
   1997     public int syncAddOrUpdateNetwork(AsyncChannel channel, WifiConfiguration config) {
   1998         Message resultMsg = channel.sendMessageSynchronously(CMD_ADD_OR_UPDATE_NETWORK, config);
   1999         int result = resultMsg.arg1;
   2000         resultMsg.recycle();
   2001         return result;
   2002     }
   2003 
   2004     /**
   2005      * Get configured networks synchronously
   2006      *
   2007      * @param channel
   2008      * @return
   2009      */
   2010 
   2011     public List<WifiConfiguration> syncGetConfiguredNetworks(int uuid, AsyncChannel channel) {
   2012         Message resultMsg = channel.sendMessageSynchronously(CMD_GET_CONFIGURED_NETWORKS, uuid);
   2013         List<WifiConfiguration> result = (List<WifiConfiguration>) resultMsg.obj;
   2014         resultMsg.recycle();
   2015         return result;
   2016     }
   2017 
   2018     public List<WifiConfiguration> syncGetPrivilegedConfiguredNetwork(AsyncChannel channel) {
   2019         Message resultMsg = channel.sendMessageSynchronously(
   2020                 CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS);
   2021         List<WifiConfiguration> result = (List<WifiConfiguration>) resultMsg.obj;
   2022         resultMsg.recycle();
   2023         return result;
   2024     }
   2025 
   2026     public WifiConfiguration syncGetMatchingWifiConfig(ScanResult scanResult, AsyncChannel channel) {
   2027         Message resultMsg = channel.sendMessageSynchronously(CMD_GET_MATCHING_CONFIG, scanResult);
   2028         return (WifiConfiguration) resultMsg.obj;
   2029     }
   2030 
   2031     /**
   2032      * Get connection statistics synchronously
   2033      *
   2034      * @param channel
   2035      * @return
   2036      */
   2037 
   2038     public WifiConnectionStatistics syncGetConnectionStatistics(AsyncChannel channel) {
   2039         Message resultMsg = channel.sendMessageSynchronously(CMD_GET_CONNECTION_STATISTICS);
   2040         WifiConnectionStatistics result = (WifiConnectionStatistics) resultMsg.obj;
   2041         resultMsg.recycle();
   2042         return result;
   2043     }
   2044 
   2045     /**
   2046      * Get adaptors synchronously
   2047      */
   2048 
   2049     public int syncGetSupportedFeatures(AsyncChannel channel) {
   2050         Message resultMsg = channel.sendMessageSynchronously(CMD_GET_SUPPORTED_FEATURES);
   2051         int supportedFeatureSet = resultMsg.arg1;
   2052         resultMsg.recycle();
   2053         return supportedFeatureSet;
   2054     }
   2055 
   2056     /**
   2057      * Get link layers stats for adapter synchronously
   2058      */
   2059     public WifiLinkLayerStats syncGetLinkLayerStats(AsyncChannel channel) {
   2060         Message resultMsg = channel.sendMessageSynchronously(CMD_GET_LINK_LAYER_STATS);
   2061         WifiLinkLayerStats result = (WifiLinkLayerStats) resultMsg.obj;
   2062         resultMsg.recycle();
   2063         return result;
   2064     }
   2065 
   2066     /**
   2067      * Delete a network
   2068      *
   2069      * @param networkId id of the network to be removed
   2070      */
   2071     public boolean syncRemoveNetwork(AsyncChannel channel, int networkId) {
   2072         Message resultMsg = channel.sendMessageSynchronously(CMD_REMOVE_NETWORK, networkId);
   2073         boolean result = (resultMsg.arg1 != FAILURE);
   2074         resultMsg.recycle();
   2075         return result;
   2076     }
   2077 
   2078     /**
   2079      * Enable a network
   2080      *
   2081      * @param netId         network id of the network
   2082      * @param disableOthers true, if all other networks have to be disabled
   2083      * @return {@code true} if the operation succeeds, {@code false} otherwise
   2084      */
   2085     public boolean syncEnableNetwork(AsyncChannel channel, int netId, boolean disableOthers) {
   2086         Message resultMsg = channel.sendMessageSynchronously(CMD_ENABLE_NETWORK, netId,
   2087                 disableOthers ? 1 : 0);
   2088         boolean result = (resultMsg.arg1 != FAILURE);
   2089         resultMsg.recycle();
   2090         return result;
   2091     }
   2092 
   2093     /**
   2094      * Disable a network
   2095      *
   2096      * @param netId network id of the network
   2097      * @return {@code true} if the operation succeeds, {@code false} otherwise
   2098      */
   2099     public boolean syncDisableNetwork(AsyncChannel channel, int netId) {
   2100         Message resultMsg = channel.sendMessageSynchronously(WifiManager.DISABLE_NETWORK, netId);
   2101         boolean result = (resultMsg.arg1 != WifiManager.DISABLE_NETWORK_FAILED);
   2102         resultMsg.recycle();
   2103         return result;
   2104     }
   2105 
   2106     /**
   2107      * Retrieves a WPS-NFC configuration token for the specified network
   2108      *
   2109      * @return a hex string representation of the WPS-NFC configuration token
   2110      */
   2111     public String syncGetWpsNfcConfigurationToken(int netId) {
   2112         return mWifiNative.getNfcWpsConfigurationToken(netId);
   2113     }
   2114 
   2115     /**
   2116      * Blacklist a BSSID. This will avoid the AP if there are
   2117      * alternate APs to connect
   2118      *
   2119      * @param bssid BSSID of the network
   2120      */
   2121     public void addToBlacklist(String bssid) {
   2122         sendMessage(CMD_BLACKLIST_NETWORK, bssid);
   2123     }
   2124 
   2125     /**
   2126      * Clear the blacklist list
   2127      */
   2128     public void clearBlacklist() {
   2129         sendMessage(CMD_CLEAR_BLACKLIST);
   2130     }
   2131 
   2132     public void enableRssiPolling(boolean enabled) {
   2133         sendMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0);
   2134     }
   2135 
   2136     public void enableAllNetworks() {
   2137         sendMessage(CMD_ENABLE_ALL_NETWORKS);
   2138     }
   2139 
   2140     /**
   2141      * Start filtering Multicast v4 packets
   2142      */
   2143     public void startFilteringMulticastPackets() {
   2144         mIpManager.setMulticastFilter(true);
   2145     }
   2146 
   2147     /**
   2148      * Stop filtering Multicast v4 packets
   2149      */
   2150     public void stopFilteringMulticastPackets() {
   2151         mIpManager.setMulticastFilter(false);
   2152     }
   2153 
   2154     /**
   2155      * Set high performance mode of operation.
   2156      * Enabling would set active power mode and disable suspend optimizations;
   2157      * disabling would set auto power mode and enable suspend optimizations
   2158      *
   2159      * @param enable true if enable, false otherwise
   2160      */
   2161     public void setHighPerfModeEnabled(boolean enable) {
   2162         sendMessage(CMD_SET_HIGH_PERF_MODE, enable ? 1 : 0, 0);
   2163     }
   2164 
   2165 
   2166     /**
   2167      * reset cached SIM credential data
   2168      */
   2169     public synchronized void resetSimAuthNetworks(boolean simPresent) {
   2170         sendMessage(CMD_RESET_SIM_NETWORKS, simPresent ? 1 : 0);
   2171     }
   2172 
   2173     /**
   2174      * Get Network object of current wifi network
   2175      * @return Network object of current wifi network
   2176      */
   2177     public Network getCurrentNetwork() {
   2178         if (mNetworkAgent != null) {
   2179             return new Network(mNetworkAgent.netId);
   2180         } else {
   2181             return null;
   2182         }
   2183     }
   2184 
   2185 
   2186     /**
   2187      * Set the operational frequency band
   2188      *
   2189      * @param band
   2190      * @param persist {@code true} if the setting should be remembered.
   2191      */
   2192     public void setFrequencyBand(int band, boolean persist) {
   2193         if (persist) {
   2194             Settings.Global.putInt(mContext.getContentResolver(),
   2195                     Settings.Global.WIFI_FREQUENCY_BAND,
   2196                     band);
   2197         }
   2198         sendMessage(CMD_SET_FREQUENCY_BAND, band, 0);
   2199     }
   2200 
   2201     /**
   2202      * Enable TDLS for a specific MAC address
   2203      */
   2204     public void enableTdls(String remoteMacAddress, boolean enable) {
   2205         int enabler = enable ? 1 : 0;
   2206         sendMessage(CMD_ENABLE_TDLS, enabler, 0, remoteMacAddress);
   2207     }
   2208 
   2209     /**
   2210      * Returns the operational frequency band
   2211      */
   2212     public int getFrequencyBand() {
   2213         return mFrequencyBand.get();
   2214     }
   2215 
   2216     /**
   2217      * Returns the wifi configuration file
   2218      */
   2219     public String getConfigFile() {
   2220         return mWifiConfigManager.getConfigFile();
   2221     }
   2222 
   2223     /**
   2224      * Send a message indicating bluetooth adapter connection state changed
   2225      */
   2226     public void sendBluetoothAdapterStateChange(int state) {
   2227         sendMessage(CMD_BLUETOOTH_ADAPTER_STATE_CHANGE, state, 0);
   2228     }
   2229 
   2230     /**
   2231      * Send a message indicating a package has been uninstalled.
   2232      */
   2233     public void removeAppConfigs(String packageName, int uid) {
   2234         // Build partial AppInfo manually - package may not exist in database any more
   2235         ApplicationInfo ai = new ApplicationInfo();
   2236         ai.packageName = packageName;
   2237         ai.uid = uid;
   2238         sendMessage(CMD_REMOVE_APP_CONFIGURATIONS, ai);
   2239     }
   2240 
   2241     /**
   2242      * Send a message indicating a user has been removed.
   2243      */
   2244     public void removeUserConfigs(int userId) {
   2245         sendMessage(CMD_REMOVE_USER_CONFIGURATIONS, userId);
   2246     }
   2247 
   2248     /**
   2249      * Save configuration on supplicant
   2250      *
   2251      * @return {@code true} if the operation succeeds, {@code false} otherwise
   2252      * <p/>
   2253      * TODO: deprecate this
   2254      */
   2255     public boolean syncSaveConfig(AsyncChannel channel) {
   2256         Message resultMsg = channel.sendMessageSynchronously(CMD_SAVE_CONFIG);
   2257         boolean result = (resultMsg.arg1 != FAILURE);
   2258         resultMsg.recycle();
   2259         return result;
   2260     }
   2261 
   2262     public void updateBatteryWorkSource(WorkSource newSource) {
   2263         synchronized (mRunningWifiUids) {
   2264             try {
   2265                 if (newSource != null) {
   2266                     mRunningWifiUids.set(newSource);
   2267                 }
   2268                 if (mIsRunning) {
   2269                     if (mReportedRunning) {
   2270                         // If the work source has changed since last time, need
   2271                         // to remove old work from battery stats.
   2272                         if (mLastRunningWifiUids.diff(mRunningWifiUids)) {
   2273                             mBatteryStats.noteWifiRunningChanged(mLastRunningWifiUids,
   2274                                     mRunningWifiUids);
   2275                             mLastRunningWifiUids.set(mRunningWifiUids);
   2276                         }
   2277                     } else {
   2278                         // Now being started, report it.
   2279                         mBatteryStats.noteWifiRunning(mRunningWifiUids);
   2280                         mLastRunningWifiUids.set(mRunningWifiUids);
   2281                         mReportedRunning = true;
   2282                     }
   2283                 } else {
   2284                     if (mReportedRunning) {
   2285                         // Last reported we were running, time to stop.
   2286                         mBatteryStats.noteWifiStopped(mLastRunningWifiUids);
   2287                         mLastRunningWifiUids.clear();
   2288                         mReportedRunning = false;
   2289                     }
   2290                 }
   2291                 mWakeLock.setWorkSource(newSource);
   2292             } catch (RemoteException ignore) {
   2293             }
   2294         }
   2295     }
   2296 
   2297     public void dumpIpManager(FileDescriptor fd, PrintWriter pw, String[] args) {
   2298         mIpManager.dump(fd, pw, args);
   2299     }
   2300 
   2301     @Override
   2302     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   2303         super.dump(fd, pw, args);
   2304         mSupplicantStateTracker.dump(fd, pw, args);
   2305         pw.println("mLinkProperties " + mLinkProperties);
   2306         pw.println("mWifiInfo " + mWifiInfo);
   2307         pw.println("mDhcpResults " + mDhcpResults);
   2308         pw.println("mNetworkInfo " + mNetworkInfo);
   2309         pw.println("mLastSignalLevel " + mLastSignalLevel);
   2310         pw.println("mLastBssid " + mLastBssid);
   2311         pw.println("mLastNetworkId " + mLastNetworkId);
   2312         pw.println("mOperationalMode " + mOperationalMode);
   2313         pw.println("mUserWantsSuspendOpt " + mUserWantsSuspendOpt);
   2314         pw.println("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled);
   2315         pw.println("Supplicant status " + mWifiNative.status(true));
   2316         if (mCountryCode.getCountryCodeSentToDriver() != null) {
   2317             pw.println("CountryCode sent to driver " + mCountryCode.getCountryCodeSentToDriver());
   2318         } else {
   2319             if (mCountryCode.getCountryCode() != null) {
   2320                 pw.println("CountryCode: " +
   2321                         mCountryCode.getCountryCode() + " was not sent to driver");
   2322             } else {
   2323                 pw.println("CountryCode was not initialized");
   2324             }
   2325         }
   2326         pw.println("mConnectedModeGScanOffloadStarted " + mConnectedModeGScanOffloadStarted);
   2327         pw.println("mGScanPeriodMilli " + mGScanPeriodMilli);
   2328         if (mWhiteListedSsids != null && mWhiteListedSsids.length > 0) {
   2329             pw.println("SSID whitelist :" );
   2330             for (int i=0; i < mWhiteListedSsids.length; i++) {
   2331                 pw.println("       " + mWhiteListedSsids[i]);
   2332             }
   2333         }
   2334         if (mNetworkFactory != null) {
   2335             mNetworkFactory.dump(fd, pw, args);
   2336         } else {
   2337             pw.println("mNetworkFactory is not initialized");
   2338         }
   2339 
   2340         if (mUntrustedNetworkFactory != null) {
   2341             mUntrustedNetworkFactory.dump(fd, pw, args);
   2342         } else {
   2343             pw.println("mUntrustedNetworkFactory is not initialized");
   2344         }
   2345         pw.println("Wlan Wake Reasons:" + mWifiNative.getWlanWakeReasonCount());
   2346         pw.println();
   2347         updateWifiMetrics();
   2348         mWifiMetrics.dump(fd, pw, args);
   2349         pw.println();
   2350 
   2351         mWifiConfigManager.dump(fd, pw, args);
   2352         pw.println();
   2353         mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_USER_ACTION);
   2354         mWifiLogger.dump(fd, pw, args);
   2355         mWifiQualifiedNetworkSelector.dump(fd, pw, args);
   2356         dumpIpManager(fd, pw, args);
   2357         if (mWifiConnectivityManager != null) {
   2358             mWifiConnectivityManager.dump(fd, pw, args);
   2359         }
   2360     }
   2361 
   2362     public void handleUserSwitch(int userId) {
   2363         sendMessage(CMD_USER_SWITCH, userId);
   2364     }
   2365 
   2366     /**
   2367      * ******************************************************
   2368      * Internal private functions
   2369      * ******************************************************
   2370      */
   2371 
   2372     private void logStateAndMessage(Message message, State state) {
   2373         messageHandlingStatus = 0;
   2374         if (DBG) {
   2375             logd(" " + state.getClass().getSimpleName() + " " + getLogRecString(message));
   2376         }
   2377     }
   2378 
   2379     /**
   2380      * helper, prints the milli time since boot wi and w/o suspended time
   2381      */
   2382     String printTime() {
   2383         StringBuilder sb = new StringBuilder();
   2384         sb.append(" rt=").append(SystemClock.uptimeMillis());
   2385         sb.append("/").append(SystemClock.elapsedRealtime());
   2386         return sb.toString();
   2387     }
   2388 
   2389     /**
   2390      * Return the additional string to be logged by LogRec, default
   2391      *
   2392      * @param msg that was processed
   2393      * @return information to be logged as a String
   2394      */
   2395     protected String getLogRecString(Message msg) {
   2396         WifiConfiguration config;
   2397         Long now;
   2398         String report;
   2399         String key;
   2400         StringBuilder sb = new StringBuilder();
   2401         if (mScreenOn) {
   2402             sb.append("!");
   2403         }
   2404         if (messageHandlingStatus != MESSAGE_HANDLING_STATUS_UNKNOWN) {
   2405             sb.append("(").append(messageHandlingStatus).append(")");
   2406         }
   2407         sb.append(smToString(msg));
   2408         if (msg.sendingUid > 0 && msg.sendingUid != Process.WIFI_UID) {
   2409             sb.append(" uid=" + msg.sendingUid);
   2410         }
   2411         sb.append(" ").append(printTime());
   2412         switch (msg.what) {
   2413             case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION:
   2414                 sb.append(" ");
   2415                 sb.append(Integer.toString(msg.arg1));
   2416                 sb.append(" ");
   2417                 sb.append(Integer.toString(msg.arg2));
   2418                 sb.append(" autojoinAllowed=");
   2419                 sb.append(mWifiConfigManager.getEnableAutoJoinWhenAssociated());
   2420                 sb.append(" withTraffic=").append(getAllowScansWithTraffic());
   2421                 sb.append(" tx=").append(mWifiInfo.txSuccessRate);
   2422                 sb.append("/").append(mWifiConfigManager.MAX_TX_PACKET_FOR_FULL_SCANS);
   2423                 sb.append(" rx=").append(mWifiInfo.rxSuccessRate);
   2424                 sb.append("/").append(mWifiConfigManager.MAX_RX_PACKET_FOR_FULL_SCANS);
   2425                 sb.append(" -> ").append(mConnectedModeGScanOffloadStarted);
   2426                 break;
   2427             case CMD_START_SCAN:
   2428                 now = System.currentTimeMillis();
   2429                 sb.append(" ");
   2430                 sb.append(Integer.toString(msg.arg1));
   2431                 sb.append(" ");
   2432                 sb.append(Integer.toString(msg.arg2));
   2433                 sb.append(" ic=");
   2434                 sb.append(Integer.toString(sScanAlarmIntentCount));
   2435                 if (msg.obj != null) {
   2436                     Bundle bundle = (Bundle) msg.obj;
   2437                     Long request = bundle.getLong(SCAN_REQUEST_TIME, 0);
   2438                     if (request != 0) {
   2439                         sb.append(" proc(ms):").append(now - request);
   2440                     }
   2441                 }
   2442                 if (mIsScanOngoing) sb.append(" onGoing");
   2443                 if (mIsFullScanOngoing) sb.append(" full");
   2444                 sb.append(" rssi=").append(mWifiInfo.getRssi());
   2445                 sb.append(" f=").append(mWifiInfo.getFrequency());
   2446                 sb.append(" sc=").append(mWifiInfo.score);
   2447                 sb.append(" link=").append(mWifiInfo.getLinkSpeed());
   2448                 sb.append(String.format(" tx=%.1f,", mWifiInfo.txSuccessRate));
   2449                 sb.append(String.format(" %.1f,", mWifiInfo.txRetriesRate));
   2450                 sb.append(String.format(" %.1f ", mWifiInfo.txBadRate));
   2451                 sb.append(String.format(" rx=%.1f", mWifiInfo.rxSuccessRate));
   2452                 if (lastScanFreqs != null) {
   2453                     sb.append(" list=");
   2454                     for(int freq : lastScanFreqs) {
   2455                         sb.append(freq).append(",");
   2456                     }
   2457                 }
   2458                 report = reportOnTime();
   2459                 if (report != null) {
   2460                     sb.append(" ").append(report);
   2461                 }
   2462                 break;
   2463             case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
   2464                 sb.append(" ");
   2465                 sb.append(Integer.toString(msg.arg1));
   2466                 sb.append(" ");
   2467                 sb.append(Integer.toString(msg.arg2));
   2468                 StateChangeResult stateChangeResult = (StateChangeResult) msg.obj;
   2469                 if (stateChangeResult != null) {
   2470                     sb.append(stateChangeResult.toString());
   2471                 }
   2472                 break;
   2473             case WifiManager.SAVE_NETWORK:
   2474             case WifiStateMachine.CMD_AUTO_SAVE_NETWORK:
   2475                 sb.append(" ");
   2476                 sb.append(Integer.toString(msg.arg1));
   2477                 sb.append(" ");
   2478                 sb.append(Integer.toString(msg.arg2));
   2479                 if (lastSavedConfigurationAttempt != null) {
   2480                     sb.append(" ").append(lastSavedConfigurationAttempt.configKey());
   2481                     sb.append(" nid=").append(lastSavedConfigurationAttempt.networkId);
   2482                     if (lastSavedConfigurationAttempt.hiddenSSID) {
   2483                         sb.append(" hidden");
   2484                     }
   2485                     if (lastSavedConfigurationAttempt.preSharedKey != null
   2486                             && !lastSavedConfigurationAttempt.preSharedKey.equals("*")) {
   2487                         sb.append(" hasPSK");
   2488                     }
   2489                     if (lastSavedConfigurationAttempt.ephemeral) {
   2490                         sb.append(" ephemeral");
   2491                     }
   2492                     if (lastSavedConfigurationAttempt.selfAdded) {
   2493                         sb.append(" selfAdded");
   2494                     }
   2495                     sb.append(" cuid=").append(lastSavedConfigurationAttempt.creatorUid);
   2496                     sb.append(" suid=").append(lastSavedConfigurationAttempt.lastUpdateUid);
   2497                 }
   2498                 break;
   2499             case WifiManager.FORGET_NETWORK:
   2500                 sb.append(" ");
   2501                 sb.append(Integer.toString(msg.arg1));
   2502                 sb.append(" ");
   2503                 sb.append(Integer.toString(msg.arg2));
   2504                 if (lastForgetConfigurationAttempt != null) {
   2505                     sb.append(" ").append(lastForgetConfigurationAttempt.configKey());
   2506                     sb.append(" nid=").append(lastForgetConfigurationAttempt.networkId);
   2507                     if (lastForgetConfigurationAttempt.hiddenSSID) {
   2508                         sb.append(" hidden");
   2509                     }
   2510                     if (lastForgetConfigurationAttempt.preSharedKey != null) {
   2511                         sb.append(" hasPSK");
   2512                     }
   2513                     if (lastForgetConfigurationAttempt.ephemeral) {
   2514                         sb.append(" ephemeral");
   2515                     }
   2516                     if (lastForgetConfigurationAttempt.selfAdded) {
   2517                         sb.append(" selfAdded");
   2518                     }
   2519                     sb.append(" cuid=").append(lastForgetConfigurationAttempt.creatorUid);
   2520                     sb.append(" suid=").append(lastForgetConfigurationAttempt.lastUpdateUid);
   2521                     WifiConfiguration.NetworkSelectionStatus netWorkSelectionStatus =
   2522                             lastForgetConfigurationAttempt.getNetworkSelectionStatus();
   2523                     sb.append(" ajst=").append(
   2524                             netWorkSelectionStatus.getNetworkStatusString());
   2525                 }
   2526                 break;
   2527             case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
   2528                 sb.append(" ");
   2529                 sb.append(Integer.toString(msg.arg1));
   2530                 sb.append(" ");
   2531                 sb.append(Integer.toString(msg.arg2));
   2532                 String bssid = (String) msg.obj;
   2533                 if (bssid != null && bssid.length() > 0) {
   2534                     sb.append(" ");
   2535                     sb.append(bssid);
   2536                 }
   2537                 sb.append(" blacklist=" + Boolean.toString(didBlackListBSSID));
   2538                 break;
   2539             case WifiMonitor.SCAN_RESULTS_EVENT:
   2540                 sb.append(" ");
   2541                 sb.append(Integer.toString(msg.arg1));
   2542                 sb.append(" ");
   2543                 sb.append(Integer.toString(msg.arg2));
   2544                 if (mScanResults != null) {
   2545                     sb.append(" found=");
   2546                     sb.append(mScanResults.size());
   2547                 }
   2548                 sb.append(" known=").append(mNumScanResultsKnown);
   2549                 sb.append(" got=").append(mNumScanResultsReturned);
   2550                 sb.append(String.format(" bcn=%d", mRunningBeaconCount));
   2551                 sb.append(String.format(" con=%d", mConnectionRequests));
   2552                 key = mWifiConfigManager.getLastSelectedConfiguration();
   2553                 if (key != null) {
   2554                     sb.append(" last=").append(key);
   2555                 }
   2556                 break;
   2557             case WifiMonitor.SCAN_FAILED_EVENT:
   2558                 break;
   2559             case WifiMonitor.NETWORK_CONNECTION_EVENT:
   2560                 sb.append(" ");
   2561                 sb.append(Integer.toString(msg.arg1));
   2562                 sb.append(" ");
   2563                 sb.append(Integer.toString(msg.arg2));
   2564                 sb.append(" ").append(mLastBssid);
   2565                 sb.append(" nid=").append(mLastNetworkId);
   2566                 config = getCurrentWifiConfiguration();
   2567                 if (config != null) {
   2568                     sb.append(" ").append(config.configKey());
   2569                 }
   2570                 key = mWifiConfigManager.getLastSelectedConfiguration();
   2571                 if (key != null) {
   2572                     sb.append(" last=").append(key);
   2573                 }
   2574                 break;
   2575             case CMD_TARGET_BSSID:
   2576             case CMD_ASSOCIATED_BSSID:
   2577                 sb.append(" ");
   2578                 sb.append(Integer.toString(msg.arg1));
   2579                 sb.append(" ");
   2580                 sb.append(Integer.toString(msg.arg2));
   2581                 if (msg.obj != null) {
   2582                     sb.append(" BSSID=").append((String) msg.obj);
   2583                 }
   2584                 if (mTargetRoamBSSID != null) {
   2585                     sb.append(" Target=").append(mTargetRoamBSSID);
   2586                 }
   2587                 sb.append(" roam=").append(Boolean.toString(mAutoRoaming));
   2588                 break;
   2589             case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
   2590                 if (msg.obj != null) {
   2591                     sb.append(" ").append((String) msg.obj);
   2592                 }
   2593                 sb.append(" nid=").append(msg.arg1);
   2594                 sb.append(" reason=").append(msg.arg2);
   2595                 if (mLastBssid != null) {
   2596                     sb.append(" lastbssid=").append(mLastBssid);
   2597                 }
   2598                 if (mWifiInfo.getFrequency() != -1) {
   2599                     sb.append(" freq=").append(mWifiInfo.getFrequency());
   2600                     sb.append(" rssi=").append(mWifiInfo.getRssi());
   2601                 }
   2602                 if (linkDebouncing) {
   2603                     sb.append(" debounce");
   2604                 }
   2605                 break;
   2606             case WifiMonitor.SSID_TEMP_DISABLED:
   2607             case WifiMonitor.SSID_REENABLED:
   2608                 sb.append(" nid=").append(msg.arg1);
   2609                 if (msg.obj != null) {
   2610                     sb.append(" ").append((String) msg.obj);
   2611                 }
   2612                 config = getCurrentWifiConfiguration();
   2613                 if (config != null) {
   2614                     WifiConfiguration.NetworkSelectionStatus netWorkSelectionStatus =
   2615                             config.getNetworkSelectionStatus();
   2616                     sb.append(" cur=").append(config.configKey());
   2617                     sb.append(" ajst=").append(netWorkSelectionStatus.getNetworkStatusString());
   2618                     if (config.selfAdded) {
   2619                         sb.append(" selfAdded");
   2620                     }
   2621                     if (config.status != 0) {
   2622                         sb.append(" st=").append(config.status);
   2623                         sb.append(" rs=").append(
   2624                                 netWorkSelectionStatus.getNetworkDisableReasonString());
   2625                     }
   2626                     if (config.lastConnected != 0) {
   2627                         now = System.currentTimeMillis();
   2628                         sb.append(" lastconn=").append(now - config.lastConnected).append("(ms)");
   2629                     }
   2630                     if (mLastBssid != null) {
   2631                         sb.append(" lastbssid=").append(mLastBssid);
   2632                     }
   2633                     if (mWifiInfo.getFrequency() != -1) {
   2634                         sb.append(" freq=").append(mWifiInfo.getFrequency());
   2635                         sb.append(" rssi=").append(mWifiInfo.getRssi());
   2636                         sb.append(" bssid=").append(mWifiInfo.getBSSID());
   2637                     }
   2638                 }
   2639                 break;
   2640             case CMD_RSSI_POLL:
   2641             case CMD_UNWANTED_NETWORK:
   2642             case WifiManager.RSSI_PKTCNT_FETCH:
   2643                 sb.append(" ");
   2644                 sb.append(Integer.toString(msg.arg1));
   2645                 sb.append(" ");
   2646                 sb.append(Integer.toString(msg.arg2));
   2647                 if (mWifiInfo.getSSID() != null)
   2648                     if (mWifiInfo.getSSID() != null)
   2649                         sb.append(" ").append(mWifiInfo.getSSID());
   2650                 if (mWifiInfo.getBSSID() != null)
   2651                     sb.append(" ").append(mWifiInfo.getBSSID());
   2652                 sb.append(" rssi=").append(mWifiInfo.getRssi());
   2653                 sb.append(" f=").append(mWifiInfo.getFrequency());
   2654                 sb.append(" sc=").append(mWifiInfo.score);
   2655                 sb.append(" link=").append(mWifiInfo.getLinkSpeed());
   2656                 sb.append(String.format(" tx=%.1f,", mWifiInfo.txSuccessRate));
   2657                 sb.append(String.format(" %.1f,", mWifiInfo.txRetriesRate));
   2658                 sb.append(String.format(" %.1f ", mWifiInfo.txBadRate));
   2659                 sb.append(String.format(" rx=%.1f", mWifiInfo.rxSuccessRate));
   2660                 sb.append(String.format(" bcn=%d", mRunningBeaconCount));
   2661                 report = reportOnTime();
   2662                 if (report != null) {
   2663                     sb.append(" ").append(report);
   2664                 }
   2665                 if (mWifiScoreReport != null) {
   2666                     sb.append(mWifiScoreReport.getReport());
   2667                 }
   2668                 if (mConnectedModeGScanOffloadStarted) {
   2669                     sb.append(" offload-started periodMilli " + mGScanPeriodMilli);
   2670                 } else {
   2671                     sb.append(" offload-stopped");
   2672                 }
   2673                 break;
   2674             case CMD_AUTO_CONNECT:
   2675             case WifiManager.CONNECT_NETWORK:
   2676                 sb.append(" ");
   2677                 sb.append(Integer.toString(msg.arg1));
   2678                 sb.append(" ");
   2679                 sb.append(Integer.toString(msg.arg2));
   2680                 config = mWifiConfigManager.getWifiConfiguration(msg.arg1);
   2681                 if (config != null) {
   2682                     sb.append(" ").append(config.configKey());
   2683                     if (config.visibility != null) {
   2684                         sb.append(" ").append(config.visibility.toString());
   2685                     }
   2686                 }
   2687                 if (mTargetRoamBSSID != null) {
   2688                     sb.append(" ").append(mTargetRoamBSSID);
   2689                 }
   2690                 sb.append(" roam=").append(Boolean.toString(mAutoRoaming));
   2691                 config = getCurrentWifiConfiguration();
   2692                 if (config != null) {
   2693                     sb.append(config.configKey());
   2694                     if (config.visibility != null) {
   2695                         sb.append(" ").append(config.visibility.toString());
   2696                     }
   2697                 }
   2698                 break;
   2699             case CMD_AUTO_ROAM:
   2700                 sb.append(" ");
   2701                 sb.append(Integer.toString(msg.arg1));
   2702                 sb.append(" ");
   2703                 sb.append(Integer.toString(msg.arg2));
   2704                 ScanResult result = (ScanResult) msg.obj;
   2705                 if (result != null) {
   2706                     now = System.currentTimeMillis();
   2707                     sb.append(" bssid=").append(result.BSSID);
   2708                     sb.append(" rssi=").append(result.level);
   2709                     sb.append(" freq=").append(result.frequency);
   2710                     if (result.seen > 0 && result.seen < now) {
   2711                         sb.append(" seen=").append(now - result.seen);
   2712                     } else {
   2713                         // Somehow the timestamp for this scan result is inconsistent
   2714                         sb.append(" !seen=").append(result.seen);
   2715                     }
   2716                 }
   2717                 if (mTargetRoamBSSID != null) {
   2718                     sb.append(" ").append(mTargetRoamBSSID);
   2719                 }
   2720                 sb.append(" roam=").append(Boolean.toString(mAutoRoaming));
   2721                 sb.append(" fail count=").append(Integer.toString(mRoamFailCount));
   2722                 break;
   2723             case CMD_ADD_OR_UPDATE_NETWORK:
   2724                 sb.append(" ");
   2725                 sb.append(Integer.toString(msg.arg1));
   2726                 sb.append(" ");
   2727                 sb.append(Integer.toString(msg.arg2));
   2728                 if (msg.obj != null) {
   2729                     config = (WifiConfiguration) msg.obj;
   2730                     sb.append(" ").append(config.configKey());
   2731                     sb.append(" prio=").append(config.priority);
   2732                     sb.append(" status=").append(config.status);
   2733                     if (config.BSSID != null) {
   2734                         sb.append(" ").append(config.BSSID);
   2735                     }
   2736                     WifiConfiguration curConfig = getCurrentWifiConfiguration();
   2737                     if (curConfig != null) {
   2738                         if (curConfig.configKey().equals(config.configKey())) {
   2739                             sb.append(" is current");
   2740                         } else {
   2741                             sb.append(" current=").append(curConfig.configKey());
   2742                             sb.append(" prio=").append(curConfig.priority);
   2743                             sb.append(" status=").append(curConfig.status);
   2744                         }
   2745                     }
   2746                 }
   2747                 break;
   2748             case WifiManager.DISABLE_NETWORK:
   2749             case CMD_ENABLE_NETWORK:
   2750                 sb.append(" ");
   2751                 sb.append(Integer.toString(msg.arg1));
   2752                 sb.append(" ");
   2753                 sb.append(Integer.toString(msg.arg2));
   2754                 key = mWifiConfigManager.getLastSelectedConfiguration();
   2755                 if (key != null) {
   2756                     sb.append(" last=").append(key);
   2757                 }
   2758                 config = mWifiConfigManager.getWifiConfiguration(msg.arg1);
   2759                 if (config != null && (key == null || !config.configKey().equals(key))) {
   2760                     sb.append(" target=").append(key);
   2761                 }
   2762                 break;
   2763             case CMD_GET_CONFIGURED_NETWORKS:
   2764                 sb.append(" ");
   2765                 sb.append(Integer.toString(msg.arg1));
   2766                 sb.append(" ");
   2767                 sb.append(Integer.toString(msg.arg2));
   2768                 sb.append(" num=").append(mWifiConfigManager.getConfiguredNetworksSize());
   2769                 break;
   2770             case DhcpClient.CMD_PRE_DHCP_ACTION:
   2771                 sb.append(" ");
   2772                 sb.append(Integer.toString(msg.arg1));
   2773                 sb.append(" ");
   2774                 sb.append(Integer.toString(msg.arg2));
   2775                 sb.append(" txpkts=").append(mWifiInfo.txSuccess);
   2776                 sb.append(",").append(mWifiInfo.txBad);
   2777                 sb.append(",").append(mWifiInfo.txRetries);
   2778                 break;
   2779             case DhcpClient.CMD_POST_DHCP_ACTION:
   2780                 sb.append(" ");
   2781                 sb.append(Integer.toString(msg.arg1));
   2782                 sb.append(" ");
   2783                 sb.append(Integer.toString(msg.arg2));
   2784                 if (msg.arg1 == DhcpClient.DHCP_SUCCESS) {
   2785                     sb.append(" OK ");
   2786                 } else if (msg.arg1 == DhcpClient.DHCP_FAILURE) {
   2787                     sb.append(" FAIL ");
   2788                 }
   2789                 if (mLinkProperties != null) {
   2790                     sb.append(" ");
   2791                     sb.append(getLinkPropertiesSummary(mLinkProperties));
   2792                 }
   2793                 break;
   2794             case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED:
   2795                 sb.append(" ");
   2796                 sb.append(Integer.toString(msg.arg1));
   2797                 sb.append(" ");
   2798                 sb.append(Integer.toString(msg.arg2));
   2799                 if (msg.obj != null) {
   2800                     NetworkInfo info = (NetworkInfo) msg.obj;
   2801                     NetworkInfo.State state = info.getState();
   2802                     NetworkInfo.DetailedState detailedState = info.getDetailedState();
   2803                     if (state != null) {
   2804                         sb.append(" st=").append(state);
   2805                     }
   2806                     if (detailedState != null) {
   2807                         sb.append("/").append(detailedState);
   2808                     }
   2809                 }
   2810                 break;
   2811             case CMD_IP_CONFIGURATION_LOST:
   2812                 int count = -1;
   2813                 WifiConfiguration c = getCurrentWifiConfiguration();
   2814                 if (c != null) {
   2815                     count = c.getNetworkSelectionStatus().getDisableReasonCounter(
   2816                             WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE);
   2817                 }
   2818                 sb.append(" ");
   2819                 sb.append(Integer.toString(msg.arg1));
   2820                 sb.append(" ");
   2821                 sb.append(Integer.toString(msg.arg2));
   2822                 sb.append(" failures: ");
   2823                 sb.append(Integer.toString(count));
   2824                 sb.append("/");
   2825                 sb.append(Integer.toString(mWifiConfigManager.getMaxDhcpRetries()));
   2826                 if (mWifiInfo.getBSSID() != null) {
   2827                     sb.append(" ").append(mWifiInfo.getBSSID());
   2828                 }
   2829                 sb.append(String.format(" bcn=%d", mRunningBeaconCount));
   2830                 break;
   2831             case CMD_UPDATE_LINKPROPERTIES:
   2832                 sb.append(" ");
   2833                 sb.append(Integer.toString(msg.arg1));
   2834                 sb.append(" ");
   2835                 sb.append(Integer.toString(msg.arg2));
   2836                 if (mLinkProperties != null) {
   2837                     sb.append(" ");
   2838                     sb.append(getLinkPropertiesSummary(mLinkProperties));
   2839                 }
   2840                 break;
   2841             case CMD_IP_REACHABILITY_LOST:
   2842                 if (msg.obj != null) {
   2843                     sb.append(" ").append((String) msg.obj);
   2844                 }
   2845                 break;
   2846             case CMD_INSTALL_PACKET_FILTER:
   2847                 sb.append(" len=" + ((byte[])msg.obj).length);
   2848                 break;
   2849             case CMD_SET_FALLBACK_PACKET_FILTERING:
   2850                 sb.append(" enabled=" + (boolean)msg.obj);
   2851                 break;
   2852             case CMD_ROAM_WATCHDOG_TIMER:
   2853                 sb.append(" ");
   2854                 sb.append(Integer.toString(msg.arg1));
   2855                 sb.append(" ");
   2856                 sb.append(Integer.toString(msg.arg2));
   2857                 sb.append(" cur=").append(roamWatchdogCount);
   2858                 break;
   2859             case CMD_DISCONNECTING_WATCHDOG_TIMER:
   2860                 sb.append(" ");
   2861                 sb.append(Integer.toString(msg.arg1));
   2862                 sb.append(" ");
   2863                 sb.append(Integer.toString(msg.arg2));
   2864                 sb.append(" cur=").append(disconnectingWatchdogCount);
   2865                 break;
   2866             case CMD_START_RSSI_MONITORING_OFFLOAD:
   2867             case CMD_STOP_RSSI_MONITORING_OFFLOAD:
   2868             case CMD_RSSI_THRESHOLD_BREACH:
   2869                 sb.append(" rssi=");
   2870                 sb.append(Integer.toString(msg.arg1));
   2871                 sb.append(" thresholds=");
   2872                 sb.append(Arrays.toString(mRssiRanges));
   2873                 break;
   2874             case CMD_USER_SWITCH:
   2875                 sb.append(" userId=");
   2876                 sb.append(Integer.toString(msg.arg1));
   2877                 break;
   2878             case CMD_IPV4_PROVISIONING_SUCCESS:
   2879                 sb.append(" ");
   2880                 if (msg.arg1 == DhcpClient.DHCP_SUCCESS) {
   2881                     sb.append("DHCP_OK");
   2882                 } else if (msg.arg1 == CMD_STATIC_IP_SUCCESS) {
   2883                     sb.append("STATIC_OK");
   2884                 } else {
   2885                     sb.append(Integer.toString(msg.arg1));
   2886                 }
   2887                 break;
   2888             case CMD_IPV4_PROVISIONING_FAILURE:
   2889                 sb.append(" ");
   2890                 if (msg.arg1 == DhcpClient.DHCP_FAILURE) {
   2891                     sb.append("DHCP_FAIL");
   2892                 } else if (msg.arg1 == CMD_STATIC_IP_FAILURE) {
   2893                     sb.append("STATIC_FAIL");
   2894                 } else {
   2895                     sb.append(Integer.toString(msg.arg1));
   2896                 }
   2897                 break;
   2898             default:
   2899                 sb.append(" ");
   2900                 sb.append(Integer.toString(msg.arg1));
   2901                 sb.append(" ");
   2902                 sb.append(Integer.toString(msg.arg2));
   2903                 break;
   2904         }
   2905 
   2906         return sb.toString();
   2907     }
   2908 
   2909     private void handleScreenStateChanged(boolean screenOn) {
   2910         mScreenOn = screenOn;
   2911         if (DBG) {
   2912             logd(" handleScreenStateChanged Enter: screenOn=" + screenOn
   2913                     + " mUserWantsSuspendOpt=" + mUserWantsSuspendOpt
   2914                     + " state " + getCurrentState().getName()
   2915                     + " suppState:" + mSupplicantStateTracker.getSupplicantStateName());
   2916         }
   2917         enableRssiPolling(screenOn);
   2918         if (mUserWantsSuspendOpt.get()) {
   2919             int shouldReleaseWakeLock = 0;
   2920             if (screenOn) {
   2921                 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 0, shouldReleaseWakeLock);
   2922             } else {
   2923                 if (isConnected()) {
   2924                     // Allow 2s for suspend optimizations to be set
   2925                     mSuspendWakeLock.acquire(2000);
   2926                     shouldReleaseWakeLock = 1;
   2927                 }
   2928                 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 1, shouldReleaseWakeLock);
   2929             }
   2930         }
   2931         mScreenBroadcastReceived.set(true);
   2932 
   2933         getWifiLinkLayerStats(false);
   2934         mOnTimeScreenStateChange = mOnTime;
   2935         lastScreenStateChangeTimeStamp = lastLinkLayerStatsUpdate;
   2936 
   2937         mWifiMetrics.setScreenState(screenOn);
   2938 
   2939         if (mWifiConnectivityManager != null) {
   2940             mWifiConnectivityManager.handleScreenStateChanged(screenOn);
   2941         }
   2942 
   2943         if (DBG) log("handleScreenStateChanged Exit: " + screenOn);
   2944     }
   2945 
   2946     private void checkAndSetConnectivityInstance() {
   2947         if (mCm == null) {
   2948             mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
   2949         }
   2950     }
   2951 
   2952 
   2953     /**
   2954      * Set the frequency band from the system setting value, if any.
   2955      */
   2956     private void setFrequencyBand() {
   2957         int band = WifiManager.WIFI_FREQUENCY_BAND_AUTO;
   2958 
   2959         if (mWifiNative.setBand(band)) {
   2960             mFrequencyBand.set(band);
   2961             if (mWifiConnectivityManager != null) {
   2962                 mWifiConnectivityManager.setUserPreferredBand(band);
   2963             }
   2964             if (DBG) {
   2965                 logd("done set frequency band " + band);
   2966             }
   2967         } else {
   2968             loge("Failed to set frequency band " + band);
   2969         }
   2970     }
   2971 
   2972     private void setSuspendOptimizationsNative(int reason, boolean enabled) {
   2973         if (DBG) {
   2974             log("setSuspendOptimizationsNative: " + reason + " " + enabled
   2975                     + " -want " + mUserWantsSuspendOpt.get()
   2976                     + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
   2977                     + " - " + Thread.currentThread().getStackTrace()[3].getMethodName()
   2978                     + " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
   2979                     + " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
   2980         }
   2981         //mWifiNative.setSuspendOptimizations(enabled);
   2982 
   2983         if (enabled) {
   2984             mSuspendOptNeedsDisabled &= ~reason;
   2985             /* None of dhcp, screen or highperf need it disabled and user wants it enabled */
   2986             if (mSuspendOptNeedsDisabled == 0 && mUserWantsSuspendOpt.get()) {
   2987                 if (DBG) {
   2988                     log("setSuspendOptimizationsNative do it " + reason + " " + enabled
   2989                             + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
   2990                             + " - " + Thread.currentThread().getStackTrace()[3].getMethodName()
   2991                             + " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
   2992                             + " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
   2993                 }
   2994                 mWifiNative.setSuspendOptimizations(true);
   2995             }
   2996         } else {
   2997             mSuspendOptNeedsDisabled |= reason;
   2998             mWifiNative.setSuspendOptimizations(false);
   2999         }
   3000     }
   3001 
   3002     private void setSuspendOptimizations(int reason, boolean enabled) {
   3003         if (DBG) log("setSuspendOptimizations: " + reason + " " + enabled);
   3004         if (enabled) {
   3005             mSuspendOptNeedsDisabled &= ~reason;
   3006         } else {
   3007             mSuspendOptNeedsDisabled |= reason;
   3008         }
   3009         if (DBG) log("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled);
   3010     }
   3011 
   3012     private void setWifiState(int wifiState) {
   3013         final int previousWifiState = mWifiState.get();
   3014 
   3015         try {
   3016             if (wifiState == WIFI_STATE_ENABLED) {
   3017                 mBatteryStats.noteWifiOn();
   3018             } else if (wifiState == WIFI_STATE_DISABLED) {
   3019                 mBatteryStats.noteWifiOff();
   3020             }
   3021         } catch (RemoteException e) {
   3022             loge("Failed to note battery stats in wifi");
   3023         }
   3024 
   3025         mWifiState.set(wifiState);
   3026 
   3027         if (DBG) log("setWifiState: " + syncGetWifiStateByName());
   3028 
   3029         final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
   3030         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   3031         intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState);
   3032         intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState);
   3033         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   3034     }
   3035 
   3036     private void setWifiApState(int wifiApState, int reason) {
   3037         final int previousWifiApState = mWifiApState.get();
   3038 
   3039         try {
   3040             if (wifiApState == WIFI_AP_STATE_ENABLED) {
   3041                 mBatteryStats.noteWifiOn();
   3042             } else if (wifiApState == WIFI_AP_STATE_DISABLED) {
   3043                 mBatteryStats.noteWifiOff();
   3044             }
   3045         } catch (RemoteException e) {
   3046             loge("Failed to note battery stats in wifi");
   3047         }
   3048 
   3049         // Update state
   3050         mWifiApState.set(wifiApState);
   3051 
   3052         if (DBG) log("setWifiApState: " + syncGetWifiApStateByName());
   3053 
   3054         final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
   3055         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   3056         intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, wifiApState);
   3057         intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousWifiApState);
   3058         if (wifiApState == WifiManager.WIFI_AP_STATE_FAILED) {
   3059             //only set reason number when softAP start failed
   3060             intent.putExtra(WifiManager.EXTRA_WIFI_AP_FAILURE_REASON, reason);
   3061         }
   3062 
   3063         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   3064     }
   3065 
   3066     private void setScanResults() {
   3067         mNumScanResultsKnown = 0;
   3068         mNumScanResultsReturned = 0;
   3069 
   3070         ArrayList<ScanDetail> scanResults = mWifiNative.getScanResults();
   3071 
   3072         if (scanResults.isEmpty()) {
   3073             mScanResults = new ArrayList<>();
   3074             return;
   3075         }
   3076 
   3077         mWifiConfigManager.trimANQPCache(false);
   3078 
   3079         boolean connected = mLastBssid != null;
   3080         long activeBssid = 0L;
   3081         if (connected) {
   3082             try {
   3083                 activeBssid = Utils.parseMac(mLastBssid);
   3084             } catch (IllegalArgumentException iae) {
   3085                 connected = false;
   3086             }
   3087         }
   3088 
   3089         synchronized (mScanResultsLock) {
   3090             ScanDetail activeScanDetail = null;
   3091             mScanResults = scanResults;
   3092             mNumScanResultsReturned = mScanResults.size();
   3093             for (ScanDetail resultDetail : mScanResults) {
   3094                 if (connected && resultDetail.getNetworkDetail().getBSSID() == activeBssid) {
   3095                     if (activeScanDetail == null
   3096                             || activeScanDetail.getNetworkDetail().getBSSID() != activeBssid
   3097                             || activeScanDetail.getNetworkDetail().getANQPElements() == null) {
   3098                         activeScanDetail = resultDetail;
   3099                     }
   3100                 }
   3101                 // Cache DTIM values parsed from the beacon frame Traffic Indication Map (TIM)
   3102                 // Information Element (IE), into the associated WifiConfigurations. Most of the
   3103                 // time there is no TIM IE in the scan result (Probe Response instead of Beacon
   3104                 // Frame), these scanResult DTIM's are negative and ignored.
   3105                 // <TODO> Cache these per BSSID, since dtim can change vary
   3106                 NetworkDetail networkDetail = resultDetail.getNetworkDetail();
   3107                 if (networkDetail != null && networkDetail.getDtimInterval() > 0) {
   3108                     List<WifiConfiguration> associatedWifiConfigurations =
   3109                             mWifiConfigManager.getSavedNetworkFromScanDetail(resultDetail);
   3110                     if (associatedWifiConfigurations != null) {
   3111                         for (WifiConfiguration associatedConf : associatedWifiConfigurations) {
   3112                             if (associatedConf != null) {
   3113                                 associatedConf.dtimInterval = networkDetail.getDtimInterval();
   3114                             }
   3115                         }
   3116                     }
   3117                 }
   3118             }
   3119             mWifiConfigManager.setActiveScanDetail(activeScanDetail);
   3120         }
   3121 
   3122         if (linkDebouncing) {
   3123             // If debouncing, we dont re-select a SSID or BSSID hence
   3124             // there is no need to call the network selection code
   3125             // in WifiAutoJoinController, instead,
   3126             // just try to reconnect to the same SSID by triggering a roam
   3127             // The third parameter 1 means roam not from network selection but debouncing
   3128             sendMessage(CMD_AUTO_ROAM, mLastNetworkId, 1, null);
   3129         }
   3130     }
   3131 
   3132     /*
   3133      * Fetch RSSI, linkspeed, and frequency on current connection
   3134      */
   3135     private void fetchRssiLinkSpeedAndFrequencyNative() {
   3136         Integer newRssi = null;
   3137         Integer newLinkSpeed = null;
   3138         Integer newFrequency = null;
   3139 
   3140         String signalPoll = mWifiNative.signalPoll();
   3141 
   3142         if (signalPoll != null) {
   3143             String[] lines = signalPoll.split("\n");
   3144             for (String line : lines) {
   3145                 String[] prop = line.split("=");
   3146                 if (prop.length < 2) continue;
   3147                 try {
   3148                     if (prop[0].equals("RSSI")) {
   3149                         newRssi = Integer.parseInt(prop[1]);
   3150                     } else if (prop[0].equals("LINKSPEED")) {
   3151                         newLinkSpeed = Integer.parseInt(prop[1]);
   3152                     } else if (prop[0].equals("FREQUENCY")) {
   3153                         newFrequency = Integer.parseInt(prop[1]);
   3154                     }
   3155                 } catch (NumberFormatException e) {
   3156                     //Ignore, defaults on rssi and linkspeed are assigned
   3157                 }
   3158             }
   3159         }
   3160 
   3161         if (DBG) {
   3162             logd("fetchRssiLinkSpeedAndFrequencyNative rssi=" + newRssi +
   3163                  " linkspeed=" + newLinkSpeed + " freq=" + newFrequency);
   3164         }
   3165 
   3166         if (newRssi != null && newRssi > WifiInfo.INVALID_RSSI && newRssi < WifiInfo.MAX_RSSI) {
   3167             // screen out invalid values
   3168             /* some implementations avoid negative values by adding 256
   3169              * so we need to adjust for that here.
   3170              */
   3171             if (newRssi > 0) newRssi -= 256;
   3172             mWifiInfo.setRssi(newRssi);
   3173             /*
   3174              * Log the rssi poll value in metrics
   3175              */
   3176             mWifiMetrics.incrementRssiPollRssiCount(newRssi);
   3177             /*
   3178              * Rather then sending the raw RSSI out every time it
   3179              * changes, we precalculate the signal level that would
   3180              * be displayed in the status bar, and only send the
   3181              * broadcast if that much more coarse-grained number
   3182              * changes. This cuts down greatly on the number of
   3183              * broadcasts, at the cost of not informing others
   3184              * interested in RSSI of all the changes in signal
   3185              * level.
   3186              */
   3187             int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, WifiManager.RSSI_LEVELS);
   3188             if (newSignalLevel != mLastSignalLevel) {
   3189                 updateCapabilities(getCurrentWifiConfiguration());
   3190                 sendRssiChangeBroadcast(newRssi);
   3191             }
   3192             mLastSignalLevel = newSignalLevel;
   3193         } else {
   3194             mWifiInfo.setRssi(WifiInfo.INVALID_RSSI);
   3195             updateCapabilities(getCurrentWifiConfiguration());
   3196         }
   3197 
   3198         if (newLinkSpeed != null) {
   3199             mWifiInfo.setLinkSpeed(newLinkSpeed);
   3200         }
   3201         if (newFrequency != null && newFrequency > 0) {
   3202             if (ScanResult.is5GHz(newFrequency)) {
   3203                 mWifiConnectionStatistics.num5GhzConnected++;
   3204             }
   3205             if (ScanResult.is24GHz(newFrequency)) {
   3206                 mWifiConnectionStatistics.num24GhzConnected++;
   3207             }
   3208             mWifiInfo.setFrequency(newFrequency);
   3209         }
   3210         mWifiConfigManager.updateConfiguration(mWifiInfo);
   3211     }
   3212 
   3213     // Polling has completed, hence we wont have a score anymore
   3214     private void cleanWifiScore() {
   3215         mWifiInfo.txBadRate = 0;
   3216         mWifiInfo.txSuccessRate = 0;
   3217         mWifiInfo.txRetriesRate = 0;
   3218         mWifiInfo.rxSuccessRate = 0;
   3219         mWifiScoreReport = null;
   3220     }
   3221 
   3222     // Object holding most recent wifi score report and bad Linkspeed count
   3223     WifiScoreReport mWifiScoreReport = null;
   3224 
   3225     public double getTxPacketRate() {
   3226         return mWifiInfo.txSuccessRate;
   3227     }
   3228 
   3229     public double getRxPacketRate() {
   3230         return mWifiInfo.rxSuccessRate;
   3231     }
   3232 
   3233     /**
   3234      * Fetch TX packet counters on current connection
   3235      */
   3236     private void fetchPktcntNative(RssiPacketCountInfo info) {
   3237         String pktcntPoll = mWifiNative.pktcntPoll();
   3238 
   3239         if (pktcntPoll != null) {
   3240             String[] lines = pktcntPoll.split("\n");
   3241             for (String line : lines) {
   3242                 String[] prop = line.split("=");
   3243                 if (prop.length < 2) continue;
   3244                 try {
   3245                     if (prop[0].equals("TXGOOD")) {
   3246                         info.txgood = Integer.parseInt(prop[1]);
   3247                     } else if (prop[0].equals("TXBAD")) {
   3248                         info.txbad = Integer.parseInt(prop[1]);
   3249                     }
   3250                 } catch (NumberFormatException e) {
   3251                     // Ignore
   3252                 }
   3253             }
   3254         }
   3255     }
   3256 
   3257     private void updateLinkProperties(LinkProperties newLp) {
   3258         if (DBG) {
   3259             log("Link configuration changed for netId: " + mLastNetworkId
   3260                     + " old: " + mLinkProperties + " new: " + newLp);
   3261         }
   3262         // We own this instance of LinkProperties because IpManager passes us a copy.
   3263         mLinkProperties = newLp;
   3264         if (mNetworkAgent != null) {
   3265             mNetworkAgent.sendLinkProperties(mLinkProperties);
   3266         }
   3267 
   3268         if (getNetworkDetailedState() == DetailedState.CONNECTED) {
   3269             // If anything has changed and we're already connected, send out a notification.
   3270             // TODO: Update all callers to use NetworkCallbacks and delete this.
   3271             sendLinkConfigurationChangedBroadcast();
   3272         }
   3273 
   3274         if (DBG) {
   3275             StringBuilder sb = new StringBuilder();
   3276             sb.append("updateLinkProperties nid: " + mLastNetworkId);
   3277             sb.append(" state: " + getNetworkDetailedState());
   3278 
   3279             if (mLinkProperties != null) {
   3280                 sb.append(" ");
   3281                 sb.append(getLinkPropertiesSummary(mLinkProperties));
   3282             }
   3283             logd(sb.toString());
   3284         }
   3285     }
   3286 
   3287     /**
   3288      * Clears all our link properties.
   3289      */
   3290     private void clearLinkProperties() {
   3291         // Clear the link properties obtained from DHCP. The only caller of this
   3292         // function has already called IpManager#stop(), which clears its state.
   3293         synchronized (mDhcpResultsLock) {
   3294             if (mDhcpResults != null) {
   3295                 mDhcpResults.clear();
   3296             }
   3297         }
   3298 
   3299         // Now clear the merged link properties.
   3300         mLinkProperties.clear();
   3301         if (mNetworkAgent != null) mNetworkAgent.sendLinkProperties(mLinkProperties);
   3302     }
   3303 
   3304     /**
   3305      * try to update default route MAC address.
   3306      */
   3307     private String updateDefaultRouteMacAddress(int timeout) {
   3308         String address = null;
   3309         for (RouteInfo route : mLinkProperties.getRoutes()) {
   3310             if (route.isDefaultRoute() && route.hasGateway()) {
   3311                 InetAddress gateway = route.getGateway();
   3312                 if (gateway instanceof Inet4Address) {
   3313                     if (DBG) {
   3314                         logd("updateDefaultRouteMacAddress found Ipv4 default :"
   3315                                 + gateway.getHostAddress());
   3316                     }
   3317                     address = macAddressFromRoute(gateway.getHostAddress());
   3318                     /* The gateway's MAC address is known */
   3319                     if ((address == null) && (timeout > 0)) {
   3320                         boolean reachable = false;
   3321                         try {
   3322                             reachable = gateway.isReachable(timeout);
   3323                         } catch (Exception e) {
   3324                             loge("updateDefaultRouteMacAddress exception reaching :"
   3325                                     + gateway.getHostAddress());
   3326 
   3327                         } finally {
   3328                             if (reachable == true) {
   3329 
   3330                                 address = macAddressFromRoute(gateway.getHostAddress());
   3331                                 if (DBG) {
   3332                                     logd("updateDefaultRouteMacAddress reachable (tried again) :"
   3333                                             + gateway.getHostAddress() + " found " + address);
   3334                                 }
   3335                             }
   3336                         }
   3337                     }
   3338                     if (address != null) {
   3339                         mWifiConfigManager.setDefaultGwMacAddress(mLastNetworkId, address);
   3340                     }
   3341                 }
   3342             }
   3343         }
   3344         return address;
   3345     }
   3346 
   3347     void sendScanResultsAvailableBroadcast(boolean scanSucceeded) {
   3348         Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
   3349         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   3350         intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, scanSucceeded);
   3351         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
   3352     }
   3353 
   3354     private void sendRssiChangeBroadcast(final int newRssi) {
   3355         try {
   3356             mBatteryStats.noteWifiRssiChanged(newRssi);
   3357         } catch (RemoteException e) {
   3358             // Won't happen.
   3359         }
   3360         Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION);
   3361         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   3362         intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi);
   3363         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   3364     }
   3365 
   3366     private void sendNetworkStateChangeBroadcast(String bssid) {
   3367         Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
   3368         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   3369         intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
   3370         intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties));
   3371         if (bssid != null)
   3372             intent.putExtra(WifiManager.EXTRA_BSSID, bssid);
   3373         if (mNetworkInfo.getDetailedState() == DetailedState.VERIFYING_POOR_LINK ||
   3374                 mNetworkInfo.getDetailedState() == DetailedState.CONNECTED) {
   3375             // We no longer report MAC address to third-parties and our code does
   3376             // not rely on this broadcast, so just send the default MAC address.
   3377             fetchRssiLinkSpeedAndFrequencyNative();
   3378             WifiInfo sentWifiInfo = new WifiInfo(mWifiInfo);
   3379             sentWifiInfo.setMacAddress(WifiInfo.DEFAULT_MAC_ADDRESS);
   3380             intent.putExtra(WifiManager.EXTRA_WIFI_INFO, sentWifiInfo);
   3381         }
   3382         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   3383     }
   3384 
   3385     private WifiInfo getWiFiInfoForUid(int uid) {
   3386         if (Binder.getCallingUid() == Process.myUid()) {
   3387             return mWifiInfo;
   3388         }
   3389 
   3390         WifiInfo result = new WifiInfo(mWifiInfo);
   3391         result.setMacAddress(WifiInfo.DEFAULT_MAC_ADDRESS);
   3392 
   3393         IBinder binder = mFacade.getService("package");
   3394         IPackageManager packageManager = IPackageManager.Stub.asInterface(binder);
   3395 
   3396         try {
   3397             if (packageManager.checkUidPermission(Manifest.permission.LOCAL_MAC_ADDRESS,
   3398                     uid) == PackageManager.PERMISSION_GRANTED) {
   3399                 result.setMacAddress(mWifiInfo.getMacAddress());
   3400             }
   3401         } catch (RemoteException e) {
   3402             Log.e(TAG, "Error checking receiver permission", e);
   3403         }
   3404 
   3405         return result;
   3406     }
   3407 
   3408     private void sendLinkConfigurationChangedBroadcast() {
   3409         Intent intent = new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
   3410         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   3411         intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties));
   3412         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
   3413     }
   3414 
   3415     private void sendSupplicantConnectionChangedBroadcast(boolean connected) {
   3416         Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
   3417         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   3418         intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected);
   3419         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
   3420     }
   3421 
   3422     /**
   3423      * Record the detailed state of a network.
   3424      *
   3425      * @param state the new {@code DetailedState}
   3426      */
   3427     private boolean setNetworkDetailedState(NetworkInfo.DetailedState state) {
   3428         boolean hidden = false;
   3429 
   3430         if (linkDebouncing || isRoaming()) {
   3431             // There is generally a confusion in the system about colluding
   3432             // WiFi Layer 2 state (as reported by supplicant) and the Network state
   3433             // which leads to multiple confusion.
   3434             //
   3435             // If link is de-bouncing or roaming, we already have an IP address
   3436             // as well we were connected and are doing L2 cycles of
   3437             // reconnecting or renewing IP address to check that we still have it
   3438             // This L2 link flapping should ne be reflected into the Network state
   3439             // which is the state of the WiFi Network visible to Layer 3 and applications
   3440             // Note that once debouncing and roaming are completed, we will
   3441             // set the Network state to where it should be, or leave it as unchanged
   3442             //
   3443             hidden = true;
   3444         }
   3445         if (DBG) {
   3446             log("setDetailed state, old ="
   3447                     + mNetworkInfo.getDetailedState() + " and new state=" + state
   3448                     + " hidden=" + hidden);
   3449         }
   3450         if (mNetworkInfo.getExtraInfo() != null && mWifiInfo.getSSID() != null
   3451                 && !mWifiInfo.getSSID().equals(WifiSsid.NONE)) {
   3452             // Always indicate that SSID has changed
   3453             if (!mNetworkInfo.getExtraInfo().equals(mWifiInfo.getSSID())) {
   3454                 if (DBG) {
   3455                     log("setDetailed state send new extra info" + mWifiInfo.getSSID());
   3456                 }
   3457                 mNetworkInfo.setExtraInfo(mWifiInfo.getSSID());
   3458                 sendNetworkStateChangeBroadcast(null);
   3459             }
   3460         }
   3461         if (hidden == true) {
   3462             return false;
   3463         }
   3464 
   3465         if (state != mNetworkInfo.getDetailedState()) {
   3466             mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());
   3467             if (mNetworkAgent != null) {
   3468                 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
   3469             }
   3470             sendNetworkStateChangeBroadcast(null);
   3471             return true;
   3472         }
   3473         return false;
   3474     }
   3475 
   3476     private DetailedState getNetworkDetailedState() {
   3477         return mNetworkInfo.getDetailedState();
   3478     }
   3479 
   3480     private SupplicantState handleSupplicantStateChange(Message message) {
   3481         StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
   3482         SupplicantState state = stateChangeResult.state;
   3483         // Supplicant state change
   3484         // [31-13] Reserved for future use
   3485         // [8 - 0] Supplicant state (as defined in SupplicantState.java)
   3486         // 50023 supplicant_state_changed (custom|1|5)
   3487         mWifiInfo.setSupplicantState(state);
   3488         // If we receive a supplicant state change with an empty SSID,
   3489         // this implies that wpa_supplicant is already disconnected.
   3490         // We should pretend we are still connected when linkDebouncing is on.
   3491         if ((stateChangeResult.wifiSsid == null
   3492                 || stateChangeResult.wifiSsid.toString().isEmpty()) && linkDebouncing) {
   3493             return state;
   3494         }
   3495         // Network id is only valid when we start connecting
   3496         if (SupplicantState.isConnecting(state)) {
   3497             mWifiInfo.setNetworkId(stateChangeResult.networkId);
   3498         } else {
   3499             mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
   3500         }
   3501 
   3502         mWifiInfo.setBSSID(stateChangeResult.BSSID);
   3503 
   3504         if (mWhiteListedSsids != null
   3505                 && mWhiteListedSsids.length > 0
   3506                 && stateChangeResult.wifiSsid != null) {
   3507             String SSID = stateChangeResult.wifiSsid.toString();
   3508             String currentSSID = mWifiInfo.getSSID();
   3509             if (SSID != null && currentSSID != null && !SSID.equals(WifiSsid.NONE)) {
   3510                 // Remove quote before comparing
   3511                 if (SSID.length() >= 2 && SSID.charAt(0) == '"'
   3512                         && SSID.charAt(SSID.length() - 1) == '"') {
   3513                     SSID = SSID.substring(1, SSID.length() - 1);
   3514                 }
   3515                 if (currentSSID.length() >= 2 && currentSSID.charAt(0) == '"'
   3516                         && currentSSID.charAt(currentSSID.length() - 1) == '"') {
   3517                     currentSSID = currentSSID.substring(1, currentSSID.length() - 1);
   3518                 }
   3519                 if ((!SSID.equals(currentSSID)) && (getCurrentState() == mConnectedState)) {
   3520                     lastConnectAttemptTimestamp = System.currentTimeMillis();
   3521                     targetWificonfiguration =
   3522                             mWifiConfigManager.getWifiConfiguration(mWifiInfo.getNetworkId());
   3523                     transitionTo(mRoamingState);
   3524                 }
   3525             }
   3526         }
   3527 
   3528         mWifiInfo.setSSID(stateChangeResult.wifiSsid);
   3529         mWifiInfo.setEphemeral(mWifiConfigManager.isEphemeral(mWifiInfo.getNetworkId()));
   3530         if (!mWifiInfo.getMeteredHint()) { // don't override the value if already set.
   3531             mWifiInfo.setMeteredHint(mWifiConfigManager.getMeteredHint(mWifiInfo.getNetworkId()));
   3532         }
   3533 
   3534         mSupplicantStateTracker.sendMessage(Message.obtain(message));
   3535 
   3536         return state;
   3537     }
   3538 
   3539     /**
   3540      * Resets the Wi-Fi Connections by clearing any state, resetting any sockets
   3541      * using the interface, stopping DHCP & disabling interface
   3542      */
   3543     private void handleNetworkDisconnect() {
   3544         if (DBG) log("handleNetworkDisconnect: Stopping DHCP and clearing IP"
   3545                 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
   3546                 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName()
   3547                 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
   3548                 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
   3549 
   3550         stopRssiMonitoringOffload();
   3551 
   3552         clearCurrentConfigBSSID("handleNetworkDisconnect");
   3553 
   3554         stopIpManager();
   3555 
   3556         /* Reset data structures */
   3557         mWifiScoreReport = null;
   3558         mWifiInfo.reset();
   3559         linkDebouncing = false;
   3560         /* Reset roaming parameters */
   3561         mAutoRoaming = false;
   3562 
   3563         setNetworkDetailedState(DetailedState.DISCONNECTED);
   3564         if (mNetworkAgent != null) {
   3565             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
   3566             mNetworkAgent = null;
   3567         }
   3568         mWifiConfigManager.updateStatus(mLastNetworkId, DetailedState.DISCONNECTED);
   3569 
   3570         /* Clear network properties */
   3571         clearLinkProperties();
   3572 
   3573         /* Cend event to CM & network change broadcast */
   3574         sendNetworkStateChangeBroadcast(mLastBssid);
   3575 
   3576         /* Cancel auto roam requests */
   3577         autoRoamSetBSSID(mLastNetworkId, "any");
   3578         mLastBssid = null;
   3579         registerDisconnected();
   3580         mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
   3581     }
   3582 
   3583     private void handleSupplicantConnectionLoss(boolean killSupplicant) {
   3584         /* Socket connection can be lost when we do a graceful shutdown
   3585         * or when the driver is hung. Ensure supplicant is stopped here.
   3586         */
   3587         if (killSupplicant) {
   3588             mWifiMonitor.killSupplicant(mP2pSupported);
   3589         }
   3590         mWifiNative.closeSupplicantConnection();
   3591         sendSupplicantConnectionChangedBroadcast(false);
   3592         setWifiState(WIFI_STATE_DISABLED);
   3593     }
   3594 
   3595     void handlePreDhcpSetup() {
   3596         if (!mBluetoothConnectionActive) {
   3597             /*
   3598              * There are problems setting the Wi-Fi driver's power
   3599              * mode to active when bluetooth coexistence mode is
   3600              * enabled or sense.
   3601              * <p>
   3602              * We set Wi-Fi to active mode when
   3603              * obtaining an IP address because we've found
   3604              * compatibility issues with some routers with low power
   3605              * mode.
   3606              * <p>
   3607              * In order for this active power mode to properly be set,
   3608              * we disable coexistence mode until we're done with
   3609              * obtaining an IP address.  One exception is if we
   3610              * are currently connected to a headset, since disabling
   3611              * coexistence would interrupt that connection.
   3612              */
   3613             // Disable the coexistence mode
   3614             mWifiNative.setBluetoothCoexistenceMode(
   3615                     mWifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
   3616         }
   3617 
   3618         // Disable power save and suspend optimizations during DHCP
   3619         // Note: The order here is important for now. Brcm driver changes
   3620         // power settings when we control suspend mode optimizations.
   3621         // TODO: Remove this comment when the driver is fixed.
   3622         setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false);
   3623         mWifiNative.setPowerSave(false);
   3624 
   3625         // Update link layer stats
   3626         getWifiLinkLayerStats(false);
   3627 
   3628         /* P2p discovery breaks dhcp, shut it down in order to get through this */
   3629         Message msg = new Message();
   3630         msg.what = WifiP2pServiceImpl.BLOCK_DISCOVERY;
   3631         msg.arg1 = WifiP2pServiceImpl.ENABLED;
   3632         msg.arg2 = DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE;
   3633         msg.obj = WifiStateMachine.this;
   3634         mWifiP2pChannel.sendMessage(msg);
   3635     }
   3636 
   3637     void handlePostDhcpSetup() {
   3638         /* Restore power save and suspend optimizations */
   3639         setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true);
   3640         mWifiNative.setPowerSave(true);
   3641 
   3642         mWifiP2pChannel.sendMessage(WifiP2pServiceImpl.BLOCK_DISCOVERY,
   3643                 WifiP2pServiceImpl.DISABLED);
   3644 
   3645         // Set the coexistence mode back to its default value
   3646         mWifiNative.setBluetoothCoexistenceMode(
   3647                 mWifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE);
   3648     }
   3649 
   3650     /**
   3651      * Inform other components (WifiMetrics, WifiLogger, etc.) that the current connection attempt
   3652      * has concluded.
   3653      */
   3654     private void reportConnectionAttemptEnd(int level2FailureCode, int connectivityFailureCode) {
   3655         mWifiMetrics.endConnectionEvent(level2FailureCode, connectivityFailureCode);
   3656         switch (level2FailureCode) {
   3657             case WifiMetrics.ConnectionEvent.FAILURE_NONE:
   3658             case WifiMetrics.ConnectionEvent.FAILURE_REDUNDANT_CONNECTION_ATTEMPT:
   3659                 // WifiLogger doesn't care about success, or pre-empted connections.
   3660                 break;
   3661             default:
   3662                 mWifiLogger.reportConnectionFailure();
   3663         }
   3664     }
   3665 
   3666     private void handleIPv4Success(DhcpResults dhcpResults) {
   3667         if (DBG) {
   3668             logd("handleIPv4Success <" + dhcpResults.toString() + ">");
   3669             logd("link address " + dhcpResults.ipAddress);
   3670         }
   3671 
   3672         Inet4Address addr;
   3673         synchronized (mDhcpResultsLock) {
   3674             mDhcpResults = dhcpResults;
   3675             addr = (Inet4Address) dhcpResults.ipAddress.getAddress();
   3676         }
   3677 
   3678         if (isRoaming()) {
   3679             int previousAddress = mWifiInfo.getIpAddress();
   3680             int newAddress = NetworkUtils.inetAddressToInt(addr);
   3681             if (previousAddress != newAddress) {
   3682                 logd("handleIPv4Success, roaming and address changed" +
   3683                         mWifiInfo + " got: " + addr);
   3684             }
   3685         }
   3686         mWifiInfo.setInetAddress(addr);
   3687         if (!mWifiInfo.getMeteredHint()) { // don't override the value if already set.
   3688             mWifiInfo.setMeteredHint(dhcpResults.hasMeteredHint());
   3689             updateCapabilities(getCurrentWifiConfiguration());
   3690         }
   3691     }
   3692 
   3693     private void handleSuccessfulIpConfiguration() {
   3694         mLastSignalLevel = -1; // Force update of signal strength
   3695         WifiConfiguration c = getCurrentWifiConfiguration();
   3696         if (c != null) {
   3697             // Reset IP failure tracking
   3698             c.getNetworkSelectionStatus().clearDisableReasonCounter(
   3699                     WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE);
   3700 
   3701             // Tell the framework whether the newly connected network is trusted or untrusted.
   3702             updateCapabilities(c);
   3703         }
   3704         if (c != null) {
   3705             ScanResult result = getCurrentScanResult();
   3706             if (result == null) {
   3707                 logd("WifiStateMachine: handleSuccessfulIpConfiguration and no scan results" +
   3708                         c.configKey());
   3709             } else {
   3710                 // Clear the per BSSID failure count
   3711                 result.numIpConfigFailures = 0;
   3712                 // Clear the WHOLE BSSID blacklist, which means supplicant is free to retry
   3713                 // any BSSID, even though it may already have a non zero ip failure count,
   3714                 // this will typically happen if the user walks away and come back to his arrea
   3715                 // TODO: implement blacklisting based on a timer, i.e. keep BSSID blacklisted
   3716                 // in supplicant for a couple of hours or a day
   3717                 mWifiConfigManager.clearBssidBlacklist();
   3718             }
   3719         }
   3720     }
   3721 
   3722     private void handleIPv4Failure() {
   3723         // TODO: Move this to provisioning failure, not DHCP failure.
   3724         // DHCPv4 failure is expected on an IPv6-only network.
   3725         mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_DHCP_FAILURE);
   3726         if (DBG) {
   3727             int count = -1;
   3728             WifiConfiguration config = getCurrentWifiConfiguration();
   3729             if (config != null) {
   3730                 count = config.getNetworkSelectionStatus().getDisableReasonCounter(
   3731                         WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE);
   3732             }
   3733             log("DHCP failure count=" + count);
   3734         }
   3735         reportConnectionAttemptEnd(
   3736                 WifiMetrics.ConnectionEvent.FAILURE_DHCP,
   3737                 WifiMetricsProto.ConnectionEvent.HLF_DHCP);
   3738         synchronized(mDhcpResultsLock) {
   3739              if (mDhcpResults != null) {
   3740                  mDhcpResults.clear();
   3741              }
   3742         }
   3743         if (DBG) {
   3744             logd("handleIPv4Failure");
   3745         }
   3746     }
   3747 
   3748     private void handleIpConfigurationLost() {
   3749         mWifiInfo.setInetAddress(null);
   3750         mWifiInfo.setMeteredHint(false);
   3751 
   3752         mWifiConfigManager.updateNetworkSelectionStatus(mLastNetworkId,
   3753                 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE);
   3754 
   3755         /* DHCP times out after about 30 seconds, we do a
   3756          * disconnect thru supplicant, we will let autojoin retry connecting to the network
   3757          */
   3758         mWifiNative.disconnect();
   3759     }
   3760 
   3761     // TODO: De-duplicated this and handleIpConfigurationLost().
   3762     private void handleIpReachabilityLost() {
   3763         mWifiInfo.setInetAddress(null);
   3764         mWifiInfo.setMeteredHint(false);
   3765 
   3766         // TODO: Determine whether to call some form of mWifiConfigManager.handleSSIDStateChange().
   3767 
   3768         // Disconnect via supplicant, and let autojoin retry connecting to the network.
   3769         mWifiNative.disconnect();
   3770     }
   3771 
   3772     private int convertFrequencyToChannelNumber(int frequency) {
   3773         if (frequency >= 2412 && frequency <= 2484) {
   3774             return (frequency -2412) / 5 + 1;
   3775         } else if (frequency >= 5170  &&  frequency <=5825) {
   3776             //DFS is included
   3777             return (frequency -5170) / 5 + 34;
   3778         } else {
   3779             return 0;
   3780         }
   3781     }
   3782 
   3783     private int chooseApChannel(int apBand) {
   3784         int apChannel;
   3785         int[] channel;
   3786 
   3787         if (apBand == 0)  {
   3788             ArrayList<Integer> allowed2GChannel =
   3789                     mWifiApConfigStore.getAllowed2GChannel();
   3790             if (allowed2GChannel == null || allowed2GChannel.size() == 0) {
   3791                 //most safe channel to use
   3792                 if (DBG) {
   3793                     Log.d(TAG, "No specified 2G allowed channel list");
   3794                 }
   3795                 apChannel = 6;
   3796             } else {
   3797                 int index = mRandom.nextInt(allowed2GChannel.size());
   3798                 apChannel = allowed2GChannel.get(index).intValue();
   3799             }
   3800         } else {
   3801             //5G without DFS
   3802             channel = mWifiNative.getChannelsForBand(2);
   3803             if (channel != null && channel.length > 0) {
   3804                 apChannel = channel[mRandom.nextInt(channel.length)];
   3805                 apChannel = convertFrequencyToChannelNumber(apChannel);
   3806             } else {
   3807                 Log.e(TAG, "SoftAp do not get available channel list");
   3808                 apChannel = 0;
   3809             }
   3810         }
   3811 
   3812         if (DBG) {
   3813             Log.d(TAG, "SoftAp set on channel " + apChannel);
   3814         }
   3815 
   3816         return apChannel;
   3817     }
   3818 
   3819     /* Driver/firmware setup for soft AP. */
   3820     private boolean setupDriverForSoftAp() {
   3821         if (!mWifiNative.loadDriver()) {
   3822             Log.e(TAG, "Failed to load driver for softap");
   3823             return false;
   3824         }
   3825 
   3826         int index = mWifiNative.queryInterfaceIndex(mInterfaceName);
   3827         if (index != -1) {
   3828             if (!mWifiNative.setInterfaceUp(false)) {
   3829                 Log.e(TAG, "toggleInterface failed");
   3830                 return false;
   3831             }
   3832         } else {
   3833             if (DBG) Log.d(TAG, "No interfaces to bring down");
   3834         }
   3835 
   3836         try {
   3837             mNwService.wifiFirmwareReload(mInterfaceName, "AP");
   3838             if (DBG) Log.d(TAG, "Firmware reloaded in AP mode");
   3839         } catch (Exception e) {
   3840             Log.e(TAG, "Failed to reload AP firmware " + e);
   3841         }
   3842 
   3843         if (!mWifiNative.startHal()) {
   3844             /* starting HAL is optional */
   3845             Log.e(TAG, "Failed to start HAL");
   3846         }
   3847         return true;
   3848     }
   3849 
   3850     private byte[] macAddressFromString(String macString) {
   3851         String[] macBytes = macString.split(":");
   3852         if (macBytes.length != 6) {
   3853             throw new IllegalArgumentException("MAC address should be 6 bytes long!");
   3854         }
   3855         byte[] mac = new byte[6];
   3856         for (int i = 0; i < macBytes.length; i++) {
   3857             Integer hexVal = Integer.parseInt(macBytes[i], 16);
   3858             mac[i] = hexVal.byteValue();
   3859         }
   3860         return mac;
   3861     }
   3862 
   3863     /*
   3864      * Read a MAC address in /proc/arp/table, used by WifistateMachine
   3865      * so as to record MAC address of default gateway.
   3866      **/
   3867     private String macAddressFromRoute(String ipAddress) {
   3868         String macAddress = null;
   3869         BufferedReader reader = null;
   3870         try {
   3871             reader = new BufferedReader(new FileReader("/proc/net/arp"));
   3872 
   3873             // Skip over the line bearing colum titles
   3874             String line = reader.readLine();
   3875 
   3876             while ((line = reader.readLine()) != null) {
   3877                 String[] tokens = line.split("[ ]+");
   3878                 if (tokens.length < 6) {
   3879                     continue;
   3880                 }
   3881 
   3882                 // ARP column format is
   3883                 // Address HWType HWAddress Flags Mask IFace
   3884                 String ip = tokens[0];
   3885                 String mac = tokens[3];
   3886 
   3887                 if (ipAddress.equals(ip)) {
   3888                     macAddress = mac;
   3889                     break;
   3890                 }
   3891             }
   3892 
   3893             if (macAddress == null) {
   3894                 loge("Did not find remoteAddress {" + ipAddress + "} in " +
   3895                         "/proc/net/arp");
   3896             }
   3897 
   3898         } catch (FileNotFoundException e) {
   3899             loge("Could not open /proc/net/arp to lookup mac address");
   3900         } catch (IOException e) {
   3901             loge("Could not read /proc/net/arp to lookup mac address");
   3902         } finally {
   3903             try {
   3904                 if (reader != null) {
   3905                     reader.close();
   3906                 }
   3907             } catch (IOException e) {
   3908                 // Do nothing
   3909             }
   3910         }
   3911         return macAddress;
   3912 
   3913     }
   3914 
   3915     private class WifiNetworkFactory extends NetworkFactory {
   3916         public WifiNetworkFactory(Looper l, Context c, String TAG, NetworkCapabilities f) {
   3917             super(l, c, TAG, f);
   3918         }
   3919 
   3920         @Override
   3921         protected void needNetworkFor(NetworkRequest networkRequest, int score) {
   3922             ++mConnectionRequests;
   3923         }
   3924 
   3925         @Override
   3926         protected void releaseNetworkFor(NetworkRequest networkRequest) {
   3927             --mConnectionRequests;
   3928         }
   3929 
   3930         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   3931             pw.println("mConnectionRequests " + mConnectionRequests);
   3932         }
   3933 
   3934     }
   3935 
   3936     private class UntrustedWifiNetworkFactory extends NetworkFactory {
   3937         private int mUntrustedReqCount;
   3938 
   3939         public UntrustedWifiNetworkFactory(Looper l, Context c, String tag, NetworkCapabilities f) {
   3940             super(l, c, tag, f);
   3941         }
   3942 
   3943         @Override
   3944         protected void needNetworkFor(NetworkRequest networkRequest, int score) {
   3945             if (!networkRequest.networkCapabilities.hasCapability(
   3946                     NetworkCapabilities.NET_CAPABILITY_TRUSTED)) {
   3947                 if (++mUntrustedReqCount == 1) {
   3948                     if (mWifiConnectivityManager != null) {
   3949                         mWifiConnectivityManager.setUntrustedConnectionAllowed(true);
   3950                     }
   3951                 }
   3952             }
   3953         }
   3954 
   3955         @Override
   3956         protected void releaseNetworkFor(NetworkRequest networkRequest) {
   3957             if (!networkRequest.networkCapabilities.hasCapability(
   3958                     NetworkCapabilities.NET_CAPABILITY_TRUSTED)) {
   3959                 if (--mUntrustedReqCount == 0) {
   3960                     if (mWifiConnectivityManager != null) {
   3961                         mWifiConnectivityManager.setUntrustedConnectionAllowed(false);
   3962                     }
   3963                 }
   3964             }
   3965         }
   3966 
   3967         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   3968             pw.println("mUntrustedReqCount " + mUntrustedReqCount);
   3969         }
   3970     }
   3971 
   3972     void maybeRegisterNetworkFactory() {
   3973         if (mNetworkFactory == null) {
   3974             checkAndSetConnectivityInstance();
   3975             if (mCm != null) {
   3976                 mNetworkFactory = new WifiNetworkFactory(getHandler().getLooper(), mContext,
   3977                         NETWORKTYPE, mNetworkCapabilitiesFilter);
   3978                 mNetworkFactory.setScoreFilter(60);
   3979                 mNetworkFactory.register();
   3980 
   3981                 // We can't filter untrusted network in the capabilities filter because a trusted
   3982                 // network would still satisfy a request that accepts untrusted ones.
   3983                 mUntrustedNetworkFactory = new UntrustedWifiNetworkFactory(getHandler().getLooper(),
   3984                         mContext, NETWORKTYPE_UNTRUSTED, mNetworkCapabilitiesFilter);
   3985                 mUntrustedNetworkFactory.setScoreFilter(Integer.MAX_VALUE);
   3986                 mUntrustedNetworkFactory.register();
   3987             }
   3988         }
   3989     }
   3990 
   3991     /********************************************************
   3992      * HSM states
   3993      *******************************************************/
   3994 
   3995     class DefaultState extends State {
   3996         @Override
   3997         public boolean processMessage(Message message) {
   3998             logStateAndMessage(message, this);
   3999 
   4000             switch (message.what) {
   4001                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
   4002                     AsyncChannel ac = (AsyncChannel) message.obj;
   4003                     if (ac == mWifiP2pChannel) {
   4004                         if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
   4005                             mWifiP2pChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
   4006                         } else {
   4007                             loge("WifiP2pService connection failure, error=" + message.arg1);
   4008                         }
   4009                     } else {
   4010                         loge("got HALF_CONNECTED for unknown channel");
   4011                     }
   4012                     break;
   4013                 }
   4014                 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
   4015                     AsyncChannel ac = (AsyncChannel) message.obj;
   4016                     if (ac == mWifiP2pChannel) {
   4017                         loge("WifiP2pService channel lost, message.arg1 =" + message.arg1);
   4018                         //TODO: Re-establish connection to state machine after a delay
   4019                         // mWifiP2pChannel.connect(mContext, getHandler(),
   4020                         // mWifiP2pManager.getMessenger());
   4021                     }
   4022                     break;
   4023                 }
   4024                 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE:
   4025                     mBluetoothConnectionActive = (message.arg1 !=
   4026                             BluetoothAdapter.STATE_DISCONNECTED);
   4027                     break;
   4028                     /* Synchronous call returns */
   4029                 case CMD_PING_SUPPLICANT:
   4030                 case CMD_ENABLE_NETWORK:
   4031                 case CMD_ADD_OR_UPDATE_NETWORK:
   4032                 case CMD_REMOVE_NETWORK:
   4033                 case CMD_SAVE_CONFIG:
   4034                     replyToMessage(message, message.what, FAILURE);
   4035                     break;
   4036                 case CMD_GET_CAPABILITY_FREQ:
   4037                     replyToMessage(message, message.what, null);
   4038                     break;
   4039                 case CMD_GET_CONFIGURED_NETWORKS:
   4040                     replyToMessage(message, message.what, (List<WifiConfiguration>) null);
   4041                     break;
   4042                 case CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS:
   4043                     replyToMessage(message, message.what, (List<WifiConfiguration>) null);
   4044                     break;
   4045                 case CMD_ENABLE_RSSI_POLL:
   4046                     mEnableRssiPolling = (message.arg1 == 1);
   4047                     break;
   4048                 case CMD_SET_HIGH_PERF_MODE:
   4049                     if (message.arg1 == 1) {
   4050                         setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, false);
   4051                     } else {
   4052                         setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, true);
   4053                     }
   4054                     break;
   4055                 case CMD_BOOT_COMPLETED:
   4056                     maybeRegisterNetworkFactory();
   4057                     break;
   4058                 case CMD_SCREEN_STATE_CHANGED:
   4059                     handleScreenStateChanged(message.arg1 != 0);
   4060                     break;
   4061                     /* Discard */
   4062                 case CMD_START_SCAN:
   4063                     messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
   4064                     break;
   4065                 case CMD_START_SUPPLICANT:
   4066                 case CMD_STOP_SUPPLICANT:
   4067                 case CMD_STOP_SUPPLICANT_FAILED:
   4068                 case CMD_START_DRIVER:
   4069                 case CMD_STOP_DRIVER:
   4070                 case CMD_DRIVER_START_TIMED_OUT:
   4071                 case CMD_START_AP:
   4072                 case CMD_START_AP_FAILURE:
   4073                 case CMD_STOP_AP:
   4074                 case CMD_AP_STOPPED:
   4075                 case CMD_DISCONNECT:
   4076                 case CMD_RECONNECT:
   4077                 case CMD_REASSOCIATE:
   4078                 case CMD_RELOAD_TLS_AND_RECONNECT:
   4079                 case WifiMonitor.SUP_CONNECTION_EVENT:
   4080                 case WifiMonitor.SUP_DISCONNECTION_EVENT:
   4081                 case WifiMonitor.NETWORK_CONNECTION_EVENT:
   4082                 case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
   4083                 case WifiMonitor.SCAN_RESULTS_EVENT:
   4084                 case WifiMonitor.SCAN_FAILED_EVENT:
   4085                 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
   4086                 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
   4087                 case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
   4088                 case WifiMonitor.WPS_OVERLAP_EVENT:
   4089                 case CMD_BLACKLIST_NETWORK:
   4090                 case CMD_CLEAR_BLACKLIST:
   4091                 case CMD_SET_OPERATIONAL_MODE:
   4092                 case CMD_SET_FREQUENCY_BAND:
   4093                 case CMD_RSSI_POLL:
   4094                 case CMD_ENABLE_ALL_NETWORKS:
   4095                 case DhcpClient.CMD_PRE_DHCP_ACTION:
   4096                 case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE:
   4097                 case DhcpClient.CMD_POST_DHCP_ACTION:
   4098                 case CMD_NO_NETWORKS_PERIODIC_SCAN:
   4099                 case CMD_DISABLE_P2P_RSP:
   4100                 case WifiMonitor.SUP_REQUEST_IDENTITY:
   4101                 case CMD_TEST_NETWORK_DISCONNECT:
   4102                 case CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER:
   4103                 case WifiMonitor.SUP_REQUEST_SIM_AUTH:
   4104                 case CMD_TARGET_BSSID:
   4105                 case CMD_AUTO_CONNECT:
   4106                 case CMD_AUTO_ROAM:
   4107                 case CMD_AUTO_SAVE_NETWORK:
   4108                 case CMD_ASSOCIATED_BSSID:
   4109                 case CMD_UNWANTED_NETWORK:
   4110                 case CMD_DISCONNECTING_WATCHDOG_TIMER:
   4111                 case CMD_ROAM_WATCHDOG_TIMER:
   4112                 case CMD_DISABLE_EPHEMERAL_NETWORK:
   4113                 case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION:
   4114                     messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
   4115                     break;
   4116                 case CMD_SET_SUSPEND_OPT_ENABLED:
   4117                     if (message.arg1 == 1) {
   4118                         if (message.arg2 == 1) {
   4119                             mSuspendWakeLock.release();
   4120                         }
   4121                         setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, true);
   4122                     } else {
   4123                         setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, false);
   4124                     }
   4125                     break;
   4126                 case WifiMonitor.DRIVER_HUNG_EVENT:
   4127                     setSupplicantRunning(false);
   4128                     setSupplicantRunning(true);
   4129                     break;
   4130                 case WifiManager.CONNECT_NETWORK:
   4131                     replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED,
   4132                             WifiManager.BUSY);
   4133                     break;
   4134                 case WifiManager.FORGET_NETWORK:
   4135                     replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED,
   4136                             WifiManager.BUSY);
   4137                     break;
   4138                 case WifiManager.SAVE_NETWORK:
   4139                     messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL;
   4140                     replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED,
   4141                             WifiManager.BUSY);
   4142                     break;
   4143                 case WifiManager.START_WPS:
   4144                     replyToMessage(message, WifiManager.WPS_FAILED,
   4145                             WifiManager.BUSY);
   4146                     break;
   4147                 case WifiManager.CANCEL_WPS:
   4148                     replyToMessage(message, WifiManager.CANCEL_WPS_FAILED,
   4149                             WifiManager.BUSY);
   4150                     break;
   4151                 case WifiManager.DISABLE_NETWORK:
   4152                     replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED,
   4153                             WifiManager.BUSY);
   4154                     break;
   4155                 case WifiManager.RSSI_PKTCNT_FETCH:
   4156                     replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_FAILED,
   4157                             WifiManager.BUSY);
   4158                     break;
   4159                 case CMD_GET_SUPPORTED_FEATURES:
   4160                     int featureSet = mWifiNative.getSupportedFeatureSet();
   4161                     replyToMessage(message, message.what, featureSet);
   4162                     break;
   4163                 case CMD_FIRMWARE_ALERT:
   4164                     if (mWifiLogger != null) {
   4165                         byte[] buffer = (byte[])message.obj;
   4166                         mWifiLogger.captureAlertData(message.arg1, buffer);
   4167                     }
   4168                     break;
   4169                 case CMD_GET_LINK_LAYER_STATS:
   4170                     // Not supported hence reply with error message
   4171                     replyToMessage(message, message.what, null);
   4172                     break;
   4173                 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED:
   4174                     NetworkInfo info = (NetworkInfo) message.obj;
   4175                     mP2pConnected.set(info.isConnected());
   4176                     break;
   4177                 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST:
   4178                     mTemporarilyDisconnectWifi = (message.arg1 == 1);
   4179                     replyToMessage(message, WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE);
   4180                     break;
   4181                 /* Link configuration (IP address, DNS, ...) changes notified via netlink */
   4182                 case CMD_UPDATE_LINKPROPERTIES:
   4183                     updateLinkProperties((LinkProperties) message.obj);
   4184                     break;
   4185                 case CMD_GET_MATCHING_CONFIG:
   4186                     replyToMessage(message, message.what);
   4187                     break;
   4188                 case CMD_IP_CONFIGURATION_SUCCESSFUL:
   4189                 case CMD_IP_CONFIGURATION_LOST:
   4190                 case CMD_IP_REACHABILITY_LOST:
   4191                     messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
   4192                     break;
   4193                 case CMD_GET_CONNECTION_STATISTICS:
   4194                     replyToMessage(message, message.what, mWifiConnectionStatistics);
   4195                     break;
   4196                 case CMD_REMOVE_APP_CONFIGURATIONS:
   4197                     deferMessage(message);
   4198                     break;
   4199                 case CMD_REMOVE_USER_CONFIGURATIONS:
   4200                     deferMessage(message);
   4201                     break;
   4202                 case CMD_START_IP_PACKET_OFFLOAD:
   4203                     if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent(
   4204                             message.arg1,
   4205                             ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
   4206                     break;
   4207                 case CMD_STOP_IP_PACKET_OFFLOAD:
   4208                     if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent(
   4209                             message.arg1,
   4210                             ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
   4211                     break;
   4212                 case CMD_START_RSSI_MONITORING_OFFLOAD:
   4213