Wifi服務框架介紹(原)
阿新 • • 發佈:2019-01-22
本文簡要介紹WIFI服務的主要框架以及運作機制。
1、在初始化時,也就是構造方法中,建立WifiServiceImpl物件。
2、在onStart時,將WifiServiceImpl物件註冊到ServiceManager中。
這裡建立的WifiServiceImpl是整個WIFI服務的管理者,他負責將客戶端對WIFI的請求分類,然後派發給不同的處理中心。
下面先來看WifiServiceImpl的屬性:
然後來看該物件的初始化過程,也就是構造方法:
以上就是WifiService的全部初始化過程,其主要過程分為以下四個部分:
1、在SystemServer中啟動WifiService;
2、在WifiService啟動過程中建立並初始化WifiServiceImpl;
3、在WifiServiceImpl初始化過程中建立並初始化WifiStateMachine物件;
當系統初始化時,會在Context物件的實現類ContextImpl中註冊一些常用的服務,這樣就可以在應用內部通過Context物件的getSystemService()方法來獲取相應的服務。而WIFI在ContextImpl中註冊了WifiManager用於向一般應用提供WIFI的服務:
1、應用可以通過Context物件的getSystemService(Context.WIFI_SERVICE)的方法獲取到一個WifiManager的物件用於控制WIFI;
2、WifiManager的建立需要使用ServiceManager的WIFI_SERVICE服務,而這個WIFI_SERVICE就是在WifiService中註冊的WifiServiceImpl物件;
下面來看WifiManager的建立過程:
1、用WifiServiceImpl初始化mService物件;
2、向WifiServiceImpl申請單向的AsyncChannel(想要連線AsyncChannel請點選這裡);
至此,WIFI框架就完成了所有需要初始化的動作,我們用一張流程圖來標識該過程:
以下是WifiManager提供的幾個比較重要的對外介面:
我們繼續跟蹤上面兩個方法的呼叫流程來檢視WifiServiceImpl的處理過程。
先來看setWifiEnabled()方法,該方法是直接由WifiManager呼叫到WifiServiceImpl中的,其實現如下:
下面來看WifiManager中connect()方法的處理,當初WifiManager收到該請求後,通過AsyncChannel的方式向WifiServiceImpl傳送CONNECT_NETWORK的請求,那麼WifiServiceImpl的接下來就需要在自己的Messenger中處理,而這個Messenger是從getWifiServiceMessenger()中傳遞給WifiManager的,我們來看是哪個Messenger來處理該請求:
其實WifiServiceImpl對請求的處理與WifiManager類似,他本身並不具備處理事物的能力,只是將請求分類後交由不同的處理者去處理。
以上就是整個WIFI框架的初始化以及內部訊息處理機制,下面用一張圖來標識WIFI內部的訊息流:
WIFI框架主要涉及到以下幾個物件:WifiService、WifiManager、WifiServiceImpl、WifiStateMachine等。下面來介紹這四個物件的內在聯絡。
一、WIFI服務的初始化
WIFI服務的初始化分為兩個部分,WifiService的初始化和WifiManager的初始化,下面分別介紹。
1.1、WifiService的初始化流程
WifiService的初始化流程是在SystemService中被啟動的:在這裡通過SystemServiceManager將WIFI的主服務(WifiService)啟動,然後來看該Service的啟動過程:@SystemServer.java private static final String WIFI_SERVICE_CLASS = "com.android.server.wifi.WifiService"; private void startOtherServices() { mSystemServiceManager.startService(WIFI_SERVICE_CLASS); }
以上是WifiService的全部內容,其實該Service只完成了兩個任務:@WifiService.java public final class WifiService extends SystemService { private static final String TAG = "WifiService"; final WifiServiceImpl mImpl; public WifiService(Context context) { super(context); //建立WifiServiceImpl物件 mImpl = new WifiServiceImpl(context); } @Override public void onStart() { //將WifiServiceImpl註冊到ServiceManager publishBinderService(Context.WIFI_SERVICE, mImpl); } @Override public void onBootPhase(int phase) { if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { mImpl.checkAndStartWifi(); } } }
1、在初始化時,也就是構造方法中,建立WifiServiceImpl物件。
2、在onStart時,將WifiServiceImpl物件註冊到ServiceManager中。
這裡建立的WifiServiceImpl是整個WIFI服務的管理者,他負責將客戶端對WIFI的請求分類,然後派發給不同的處理中心。
下面先來看WifiServiceImpl的屬性:
這說明該類是一個服務的實現類。public final class WifiServiceImpl extends IWifiManager.Stub {}
然後來看該物件的初始化過程,也就是構造方法:
@WifiServiceImpl.java
public WifiServiceImpl(Context context) {
mContext = context;
mInterfaceName = SystemProperties.get("wifi.interface", "wlan0");
mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName);
//建立wifi狀態機
mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName, mTrafficPoller);
mWifiStateMachine.enableRssiPolling(true);
//初始化各種管理者
mBatteryStats = BatteryStatsService.getService();
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine);
mSettingsStore = new WifiSettingsStore(mContext);
HandlerThread wifiThread = new HandlerThread("WifiService");
wifiThread.start();
mClientHandler = new ClientHandler(wifiThread.getLooper());
mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());
mWifiController = new WifiController(mContext, this, wifiThread.getLooper());
mBatchedScanSupported = mContext.getResources().getBoolean( R.bool.config_wifi_batched_scan_supported);
}
在這裡初始化各種與WIFI管理有關的輔助類,其中包含最重要的一個就是WIFI的狀態機WifiStateMachine,他是整個WIFI機制的核心。下面來看該狀態機的初始化流程: @WifiStateMachine.java
public WifiStateMachine(Context context, String wlanInterface, WifiTrafficPoller trafficPoller){
super("WifiStateMachine");
mContext = context;
mInterfaceName = wlanInterface;
//建立NetworkInfo物件
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService( BatteryStats.SERVICE_NAME));
//建立各種輔助類
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
mNwService = INetworkManagementService.Stub.asInterface(b);
mP2pSupported = mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_WIFI_DIRECT);
mWifiNative = new WifiNative(mInterfaceName);
mWifiConfigStore = new WifiConfigStore(context, mWifiNative);
mWifiAutoJoinController = new WifiAutoJoinController(context, this, mWifiConfigStore, mWifiConnectionStatistics, mWifiNative);
mWifiMonitor = new WifiMonitor(this, mWifiNative);
mWifiInfo = new WifiInfo();
......
//初始化狀態機
addState(mDefaultState);
addState(mInitialState, mDefaultState);
addState(mSupplicantStartingState, mDefaultState);
addState(mSupplicantStartedState, mDefaultState);
addState(mDriverStartingState, mSupplicantStartedState);
addState(mDriverStartedState, mSupplicantStartedState);
addState(mScanModeState, mDriverStartedState);
addState(mConnectModeState, mDriverStartedState);
addState(mL2ConnectedState, mConnectModeState);
addState(mObtainingIpState, mL2ConnectedState);
addState(mVerifyingLinkState, mL2ConnectedState);
addState(mConnectedState, mL2ConnectedState);
addState(mRoamingState, mL2ConnectedState);
addState(mDisconnectingState, mConnectModeState);
addState(mDisconnectedState, mConnectModeState);
addState(mWpsRunningState, mConnectModeState);
addState(mWaitForP2pDisableState, mSupplicantStartedState);
addState(mDriverStoppingState, mSupplicantStartedState);
addState(mDriverStoppedState, mSupplicantStartedState);
addState(mSupplicantStoppingState, mDefaultState);
addState(mSoftApStartingState, mDefaultState);
addState(mSoftApStartedState, mDefaultState);
addState(mTetheringState, mSoftApStartedState);
addState(mTetheredState, mSoftApStartedState);
addState(mUntetheringState, mSoftApStartedState);
//設定狀態機初始模式
setInitialState(mInitialState);
//啟動狀態機
start();
......
}
我們看到,在WifiStateMachine的初始化過程中建立了大量的輔助類,其中就包括NetworkInfo,他的作用就是標記當前網路的各項屬性,比如當前網路的型別、是否可用、是否處於漫遊等,然後還建立了許多WIFI的狀態機,標識當前WIFI所處的狀態,最後將狀態機初始狀態設定為mInitialState,並將狀態機start。以上就是WifiService的全部初始化過程,其主要過程分為以下四個部分:
1、在SystemServer中啟動WifiService;
2、在WifiService啟動過程中建立並初始化WifiServiceImpl;
3、在WifiServiceImpl初始化過程中建立並初始化WifiStateMachine物件;
4、在WifiStateMachine初始化過程中建立各種狀態機並啟動他們;
1.2、WifiManager的初始化流程
WIFI框架還有另外一個初始化流程實在ContextImpl中進行的。當系統初始化時,會在Context物件的實現類ContextImpl中註冊一些常用的服務,這樣就可以在應用內部通過Context物件的getSystemService()方法來獲取相應的服務。而WIFI在ContextImpl中註冊了WifiManager用於向一般應用提供WIFI的服務:
@ContextImpl.java
registerService(WIFI_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(WIFI_SERVICE);
IWifiManager service = IWifiManager.Stub.asInterface(b);
return new WifiManager(ctx.getOuterContext(), service);
}});
從這裡可以知道兩個資訊:1、應用可以通過Context物件的getSystemService(Context.WIFI_SERVICE)的方法獲取到一個WifiManager的物件用於控制WIFI;
2、WifiManager的建立需要使用ServiceManager的WIFI_SERVICE服務,而這個WIFI_SERVICE就是在WifiService中註冊的WifiServiceImpl物件;
下面來看WifiManager的建立過程:
@WifiManager.java
public WifiManager(Context context, IWifiManager service) {
mContext = context;
//這裡的mService就是建立WifiManager時傳遞進來的WifiServiceImpl物件
mService = service;
init();
}
private void init() {
synchronized (sThreadRefLock) {
if (++sThreadRefCount == 1) {
//獲取WifiServiceImpl中的Messenger物件
Messenger messenger = getWifiServiceMessenger();
if (messenger == null) {
sAsyncChannel = null;
return;
}
//建立AsyncChannel通道
sHandlerThread = new HandlerThread("WifiManager");
sAsyncChannel = new AsyncChannel();
sConnected = new CountDownLatch(1);
sHandlerThread.start();
Handler handler = new ServiceHandler(sHandlerThread.getLooper());
//與WifiServiceImpl申請建立單向AsyncChannel
sAsyncChannel.connect(mContext, handler, messenger);
try {
sConnected.await();
} catch (InterruptedException e) {
Log.e(TAG, "interrupted wait at init");
}
}
}
}
從上面WifiManager的初始化過程中我們看到,其初始化的過程中完成了以下兩個任務:1、用WifiServiceImpl初始化mService物件;
2、向WifiServiceImpl申請單向的AsyncChannel(想要連線AsyncChannel請點選這裡);
至此,WIFI框架就完成了所有需要初始化的動作,我們用一張流程圖來標識該過程:
二、WIFI服務的運作機制
由於應用操作WIFI是通過WifiManager進行的,那麼我們可以從WifiManager開始來查詢訊息在WIFI內部的傳遞機制。以下是WifiManager提供的幾個比較重要的對外介面:
//獲取所有網路連線
public List<WifiConfiguration> getConfiguredNetworks() {}
//新增網路連線
public int addNetwork(WifiConfiguration config) {}
//更新網路連線
public int updateNetwork(WifiConfiguration config) {}
//是否支援5Ghz
public boolean is5GHzBandSupported() {}
//是否支援WIFI熱點
public boolean isPortableHotspotSupported() {}
//開啟關閉WIFI
public boolean setWifiEnabled(boolean enabled) {}
//連線某個WIFI
public void connect(int networkId, ActionListener listener) {}
//斷開當前連線
public boolean disconnect() {}
//新增黑名單
public boolean addToBlacklist(String bssid) {}
//清除黑名單
public boolean clearBlacklist() {}
我們挑選兩個比較典型的方法進行跟蹤,分別是:控制WIFI開關的setWifiEnabled()和連線某個WIFI的connect()方法。為什麼要挑選這兩個方法呢?是因為這兩個方法分別使用兩種方式與WifiService進行通訊。
2.1、setWifiEnabled方式
在該方式中,WifiManager通過直接呼叫的方式與WifiServiceImpl進行通訊。 @WifiManager.java
public boolean setWifiEnabled(boolean enabled) {
try {
//直接呼叫mService的setWifiEnabled方法
return mService.setWifiEnabled(enabled);
} catch (RemoteException e) {
return false;
}
}
2.2、connect方式
與setWifiEnabled不同,在該方式中,WifiManager利用與WifiServiceImpl之間的AsyncChannel來交換資訊: @WifiManager.java
public void connect(int networkId, ActionListener listener) {
if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
validateChannel();
//通過AsyncChannel與WifiServiceImpl傳遞資訊
sAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, putListener(listener));
}
2.3、WifiManager小結
在上面兩節中分別介紹了兩種WifiManager與WifiServiceImpl通訊的方式,其實不僅是以上兩個方法,WifiManager中所有的對外公開的public方法,最終都是通過這兩種方式與WifiServiceImpl進行溝通。我們可以這樣理解WifiManager:他是WIFI模組向外部應用透漏出來的介面,其他所有應用都可以通過WifiManager操作WIFI各項功能,但是WifiManager本身並不具備處理請求的能力,而是把所有請求轉發給WifiServiceImpl物件,而傳送請求的方式就是直接呼叫或者通過AsyncChannel。
2.4、WifiServiceImpl中對請求的處理
無論採用何種溝通方式,WifiManager最終都會把應用的請求轉交給WifiServiceImpl來處理。那麼接下來的流程是怎樣的呢?WifiServiceImpl將會如何處理WifiManager轉發過來的請求呢?我們繼續跟蹤上面兩個方法的呼叫流程來檢視WifiServiceImpl的處理過程。
先來看setWifiEnabled()方法,該方法是直接由WifiManager呼叫到WifiServiceImpl中的,其實現如下:
@WifiServiceImpl.java
public synchronized boolean setWifiEnabled(boolean enable) {
//許可權檢查
enforceChangePermission();
//許可權檢查
long ident = Binder.clearCallingIdentity();
try {
if (! mSettingsStore.handleWifiToggled(enable)) {
return true;
}
} finally {
Binder.restoreCallingIdentity(ident);
}
//向WifiController傳送請求
mWifiController.sendMessage(CMD_WIFI_TOGGLED);
return true;
}
在這裡我們看到,WifiServiceImpl將請求轉交給WifiController來處理。下面來看WifiManager中connect()方法的處理,當初WifiManager收到該請求後,通過AsyncChannel的方式向WifiServiceImpl傳送CONNECT_NETWORK的請求,那麼WifiServiceImpl的接下來就需要在自己的Messenger中處理,而這個Messenger是從getWifiServiceMessenger()中傳遞給WifiManager的,我們來看是哪個Messenger來處理該請求:
@WifiServiceImpl.java
public Messenger getWifiServiceMessenger() {
//許可權檢查
enforceAccessPermission();
enforceChangePermission();
//這裡的Messenger的Handler是mClientHandler
return new Messenger(mClientHandler);
}
從這裡看到,WifiManager拿到的Messenger中的Handler其實就是mClientHandler,他是在WifiServiceImpl初始化時被建立的: @WifiServiceImpl.java
public WifiServiceImpl(Context context) {
......
HandlerThread wifiThread = new HandlerThread("WifiService");
wifiThread.start();
mClientHandler = new ClientHandler(wifiThread.getLooper());
}
也就是說WifiManager通過AsyncChannel傳送的訊息都會在ClientHandler中接收到: private class ClientHandler extends Handler {
ClientHandler(android.os.Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case WifiManager.CONNECT_NETWORK:
case WifiManager.SAVE_NETWORK: {
WifiConfiguration config = (WifiConfiguration) msg.obj;
int networkId = msg.arg1;
if (msg.what == WifiManager.SAVE_NETWORK) {
}
if (msg.what == WifiManager.CONNECT_NETWORK) {
if (config != null) {
//配置config
if (config.networkId == WifiConfiguration.INVALID_NETWORK_ID) {
config.creatorUid = Binder.getCallingUid();
} else {
config.lastUpdateUid = Binder.getCallingUid();
}
}
}
if (config != null && config.isValid()) {
//將請求傳送給WifiStateMachine
mWifiStateMachine.sendMessage(Message.obtain(msg));
} else if (config == null && networkId != WifiConfiguration.INVALID_NETWORK_ID) {
mWifiStateMachine.sendMessage(Message.obtain(msg));
} else {
if (msg.what == WifiManager.CONNECT_NETWORK) {
replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED, WifiManager.INVALID_ARGS);
} else {
replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED, WifiManager.INVALID_ARGS);
}
}
break;
}
}
}
}
從上面這個處理來看,WifiServiceImpl將請求轉交給WifiStateMachine來處理。其實WifiServiceImpl對請求的處理與WifiManager類似,他本身並不具備處理事物的能力,只是將請求分類後交由不同的處理者去處理。
以上就是整個WIFI框架的初始化以及內部訊息處理機制,下面用一張圖來標識WIFI內部的訊息流: