(90) Android O combing WIFI DHCP process with WiFi state machine

Keywords: network DNS Mac Android

Preface: before (87) WiFi & DHCP Combing the DHCP process, now combing the next process with WiFi state machine.

 

Preparatory work: grab the log from Xiaomi mix2 8.0 WiFi state machine to the beginning of ObtainingIpState and the end of ConnectedState.

09-01 21:09:28.135  1561  2457 D WifiStateMachine: enter ObtainingIpState netId=16 "jiatai 5G"-WPA_PSK  roam=false static=false
09-01 21:09:28.135  1561  2457 D WifiStateMachine: setDetailed state, old =CONNECTING and new state=OBTAINING_IPADDR hidden=false
09-01 21:09:28.136  1561  2457 D WifiStateMachine: ObtainingIpAddress clearTargetBssid any key="jiatai 5G"-WPA_PSK
09-01 21:09:28.137  1561  2457 D WifiStateMachine: setSuspendOptimizationsNative: 1 true -want true stack:setSuspendOptimizationsNative - handlePostDhcpSetup - stopIpManager - -wrap48
09-01 21:09:28.142  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_GET_CONFIGURED_NETWORKS uid=1000 rt=411753411/1208576024 1000 0 num=13
09-01 21:09:28.142  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_GET_CONFIGURED_NETWORKS uid=1000 rt=411753411/1208576024 1000 0 num=13
09-01 21:09:28.142  1561  2457 D WifiStateMachine:  ConnectModeState !CMD_GET_CONFIGURED_NETWORKS uid=1000 rt=411753411/1208576024 1000 0 num=13
09-01 21:09:28.142  1561  2457 D WifiStateMachine:  SupplicantStartedState !CMD_GET_CONFIGURED_NETWORKS uid=1000 rt=411753411/1208576024 1000 0 num=13
09-01 21:09:28.142  1561  2457 D WifiStateMachine:  DefaultState !CMD_GET_CONFIGURED_NETWORKS uid=1000 rt=411753411/1208576024 1000 0 num=13
09-01 21:09:28.143  1561  2457 D WifiStateMachine:  ObtainingIpState !SUPPLICANT_STATE_CHANGE_EVENT rt=411753412/1208576025 0 0 SSID: jiatai 5G BSSID: 20:6b:e7:93:84:f9 nid: 16 state: COMPLETED
09-01 21:09:28.143  1561  2457 D WifiStateMachine:  L2ConnectedState !SUPPLICANT_STATE_CHANGE_EVENT rt=411753412/1208576025 0 0 SSID: jiatai 5G BSSID: 20:6b:e7:93:84:f9 nid: 16 state: COMPLETED
09-01 21:09:28.143  1561  2457 D WifiStateMachine:  ConnectModeState !SUPPLICANT_STATE_CHANGE_EVENT rt=411753412/1208576025 0 0 SSID: jiatai 5G BSSID: 20:6b:e7:93:84:f9 nid: 16 state: COMPLETED
09-01 21:09:28.143  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_RSSI_POLL rt=411753412/1208576025 1332 0 "jiatai 5G" 20:6b:e7:93:84:f9 rssi=-127 f=-1 sc=0 link=-1 tx=795242.0, 0.0, 0.0  rx=1663737.8 bcn=2413 [on:0 tx:0 rx:0 period:4689] from screen [on:0 period:1033485890]
09-01 21:09:28.143  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_RSSI_POLL rt=411753412/1208576025 1332 0 "jiatai 5G" 20:6b:e7:93:84:f9 rssi=-127 f=-1 sc=0 link=-1 tx=795242.0, 0.0, 0.0  rx=1663737.8 bcn=2413 [on:0 tx:0 rx:0 period:0] from screen [on:0 period:1033485890]
09-01 21:09:28.143  1561  2457 D WifiStateMachine:  get link layer stats 0
09-01 21:09:28.145  1561  2457 D WifiStateMachine: fetchRssiLinkSpeedAndFrequencyNative rssi=-42 linkspeed=866 freq=5765
09-01 21:09:28.146  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_CONFIG_ND_OFFLOAD rt=411753415/1208576029 1 0
09-01 21:09:28.146  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_CONFIG_ND_OFFLOAD rt=411753415/1208576029 1 0
09-01 21:09:28.146  1561  2457 D WifiStateMachine:  ConnectModeState !CMD_CONFIG_ND_OFFLOAD rt=411753416/1208576029 1 0
09-01 21:09:28.146  1561  2457 D WifiStateMachine:  SupplicantStartedState !CMD_CONFIG_ND_OFFLOAD rt=411753416/1208576029 1 0
09-01 21:09:28.147  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_SET_FALLBACK_PACKET_FILTERING rt=411753416/1208576029 enabled=true
09-01 21:09:28.147  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_SET_FALLBACK_PACKET_FILTERING rt=411753416/1208576029 enabled=true
09-01 21:09:28.147  1561  2457 D WifiStateMachine:  ConnectModeState !CMD_SET_FALLBACK_PACKET_FILTERING rt=411753416/1208576029 enabled=true
09-01 21:09:28.147  1561  2457 D WifiStateMachine:  SupplicantStartedState !CMD_SET_FALLBACK_PACKET_FILTERING rt=411753416/1208576029 enabled=true
09-01 21:09:28.147  1561  2457 D WifiStateMachine:  DefaultState !CMD_SET_FALLBACK_PACKET_FILTERING rt=411753416/1208576029 enabled=true
09-01 21:09:28.149  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_UPDATE_LINKPROPERTIES rt=411753418/1208576032 0 0 
09-01 21:09:28.149  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_UPDATE_LINKPROPERTIES rt=411753418/1208576032 0 0 
09-01 21:09:28.149  1561  2457 D WifiStateMachine:  ConnectModeState !CMD_UPDATE_LINKPROPERTIES rt=411753418/1208576032 0 0 
09-01 21:09:28.149  1561  2457 D WifiStateMachine:  SupplicantStartedState !CMD_UPDATE_LINKPROPERTIES rt=411753418/1208576032 0 0 
09-01 21:09:28.149  1561  2457 D WifiStateMachine:  DefaultState !CMD_UPDATE_LINKPROPERTIES rt=411753418/1208576032 0 0 
09-01 21:09:28.149  1561  2457 D WifiStateMachine: Link configuration changed for netId: 16 old: {LinkAddresses: []  Routes: [] DnsAddresses: [] Domains: null MTU: 0} new: {InterfaceName: wlan0 LinkAddresses: [fe80::e646:daff:fe6b:f550/64,]  Routes: [fe80::/64 -> :: wlan0,] DnsAddresses: [] Domains: null MTU: 0 TcpBufferSizes: 524288,1048576,5505024,262144,524288,5505024}
09-01 21:09:28.150  1561  2457 D WifiStateMachine: updateLinkProperties nid: 16 state: OBTAINING_IPADDR 
09-01 21:09:28.151  1561  4875 D DhcpClient: Receive thread started
09-01 21:09:28.151  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_PRE_DHCP_ACTION rt=411753420/1208576033 0 0 txpkts=3180968,0,0
09-01 21:09:28.151  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_PRE_DHCP_ACTION rt=411753420/1208576033 0 0 txpkts=3180968,0,0
09-01 21:09:28.151  1561  2457 D WifiStateMachine: setSuspendOptimizationsNative: 1 false -want true stack:setSuspendOptimizationsNative - handlePreDhcpSetup - processMessage - processMsg
09-01 21:09:28.153  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_PRE_DHCP_ACTION_COMPLETE rt=411753422/1208576035 0 0
09-01 21:09:28.153  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_PRE_DHCP_ACTION_COMPLETE rt=411753422/1208576035 0 0
09-01 21:09:28.153  1561  4872 D DhcpClient: Broadcasting DHCPDISCOVER
09-01 21:09:28.157  1561  4875 D DhcpClient: Received packet: e4:46:da:6b:f5:50 OFFER, ip /192.168.0.105, mask /255.255.255.0, DNS servers: /192.168.0.1 , gateways [/192.168.0.1] lease time 7200, domain null
09-01 21:09:28.158  1561  4872 D DhcpClient: Got pending lease: IP address 192.168.0.105/24 Gateway 192.168.0.1  DNS servers: [ 192.168.0.1 ] Domains  DHCP server /192.168.0.1 Vendor info null lease 7200 seconds
09-01 21:09:28.158  1561  4872 D DhcpClient: Broadcasting DHCPREQUEST ciaddr=0.0.0.0 request=192.168.0.105 serverid=192.168.0.1
09-01 21:09:28.162  1561  4875 D DhcpClient: Received packet: e4:46:da:6b:f5:50 ACK: your new IP /192.168.0.105, netmask /255.255.255.0, gateways [/192.168.0.1] DNS servers: /192.168.0.1 , lease time 7200
09-01 21:09:28.162  1561  4872 D DhcpClient: Confirmed lease: IP address 192.168.0.105/24 Gateway 192.168.0.1  DNS servers: [ 192.168.0.1 ] Domains  DHCP server /192.168.0.1 Vendor info null lease 7200 seconds
09-01 21:09:28.163  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_POST_DHCP_ACTION rt=411753432/1208576045 0 0 
09-01 21:09:28.163  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_POST_DHCP_ACTION rt=411753432/1208576045 0 0 
09-01 21:09:28.163  1561  2457 D WifiStateMachine: setSuspendOptimizationsNative: 1 true -want true stack:setSuspendOptimizationsNative - handlePostDhcpSetup - processMessage - processMsg
09-01 21:09:28.164  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_IPV4_PROVISIONING_SUCCESS rt=411753434/1208576047 0
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_IPV4_PROVISIONING_SUCCESS rt=411753434/1208576047 0
09-01 21:09:28.165  1561  2457 D WifiStateMachine: handleIPv4Success <IP address 192.168.0.105/24 Gateway 192.168.0.1  DNS servers: [ 192.168.0.1 ] Domains  DHCP server /192.168.0.1 Vendor info null lease 7200 seconds>
09-01 21:09:28.165  1561  2457 D WifiStateMachine: link address 192.168.0.105/24
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_UPDATE_LINKPROPERTIES rt=411753434/1208576047 0 0 
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_UPDATE_LINKPROPERTIES rt=411753434/1208576047 0 0 
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  ConnectModeState !CMD_UPDATE_LINKPROPERTIES rt=411753434/1208576047 0 0 
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  SupplicantStartedState !CMD_UPDATE_LINKPROPERTIES rt=411753434/1208576047 0 0 
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  DefaultState !CMD_UPDATE_LINKPROPERTIES rt=411753434/1208576047 0 0 
09-01 21:09:28.165  1561  2457 D WifiStateMachine: Link configuration changed for netId: 16 old: {InterfaceName: wlan0 LinkAddresses: [fe80::e646:daff:fe6b:f550/64,]  Routes: [fe80::/64 -> :: wlan0,] DnsAddresses: [] Domains: null MTU: 0 TcpBufferSizes: 524288,1048576,5505024,262144,524288,5505024} new: {InterfaceName: wlan0 LinkAddresses: [fe80::e646:daff:fe6b:f550/64,]  Routes: [fe80::/64 -> :: wlan0,192.168.0.0/24 -> 0.0.0.0 wlan0,0.0.0.0/0 -> 192.168.0.1 wlan0,] DnsAddresses: [] Domains: null MTU: 0 TcpBufferSizes: 524288,1048576,5505024,262144,524288,5505024}
09-01 21:09:28.165  1561  2457 D WifiStateMachine: updateLinkProperties nid: 16 state: OBTAINING_IPADDR v4r
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_UPDATE_LINKPROPERTIES rt=411753434/1208576048 0 0 v4r
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_UPDATE_LINKPROPERTIES rt=411753434/1208576048 0 0 v4r
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  ConnectModeState !CMD_UPDATE_LINKPROPERTIES rt=411753434/1208576048 0 0 v4r
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  SupplicantStartedState !CMD_UPDATE_LINKPROPERTIES rt=411753434/1208576048 0 0 v4r
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  DefaultState !CMD_UPDATE_LINKPROPERTIES rt=411753434/1208576048 0 0 v4r
09-01 21:09:28.165  1561  2457 D WifiStateMachine: Link configuration changed for netId: 16 old: {InterfaceName: wlan0 LinkAddresses: [fe80::e646:daff:fe6b:f550/64,]  Routes: [fe80::/64 -> :: wlan0,192.168.0.0/24 -> 0.0.0.0 wlan0,0.0.0.0/0 -> 192.168.0.1 wlan0,] DnsAddresses: [] Domains: null MTU: 0 TcpBufferSizes: 524288,1048576,5505024,262144,524288,5505024} new: {InterfaceName: wlan0 LinkAddresses: [fe80::e646:daff:fe6b:f550/64,192.168.0.105/24,]  Routes: [fe80::/64 -> :: wlan0,192.168.0.0/24 -> 0.0.0.0 wlan0,0.0.0.0/0 -> 192.168.0.1 wlan0,] DnsAddresses: [192.168.0.1,] Domains: null MTU: 0 TcpBufferSizes: 524288,1048576,5505024,262144,524288,5505024}
09-01 21:09:28.166  1561  2457 D WifiStateMachine: updateLinkProperties nid: 16 state: OBTAINING_IPADDR v4 v4r v4dns
09-01 21:09:28.166  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_IP_CONFIGURATION_SUCCESSFUL rt=411753435/1208576048 0 0
09-01 21:09:28.166  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_IP_CONFIGURATION_SUCCESSFUL rt=411753435/1208576048 0 0
09-01 21:09:28.166  1561  2457 D WifiStateMachine: WifiStateMachine: handleSuccessfulIpConfiguration and no scan results"jiatai 5G"-WPA_PSK
09-01 21:09:28.166  1561  2457 D WifiStateMachine: Network selected by UID 1000 prompt=true
09-01 21:09:28.166  1561  2457 D WifiStateMachine: explictlySelected acceptUnvalidated=false
09-01 21:09:28.166  1561  2457 D WifiStateMachine: setDetailed state, old =OBTAINING_IPADDR and new state=CONNECTED hidden=false
09-01 21:09:28.168  1561  2457 D WifiStateMachine: fetchRssiLinkSpeedAndFrequencyNative rssi=-42 linkspeed=866 freq=5765
09-01 21:09:28.173  1561  4872 D DhcpClient: Scheduling renewal in 3599s
09-01 21:09:28.173  1561  4872 D DhcpClient: Scheduling rebind in 6299s
09-01 21:09:28.173  1561  4872 D DhcpClient: Scheduling expiry in 7199s
09-01 21:09:28.173  1561  2457 D WifiStateMachine: fetchRssiLinkSpeedAndFrequencyNative rssi=-42 linkspeed=866 freq=5765
09-01 21:09:28.174  1561  2457 D WifiStateMachine: updateDefaultRouteMacAddress found Ipv4 default :192.168.0.1
09-01 21:09:28.174  1561  2457 E WifiStateMachine: Did not find remoteAddress {192.168.0.1} in /proc/net/arp
09-01 21:09:28.178  1561  2457 D WifiStateMachine: Enter ConnectedState  mScreenOn=true

 

