Conexión wifi de Andriod P

Prefacio:

  • Cada versión de wifi de Android se itera y actualiza. Aparte de los cambios importantes en la versión O del marco, el marco de actualización futuro no ha cambiado mucho, pero todavía hay muchos nombres de archivos java y cambios en el proceso de llamada. El nombre de la función que llama todavía se puede distinguir básicamente
  • Anteriormente, resolvimos el escaneo de wifi y el proceso de llevar los datos del escaneo a la pantalla de la interfaz de la aplicación. A continuación, resolvimos el proceso de conexión de hacer clic en ap e ingresar la información de conexión.
  • wifistatemachine es el núcleo del mecanismo wifi
  • wifiserviceImpl es el administrador del servicio wifi

Proceso de peinado

Esta función se llamará después de hacer clic en el wifi que desea conectarse:

WifiSettings.java

@Override
      public boolean onPreferenceTreeClick(Preference preference) {
    
    
          // If the preference has a fragment set, open that
          if (preference.getFragment() != null) {
    
    
              preference.setOnPreferenceClickListener(null);
              return super.onPreferenceTreeClick(preference);
          }
  
      ......
          return true;
      }

Una vez configurado el usuario, haga clic en el botón de conexión y haga clic en el botón Aceptar en el cuadro emergente para ejecutar el código, se llamará a la función onClick:

WifiDialog.java

 public void onClick(DialogInterface dialogInterface, int button) {
    
    
        if (button == WifiDialog.BUTTON_FORGET && mSelected != null) {
    
    
            forget(mSelected.networkId);
        } else if (button == WifiDialog.BUTTON_SUBMIT && mDialog != null) {
    
    
            WifiConfiguration config = mDialog.getConfig();
            if (config == null) {
    
    
                if (mSelected != null && !requireKeyStore(mSelected.getConfig())) {
    
    
                    connect(mSelected.networkId);
                }
            } else if (config.networkId != -1) {
    
    
                if (mSelected != null) {
    
    
                    mWifiManager.updateNetwork(config);
                    saveNetworks();
                }
            } else {
    
    
                int networkId = mWifiManager.addNetwork(config);
                if (networkId != -1) {
    
    
                    mWifiManager.enableNetwork(networkId, false);
                    config.networkId = networkId;
                    if (mDialog.edit || requireKeyStore(config)) {
    
    
                        saveNetworks();
                    } else {
    
    
                        connect(networkId);
                    }
                }
            }
        }

También en WifiSettings.java en

@Override
      public void onSubmit(WifiDialog dialog) {
    
    
          if (mDialog != null) {
    
    
              submit(mDialog.getController());
          }
      }

Enviar llamada, después de completar el ssid y la contraseña en el cuadro de diálogo, vaya a Guardar WifiManager

void submit(WifiConfigController configController) {
    
    
          final WifiConfiguration config = configController.getConfig();  
          if (config == null) {
    
    
              if (mSelectedAccessPoint != null
                      && mSelectedAccessPoint.isSaved()) {
    
    
                  connect(mSelectedAccessPoint.getConfig(), true /* isSavedNetwork */);
              }
          } else if (configController.getMode() == WifiConfigUiBase.MODE_MODIFY) {
    
    
              mWifiManager.save(config, mSaveListener);
          } else {
    
    
              mWifiManager.save(config, mSaveListener);
              if (mSelectedAccessPoint != null) {
    
     // Not an "Add network"
                  connect(config, false /* isSavedNetwork */);
              }
          }
          mWifiTracker.resumeScanning();
      }

Establezca una conexión de red:

protected void connect(final WifiConfiguration config, boolean isSavedNetwork) {
    
    
          // Log subtype if configuration is a saved network.
          mMetricsFeatureProvider.action(getContext(), SettingsEnums.ACTION_WIFI_CONNECT,
                  isSavedNetwork);
          mWifiManager.connect(config, mConnectListener);
          mClickedConnect = true;
      }

Ingrese a la función de guardar de WifiManager:

WifiManager.java

public void save(WifiConfiguration config, ActionListener listener) {
    
    
    getChannel().sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
}

Dar SAVE_NETWORK a WifiServiceImpl de WifiService

WifiServiceImpl.java

private class ClientHandler extends WifiHandler {
    
    
	case WifiManager.SAVE_NETWORK:
	{
    
    
		mWifiStateMachine.sendMessage(Message.obtain(msg));
}
}

WifiServiceImpl envía SAVE_NETWORK a la estación de procesamiento de cmd intermedia: WifiStateMachine

WifiEstadoMáquina

WifiStateMachine envía internamente el comando CMD_START_CONNECT comando a la máquina de estado interna: procesamiento ConnectModeState,


    private boolean connectToUserSelectNetwork(int netId, int uid, boolean forceReconnect) {
    
    
        logd("connectToUserSelectNetwork netId " + netId + ", uid " + uid
                + ", forceReconnect = " + forceReconnect);
        if (mWifiConfigManager.getConfiguredNetwork(netId) == null) {
    
    
            loge("connectToUserSelectNetwork Invalid network Id=" + netId);
            return false;
        }
        if (!mWifiConfigManager.enableNetwork(netId, true, uid)
                || !mWifiConfigManager.updateLastConnectUid(netId, uid)) {
    
    
            logi("connectToUserSelectNetwork Allowing uid " + uid
                    + " with insufficient permissions to connect=" + netId);
        } else if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) {
    
    
            // Note user connect choice here, so that it will be considered in the next network
            // selection.
            mWifiConnectivityManager.setUserConnectChoice(netId);
        }
        if (!forceReconnect && mWifiInfo.getNetworkId() == netId) {
    
    
            // We're already connected to the user specified network, don't trigger a
            // reconnection unless it was forced.
            logi("connectToUserSelectNetwork already connecting/connected=" + netId);
        } else {
    
    
            mWifiConnectivityManager.prepareForForcedConnection(netId);
            startConnectToNetwork(netId, uid, SUPPLICANT_BSSID_ANY);
        }
        return true;
    }
