基于rk3288平台android5.1系统的wifi流程分析 ---- 打开热点,作为AP

前两篇讲了打开wifi,扫描热点和连接热点的流程, 那是wifi作为station模式下, 那么这一篇来了解下wifi作为AP的流程, 即打开热点。

 // ----------- packages/apps/settings/src/com/android/settings/TetherSettings.java ------------ //
public boolean onPreferenceChange(Preference preference, Object value) {
    boolean enable = (Boolean) value;

    if (enable) {
        startProvisioningIfNecessary(WIFI_TETHERING);
    } else {
        if (isProvisioningNeeded(mProvisionApp)) {
            TetherService.cancelRecheckAlarmIfNecessary(getActivity(), WIFI_TETHERING);
        }
        mWifiApEnabler.setSoftapEnabled(false);
    }
    return false;
}

private void startProvisioningIfNecessary(int choice) {
    mTetherChoice = choice;
    if (isProvisioningNeeded(mProvisionApp)) {
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.setClassName(mProvisionApp[0], mProvisionApp[1]);
        intent.putExtra(TETHER_CHOICE, mTetherChoice);
        startActivityForResult(intent, PROVISION_REQUEST);
    } else {
        startTethering();
    }
}

private void startTethering() {
    switch (mTetherChoice) {
        case WIFI_TETHERING:
            mWifiApEnabler.setSoftapEnabled(true);
            break;
    }
}
// --------- packages/apps/settings/src/com/android/settings/wifi/WifiApEnabler.java --------- //
public void setSoftapEnabled(boolean enable) {
    mWifiManager.setWifiApEnabled(null, enable);
}
// ------------- frameworks/base/wifi/java/android/net/wifi/WifiManager.java --------------- //
public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
    mService.setWifiApEnabled(wifiConfig, enabled);
}
// ----------- frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java ------------ //
public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
    if (wifiConfig == null || wifiConfig.isValid()) {
        mWifiController.obtainMessage(CMD_SET_AP, enabled ? 1 : 0, 0, wifiConfig).sendToTarget();
    }
}
// ----------- frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiController.java ------------ //
class ApStaDisabledState extends State {
    public boolean processMessage(Message msg) {
        switch (msg.what) {
            case CMD_SET_AP:
                if (msg.arg1 == 1) {
                    mWifiStateMachine.setHostApRunning((WifiConfiguration) msg.obj,true);
                    transitionTo(mApEnabledState);  // 这个状态是在WifiController中的状态机
                }
                break;
        }
    }
}
// ---------- frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java ----------- //
public void setHostApRunning(WifiConfiguration wifiConfig, boolean enable) {
    if (enable) {
        sendMessage(CMD_START_AP, wifiConfig);
    } else {
        sendMessage(CMD_STOP_AP);
    }
}
由于 WifiStateMachine状态机的初始状态为InitialState :

class InitialState extends State {
    public void enter() {
        if (mWifiApConfigChannel == null) {
            mWifiApConfigChannel = new AsyncChannel();
            WifiApConfigStore wifiApConfigStore = WifiApConfigStore.makeWifiApConfigStore(
                    mContext, getHandler());
            wifiApConfigStore.loadApConfiguration();        // 在这里就会从/data/misc/wifi/softap.conf文件中读取AP的配置!!
            // 并将配置保存在该类的mWifiApConfig变量中, 下面要用到!!
            mWifiApConfigChannel.connectSync(mContext, getHandler(),
                    wifiApConfigStore.getMessenger());      // mWifiApConfigChannel指定wifiApConfigStore为sendMessage的类。
        }
    }
    public boolean processMessage(Message message) {
        switch (message.what) {
            case CMD_START_AP:
                if (mWifiNative.loadDriver()) {                 // 这里会加载底层驱动,如果是编译成模块,则加载ko文件
                    setWifiApState(WIFI_AP_STATE_ENABLING);
                    transitionTo(mSoftApStartingState);
                } else {
                    loge("Failed to load driver for softap");
                }
        }
    }
}
class SoftApStartingState extends State {
    public void enter() {
        if (message.what == CMD_START_AP) {
            final WifiConfiguration config = (WifiConfiguration) message.obj;

            if (config == null) {
                mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG);        // 第一次是走这里,没有配置文件
            } else {
                mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);
                startSoftApWithConfig(config);
            }
        }
    }
}
从上面可以看到,mWifiApConfigChannel和WifiApConfigStore是关联的,由WifiApConfigStore来处理消息:

