Android -- Wifi的save()操作

来源:互联网 发布:嘻游网络加速器 编辑:程序博客网 时间:2024/06/06 02:44

Android -- Wifi的save()操作

代码主要来自android 6.0
当我们在Settings中设置静态IP连接时,会调用到WifiManager::save()函数:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. /** 
  2.   * Save the given network in the supplicant config. If the network already 
  3.   * exists, the configuration is updated. A new network is enabled 
  4.   * by default. 
  5.   * 
  6.   * For a new network, this function is used instead of a 
  7.   * sequence of addNetwork(), enableNetwork() and saveConfiguration(). 
  8.   * 
  9.   * For an existing network, it accomplishes the task of updateNetwork() 
  10.   * and saveConfiguration() 
  11.   * 
  12.   * @param config the set of variables that describe the configuration, 
  13.   *            contained in a {@link WifiConfiguration} object. 
  14.   * @param listener for callbacks on success or failure. Can be null. 
  15.   * @throws IllegalStateException if the WifiManager instance needs to be 
  16.   * initialized again 
  17.   * @hide 
  18.   */  
  19.  public void save(WifiConfiguration config, ActionListener listener) {  
  20.      if (config == nullthrow new IllegalArgumentException("config cannot be null");  
  21.      validateChannel();  
  22.      sAsyncChannel.sendMessage(SAVE_NETWORK, 0, putListener(listener), config);  
  23.  }  
有注释可知,save函数会把传入WifiConfiguration信息代表的网络保存进wpa_supplicant.conf文件中;如果网络是已经存在的,则会更新信息;如果是新添加的,则会重新添加到配置文件中。
WifiServiceImpl::ClientHandler处理该消息:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. /* Client commands are forwarded to state machine */  
  2.                 case WifiManager.CONNECT_NETWORK:  
  3.                 case WifiManager.SAVE_NETWORK: {  
  4.                     WifiConfiguration config = (WifiConfiguration) msg.obj;  
  5.                     int networkId = msg.arg1;  
  6.                     if (msg.what == WifiManager.SAVE_NETWORK) {  
  7.                         Slog.e("WiFiServiceImpl ""SAVE"  
  8.                                 + " nid=" + Integer.toString(networkId)  
  9.                                 + " uid=" + msg.sendingUid  
  10.                                 + " name="  
  11.                                 + mContext.getPackageManager().getNameForUid(msg.sendingUid));  
  12.                     }  
  13.                     if (msg.what == WifiManager.CONNECT_NETWORK) {  
  14.                         Slog.e("WiFiServiceImpl ""CONNECT "  
  15.                                 + " nid=" + Integer.toString(networkId)  
  16.                                 + " uid=" + msg.sendingUid  
  17.                                 + " name="  
  18.                                 + mContext.getPackageManager().getNameForUid(msg.sendingUid));  
  19.                     }  
  20.   
  21.                     if (config != null && isValid(config)) {  
  22.                         if (DBG) Slog.d(TAG, "Connect with config" + config);  
  23.                         mWifiStateMachine.sendMessage(Message.obtain(msg));  
  24.                     } else if (config == null  
  25.                             && networkId != WifiConfiguration.INVALID_NETWORK_ID) {  
  26.                         if (DBG) Slog.d(TAG, "Connect with networkId" + networkId);  
  27.                         mWifiStateMachine.sendMessage(Message.obtain(msg));  
  28.                     } else {  
  29.                         Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg);  
  30.                         if (msg.what == WifiManager.CONNECT_NETWORK) {  
  31.                             replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED,  
  32.                                     WifiManager.INVALID_ARGS);  
  33.                         } else {  
  34.                             replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED,  
  35.                                     WifiManager.INVALID_ARGS);  
  36.                         }  
  37.                     }  
  38.                     break;  
  39.                 }  
