Android(安卓)Softap启动分析
http://blog.csdn.net/airk000/article/details/9273599
设置中开关:
packages/apps/Settings/src/com/android/settings/TetherSettings.java
|----private void startTethering()
| |----mWifiApEnabler.setSoftapEnabled(true);
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);
IWifiManager.aidl
|----void setWifiApEnabled(in WifiConfiguration wifiConfig, boolean enable);
frameworks/base/services/java/com/android/server/WifiService.java
|----public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled)
| |----mWifiStateMachine.setWifiApEnabled(wifiConfig, enabled);
frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java
|----public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enable)
| |----sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_AP_STATE_ENABLING, 0));
| |----sendMessage(obtainMessage(CMD_START_AP, wifiConfig));
1.JAVA API部分
frameworks/base/wifi/java/android/net/wifi/WifiManager.java
[java] view plain copy- public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
- mService.setWifiApEnabled(wifiConfig, enabled);
- }
2.服务器端进程
frameworks/base/services/java/com/android/server/WifiService.java
[java] view plain copy- public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
- mWifiStateMachine.setWifiApEnabled(wifiConfig, enabled);
- }
消息循环,状态机
frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java
- public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enable) {
- if (enable) {
- sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_AP_STATE_ENABLING, 0));
- sendMessage(obtainMessage(CMD_START_AP, wifiConfig));
- } else {
- sendMessage(CMD_STOP_AP);
- sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_DISABLED, 0));
- }
- }
public WifiStateMachine(Context context, String wlanInterface) {
mWifiConfigStore = new WifiConfigStore(context, mWifiNative);
WifiApConfigStore wifiApConfigStore = WifiApConfigStore.makeWifiApConfigStore(
context, getHandler());
wifiApConfigStore.loadApConfiguration(); // private static final String AP_CONFIG_FILE = Environment.getDataDirectory() + "/misc/wifi/softap.conf";
mWifiApConfigChannel.connectSync(mContext, getHandler(), wifiApConfigStore.getMessenger());
}
class Initial State extends State {
if(mWifiNative.isDriverLoaded()){
transitionTo(mDriverLoadedState);
}
else{ //因为最开始驱动都是没有加载的,所以进入transitionTo(mDriverUnloadedState);
transitionTo(mDriverUnloadedState);
}
WifiStateMachine进入DriverUnloadedState
classDriverUnloadedState extends State {
publicboolean processMessage(Message message) {
switch(message.what) {
case CMD_LOAD_DRIVER:
transitionTo(mDriverLoadingState);
这里会处理刚才的CMD_LOAD_DRIVER这个消息,继续切换到mDriverLoadingState
classDriverLoadingState extends State {
publicvoid enter() {
newThread(new Runnable() {
publicvoid run() {
mWakeLock.acquire();
//enablingstate
switch(message.arg1){
case WIFI_AP_STATE_ENABLING:mWifiMode = 1;
setWifiApState(WIFI_AP_STATE_ENABLING);
}
if(mWifiNative.loadDriver()){ ---------------------------------------------------------->
sendMessage(CMD_LOAD_DRIVER_SUCCESS);
}
publicboolean processMessage(Message message) {
switch(message.what) {
caseCMD_LOAD_DRIVER_SUCCESS:
transitionTo(mDriverLoadedState);
}
这里会调用WifiNative.loadDriver()加载驱动,成功后发送消息CMD_LOAD_DRIVER_SUCCESS,然后进入mDriverLoadedState。否则发送CMD_LOAD_DRIVER_FAILURE,进入mDriverFailedState
来看另一个消息sendMessage(CMD_START_AP)
case CMD_START_AP:transitionTo(mSoftApStartingState);
class SoftApStartingState extends State {
public void enter() {
final Message message = getCurrentMessage();
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);
}
frameworks/base/wifi/java/android/net/wifi/WifiApConfigStore.java
class WifiApConfigStore extends StateMachine {
class DefaultState extends State {
case WifiStateMachine.CMD_REQUEST_AP_CONFIG:
mReplyChannel.replyToMessage(message,
WifiStateMachine.CMD_RESPONSE_AP_CONFIG, mWifiApConfig);
break;
当前WIFI状态机状态为SoftApStartingState,所以回复消息在这里处理:
class SoftApStartingState{
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;
case CMD_START_AP_SUCCESS:
setWifiApState(WIFI_AP_STATE_ENABLED);
transitionTo(mSoftApStartedState);
break;
private void startSoftApWithConfig(final WifiConfiguration config) {
// start hostapd on a seperate thread
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);
}
}).start();
}
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
mNwService = INetworkManagementService.Stub.asInterface(b);
frameworks/base/services/java/com/android/server/NetworkManagementService.java
public void startAccessPoint(
WifiConfiguration wifiConfig, String wlanIface) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
wifiFirmwareReload(wlanIface, "AP"); //mConnector.execute("softap", "fwreload", wlanIface, mode); wlanIface就是prop指定的wifi.interface,默认为wlan0,mode为"AP",共计四 个参数
if (wifiConfig == null) {
mConnector.execute("softap", "set", wlanIface);
} else {
mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID, //mConnector = new NativeDaemonConnector( new NetdCallbackReceiver(), "netd", 10, NETD_TAG, 160);
getSecurityType(wifiConfig), wifiConfig.preSharedKey);
}
mConnector.execute("softap", "startap");
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
}
class InactiveState
case WifiStateMachine.CMD_SET_AP_CONFIG:
mWifiApConfig = (WifiConfiguration) message.obj;
transitionTo(mActiveState);
break;
class ActiveState extends State {
public void enter() {
new Thread(new Runnable() {
public void run() {
writeApConfiguration(mWifiApConfig);
sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED);
}
}).start();
}
public boolean processMessage(Message message) {
switch (message.what) {
//TODO: have feedback to the user when we do this
//to indicate the write is currently in progress
case WifiStateMachine.CMD_SET_AP_CONFIG:
deferMessage(message);
break;
case WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED:
transitionTo(mInactiveState);
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
}
这里的配置文件是通过WifiManager的setWifiApConfiguration接口生成的:
- public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
- try {
- mService.setWifiApConfiguration(wifiConfig);
- return true;
- public void setWifiApConfiguration(WifiConfiguration wifiConfig) {
- enforceChangePermission();
- if (wifiConfig == null)
- return;
- mWifiStateMachine.setWifiApConfiguration(wifiConfig);
- public void setWifiApConfiguration(WifiConfiguration config) {
- mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);
- }
class InactiveState extends State {
public boolean processMessage(Message message) {
switch (message.what) {
case WifiStateMachine.CMD_SET_AP_CONFIG:
mWifiApConfig = (WifiConfiguration) message.obj;
transitionTo(mActiveState); //触发ActiveState.enter()
break ;
class ActiveState extends State {
public void enter() {
new Thread( new Runnable() {
public void run() {
writeApConfiguration(mWifiApConfig);
sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED);
}
}).start();
}
- mConnector.execute("softap", "fwreload", wlanIface, mode);
- mConnector.execute("softap", "set", wlanIface, softapIface, wifiConfig.SSID,
- getSecurityType(wifiConfig), wifiConfig.preSharedKey);
- mConnector.execute("softap", "startap");
-
固件重载
wlanIface就是prop指定的wifi.interface,默认为wlan0,mode为"AP",共计四个参数。 这两条命令都会最终执行到这里:
public NativeDaemonEvent[] execute(int timeout, String cmd, Object... args)
throws NativeDaemonConnectorException {
final ArrayList
final int sequenceNumber = mSequenceNumber.incrementAndGet();
final StringBuilder cmdBuilder =
new StringBuilder(Integer.toString(sequenceNumber)).append(' ');
final long startTime = SystemClock.elapsedRealtime();
makeCommand(cmdBuilder, cmd, args);
final String logCmd = cmdBuilder.toString(); /* includes cmdNum, cmd, args */
log("SND -> {" + logCmd + "}");
cmdBuilder.append('\0');
final String sentCmd = cmdBuilder.toString(); /* logCmd + \0 */
synchronized (mDaemonLock) {
if (mOutputStream == null) {
throw new NativeDaemonConnectorException("missing output stream");
} else {
try {
mOutputStream.write(sentCmd.getBytes(Charsets.UTF_8));
} catch (IOException e) {
throw new NativeDaemonConnectorException("problem sending command", e);
}
}
}
NativeDaemonEvent event = null;
do {
event = mResponseQueue.remove(sequenceNumber, timeout, sentCmd);
if (event == null) {
loge("timed-out waiting for response to " + logCmd);
throw new NativeDaemonFailureException(logCmd, event);
}
log("RMV <- {" + event + "}");
events.add(event);
} while (event.isClassContinue());
final long endTime = SystemClock.elapsedRealtime();
if (endTime - startTime > WARN_EXECUTE_DELAY_MS) {
loge("NDC Command {" + logCmd + "} took too long (" + (endTime - startTime) + "ms)");
}
if (event.isClassClientError()) {
throw new NativeDaemonArgumentException(logCmd, event);
}
if (event.isClassServerError()) {
throw new NativeDaemonFailureException(logCmd, event);
}
return events.toArray(new NativeDaemonEvent[events.size()]);
}
system/netd/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")) {
- rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
- } else if (!strcmp(argv[1], "clients")) {
- rc = sSoftapCtrl->clientsSoftap(&retbuf);
- if (!rc) {
- cli->sendMsg(ResponseCode::CommandOkay, retbuf, false);
- free(retbuf);
- return 0;
- }
- } else if (!strcmp(argv[1], "status")) {
- asprintf(&retbuf, "Softap service %s", (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped"));
- cli->sendMsg(ResponseCode::SoftapStatusResult, retbuf, false);
- free(retbuf);
- return 0;
- } else if (!strcmp(argv[1], "set")) {
- rc = sSoftapCtrl->setSoftap(argc, argv);
- } else {
- cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd", false);
- return 0;
- }
- }
system/netd/SoftapController.cpp
- int SoftapController::setSoftap(int argc, char *argv[]) {
- if (argc > 3) {
- ssid = argv[3];
- } else {
- ssid = (char *)"AndroidAP";
- }
- asprintf(&wbuf, "interface=%s\ndriver=nl80211\nctrl_interface="
- "/data/misc/wifi/hostapd\nssid=%s\nchannel=6\nieee80211n=1\n",
- iface, ssid);
- if (argc > 4) {
- if (!strcmp(argv[4], "wpa-psk")) {
- generatePsk(ssid, argv[5], psk_str);
- asprintf(&fbuf, "%swpa=1\nwpa_pairwise=TKIP CCMP\nwpa_psk=%s\n", wbuf, psk_str);
- } else if (!strcmp(argv[4], "wpa2-psk")) {
- generatePsk(ssid, argv[5], psk_str);
- asprintf(&fbuf, "%swpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", wbuf, psk_str);
- } else if (!strcmp(argv[4], "open")) {
- asprintf(&fbuf, "%s", wbuf);
- }
- } else {
- asprintf(&fbuf, "%s", wbuf);
- }
- //static const char HOSTAPD_CONF_FILE[] = "/data/misc/wifi/hostapd.conf";
- //配置文件/data/misc/wifi/hostapd.conf
- fd = open(HOSTAPD_CONF_FILE, O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW, 0660);
- if (write(fd, fbuf, strlen(fbuf)) < 0) {
- ALOGE("Cannot write to \"%s\": %s", HOSTAPD_CONF_FILE, strerror(errno));
- ret = -1;
- }
- }
- int SoftapController::startSoftap() {
- if ((pid = fork()) < 0) {
- ALOGE("fork failed (%s)", strerror(errno));
- return -1;
- }
- if (!pid) {
- ensure_entropy_file_exists();
- if (execl("/system/bin/hostapd", "/system/bin/hostapd",
- "-e", WIFI_ENTROPY_FILE,
- HOSTAPD_CONF_FILE, (char *) NULL)) {
- ALOGE("execl failed (%s)", strerror(errno));
- }
- ALOGE("Should never get here!");
- return -1;
- } else {
- mPid = pid;
- ALOGD("Softap startap - Ok");
- usleep(AP_BSS_START_DELAY);
- }
- }
更多相关文章
- Android(安卓)edittext刚进入页面取消焦点
- Android(安卓)进入Activity中默认不弹出软键盘
- android带消息红点的视图,超简洁的实现
- Activity配置属性
- android,进入页面textview默认获得焦点问题,如何取消焦点
- Android(安卓)的消息队列模型
- Android(安卓)的消息队列模型
- Android(安卓)的消息队列模型
- Android基本功:Handler消息传送机制