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
  1. public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {  
  2.   mService.setWifiApEnabled(wifiConfig, enabled);  
  3. }  
  4.   

2.服务器端进程

frameworks/base/services/java/com/android/server/WifiService.java

[java]  view plain copy
  1. public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {  
  2.   mWifiStateMachine.setWifiApEnabled(wifiConfig, enabled);  
  3. }  
  4.   

消息循环,状态机

frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java

  1. public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enable) {  
  2.   if (enable) {  
  3.     sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_AP_STATE_ENABLING, 0));  
  4.     sendMessage(obtainMessage(CMD_START_AP, wifiConfig));  
  5.   } else {  
  6.     sendMessage(CMD_STOP_AP);  
  7.     sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_DISABLED, 0));  
  8.   }  
  9. }  


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接口生成的:

  1. public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {  
  2.     try {  
  3.         mService.setWifiApConfiguration(wifiConfig);  
  4.         return true;  
  1. public void setWifiApConfiguration(WifiConfiguration wifiConfig) {  
  2.     enforceChangePermission();  
  3.     if (wifiConfig == null)  
  4.         return;  
  5.     mWifiStateMachine.setWifiApConfiguration(wifiConfig);  
真是的实现有抛给了WifiStateMachine:

  1. public void setWifiApConfiguration(WifiConfiguration config) {  
  2.     mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);  
  3. }   

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();  
    }  



  1. mConnector.execute("softap""fwreload", wlanIface, mode);  
  2. mConnector.execute("softap""set", wlanIface, softapIface, wifiConfig.SSID,  
  3.                         getSecurityType(wifiConfig), wifiConfig.preSharedKey);  
  4. mConnector.execute("softap""startap");

固件重载

wlanIface就是prop指定的wifi.interface,默认为wlan0,mode为"AP",共计四个参数。
这两条命令都会最终执行到这里:



    public NativeDaemonEvent[] execute(int timeout, String cmd, Object... args)
            throws NativeDaemonConnectorException {
        final ArrayList events = Lists.newArrayList();


        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

  1. int CommandListener::SoftapCmd::runCommand(SocketClient *cli,  
  2.                                         int argc, char **argv) {  
  3.   if (!strcmp(argv[1], "startap")) {  
  4.     rc = sSoftapCtrl->startSoftap();  
  5.   } else if (!strcmp(argv[1], "stopap")) {  
  6.      rc = sSoftapCtrl->stopSoftap();  
  7.   } else if (!strcmp(argv[1], "fwreload")) {  
  8.      rc = sSoftapCtrl->fwReloadSoftap(argc, argv);  
  9.   } else if (!strcmp(argv[1], "clients")) {  
  10.      rc = sSoftapCtrl->clientsSoftap(&retbuf);  
  11.      if (!rc) {  
  12.        cli->sendMsg(ResponseCode::CommandOkay, retbuf, false);  
  13.        free(retbuf);  
  14.        return 0;  
  15.      }  
  16.   } else if (!strcmp(argv[1], "status")) {  
  17.      asprintf(&retbuf, "Softap service %s", (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped"));  
  18.      cli->sendMsg(ResponseCode::SoftapStatusResult, retbuf, false);  
  19.      free(retbuf);  
  20.      return 0;  
  21.   } else if (!strcmp(argv[1], "set")) {  
  22.      rc = sSoftapCtrl->setSoftap(argc, argv);  
  23.   } else {  
  24.      cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd"false);  
  25.      return 0;  
  26.   }  
  27. }  


system/netd/SoftapController.cpp

  1. int SoftapController::setSoftap(int argc, char *argv[]) {  
  2.   if (argc > 3) {  
  3.     ssid = argv[3];  
  4.   } else {  
  5.      ssid = (char *)"AndroidAP";  
  6.   }  
  7.   asprintf(&wbuf, "interface=%s\ndriver=nl80211\nctrl_interface="  
  8.             "/data/misc/wifi/hostapd\nssid=%s\nchannel=6\nieee80211n=1\n",  
  9.             iface, ssid);   
  10.   if (argc > 4) {  
  11.     if (!strcmp(argv[4], "wpa-psk")) {  
  12.       generatePsk(ssid, argv[5], psk_str);  
  13.       asprintf(&fbuf, "%swpa=1\nwpa_pairwise=TKIP CCMP\nwpa_psk=%s\n", wbuf, psk_str);  
  14.     } else if (!strcmp(argv[4], "wpa2-psk")) {  
  15.        generatePsk(ssid, argv[5], psk_str);  
  16.        asprintf(&fbuf, "%swpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", wbuf, psk_str);  
  17.     } else if (!strcmp(argv[4], "open")) {  
  18.        asprintf(&fbuf, "%s", wbuf);  
  19.     }  
  20.   } else {  
  21.      asprintf(&fbuf, "%s", wbuf);  
  22.   }  
  23.   //static const char HOSTAPD_CONF_FILE[]    = "/data/misc/wifi/hostapd.conf";  
  24.   //配置文件/data/misc/wifi/hostapd.conf  
  25.   fd = open(HOSTAPD_CONF_FILE, O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW, 0660);  
  26.   if (write(fd, fbuf, strlen(fbuf)) < 0) {  
  27.     ALOGE("Cannot write to \"%s\": %s", HOSTAPD_CONF_FILE, strerror(errno));  
  28.     ret = -1;  
  29.   }  
  30. }  
  31.   
  32. int SoftapController::startSoftap() {  
  33.   if ((pid = fork()) < 0) {  
  34.     ALOGE("fork failed (%s)", strerror(errno));  
  35.     return -1;  
  36.   }  
  37.   if (!pid) {  
  38.     ensure_entropy_file_exists();  
  39.     if (execl("/system/bin/hostapd""/system/bin/hostapd",  
  40.                   "-e", WIFI_ENTROPY_FILE,  
  41.                   HOSTAPD_CONF_FILE, (char *) NULL)) {  
  42.       ALOGE("execl failed (%s)", strerror(errno));  
  43.     }  
  44.     ALOGE("Should never get here!");  
  45.     return -1;  
  46.   } else {  
  47.      mPid = pid;  
  48.      ALOGD("Softap startap - Ok");  
  49.      usleep(AP_BSS_START_DELAY);  
  50.   }  
  51. }  







你可能感兴趣的:(Android)