主要做消息转发处理,看WifiStateMachine中的处理流程。ConnectModeState状态处理该消息:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. case WifiManager.SAVE_NETWORK:  
  2.                     mWifiConnectionStatistics.numWifiManagerJoinAttempt++;  
  3.                     // Fall thru  
  4.                 case WifiStateMachine.CMD_AUTO_SAVE_NETWORK:  
  5.                     lastSavedConfigurationAttempt = null// Used for debug  
  6.                     config = (WifiConfiguration) message.obj;  
  7.                     if (config == null) {  
  8.                         loge("ERROR: SAVE_NETWORK with null configuration"  
  9.                                 + mSupplicantStateTracker.getSupplicantStateName()  
  10.                                 + " my state " + getCurrentState().getName());  
  11.                         messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL;  
  12.                         replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED,  
  13.                                 WifiManager.ERROR);  
  14.                         break;  
  15.                     }  
  16.                     lastSavedConfigurationAttempt = new WifiConfiguration(config);  
  17.                     int nid = config.networkId;  
  18.                     logd("SAVE_NETWORK id=" + Integer.toString(nid)  
  19.                                 + " config=" + config.SSID  
  20.                                 + " nid=" + config.networkId  
  21.                                 + " supstate=" + mSupplicantStateTracker.getSupplicantStateName()  
  22.                                 + " my state " + getCurrentState().getName());  
  23.   
  24.                     // Only record the uid if this is user initiated  
  25.                     boolean checkUid = (message.what == WifiManager.SAVE_NETWORK);  
  26.                     if (checkUid && !recordUidIfAuthorized(config, message.sendingUid,  
  27.                             /* onlyAnnotate */ false)) {  
  28.                         logw("Not authorized to update network "  
  29.                              + " config=" + config.SSID  
  30.                              + " cnid=" + config.networkId  
  31.                              + " uid=" + message.sendingUid);  
  32.                         replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED,  
  33.                                        WifiManager.NOT_AUTHORIZED);  
  34.                         break;  
  35.                     }  
  36.   
  37.                     result = mWifiConfigStore.saveNetwork(config, WifiConfiguration.UNKNOWN_UID);  
  38.                     if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) {  
  39.                         if (mWifiInfo.getNetworkId() == result.getNetworkId()) {  
  40.                             if (result.hasIpChanged()) {  
  41.                                 // The currently connection configuration was changed  
  42.                                 // We switched from DHCP to static or from static to DHCP, or the  
  43.                                 // static IP address has changed.  
  44.                                 log("Reconfiguring IP on connection");  
  45.                                 // TODO: clear addresses and disable IPv6  
  46.                                 // to simplify obtainingIpState.  
  47.                                 transitionTo(mObtainingIpState);  
  48.                             }  
  49.                             if (result.hasProxyChanged()) {  
  50.                                 log("Reconfiguring proxy on connection");  
  51.                                 updateLinkProperties(CMD_UPDATE_LINKPROPERTIES);  
  52.                             }  
  53.                         }  
  54.                         replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED);  
  55.                         broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config);  
  56.   
  57.                         if (VDBG) {  
  58.                            logd("Success save network nid="  
  59.                                     + Integer.toString(result.getNetworkId()));  
  60.                         }  
  61.   
  62.                         synchronized(mScanResultCache) {  
  63.                             /** 
  64.                              * If the command comes from WifiManager, then 
  65.                              * tell autojoin the user did try to modify and save that network, 
  66.                              * and interpret the SAVE_NETWORK as a request to connect 
  67.                              */  
  68.                             boolean user = message.what == WifiManager.SAVE_NETWORK;  
  69.   
  70.                             // Did this connect come from settings  
  71.                             boolean persistConnect =  
  72.                                 mWifiConfigStore.checkConfigOverridePermission(message.sendingUid);  
  73.   
  74.                             if (user) {  
  75.                                 mWifiConfigStore.updateLastConnectUid(config, message.sendingUid);  
  76.                                 mWifiConfigStore.writeKnownNetworkHistory(false);  
  77.                             }  
  78.   
  79.                             mWifiAutoJoinController.updateConfigurationHistory(result.getNetworkId()  
  80.                                     , user, persistConnect);  
  81.                             mWifiAutoJoinController.attemptAutoJoin();  
  82.                         }  
  83.                     } else {  
  84.                         loge("Failed to save network");  
  85.                         messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL;  
  86.                         replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED,  
  87.                                 WifiManager.ERROR);  
  88.                     }  
  89.                     break;  
