您的位置:首页 > 移动开发 > Android开发

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

2017-09-27 15:01 453 查看
前两篇讲了打开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(mSoftApStart
b7d6
edState);
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的地方, 这一点下一篇继续讲!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android wifi