1.WiFi connection process state switching

09-01 21:09:28.023  1561  2457 D WifiStateMachine: setDetailed state, old =DISCONNECTED and new state=CONNECTING hidden=false
09-01 21:09:28.023  1561  2457 D WifiStateMachine: setDetailed state send new extra info"jiatai 5G"
09-01 21:09:28.083  1561  2457 D WifiStateMachine: setDetailed state, old =CONNECTING and new state=CONNECTING hidden=false
09-01 21:09:28.085  1561  2457 D WifiStateMachine: setDetailed state, old =CONNECTING and new state=AUTHENTICATING hidden=false
09-01 21:09:28.095  1561  2457 D WifiStateMachine: setDetailed state, old =AUTHENTICATING and new state=AUTHENTICATING hidden=false
09-01 21:09:28.105  1561  2457 D WifiStateMachine: setDetailed state, old =AUTHENTICATING and new state=CONNECTING hidden=false
09-01 21:09:28.135  1561  2457 D WifiStateMachine: enter ObtainingIpState netId=16 "jiatai 5G"-WPA_PSK  roam=false static=false
09-01 21:09:28.135  1561  2457 D WifiStateMachine: setDetailed state, old =CONNECTING and new state=OBTAINING_IPADDR hidden=false
09-01 21:09:28.166  1561  2457 D WifiStateMachine: setDetailed state, old =OBTAINING_IPADDR and new state=CONNECTED hidden=false
09-01 21:09:28.178  1561  2457 D WifiStateMachine: Enter ConnectedState  mScreenOn=true

You can observe the following states during WiFi connection

  • DISCONNECTED
  • CONNECTING
  • AUTHENTICATING
  • OBTAINING_IPADDR
  • CONNECTED

This time, it mainly sorts out the process of switching the obtaining ABCD IPADDR state to CONNECTED.

NetworkInfo.java
    /**
     * The fine-grained state of a network connection. This level of detail
     * is probably of interest to few applications. Most should use
     * {@link android.net.NetworkInfo.State State} instead.
     */
    public enum DetailedState {
        /** Ready to start data connection setup. */
        IDLE,
        /** Searching for an available access point. */
        SCANNING,
        /** Currently setting up data connection. */
        CONNECTING,
        /** Network link established, performing authentication. */
        AUTHENTICATING,
        /** Awaiting response from DHCP server in order to assign IP address information. */
        OBTAINING_IPADDR,
        /** IP traffic should be available. */
        CONNECTED,
        /** IP traffic is suspended */
        SUSPENDED,
        /** Currently tearing down data connection. */
        DISCONNECTING,
        /** IP traffic not available. */
        DISCONNECTED,
        /** Attempt to connect failed. */
        FAILED,
        /** Access to this network is blocked. */
        BLOCKED,
        /** Link has poor connectivity. */
        VERIFYING_POOR_LINK,
        /** Checking if network is a captive portal */
        CAPTIVE_PORTAL_CHECK
    }

2. Process sorting

    class ObtainingIpState extends State {
        @Override
        public void enter() {
            final WifiConfiguration currentConfig = getCurrentWifiConfiguration();
            final boolean isUsingStaticIp =
                    (currentConfig.getIpAssignment() == IpConfiguration.IpAssignment.STATIC);
            if (mVerboseLoggingEnabled) {
                final String key = currentConfig.configKey();
                log("enter ObtainingIpState netId=" + Integer.toString(mLastNetworkId)
                        + " " + key + " "
                        + " roam=" + mIsAutoRoaming
                        + " static=" + isUsingStaticIp);
            }

            // Reset link Debouncing, indicating we have successfully re-connected to the AP
            // We might still be roaming
            mIsLinkDebouncing = false;

            // Send event to CM & network change broadcast
            setNetworkDetailedState(DetailedState.OBTAINING_IPADDR);

            // We must clear the config BSSID, as the wifi chipset may decide to roam
            // from this point on and having the BSSID specified in the network block would
            // cause the roam to fail and the device to disconnect.
            clearTargetBssid("ObtainingIpAddress");

            // Stop IpClient in case we're switching from DHCP to static
            // configuration or vice versa.
            //
            // TODO: Only ever enter this state the first time we connect to a
            // network, never on switching between static configuration and
            // DHCP. When we transition from static configuration to DHCP in
            // particular, we must tell ConnectivityService that we're
            // disconnected, because DHCP might take a long time during which
            // connectivity APIs such as getActiveNetworkInfo should not return
            // CONNECTED.
            stopIpClient();

            mIpClient.setHttpProxy(currentConfig.getHttpProxy());
            if (!TextUtils.isEmpty(mTcpBufferSizes)) {
                mIpClient.setTcpBufferSizes(mTcpBufferSizes);
            }
            final IpClient.ProvisioningConfiguration prov;
            if (!isUsingStaticIp) {
                prov = IpClient.buildProvisioningConfiguration()
                            .withPreDhcpAction()
                            .withApfCapabilities(mWifiNative.getApfCapabilities())
                            .withNetwork(getCurrentNetwork())
                            .withDisplayName(currentConfig.SSID)
                            .build();
            } else {
                StaticIpConfiguration staticIpConfig = currentConfig.getStaticIpConfiguration();
                prov = IpClient.buildProvisioningConfiguration()
                            .withStaticConfiguration(staticIpConfig)
                            .withApfCapabilities(mWifiNative.getApfCapabilities())
                            .withNetwork(getCurrentNetwork())
                            .withDisplayName(currentConfig.SSID)
                            .build();
            }
            mIpClient.startProvisioning(prov);
            // Get Link layer stats so as we get fresh tx packet counters
            getWifiLinkLayerStats();
        }

Set the state to detailedstate.obtainingipaddr. After the configuration is initialized, the startProvisioning of IpClient will be called

    public void startProvisioning(ProvisioningConfiguration req) {
        if (!req.isValid()) {
            doImmediateProvisioningFailure(IpManagerEvent.ERROR_INVALID_PROVISIONING);
            return;
        }

        mInterfaceParams = mDependencies.getInterfaceParams(mInterfaceName);
        if (mInterfaceParams == null) {
            logError("Failed to find InterfaceParams for " + mInterfaceName);
            doImmediateProvisioningFailure(IpManagerEvent.ERROR_INTERFACE_NOT_FOUND);
            return;
        }

        mCallback.setNeighborDiscoveryOffload(true);
        sendMessage(CMD_START, new ProvisioningConfiguration(req));
    }

Let's first look at the initialization of IpClient

        mIpClient = mFacade.makeIpClient(mContext, mInterfaceName, new IpClientCallback());

Mminterfacename defaults to WLAN 0

        mWifiNative = new WifiNative(SystemProperties.get("wifi.interface", "wlan0"),
                mWifiVendorHal, mSupplicantStaIfaceHal, mWificondControl);

        mInterfaceName = mWifiNative.getInterfaceName();

The preparation of the IPClient is to send the message "CMD start" along with the configuration

IPClient also includes a state machine

    private void configureAndStartStateMachine() {
        addState(mStoppedState);
        addState(mStartedState);
            addState(mRunningState, mStartedState);
        addState(mStoppingState);

        setInitialState(mStoppedState);

        super.start();
    }

Where StoppedState will process the CMD "start message and switch to the StartedState state state.

                case CMD_START:
                    mConfiguration = (ProvisioningConfiguration) msg.obj;
                    transitionTo(mStartedState);
                    break;

 

   class StartedState extends State {
        @Override
        public void enter() {
            mStartTimeMillis = SystemClock.elapsedRealtime();

            if (mConfiguration.mProvisioningTimeoutMs > 0) {
                final long alarmTime = SystemClock.elapsedRealtime() +
                        mConfiguration.mProvisioningTimeoutMs;
                mProvisioningTimeoutAlarm.schedule(alarmTime);
            }

            if (readyToProceed()) {
                deferMessage(obtainMessage(CMD_JUMP_STARTED_TO_RUNNING));
            } else {
                // Clear all IPv4 and IPv6 before proceeding to RunningState.
                // Clean up any leftover state from an abnormal exit from
                // tethering or during an IpClient restart.
                stopAllIP();
            }
        }

        @Override
        public void exit() {
            mProvisioningTimeoutAlarm.cancel();
        }

        @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
                case CMD_JUMP_STARTED_TO_RUNNING:
                    transitionTo(mRunningState);
                    break;

                case CMD_STOP:
                    transitionTo(mStoppingState);
                    break;

                case EVENT_NETLINK_LINKPROPERTIES_CHANGED:
                    handleLinkPropertiesUpdate(NO_CALLBACKS);
                    if (readyToProceed()) {
                        transitionTo(mRunningState);
                    }
                    break;

                case EVENT_PROVISIONING_TIMEOUT:
                    handleProvisioningFailure();
                    break;

                default:
                    // It's safe to process messages out of order because the
                    // only message that can both
                    //     a) be received at this time and
                    //     b) affect provisioning state
                    // is EVENT_NETLINK_LINKPROPERTIES_CHANGED (handled above).
                    deferMessage(msg);
            }

            mMsgStateLogger.handled(this, getCurrentState());
            return HANDLED;
        }

        private boolean readyToProceed() {
            return (!mLinkProperties.hasIPv4Address() &&
                    !mLinkProperties.hasGlobalIPv6Address());
        }
    }