如果检测出IP配置信息有变化,则会切换到ObtainingIpState状态,并触发autojoin流程。如果用户使用的是静态IP,看ObtainingIpState的enter()函数:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. if (!mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {  
  2.                 if (isRoaming()) {  
  3.                     renewDhcp();  
  4.                 } else {  
  5.                     // Remove any IP address on the interface in case we're switching from static  
  6.                     // IP configuration to DHCP. This is safe because if we get here when not  
  7.                     // roaming, we don't have a usable address.  
  8.                     clearIPv4Address(mInterfaceName);  
  9.                     startDhcp();  
  10.                 }  
  11.                 obtainingIpWatchdogCount++;  
  12.                 logd("Start Dhcp Watchdog " + obtainingIpWatchdogCount);  
  13.                 // Get Link layer stats so as we get fresh tx packet counters  
  14.                 getWifiLinkLayerStats(true);  
  15.                 sendMessageDelayed(obtainMessage(CMD_OBTAINING_IP_ADDRESS_WATCHDOG_TIMER,  
  16.                         obtainingIpWatchdogCount, 0), OBTAINING_IP_ADDRESS_GUARD_TIMER_MSEC);  
  17.             } else {  
  18.                 // stop any running dhcp before assigning static IP  
  19.                 stopDhcp();  
  20.                 StaticIpConfiguration config = mWifiConfigStore.getStaticIpConfiguration(  
  21.                         mLastNetworkId);  
  22.                 if (config.ipAddress == null) {  
  23.                     logd("Static IP lacks address");  
  24.                     sendMessage(CMD_STATIC_IP_FAILURE);  
  25.                 } else {  
  26.                     InterfaceConfiguration ifcg = new InterfaceConfiguration();  
  27.                     ifcg.setLinkAddress(config.ipAddress);  
  28.                     ifcg.setInterfaceUp();  
  29.                     try {  
  30.                         mNwService.setInterfaceConfig(mInterfaceName, ifcg);  
  31.                         if (DBG) log("Static IP configuration succeeded");  
  32.                         DhcpResults dhcpResults = new DhcpResults(config);  
  33.                         sendMessage(CMD_STATIC_IP_SUCCESS, dhcpResults);  
  34.                     } catch (RemoteException re) {  
  35.                         loge("Static IP configuration failed: " + re);  
  36.                         sendMessage(CMD_STATIC_IP_FAILURE);  
  37.                     } catch (IllegalStateException e) {  
  38.                         loge("Static IP configuration failed: " + e);  
  39.                         sendMessage(CMD_STATIC_IP_FAILURE);  
  40.                     }  
  41.                 }  
  42.             }  
看else分支,在设置静态IP之前,调用stopDhcp()停掉当前的dhcp流程,获取到上层传入的静态IP配置信息:
  1. 如果config为null,则认为静态配置失败
  2. 调用mNwService.setInterfaceConfig(),设置配置的IP地址信息
  3. 组装DhcpResults对象,并发送CMD_STATIC_IP_SUCCESS消息,更新网络状态
CMD_STATIC_IP_SUCCESS在ObtainingIpState被处理:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. case CMD_STATIC_IP_SUCCESS:  
  2.     handleIPv4Success((DhcpResults) message.obj, CMD_STATIC_IP_SUCCESS);  
  3.     break;  
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. private void handleIPv4Success(DhcpResults dhcpResults, int reason) {  
  2.   
  3.     if (PDBG) {  
  4.         logd("handleIPv4Success <" + dhcpResults.toString() + ">");  
  5.         logd("link address " + dhcpResults.ipAddress);  
  6.     }  
  7.   
  8.     Inet4Address addr;  
  9.     synchronized (mDhcpResultsLock) {  
  10.         mDhcpResults = dhcpResults;  
  11.         addr = (Inet4Address) dhcpResults.ipAddress.getAddress();  
  12.     }  
  13.   
  14.     if (isRoaming()) {  
  15.         int previousAddress = mWifiInfo.getIpAddress();  
  16.         int newAddress = NetworkUtils.inetAddressToInt(addr);  
  17.         if (previousAddress != newAddress) {  
  18.             logd("handleIPv4Success, roaming and address changed" +  
  19.                     mWifiInfo + " got: " + addr);  
  20.         }  
  21.     }  
  22.     mWifiInfo.setInetAddress(addr);  
  23.     mWifiInfo.setMeteredHint(dhcpResults.hasMeteredHint());  
  24.     updateLinkProperties(reason);  
  25. }  
将当前静态IP设置的DhcpResults赋给状态机的成员变量mDchpResults,最后调用updateLinkProperties()更新连接配置信息:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. // If we just configured or lost IP configuration, do the needful.  
  2.         // We don't just call handleSuccessfulIpConfiguration() or handleIpConfigurationLost()  
  3.         // here because those should only be called if we're attempting to connect or already  
  4.         // connected, whereas updateLinkProperties can be called at any time.  
  5.         switch (reason) {  
  6.             case DhcpStateMachine.DHCP_SUCCESS:  
  7.             case CMD_STATIC_IP_SUCCESS:  
  8.                 // IPv4 provisioning succeded. Advance to connected state.  
  9.                 sendMessage(CMD_IP_CONFIGURATION_SUCCESSFUL);  
  10.                 if (!isProvisioned) {  
  11.                     // Can never happen unless DHCP reports success but isProvisioned thinks the  
  12.                     // resulting configuration is invalid (e.g., no IPv4 address, or the state in  
  13.                     // mLinkProperties is out of sync with reality, or there's a bug in this code).  
  14.                     // TODO: disconnect here instead. If our configuration is not usable, there's no  
  15.                     // point in staying connected, and if mLinkProperties is out of sync with  
  16.                     // reality, that will cause problems in the future.  
  17.                     logd("IPv4 config succeeded, but not provisioned");  
  18.                 }  
  19.                 break;  
跟踪CMD_IP_CONFIGURATION_SUCCESSFUL消息。ObtainingIpState不处理该消息,其父状态L2ConnectedState处理:
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. case CMD_IP_CONFIGURATION_SUCCESSFUL:  
  2.     handleSuccessfulIpConfiguration();  
  3.     sendConnectedState();  
  4.     transitionTo(mConnectedState);  
  5.     break;  
静态IP配置成功后,调用handleSuccessfulIpConfiguration()做之后的一些准备工作;调用sendConnectedState(),发送WifiManager.NETWORK_STATE_CHANGED_ACTION广播,通知其他组件网络连接状态的变化(此处是CONNECTED)。最后将Wifi状态机切换到ConnectedSate,代表网络已经连接完成。
0 0
原创粉丝点击