public void startConnectToNetwork(int networkId, int uid, String bssid) {
    
    
	sendMessage(CMD_START_CONNECT, networkId, uid, bssid);
}

Luego se envía a WifiNative para procesar Connect.

class ConnectModeState extends State {
    
    
	case WifiManager.SAVE_NETWORK:
	   startConnectToNetwork(netId, message.sendingUid, SUPPLICANT_BSSID_ANY);// 连接热点
	case CMD_START_CONNECT:
		mWifiNative.connectToNetwork(mInterfaceName, config); // 转到wifiNative 进行connect 
}

Wifi Nativo

   public boolean connectToNetwork(@NonNull String ifaceName, WifiConfiguration configuration) {
    
    
        // Abort ongoing scan before connect() to unblock connection request.
        mWificondControl.abortScan(ifaceName);
        return mSupplicantStaIfaceHal.connectToNetwork(ifaceName, configuration);
    }
 

Luego vino SuplicantStaIfaceHal,

SuplicanteStaIfaceHal

  public boolean connectToNetwork(@NonNull String ifaceName, @NonNull WifiConfiguration config) {
    
    
        synchronized (mLock) {
    
    
            logd("connectToNetwork " + config.configKey());
            WifiConfiguration currentConfig = getCurrentNetworkLocalConfig(ifaceName);
            if (WifiConfigurationUtil.isSameNetwork(config, currentConfig)) {
    
    
                String networkSelectionBSSID = config.getNetworkSelectionStatus()
                        .getNetworkSelectionBSSID();
                String networkSelectionBSSIDCurrent =
                        currentConfig.getNetworkSelectionStatus().getNetworkSelectionBSSID();
                if (Objects.equals(networkSelectionBSSID, networkSelectionBSSIDCurrent)) {
    
    
                    logd("Network is already saved, will not trigger remove and add operation.");
                } else {
    
    
                    logd("Network is already saved, but need to update BSSID.");
                    if (!setCurrentNetworkBssid(
                            ifaceName,
                            config.getNetworkSelectionStatus().getNetworkSelectionBSSID())) {
    
    
                        loge("Failed to set current network BSSID.");
                        return false;
                    }
                    mCurrentNetworkLocalConfigs.put(ifaceName, new WifiConfiguration(config));
                }
            } else {
    
    
                mCurrentNetworkRemoteHandles.remove(ifaceName);
                mCurrentNetworkLocalConfigs.remove(ifaceName);
                if (!removeAllNetworks(ifaceName)) {
    
    
                    loge("Failed to remove existing networks");
                    return false;
                }
                Pair<SupplicantStaNetworkHal, WifiConfiguration> pair =
                        addNetworkAndSaveConfig(ifaceName, config);
                if (pair == null) {
    
    
                    loge("Failed to add/save network configuration: " + config.configKey());
                    return false;
                }
                mCurrentNetworkRemoteHandles.put(ifaceName, pair.first);
                mCurrentNetworkLocalConfigs.put(ifaceName, pair.second);
            }
            SupplicantStaNetworkHal networkHandle =
                    checkSupplicantStaNetworkAndLogFailure(ifaceName, "connectToNetwork");
            if (networkHandle == null || !networkHandle.select()) {
    
    
                loge("Failed to select network configuration: " + config.configKey());
                return false;
            }
            return true;
        }
    }