StartedState defirmessage CMD? Jump? Started? To? Running in the enter method, which will be processed after the execution of the enter method. So the state switches to the running state state state.

    class RunningState extends State {
        private ConnectivityPacketTracker mPacketTracker;
        private boolean mDhcpActionInFlight;

        @Override
        public void enter() {
            ApfFilter.ApfConfiguration apfConfig = new ApfFilter.ApfConfiguration();
            apfConfig.apfCapabilities = mConfiguration.mApfCapabilities;
            apfConfig.multicastFilter = mMulticastFiltering;
            // Get the Configuration for ApfFilter from Context
            apfConfig.ieee802_3Filter =
                    mContext.getResources().getBoolean(R.bool.config_apfDrop802_3Frames);
            apfConfig.ethTypeBlackList =
                    mContext.getResources().getIntArray(R.array.config_apfEthTypeBlackList);
            mApfFilter = ApfFilter.maybeCreate(mContext, apfConfig, mInterfaceParams, mCallback);
            // TODO: investigate the effects of any multicast filtering racing/interfering with the
            // rest of this IP configuration startup.
            if (mApfFilter == null) {
                mCallback.setFallbackMulticastFilter(mMulticastFiltering);
            }

            mPacketTracker = createPacketTracker();
            if (mPacketTracker != null) mPacketTracker.start(mConfiguration.mDisplayName);

            if (mConfiguration.mEnableIPv6 && !startIPv6()) {
                doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV6);
                enqueueJumpToStoppingState();
                return;
            }

            if (mConfiguration.mEnableIPv4 && !startIPv4()) {
                doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV4);
                enqueueJumpToStoppingState();
                return;
            }

            final InitialConfiguration config = mConfiguration.mInitialConfig;
            if ((config != null) && !applyInitialConfig(config)) {
                // TODO introduce a new IpManagerEvent constant to distinguish this error case.
                doImmediateProvisioningFailure(IpManagerEvent.ERROR_INVALID_PROVISIONING);
                enqueueJumpToStoppingState();
                return;
            }

            if (mConfiguration.mUsingMultinetworkPolicyTracker) {
                mMultinetworkPolicyTracker = new MultinetworkPolicyTracker(
                        mContext, getHandler(),
                        () -> { mLog.log("OBSERVED AvoidBadWifi changed"); });
                mMultinetworkPolicyTracker.start();
            }

            if (mConfiguration.mUsingIpReachabilityMonitor && !startIpReachabilityMonitor()) {
                doImmediateProvisioningFailure(
                        IpManagerEvent.ERROR_STARTING_IPREACHABILITYMONITOR);
                enqueueJumpToStoppingState();
                return;
            }
        }

The difference of the enter method is whether ipv6 is configured or ipv4 goes through different processes. Now the default is generally ipv4.

Look at the startIPv4 logic

    private boolean startIPv4() {
        // If we have a StaticIpConfiguration attempt to apply it and
        // handle the result accordingly.
        if (mConfiguration.mStaticIpConfig != null) {
            if (mInterfaceCtrl.setIPv4Address(mConfiguration.mStaticIpConfig.ipAddress)) {
                handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));
            } else {
                return false;
            }
        } else {
            // Start DHCPv4.
            mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceParams);
            mDhcpClient.registerForPreDhcpNotification();
            mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP);
        }

        return true;
    }

Since it is not a static ip, follow the DhcpClient process, which is the same as the previous one (87) WiFi & DHCP The process is right.

But the meaning of WaitBeforeStartState was not clear at that time.

Dhcclient switches to mWaitBeforeStartState. This is because mDhcpClient.registerForPreDhcpNotification() was called before. So the state here is waiting for other states to complete. In fact, some preparatory work of dhcp needs to be completed in WiFi state machine, so the process here needs to wait. After the process is completed, it will naturally switch to DhcpInitState.

    class StoppedState extends State {
        @Override
        public boolean processMessage(Message message) {
            switch (message.what) {
                case CMD_START_DHCP:
                    if (mRegisteredForPreDhcpNotification) {
                        transitionTo(mWaitBeforeStartState);
                    } else {
                        transitionTo(mDhcpInitState);
                    }
                    return HANDLED;
                default:
                    return NOT_HANDLED;
            }
        }
    }

private State mWaitBeforeStartState = new WaitBeforeStartState(mDhcpInitState);

 

 

This message is not clear: CMD? Update? Linkproperties

09-01 21:09:28.149  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_UPDATE_LINKPROPERTIES rt=411753418/1208576032 0 0 
09-01 21:09:28.149  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_UPDATE_LINKPROPERTIES rt=411753418/1208576032 0 0 
09-01 21:09:28.149  1561  2457 D WifiStateMachine:  ConnectModeState !CMD_UPDATE_LINKPROPERTIES rt=411753418/1208576032 0 0 
09-01 21:09:28.149  1561  2457 D WifiStateMachine:  SupplicantStartedState !CMD_UPDATE_LINKPROPERTIES rt=411753418/1208576032 0 0 
09-01 21:09:28.149  1561  2457 D WifiStateMachine:  DefaultState !CMD_UPDATE_LINKPROPERTIES rt=411753418/1208576032 0 0 
09-01 21:09:28.149  1561  2457 D WifiStateMachine: Link configuration changed for netId: 16 old: {LinkAddresses: []  Routes: [] DnsAddresses: [] Domains: null MTU: 0} new: {InterfaceName: wlan0 LinkAddresses: [fe80::e646:daff:fe6b:f550/64,]  Routes: [fe80::/64 -> :: wlan0,] DnsAddresses: [] Domains: null MTU: 0 TcpBufferSizes: 524288,1048576,5505024,262144,524288,5505024}
09-01 21:09:28.150  1561  2457 D WifiStateMachine: updateLinkProperties nid: 16 state: OBTAINING_IPADDR 

 

