Android -- Wifi扫描流程分析

Android -- Wifi扫描流程分析

转自 http://blog.csdn.net/csdn_of_coder/article/details/51922654
Wifi扫描的调用函数是WifiManager中的startScan()函数:
[java] view plain copy
  1. /** 
  2.      * Request a scan for access points. Returns immediately. The availability 
  3.      * of the results is made known later by means of an asynchronous event sent 
  4.      * on completion of the scan. 
  5.      * @return {@code true} if the operation succeeded, i.e., the scan was initiated 
  6.      */  
  7.     public boolean startScan() {  
  8.         try {  
  9.             mService.startScan(nullnull);  
  10.             return true;  
  11.         } catch (RemoteException e) {  
  12.             return false;  
  13.         }  
  14.     }  
  15.   
  16.     /** @hide */  
  17.     @SystemApi  
  18.     public boolean startScan(WorkSource workSource) {  
  19.         try {  
  20.             mService.startScan(null, workSource);  
  21.             return true;  
  22.         } catch (RemoteException e) {  
  23.             return false;  
  24.         }  
  25.     }  
通过AIDL调用WifiService中的同名函数:
[java] view plain copy
  1. /** 
  2.  * see {@link android.net.wifi.WifiManager#startScan} 
  3.  * and {@link android.net.wifi.WifiManager#startCustomizedScan} 
  4.  * 
  5.  * @param settings If null, use default parameter, i.e. full scan. 
  6.  * @param workSource If null, all blame is given to the calling uid. 
  7.  */  
  8. public void startScan(ScanSettings settings, WorkSource workSource) {  
  9.     enforceChangePermission();  
  10.     synchronized (this) {  
  11.         if (mInIdleMode) {  
  12.             // Need to send an immediate scan result broadcast in case the  
  13.             // caller is waiting for a result ..  
  14.   
  15.             // clear calling identity to send broadcast  
  16.             long callingIdentity = Binder.clearCallingIdentity();  
  17.             try {  
  18.                 mWifiStateMachine.sendScanResultsAvailableBroadcast(/* scanSucceeded = */ false);  
  19.             } finally {  
  20.                 // restore calling identity  
  21.                 Binder.restoreCallingIdentity(callingIdentity);  
  22.             }  
  23.             mScanPending = true;  
  24.             return;  
  25.         }  
  26.     }  
  27.     if (settings != null) {  
  28.         settings = new ScanSettings(settings);  
  29.         if (!settings.isValid()) {  
  30.             Slog.e(TAG, "invalid scan setting");  
  31.             return;  
  32.         }  
  33.     }  
  34.     if (workSource != null) {  
  35.         enforceWorkSourcePermission();  
  36.         // WifiManager currently doesn't use names, so need to clear names out of the  
  37.         // supplied WorkSource to allow future WorkSource combining.  
  38.         workSource.clearNames();  
  39.     }  
  40.     mWifiStateMachine.startScan(Binder.getCallingUid(), scanRequestCounter++,  
  41.             settings, workSource);  
  42. }  
进入WifiStateMachine,向状态机中发送CMD_START_SCAN消息开启扫描流程DriverStartedState处理,开始扫描:
[java] view plain copy
  1.  private void handleScanRequest(int type, Message message) {  
  2.          ...  
  3.         // call wifi native to start the scan  
  4.         if (startScanNative(type, freqs)) {  
  5.             // only count battery consumption if scan request is accepted  
  6.             noteScanStart(message.arg1, workSource);  
  7.             // a full scan covers everything, clearing scan request buffer  
  8.             if (freqs == null)  
  9.                 mBufferedScanMsg.clear();  
  10.             messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK;  
  11.             if (workSource != null) {  
  12.                 // External worksource was passed along the scan request,  
  13.                 // hence always send a broadcast  
  14.                 mSendScanResultsBroadcast = true;  
  15.             }  
  16.             return;  
  17.         }  
  18.         ...  
  19. }  
startScanStar():
[java] view plain copy
  1. /** 
  2.     * return true iff scan request is accepted 
  3.     */  
  4.    private boolean startScanNative(int type, String freqs) {  
  5.        if (mWifiNative.scan(type, freqs)) {  
  6.            mIsScanOngoing = true;  
  7.            mIsFullScanOngoing = (freqs == null);  
  8.            lastScanFreqs = freqs;  
  9.            return true;  
  10.        }  
  11.        return false;  
  12.    }  
调用native方法scan()向wpa_supplicant发送扫描指令;当wpa_s扫描结束后,WifiMonitor就会收到wpa_s上报的事件,framework层就知道扫描已经结束,可以去获取扫描结果了。WifiMonitor中:
[java] view plain copy
  1. /** 
  2.      * Handle all supplicant events except STATE-CHANGE 
  3.      * @param event the event type 
  4.      * @param remainder the rest of the string following the 
  5.      * event name and " — " 
  6.      */  
  7.     void handleEvent(int event, String remainder) {  
  8.         if (DBG) {  
  9.             logDbg("handleEvent " + Integer.toString(event) + "  " + remainder);  
  10.         }  
  11.         switch (event) {  
  12.             case DISCONNECTED:  
  13.                 handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED, remainder);  
  14.                 break;  
  15.   
  16.             case CONNECTED:  
  17.                 handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED, remainder);  
  18.                 break;  
  19.   
  20.             case SCAN_RESULTS:  
  21.                 mStateMachine.sendMessage(SCAN_RESULTS_EVENT);  
  22.                 break;  
  23.   
  24.             case SCAN_FAILED:  
  25.                 mStateMachine.sendMessage(SCAN_FAILED_EVENT);  
  26.                 break;  
  27.   
  28.             case UNKNOWN:  
  29.                 if (DBG) {  
  30.                     logDbg("handleEvent unknown: " + Integer.toString(event) + "  " + remainder);  
  31.                 }  
  32.                 break;  
  33.             default:  
  34.                 break;  
  35.         }  
  36.     }  
向WifiStateMachine发送SCAN_RESULTS_EVENT消息,告知现在可以获取扫描结果。
SupplicantStartedState中处理该消息:
[java] view plain copy
  1. case WifiMonitor.SCAN_RESULTS_EVENT:  
  2.                 case WifiMonitor.SCAN_FAILED_EVENT:  
  3.                     maybeRegisterNetworkFactory(); // Make sure our NetworkFactory is registered  
  4.                     closeRadioScanStats();  
  5.                     noteScanEnd();  
  6.                     setScanResults();  
  7.                     if (mIsFullScanOngoing || mSendScanResultsBroadcast) {  
  8.                         /* Just updated results from full scan, let apps know about this */  
  9.                         boolean scanSucceeded = message.what == WifiMonitor.SCAN_RESULTS_EVENT;  
  10.                         sendScanResultsAvailableBroadcast(scanSucceeded);  
  11.                     }  
  12.                     mSendScanResultsBroadcast = false;  
  13.                     mIsScanOngoing = false;  
  14.                     mIsFullScanOngoing = false;  
  15.                     if (mBufferedScanMsg.size() > 0)  
  16.                         sendMessage(mBufferedScanMsg.remove());  
  17.                     break;  
setScanResults()从wpa_s获取扫描结果,并保存;同时,也会进入autojoin流程,进行重连操作。最后发送ScanResults的广播,通知上层获取扫描结果。
本文讲述了基本的扫描处理流程,wpa_s中的处理,大家有兴趣可以自己研究。目前的工作中,wpa_s的代码基本都不涉及改动,所以这部分了解不多。

你可能感兴趣的:(android,网络框架接入分析)