public void onStateChanged(int newState, byte[/* 6 */] bssid, int id,ArrayList<Byte> ssid) {
    
    
	if (newSupplicantState == SupplicantState.COMPLETED){
    
    
		mWifiMonitor.broadcastNetworkConnectionEvent(mIfaceName, getCurrentNetworkId(mIfaceName), bssidStr);
	}
}

La función de selección está en SupplicantStaNetworkHal

SuplicanteStaNetworkHal

//Trigger a connection to this network.
public boolean select() {
    
    
        synchronized (mLock) {
    
    
            final String methodStr = "select";
            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
            try {
    
    
                SupplicantStatus status =  mISupplicantStaNetwork.select();
                return checkStatusAndLogFailure(status, methodStr);
            } catch (RemoteException e) {
    
    
                handleRemoteException(e, methodStr);
                return false;
            }
        }
    }
  • SupplicantStaIfaceHal agrega la red, ejecuta la función de selección, llama al suplicante a través de hidl, es decir, pasa la conexión a wpa_supplicant

sta_network

Return<void> StaNetwork::select(select_cb _hidl_cb)
{
    
    
	return validateAndCall(
	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
	    &StaNetwork::selectInternal, _hidl_cb);
}
 
SupplicantStatus StaNetwork::selectInternal()
{
    
    
	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
	if (wpa_ssid->disabled == 2) {
    
    
		return {
    
    SupplicantStatusCode::FAILURE_UNKNOWN, ""};
	}
	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
	wpa_s->scan_min_time.sec = 0;
	wpa_s->scan_min_time.usec = 0;
	// Make sure that the supplicant is updated to the latest
	// MAC address, which might have changed due to MAC randomization.
	wpa_supplicant_update_mac_addr(wpa_s);
	wpa_supplicant_select_network(wpa_s, wpa_ssid);
	return {
    
    SupplicantStatusCode::SUCCESS, ""};
}
  • Después de que wpa_supplicant completa una serie de tramas de baliza (sonda, asociación, 4way-handshake, group-handshake) con el enrutador, puede obtener el certificado emitido por el enrutador (es decir, el último certificado)
  • Finalmente, informe la tarea wpa_supplicant completada a través de wifiMonitor, que es la primera fase de la conexión (fase de conexión)
  • El evento reportado por WiFiMonitor es NETWORK_CONNECTION_EVENT (regrese a WifiStateMachine nuevamente)

wpa_supplicant se conecta y llama a la capa inferior y finalmente regresa a wifiMonitor
wifiMonitor informa NETWORK_CONNECTION_EVENT a WifiStateMachine y obtiene la ip en WifiStateMachine:

WifiEstadoMáquina

class ConnectModeState extends State {
    
    
	case WifiMonitor.NETWORK_CONNECTION_EVENT:
		.... 
		sendNetworkStateChangeBroadcast(mLastBssid);
		transitionTo(mObtainingIpState);
}
class ObtainingIpState extends State {
    
    
	... 
	setNetworkDetailedState(DetailedState.OBTAINING_IPADDR);
	clearTargetBssid("ObtainingIpAddress");
	stopIpClient();
	mIpClient.setHttpProxy(currentConfig.getHttpProxy());
	IpClient.buildProvisioningConfiguration(); 
	.... 
}

Después de obtener la IP de Android N, dhcpd se abandonó. IpClient e IpManager manejan el
proceso de conexión de IP en WifiStateMachine.
Aunque hay algunas diferencias en las versiones recientes del sistema Android, se puede resolver de acuerdo con mi propio código. Soy un poco paciente. Tenga cuidado, simplemente dibuje un proceso usted mismo, creo que el diagrama de flujo anterior ya es muy claro

Supongo que te gusta

Origin blog.csdn.net/weixin_42271802/article/details/112193257
Recomendado
Clasificación