Then look

09-01 21:09:28.151  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_PRE_DHCP_ACTION rt=411753420/1208576033 0 0 txpkts=3180968,0,0
09-01 21:09:28.151  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_PRE_DHCP_ACTION rt=411753420/1208576033 0 0 txpkts=3180968,0,0
09-01 21:09:28.151  1561  2457 D WifiStateMachine: setSuspendOptimizationsNative: 1 false -want true stack:setSuspendOptimizationsNative - handlePreDhcpSetup - processMessage - processMsg
09-01 21:09:28.153  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_PRE_DHCP_ACTION_COMPLETE rt=411753422/1208576035 0 0
09-01 21:09:28.153  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_PRE_DHCP_ACTION_COMPLETE rt=411753422/1208576035 0 0
    class WaitBeforeStartState extends WaitBeforeOtherState {
        public WaitBeforeStartState(State otherState) {
            super();
            mOtherState = otherState;
        }
    }

    // Sends CMD_PRE_DHCP_ACTION to the controller, waits for the controller to respond with
    // CMD_PRE_DHCP_ACTION_COMPLETE, and then transitions to mOtherState.
    abstract class WaitBeforeOtherState extends LoggingState {
        protected State mOtherState;

        @Override
        public void enter() {
            super.enter();
            mController.sendMessage(CMD_PRE_DHCP_ACTION);
        }

        @Override
        public boolean processMessage(Message message) {
            super.processMessage(message);
            switch (message.what) {
                case CMD_PRE_DHCP_ACTION_COMPLETE:
                    transitionTo(mOtherState);
                    return HANDLED;
                default:
                    return NOT_HANDLED;
            }
        }
    }

When entering this waiting state, it will send CMD ﹣ pre ﹣ DHCP ﹣ action to IpClient, and RunningState will process the message accordingly

                case DhcpClient.CMD_PRE_DHCP_ACTION:
                    if (mConfiguration.mRequestedPreDhcpActionMs > 0) {
                        ensureDhcpAction();
                    } else {
                        sendMessage(EVENT_PRE_DHCP_ACTION_COMPLETE);
                    }
                    break;

From the log view, we went to ensureDhcpAction() and didn't send the completion message directly.

        private void ensureDhcpAction() {
            if (!mDhcpActionInFlight) {
                mCallback.onPreDhcpAction();
                mDhcpActionInFlight = true;
                final long alarmTime = SystemClock.elapsedRealtime() +
                        mConfiguration.mRequestedPreDhcpActionMs;
                mDhcpActionTimeoutAlarm.schedule(alarmTime);
            }
        }

