mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);本文將探討由wifi system service到hardware做動的部分。
WifiService 註冊
ServiceManager.addService() 為所有service註冊都要用到的函式。WifiService也是,程式如下。
private ConnectivityService(Context context) { for (int netType : mPriorityList) { switch (mNetAttributes[netType].mRadio) { case ConnectivityManager.TYPE_WIFI: if (DBG) log("Starting Wifi Service."); WifiStateTracker wst = new WifiStateTracker(); WifiService wifiService = new WifiService(context); ServiceManager.addService(Context.WIFI_SERVICE, wifiService); wifiService.checkAndStartWifi(); mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst; wst.startMonitoring(context, mHandler); //TODO: as part of WWS refactor, create only when needed mWifiWatchdogService = new WifiWatchdogService(context); break;ConnectivityService是在SystemServer建構函式用到,至於SystemServer如何被叫到,自行去找Zygote的介紹
try { Slog.i(TAG, "Connectivity Service"); connectivity = ConnectivityService.getInstance(context); ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity); } catch (Throwable e) { Slog.e(TAG, "Failure starting Connectivity Service", e); }
Service
開關Wifi是透過setWifiEnabled(),其Service內的實作程式如下
public synchronized boolean setWifiEnabled(boolean enable) { enforceChangePermission(); if (DBG) { Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n"); } if (enable) { reportStartWorkSource(); } mWifiStateMachine.setWifiEnabled(enable);最重要的是它用了WifiStateMachine::setWifiEnabled(),它實作如下
public void setWifiEnabled(boolean enable) { mLastEnableUid.set(Binder.getCallingUid()); if (enable) { /* Argument is the state that is entered prior to load */ sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0)); sendMessage(CMD_START_SUPPLICANT); } else { sendMessage(CMD_STOP_SUPPLICANT); /* Argument is the state that is entered upon success */ sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_DISABLED, 0)); } }可以看到它用了很多sendMessage(),這部分用了樹狀的有限狀態機,sendMessage是拿來叫目前所處的State物件,根據sendMessage要求的狀態來呼叫processMessage()處理。WifiStateMachine的樹狀結構如下
addState(mDefaultState); addState(mInitialState, mDefaultState); addState(mDriverUnloadingState, mDefaultState); addState(mDriverUnloadedState, mDefaultState); addState(mDriverFailedState, mDriverUnloadedState); addState(mDriverLoadingState, mDefaultState); addState(mDriverLoadedState, mDefaultState); addState(mSupplicantStartingState, mDefaultState); addState(mSupplicantStartedState, mDefaultState); addState(mDriverStartingState, mSupplicantStartedState); addState(mDriverStartedState, mSupplicantStartedState); addState(mScanModeState, mDriverStartedState); addState(mConnectModeState, mDriverStartedState); addState(mConnectingState, mConnectModeState); addState(mConnectedState, mConnectModeState); addState(mDisconnectingState, mConnectModeState); addState(mDisconnectedState, mConnectModeState); addState(mWaitForWpsCompletionState, mConnectModeState); addState(mDriverStoppingState, mSupplicantStartedState); addState(mDriverStoppedState, mSupplicantStartedState); addState(mSupplicantStoppingState, mDefaultState); addState(mSoftApStartedState, mDefaultState); setInitialState(mInitialState);要先確定自己目前的狀態才能知道程式會用那個State物件的processMessage()/enter()來處理。以上面的setWifiEnabled(true)為例,它會要求DriverUnloadedState::processMessage()處理CMD_LOAD_DRIVER。
class DriverUnloadedState extends HierarchicalState { @Override public void enter() { if (DBG) Log.d(TAG, getName() + "\n"); EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); } @Override public boolean processMessage(Message message) { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); switch (message.what) { case CMD_LOAD_DRIVER: transitionTo(mDriverLoadingState); break; default: return NOT_HANDLED; } EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); return HANDLED; } }DriverUnloadedState又轉換狀態到DriverLoadingState,轉過去時會先做enter() method如下
class DriverLoadingState extends HierarchicalState { @Override public void enter() { if (DBG) Log.d(TAG, getName() + "\n"); EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); final Message message = new Message(); message.copyFrom(getCurrentMessage()); /* TODO: add a timeout to fail when driver load is hung. Similarly for driver unload. */ new Thread(new Runnable() { public void run() { mWakeLock.acquire(); //enabling state switch(message.arg1) { case WIFI_STATE_ENABLING: setWifiState(WIFI_STATE_ENABLING); break; case WIFI_AP_STATE_ENABLING: setWifiApState(WIFI_AP_STATE_ENABLING); break; } if(WifiNative.loadDriver()) { Log.d(TAG, "Driver load successful"); sendMessage(CMD_LOAD_DRIVER_SUCCESS);在此method中呼叫了WifiNative.loadDriver(),它真正會呼叫到底層叫loading kernel module的動作。終於要進入JNI了。
public class WifiNative { static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED = 0; static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED = 1; static final int BLUETOOTH_COEXISTENCE_MODE_SENSE = 2; public native static String getErrorString(int errorCode); public native static boolean loadDriver();
JNI
以上面的loadDriver()會呼叫到
static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject clazz) { return (jboolean)(::wifi_load_driver() == 0); }wifi_load_driver()則是HAL提供。
HAL
HAL該提供的函式可參考hardware/libhardware_legacy/include/hardware_legacy/wifi.h,wifi_load_driver()的實作如下,可以看到insmod的關鍵system call。
int wifi_load_driver() { char driver_status[PROPERTY_VALUE_MAX]; int count = 100; /* wait at most 20 seconds for completion */ if (is_wifi_driver_loaded()) { return 0; } if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) return -1; if (strcmp(FIRMWARE_LOADER,"") == 0) {
No comments:
Post a Comment