Android -- Wifi的save()操作

来源:互联网 发布:网络直播受众群体 编辑:程序博客网 时间:2024/05/17 04:09

Android -- Wifi的save()操作


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








0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 5岁宝宝左眼轻微散光怎么办光 孩子总吸鼻子但没有鼻涕怎么办 纹完眼线眼睛磨的很难受怎么办 我的脸型眼睛好看牙不好看怎么办 陌陌当日打招呼人数已达上限怎么办 新生婴儿白天睡觉晚上不睡怎么办 被有翅膀的蚂蚁咬了怎么办 被带翅膀的蚂蚁蛰了怎么办 被长翅膀的蚂蚁咬了怎么办 宝宝被带翅膀的蚂蚁咬了怎么办 新的小白鞋鞋子有点夹脚怎么办 单反快门按不下去里面响怎么办 在上海动漫城游戏厅里输了钱怎么办 电缝纫机扎快了上线有套那是怎么办 老式缝纫机底线总夹梭子上怎么办 两个月宝宝脸一边大一边小怎么办 炒股入金10万亏3万怎么办 如果一支股票有好几个庄家怎么办 浦发信用卡查询密码被锁定怎么办 浦发信用卡输错密码被锁定怎么办 浦发手机银行查询密码锁定怎么办 宝宝吃母乳没吃饱就睡着了怎么办 量柱画线不是方屏电脑怎么办 夏天卧室开空调太干了怎么办 健身房锻炼手臂抻的肌肉疼怎么办 人累了可以休息 心累了怎么办 上来两天班感觉不想做了怎么办 休产假的时候公司解散了怎么办 上三天班老板不给结工资怎么办 老师说孩子上课纪律不好我该怎么办 大班的孩子记不住拼音怎么办呢 家长跟孩子沟通出现问题该怎么办? 如果孩子入学分配出现问题该怎么办 2岁多的宝宝喜欢动手打人怎么办 儿童新长出的大门牙像两边撇怎么办 被烫伤了怎么办的活动反思怎么写 生完孩子脸上起蝴蝶斑了怎么办 鼻子部位突然长了晒斑怎么办 我脸上长有日晒斑.该怎么办 做为小领导同事不听你的怎么办 二年级的小孩叫写作业不听怎么办