Call back to WiFi state machine

    class IpClientCallback extends IpClient.Callback {
        @Override
        public void onPreDhcpAction() {
            sendMessage(DhcpClient.CMD_PRE_DHCP_ACTION);
        }

L2ConnectedState processing

        @Override
        public boolean processMessage(Message message) {
            logStateAndMessage(message, this);

            switch (message.what) {
                case DhcpClient.CMD_PRE_DHCP_ACTION:
                    handlePreDhcpSetup();
                    break;


    void handlePreDhcpSetup() {
        if (!mBluetoothConnectionActive) {
            /*
             * There are problems setting the Wi-Fi driver's power
             * mode to active when bluetooth coexistence mode is
             * enabled or sense.
             * <p>
             * We set Wi-Fi to active mode when
             * obtaining an IP address because we've found
             * compatibility issues with some routers with low power
             * mode.
             * <p>
             * In order for this active power mode to properly be set,
             * we disable coexistence mode until we're done with
             * obtaining an IP address.  One exception is if we
             * are currently connected to a headset, since disabling
             * coexistence would interrupt that connection.
             */
            // Disable the coexistence mode
            mWifiNative.setBluetoothCoexistenceMode(
                    WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
        }

        // Disable power save and suspend optimizations during DHCP
        // Note: The order here is important for now. Brcm driver changes
        // power settings when we control suspend mode optimizations.
        // TODO: Remove this comment when the driver is fixed.
        setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false);
        mWifiNative.setPowerSave(false);

        // Update link layer stats
        getWifiLinkLayerStats();

        if (mWifiP2pChannel != null) {
            /* P2p discovery breaks dhcp, shut it down in order to get through this */
            Message msg = new Message();
            msg.what = WifiP2pServiceImpl.BLOCK_DISCOVERY;
            msg.arg1 = WifiP2pServiceImpl.ENABLED;
            msg.arg2 = DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE;
            msg.obj = WifiStateMachine.this;
            mWifiP2pChannel.sendMessage(msg);
        } else {
            // If the p2p service is not running, we can proceed directly.
            sendMessage(DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE);
        }
    }

The WiFi 2p channel will be initialized when starting up after combing the support for p2p, so you need to disable p2p discovery to let the dhcp process continue.

WifiP2pServiceImpl P2pEnabledState

                    case BLOCK_DISCOVERY:
                        boolean blocked = (message.arg1 == ENABLED ? true : false);
                        if (mDiscoveryBlocked == blocked) break;
                        mDiscoveryBlocked = blocked;
                        if (blocked && mDiscoveryStarted) {
                            mWifiNative.p2pStopFind();
                            mDiscoveryPostponed = true;
                        }
                        if (!blocked && mDiscoveryPostponed) {
                            mDiscoveryPostponed = false;
                            mWifiNative.p2pFind(DISCOVER_TIMEOUT_S);
                        }
                        if (blocked) {
                            if (message.obj == null) {
                                Log.e(TAG, "Illegal argument(s)");
                                break;
                            }
                            StateMachine m = (StateMachine) message.obj;
                            try {
                                m.sendMessage(message.arg2);
                            } catch (Exception e) {
                                loge("unable to send BLOCK_DISCOVERY response: " + e);
                            }
                        }
                        break;

After calling p2pstoppfind, it will send dhcpclient.cmd? Pre? DHCP? Action? Complete to WiFi state machine, L2ConnectedState to continue processing

09-01 21:09:28.153  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_PRE_DHCP_ACTION_COMPLETE rt=411753422/1208576035 0 0
09-01 21:09:28.153  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_PRE_DHCP_ACTION_COMPLETE rt=411753422/1208576035 0 0
                case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE:
                    mIpClient.completedPreDhcpAction();
                    break;

IpClient

    public void completedPreDhcpAction() {
        sendMessage(EVENT_PRE_DHCP_ACTION_COMPLETE);
    }
RunningState

                case EVENT_PRE_DHCP_ACTION_COMPLETE:
                    // It's possible to reach here if, for example, someone
                    // calls completedPreDhcpAction() after provisioning with
                    // a static IP configuration.
                    if (mDhcpClient != null) {
                        mDhcpClient.sendMessage(DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE);
                    }
                    break;

DHCP client receives chcp preparation message to switch state to mDhcpInitState

    class WaitBeforeStartState extends WaitBeforeOtherState {
        public WaitBeforeStartState(State otherState) {
            super();
            mOtherState = otherState;
        }
    }

    // Sends CMD_PRE_DHCP_ACTION to the controller, waits for the controller to respond with
    // CMD_PRE_DHCP_ACTION_COMPLETE, and then transitions to mOtherState.
    abstract class WaitBeforeOtherState extends LoggingState {
        protected State mOtherState;

        @Override
        public void enter() {
            super.enter();
            mController.sendMessage(CMD_PRE_DHCP_ACTION);
        }

        @Override
        public boolean processMessage(Message message) {
            super.processMessage(message);
            switch (message.what) {
                case CMD_PRE_DHCP_ACTION_COMPLETE:
                    transitionTo(mOtherState);
                    return HANDLED;
                default:
                    return NOT_HANDLED;
            }
        }
    }
    class DhcpInitState extends PacketRetransmittingState {
        public DhcpInitState() {
            super();
        }

        @Override
        public void enter() {
            super.enter();
            startNewTransaction();
            mLastInitEnterTime = SystemClock.elapsedRealtime();
        }

        protected boolean sendPacket() {
            return sendDiscoverPacket();
        }

        protected void receivePacket(DhcpPacket packet) {
            if (!isValidPacket(packet)) return;
            if (!(packet instanceof DhcpOfferPacket)) return;
            mOffer = packet.toDhcpResults();
            if (mOffer != null) {
                Log.d(TAG, "Got pending lease: " + mOffer);
                transitionTo(mDhcpRequestingState);
            }
        }
    }

dhcp starts to work. I've combed it before, but the process is a little bit.

09-01 21:09:28.153  1561  4872 D DhcpClient: Broadcasting DHCPDISCOVER
09-01 21:09:28.157  1561  4875 D DhcpClient: Received packet: e4:46:da:6b:f5:50 OFFER, ip /192.168.0.105, mask /255.255.255.0, DNS servers: /192.168.0.1 , gateways [/192.168.0.1] lease time 7200, domain null
09-01 21:09:28.158  1561  4872 D DhcpClient: Got pending lease: IP address 192.168.0.105/24 Gateway 192.168.0.1  DNS servers: [ 192.168.0.1 ] Domains  DHCP server /192.168.0.1 Vendor info null lease 7200 seconds
09-01 21:09:28.158  1561  4872 D DhcpClient: Broadcasting DHCPREQUEST ciaddr=0.0.0.0 request=192.168.0.105 serverid=192.168.0.1
09-01 21:09:28.159  1561 12753 D WifiService: getWifiEnabledState uid=1000
09-01 21:09:28.161  1561 12753 D WifiService: getConnectionInfo uid=1000
09-01 21:09:28.161  1561 12753 D WifiService: getWifiEnabledState uid=1000
09-01 21:09:28.162  1561  4875 D DhcpClient: Received packet: e4:46:da:6b:f5:50 ACK: your new IP /192.168.0.105, netmask /255.255.255.0, gateways [/192.168.0.1] DNS servers: /192.168.0.1 , lease time 7200
09-01 21:09:28.162  1561  4872 D DhcpClient: Confirmed lease: IP address 192.168.0.105/24 Gateway 192.168.0.1  DNS servers: [ 192.168.0.1 ] Domains  DHCP server /192.168.0.1 Vendor info null lease 7200 seconds
09-01 21:09:28.163  1561 12753 D WifiService: getConnectionInfo uid=1000

 

DhcpClient

DHCPREQUEST receives a response and sends a CMD? Post? DHCP? Action message to IpClient.

    private void notifySuccess() {
        mController.sendMessage(
                CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, new DhcpResults(mDhcpLease));
    }


    private void acceptDhcpResults(DhcpResults results, String msg) {
        mDhcpLease = results;
        mOffer = null;
        Log.d(TAG, msg + " lease: " + mDhcpLease);
        notifySuccess();
    }

    class DhcpRequestingState extends PacketRetransmittingState {
        public DhcpRequestingState() {
            mTimeout = DHCP_TIMEOUT_MS / 2;
        }

        protected boolean sendPacket() {
            return sendRequestPacket(
                    INADDR_ANY,                                    // ciaddr
                    (Inet4Address) mOffer.ipAddress.getAddress(),  // DHCP_REQUESTED_IP
                    (Inet4Address) mOffer.serverAddress,           // DHCP_SERVER_IDENTIFIER
                    INADDR_BROADCAST);                             // packet destination address
        }

        protected void receivePacket(DhcpPacket packet) {
            if (!isValidPacket(packet)) return;
            if ((packet instanceof DhcpAckPacket)) {
                DhcpResults results = packet.toDhcpResults();
                if (results != null) {
                    setDhcpLeaseExpiry(packet);
                    acceptDhcpResults(results, "Confirmed");
                    transitionTo(mConfiguringInterfaceState);
                }
            } else if (packet instanceof DhcpNakPacket) {
                // TODO: Wait a while before returning into INIT state.
                Log.d(TAG, "Received NAK, returning to INIT");
                mOffer = null;
                transitionTo(mDhcpInitState);
            }
        }

IpClient for processing

09-01 21:09:28.163  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_POST_DHCP_ACTION rt=411753432/1208576045 0 0 
09-01 21:09:28.163  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_POST_DHCP_ACTION rt=411753432/1208576045 0 0 
                case DhcpClient.CMD_POST_DHCP_ACTION:
                    stopDhcpAction();

                    switch (msg.arg1) {
                        case DhcpClient.DHCP_SUCCESS:
                            handleIPv4Success((DhcpResults) msg.obj);
                            break;
                        case DhcpClient.DHCP_FAILURE:
                            handleIPv4Failure();
                            break;
                        default:
                            logError("Unknown CMD_POST_DHCP_ACTION status: %s", msg.arg1);
                    }
                    break;
        private void stopDhcpAction() {
            mDhcpActionTimeoutAlarm.cancel();
            if (mDhcpActionInFlight) {
                mCallback.onPostDhcpAction();
                mDhcpActionInFlight = false;
            }
        }

//Cancel timeout countdown and call back to WiFi state machine
        @Override
        public void onPostDhcpAction() {
            sendMessage(DhcpClient.CMD_POST_DHCP_ACTION);
        }


                case DhcpClient.CMD_POST_DHCP_ACTION:
                    handlePostDhcpSetup();
                    // We advance to mConnectedState because IpClient will also send a
                    // CMD_IPV4_PROVISIONING_SUCCESS message, which calls handleIPv4Success(),
                    // which calls updateLinkProperties, which then sends
                    // CMD_IP_CONFIGURATION_SUCCESSFUL.
                    //
                    // In the event of failure, we transition to mDisconnectingState
                    // similarly--via messages sent back from IpClient.
                    break;

//Let go of the previous control over p2p find.

    void handlePostDhcpSetup() {
        /* Restore power save and suspend optimizations */
        setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true);
        mWifiNative.setPowerSave(true);

        p2pSendMessage(WifiP2pServiceImpl.BLOCK_DISCOVERY, WifiP2pServiceImpl.DISABLED);

        // Set the coexistence mode back to its default value
        mWifiNative.setBluetoothCoexistenceMode(
                WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE);
    }

 

09-01 21:09:28.164  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_IPV4_PROVISIONING_SUCCESS rt=411753434/1208576047 0
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_IPV4_PROVISIONING_SUCCESS rt=411753434/1208576047 0
09-01 21:09:28.165  1561  2457 D WifiStateMachine: handleIPv4Success <IP address 192.168.0.105/24 Gateway 192.168.0.1  DNS servers: [ 192.168.0.1 ] Domains  DHCP server /192.168.0.1 Vendor info null lease 7200 seconds>
09-01 21:09:28.165  1561  2457 D WifiStateMachine: link address 192.168.0.105/24

 

    private void handleIPv4Success(DhcpResults dhcpResults) {
        mDhcpResults = new DhcpResults(dhcpResults);
        final LinkProperties newLp = assembleLinkProperties();
        final ProvisioningChange delta = setLinkProperties(newLp);

        if (DBG) {
            Log.d(mTag, "onNewDhcpResults(" + Objects.toString(dhcpResults) + ")");
        }
        mCallback.onNewDhcpResults(dhcpResults);
        dispatchCallback(delta, newLp);
    }

//callback of WiFi state machine
        @Override
        public void onNewDhcpResults(DhcpResults dhcpResults) {
            if (dhcpResults != null) {
                sendMessage(CMD_IPV4_PROVISIONING_SUCCESS, dhcpResults);
            } else {
                sendMessage(CMD_IPV4_PROVISIONING_FAILURE);
                mWifiInjector.getWifiLastResortWatchdog().noteConnectionFailureAndTriggerIfNeeded(
                        getTargetSsid(), mTargetRoamBSSID,
                        WifiLastResortWatchdog.FAILURE_CODE_DHCP);
            }
        }


                case CMD_IPV4_PROVISIONING_SUCCESS: {
                    handleIPv4Success((DhcpResults) message.obj);
                    sendNetworkStateChangeBroadcast(mLastBssid);
                    break;
                }

    private void handleIPv4Success(DhcpResults dhcpResults) {
        if (mVerboseLoggingEnabled) {
            logd("handleIPv4Success <" + dhcpResults.toString() + ">");
            logd("link address " + dhcpResults.ipAddress);
        }

        Inet4Address addr;
        synchronized (mDhcpResultsLock) {
            mDhcpResults = dhcpResults;
            addr = (Inet4Address) dhcpResults.ipAddress.getAddress();
        }

        if (mIsAutoRoaming) {
            int previousAddress = mWifiInfo.getIpAddress();
            int newAddress = NetworkUtils.inetAddressToInt(addr);
            if (previousAddress != newAddress) {
                logd("handleIPv4Success, roaming and address changed" +
                        mWifiInfo + " got: " + addr);
            }
        }

        mWifiInfo.setInetAddress(addr);

        final WifiConfiguration config = getCurrentWifiConfiguration();
        if (config != null) {
            mWifiInfo.setEphemeral(config.ephemeral);
        }

        // Set meteredHint if DHCP result says network is metered
        if (dhcpResults.hasMeteredHint()) {
            mWifiInfo.setMeteredHint(true);
        }

        updateCapabilities(config);
    }

    private void sendNetworkStateChangeBroadcast(String bssid) {
        Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
        intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties));
        if (bssid != null)
            intent.putExtra(WifiManager.EXTRA_BSSID, bssid);
        if (mNetworkInfo.getDetailedState() == DetailedState.VERIFYING_POOR_LINK ||
                mNetworkInfo.getDetailedState() == DetailedState.CONNECTED) {
            // We no longer report MAC address to third-parties and our code does
            // not rely on this broadcast, so just send the default MAC address.
            fetchRssiLinkSpeedAndFrequencyNative();
            WifiInfo sentWifiInfo = new WifiInfo(mWifiInfo);
            sentWifiInfo.setMacAddress(WifiInfo.DEFAULT_MAC_ADDRESS);
            intent.putExtra(WifiManager.EXTRA_WIFI_INFO, sentWifiInfo);
        }
        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
    }

 

Continue

09-01 21:09:28.165  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_UPDATE_LINKPROPERTIES rt=411753434/1208576048 0 0 v4r
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_UPDATE_LINKPROPERTIES rt=411753434/1208576048 0 0 v4r
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  ConnectModeState !CMD_UPDATE_LINKPROPERTIES rt=411753434/1208576048 0 0 v4r
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  SupplicantStartedState !CMD_UPDATE_LINKPROPERTIES rt=411753434/1208576048 0 0 v4r
09-01 21:09:28.165  1561  2457 D WifiStateMachine:  DefaultState !CMD_UPDATE_LINKPROPERTIES rt=411753434/1208576048 0 0 v4r
09-01 21:09:28.165  1561  2457 D WifiStateMachine: Link configuration changed for netId: 16 old: {InterfaceName: wlan0 LinkAddresses: [fe80::e646:daff:fe6b:f550/64,]  Routes: [fe80::/64 -> :: wlan0,192.168.0.0/24 -> 0.0.0.0 wlan0,0.0.0.0/0 -> 192.168.0.1 wlan0,] DnsAddresses: [] Domains: null MTU: 0 TcpBufferSizes: 524288,1048576,5505024,262144,524288,5505024} new: {InterfaceName: wlan0 LinkAddresses: [fe80::e646:daff:fe6b:f550/64,192.168.0.105/24,]  Routes: [fe80::/64 -> :: wlan0,192.168.0.0/24 -> 0.0.0.0 wlan0,0.0.0.0/0 -> 192.168.0.1 wlan0,] DnsAddresses: [192.168.0.1,] Domains: null MTU: 0 TcpBufferSizes: 524288,1048576,5505024,262144,524288,5505024}


09-01 21:09:28.166  1561  2457 D WifiStateMachine:  ObtainingIpState !CMD_IP_CONFIGURATION_SUCCESSFUL rt=411753435/1208576048 0 0
09-01 21:09:28.166  1561  2457 D WifiStateMachine:  L2ConnectedState !CMD_IP_CONFIGURATION_SUCCESSFUL rt=411753435/1208576048 0 0
09-01 21:09:28.166  1561  2457 D WifiStateMachine: WifiStateMachine: handleSuccessfulIpConfiguration and no scan results"jiatai 5G"-WPA_PSK
09-01 21:09:28.166  2552  2552 D ToggleManager: updateWifiToggle wifiState=-1 mWifiConnected=false action=android.net.wifi.STATE_CHANGE
09-01 21:09:28.166  1561  2457 D WifiStateMachine: Network selected by UID 1000 prompt=true
09-01 21:09:28.166  1561  2457 D WifiStateMachine: explictlySelected acceptUnvalidated=false
09-01 21:09:28.166  1561  2457 D WifiStateMachine: setDetailed state, old =OBTAINING_IPADDR and new state=CONNECTED hidden=false

IpClient

    private void dispatchCallback(ProvisioningChange delta, LinkProperties newLp) {
        switch (delta) {
            case GAINED_PROVISIONING:
                if (DBG) { Log.d(mTag, "onProvisioningSuccess()"); }
                recordMetric(IpManagerEvent.PROVISIONING_OK);
                mCallback.onProvisioningSuccess(newLp);
                break;

            case LOST_PROVISIONING:
                if (DBG) { Log.d(mTag, "onProvisioningFailure()"); }
                recordMetric(IpManagerEvent.PROVISIONING_FAIL);
                mCallback.onProvisioningFailure(newLp);
                break;

            default:
                if (DBG) { Log.d(mTag, "onLinkPropertiesChange()"); }
                mCallback.onLinkPropertiesChange(newLp);
                break;
        }
    }

callback of WiFi state machine

        @Override
        public void onProvisioningSuccess(LinkProperties newLp) {
            mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL);
            sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp);
            sendMessage(CMD_IP_CONFIGURATION_SUCCESSFUL);
        }

 

                /* Link configuration (IP address, DNS, ...) changes notified via netlink */
                case CMD_UPDATE_LINKPROPERTIES:
                    updateLinkProperties((LinkProperties) message.obj);
                    break;

    private void updateLinkProperties(LinkProperties newLp) {
        if (mVerboseLoggingEnabled) {
            log("Link configuration changed for netId: " + mLastNetworkId
                    + " old: " + mLinkProperties + " new: " + newLp);
        }
        // We own this instance of LinkProperties because IpClient passes us a copy.
        mLinkProperties = newLp;
        if (mNetworkAgent != null) {
            mNetworkAgent.sendLinkProperties(mLinkProperties);
        }

        if (getNetworkDetailedState() == DetailedState.CONNECTED) {
            // If anything has changed and we're already connected, send out a notification.
            // TODO: Update all callers to use NetworkCallbacks and delete this.
            sendLinkConfigurationChangedBroadcast();
        }

        if (mVerboseLoggingEnabled) {
            StringBuilder sb = new StringBuilder();
            sb.append("updateLinkProperties nid: " + mLastNetworkId);
            sb.append(" state: " + getNetworkDetailedState());

            if (mLinkProperties != null) {
                sb.append(" ");
                sb.append(getLinkPropertiesSummary(mLinkProperties));
            }
            logd(sb.toString());
        }
    }

 

                case CMD_IP_CONFIGURATION_SUCCESSFUL:
                    handleSuccessfulIpConfiguration();
                    reportConnectionAttemptEnd(
                            WifiMetrics.ConnectionEvent.FAILURE_NONE,
                            WifiMetricsProto.ConnectionEvent.HLF_NONE);
                    if (getCurrentWifiConfiguration() == null) {
                        // The current config may have been removed while we were connecting,
                        // trigger a disconnect to clear up state.
                        mWifiNative.disconnect();
                        transitionTo(mDisconnectingState);
                    } else {
                        sendConnectedState();
                        transitionTo(mConnectedState);
                    }
                    break;

    private void handleSuccessfulIpConfiguration() {
        mLastSignalLevel = -1; // Force update of signal strength
        WifiConfiguration c = getCurrentWifiConfiguration();
        if (c != null) {
            // Reset IP failure tracking
            c.getNetworkSelectionStatus().clearDisableReasonCounter(
                    WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE);

            // Tell the framework whether the newly connected network is trusted or untrusted.
            updateCapabilities(c);
        }
        if (c != null) {
            ScanResult result = getCurrentScanResult();
            if (result == null) {
                logd("WifiStateMachine: handleSuccessfulIpConfiguration and no scan results" +
                        c.configKey());
            } else {
                // Clear the per BSSID failure count
                result.numIpConfigFailures = 0;
        

    private void sendConnectedState() {
        // If this network was explicitly selected by the user, evaluate whether to call
        // explicitlySelected() so the system can treat it appropriately.
        WifiConfiguration config = getCurrentWifiConfiguration();
        if (shouldEvaluateWhetherToSendExplicitlySelected(config)) {
            boolean prompt =
                    mWifiPermissionsUtil.checkNetworkSettingsPermission(config.lastConnectUid);
            if (mVerboseLoggingEnabled) {
                log("Network selected by UID " + config.lastConnectUid + " prompt=" + prompt);
            }
            if (prompt) {
                // Selected by the user via Settings or QuickSettings. If this network has Internet
                // access, switch to it. Otherwise, switch to it only if the user confirms that they
                // really want to switch, or has already confirmed and selected "Don't ask again".
                if (mVerboseLoggingEnabled) {
                    log("explictlySelected acceptUnvalidated=" + config.noInternetAccessExpected);
                }
                if (mNetworkAgent != null) {
                    mNetworkAgent.explicitlySelected(config.noInternetAccessExpected);
                }
            }
        }

        setNetworkDetailedState(DetailedState.CONNECTED);
        mWifiConfigManager.updateNetworkAfterConnect(mLastNetworkId);
        sendNetworkStateChangeBroadcast(mLastBssid);
    }

After ip configuration is successful, set the network state to connected and send broadcast notification. Finally, switch the state to connected state.

    class ConnectedState extends State {
        @Override
        public void enter() {
            // TODO: b/64349637 Investigate getting default router IP/MAC address info from
            // IpManager
            //updateDefaultRouteMacAddress(1000);
            if (mVerboseLoggingEnabled) {
                log("Enter ConnectedState "
                       + " mScreenOn=" + mScreenOn);
            }

            mWifiConnectivityManager.handleConnectionStateChanged(
                    WifiConnectivityManager.WIFI_STATE_CONNECTED);
            registerConnected();
            lastConnectAttemptTimestamp = 0;
            targetWificonfiguration = null;
            // Paranoia
            mIsLinkDebouncing = false;

            // Not roaming anymore
            mIsAutoRoaming = false;

            if (testNetworkDisconnect) {
                testNetworkDisconnectCounter++;
                logd("ConnectedState Enter start disconnect test " +
                        testNetworkDisconnectCounter);
                sendMessageDelayed(obtainMessage(CMD_TEST_NETWORK_DISCONNECT,
                        testNetworkDisconnectCounter, 0), 15000);
            }

            mLastDriverRoamAttempt = 0;
            mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
            mWifiInjector.getWifiLastResortWatchdog().connectedStateTransition(true);
            mWifiStateTracker.updateState(WifiStateTracker.CONNECTED);
        }

Look at the logic processing after the connection. Here is the scanning logic after the connection. singleScan/pnoScan/periodicScan. The scanning logic will be sorted out and continued.

The startConnectivityScan logic shown here is to light up the screen and connect the ap. If the ap is not connected and the pno scan is not started, the pno scan will be performed. The pno scan is only for the saved network.

WifiConnectivityManager

    /**
     * Handler for WiFi state (connected/disconnected) changes
     */
    public void handleConnectionStateChanged(int state) {
        localLog("handleConnectionStateChanged: state=" + stateToString(state));

        mWifiState = state;

        if (mWifiState == WIFI_STATE_CONNECTED) {
            mOpenNetworkNotifier.handleWifiConnected();
        }

        // Reset BSSID of last connection attempt and kick off
        // the watchdog timer if entering disconnected state.
        if (mWifiState == WIFI_STATE_DISCONNECTED) {
            mLastConnectionAttemptBssid = null;
            scheduleWatchdogTimer();
            startConnectivityScan(SCAN_IMMEDIATELY);
        } else {
            startConnectivityScan(SCAN_ON_SCHEDULE);
        }
    }

    // Start a connectivity scan. The scan method is chosen according to
    // the current screen state and WiFi state.
    private void startConnectivityScan(boolean scanImmediately) {
        localLog("startConnectivityScan: screenOn=" + mScreenOn
                + " wifiState=" + stateToString(mWifiState)
                + " scanImmediately=" + scanImmediately
                + " wifiEnabled=" + mWifiEnabled
                + " wifiConnectivityManagerEnabled="
                + mWifiConnectivityManagerEnabled);

        if (!mWifiEnabled || !mWifiConnectivityManagerEnabled) {
            return;
        }

        // Always stop outstanding connecivity scan if there is any
        stopConnectivityScan();

        // Don't start a connectivity scan while Wifi is in the transition
        // between connected and disconnected states.
        if (mWifiState != WIFI_STATE_CONNECTED && mWifiState != WIFI_STATE_DISCONNECTED) {
            return;
        }

        if (mScreenOn) {
            startPeriodicScan(scanImmediately);
        } else {
            if (mWifiState == WIFI_STATE_DISCONNECTED && !mPnoScanStarted) {
                startDisconnectedPnoScan();
            }
        }

    }

    // Start a periodic scan when screen is on
    private void startPeriodicScan(boolean scanImmediately) {
        mPnoScanListener.resetLowRssiNetworkRetryDelay();

        // No connectivity scan if auto roaming is disabled.
        if (mWifiState == WIFI_STATE_CONNECTED && !mEnableAutoJoinWhenAssociated) {
            return;
        }

        // Due to b/28020168, timer based single scan will be scheduled
        // to provide periodic scan in an exponential backoff fashion.
        if (scanImmediately) {
            resetLastPeriodicSingleScanTimeStamp();
        }
        mPeriodicSingleScanInterval = PERIODIC_SCAN_INTERVAL_MS;
        startPeriodicSingleScan();
    }

Come here first.

 

3. summary

 

Posted by ok on Thu, 02 Jan 2020 19:27:40 -0800