// --------- frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiApConfigStore.java ----------- //
class WifiApConfigStore extends StateMachine {
    WifiApConfigStore(Context context, Handler target) {
        addState(mDefaultState);
        addState(mInactiveState, mDefaultState);
        addState(mActiveState, mDefaultState);

        setInitialState(mInactiveState);
    }
}
虽然初始状态为mInactiveState, 由于mInactiveState状态机中没有对CMD_REQUEST_AP_CONFIG的处理,故追溯到其父类mDefaultState :

class DefaultState extends State {
    public boolean processMessage(Message message) {
        switch (message.what) {
           case WifiStateMachine.CMD_REQUEST_AP_CONFIG:
               mReplyChannel.replyToMessage(message,
                       WifiStateMachine.CMD_RESPONSE_AP_CONFIG, mWifiApConfig);     // 这里就将上面从/data/misc/wifi/softap.conf读到的配置返回
               break;
        }
    }
}
回到WifiStateMachine类,上面说到它现在所处状态是SoftApStartingState:

// --------- frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java --------- //
class SoftApStartingState extends State {
    public boolean processMessage(Message message) {
        switch(message.what) {
            case WifiStateMachine.CMD_RESPONSE_AP_CONFIG:
                WifiConfiguration config = (WifiConfiguration) message.obj;
                if (config != null) {
                    startSoftApWithConfig(config);
                } else {
                    loge("Softap config is null!");
                    sendMessage(CMD_START_AP_FAILURE);
                }
                break;
        }
    }
}

private void startSoftApWithConfig(final WifiConfiguration config) {
    // 在这里创建并启动一个线程
    new Thread(new Runnable() {
            public void run() {
                try {
                    mNwService.startAccessPoint(config, mInterfaceName); 
                } catch (Exception e) {
                    loge("Exception in softap start " + e);
                    try {
                        mNwService.stopAccessPoint(mInterfaceName);
                        mNwService.startAccessPoint(config, mInterfaceName);
                    } catch (Exception e1) {
                        loge("Exception in softap re-start " + e1);
                        sendMessage(CMD_START_AP_FAILURE);
                        return;
                    }
                }
                if (DBG) log("Soft AP start successful");
                sendMessage(CMD_START_AP_SUCCESS);
                if(!mSoftApWakeLock.isHeld()) {
                    loge("---- mSoftApWakeLock.acquire ----");
                    mSoftApWakeLock.acquire();
                }
            }
    }).start();
}
其中mNwService定义如下:
private INetworkManagementService mNwService;
mNwService = INetworkManagementService.Stub.asInterface(b);
这里调用了startAccessPoint方法!!

// -------- frameworks/base/services/core/java/com/android/server/NetworkManagementService.java ----------- //
public void startAccessPoint( WifiConfiguration wifiConfig, String wlanIface) {
    mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
    try {
        wifiFirmwareReload(wlanIface, "AP");                                    // 重新加载固件, 因为默认加载的是station的固件
        if (wifiConfig == null) {
            mConnector.execute("softap", "set", wlanIface);
        } else {
            mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
                    "broadcast", "6", getSecurityType(wifiConfig),
                    new SensitiveArg(wifiConfig.preSharedKey));                 // 先设置要打开的热点
        }
        mConnector.execute("softap", "startap");                                // 启动热点
    } catch (NativeDaemonConnectorException e) {
        throw e.rethrowAsParcelableException();
    }
}
上面执行的mConnector.execute,指定的command是“softap”,故执行的是以下命令:

// --------------- system\netd\server/CommandListener.cpp ------------------- //
int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
                                        int argc, char **argv) {
    if (!strcmp(argv[1], "startap")) {                      // 第二步执行
        rc = sSoftapCtrl->startSoftap();
    } else if (!strcmp(argv[1], "stopap")) {
        rc = sSoftapCtrl->stopSoftap();
    } else if (!strcmp(argv[1], "fwreload")) {
       check_wifi_chip_type_string(type);
       if(!strncmp(type, "ESP", 3))
        rc = 0;
       else
        rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
    } else if (!strcmp(argv[1], "status")) {
        asprintf(&retbuf, "Softap service %s running",
                 (sSoftapCtrl->isSoftapStarted() ? "is" : "is not"));
        cli->sendMsg(rc, retbuf, false);
        free(retbuf);
        return 0;
    } else if (!strcmp(argv[1], "set")) {                   // 第一步先执行
        rc = sSoftapCtrl->setSoftap(argc, argv);
    } else {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unrecognized SoftAP command", false);
        return 0;
    }
}
其中SoftapController *CommandListener::sSoftapCtrl = NULL;

// -------------- system/netd/server/SoftapController.cpp ---------------- //
static const char HOSTAPD_CONF_FILE[]    = "/data/misc/wifi/hostapd.conf";

int SoftapController::setSoftap(int argc, char *argv[]) {
    fd = open(HOSTAPD_CONF_FILE, O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW, 0660);
    write(fd, fbuf, strlen(fbuf);           // 这里会将从/data/misc/wifi/softap.conf读到的配置还有其他默认配置写入hostapd.conf文件
    fchmod(fd, 0660);                       // 改变文件属性
    fchown(fd, AID_SYSTEM, AID_WIFI);       // 改变文件属主
}

int SoftapController::startSoftap() {

    // 这里会判断/data/misc/wifi/entropy.bin文件是否存在,不存在则创建之, 并写入固定的加密数组内容!!
    if (ensure_entropy_file_exists() < 0) {             
        ALOGE("Wi-Fi entropy file was not created");
    }

    if ((pid = fork()) < 0) {                           // 这里用fork创建了子进程
        ALOGE("fork failed (%s)", strerror(errno));
        return ResponseCode::ServiceStartFailed;
    }

    if (!pid) {                                         // 在子进程中通过exec函数族替换掉子进程
        ensure_entropy_file_exists();

        // 这里就会执行hostapd -e /data/misc/wifi/entropy.bin /data/misc/wifi/hostapd.conf, 启动hostapd服务!!
        if (execl(hostapd_name, hostapd_name,           
                "-e", WIFI_ENTROPY_FILE,
                HOSTAPD_CONF_FILE, (char *) NULL)) {
            ALOGE("execl failed (%s)", strerror(errno));
        }
        ALOGE("SoftAP failed to start");
        return ResponseCode::ServiceStartFailed;
    } else {
        mPid = pid;
        ALOGD("SoftAP started successfully");
        usleep(AP_BSS_START_DELAY);
    }
}
回到WifiStateMachine类,上面说到它现在所处状态是SoftApStartingState, 执行到startSoftApWithConfig函数中的
mNwService.startAccessPoint(config, mInterfaceName); 之后就应该执行sendMessage(CMD_START_AP_SUCCESS);

// --------- frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java --------- //
class SoftApStartingState extends State {
    public boolean processMessage(Message message) {
        switch(message.what) {
            case CMD_START_AP_SUCCESS:
                setWifiApState(WIFI_AP_STATE_ENABLED);
                transitionTo(mSoftApStartedState);
                break;
        }
    }
}
class SoftApStartedState extends State {
    public boolean processMessage(Message message) {
        switch(message.what) {
            case CMD_STOP_AP:
                try {
                    mNwService.stopAccessPoint(mInterfaceName);
                } catch(Exception e) {
                    loge("Exception in stopAccessPoint()");
                }
                setWifiApState(WIFI_AP_STATE_DISABLED);
                transitionTo(mInitialState);
                break;

            case CMD_TETHER_STATE_CHANGE:
                TetherStateChange stateChange = (TetherStateChange) message.obj;
                if (startTethering(stateChange.available)) {
                    transitionTo(mTetheringState);
                }
                break;
        }
    }
}
收到CMD_START_AP_SUCCESS , AP已经成功开启了, 可以搜索的到该热点了, 但是此时是没法连接成功的,会卡在获取IP的地方, 这一点下一篇继续讲!















  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值