天天看點

Android8.1的WIFI掃描後連接配接過程和配置IP位址

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

在service中開啟掃描。

@RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
    public boolean startScan(WorkSource workSource) {
        try {
            String packageName = getContext().getOpPackageName();
            mService.startScan(null, workSource, packageName);
            return true;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }           

複制

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java

跳轉到Wifi狀态機中的開始掃描。

public void startScan(ScanSettings settings, WorkSource workSource, String packageName) {
        enforceChangePermission();

        mWifiStateMachine.startScan(Binder.getCallingUid(), scanRequestCounter++,
                settings, workSource);
    }           

複制

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java

發送`CMD_START_SCAN消息

public void startScan(int callingUid, int scanCounter,
                          ScanSettings settings, WorkSource workSource) {
        Bundle bundle = new Bundle();
        bundle.putParcelable(CUSTOMIZED_SCAN_SETTING, settings);
        bundle.putParcelable(CUSTOMIZED_SCAN_WORKSOURCE, workSource);
        bundle.putLong(SCAN_REQUEST_TIME, mClock.getWallClockMillis());
        sendMessage(CMD_START_SCAN, callingUid, scanCounter, bundle);
    }           

複制

處理CMD_START_SCAN消息

case CMD_START_SCAN:
                    handleScanRequest(message);
                    break;           

複制

跳轉到handleScanRequest函數。

1636    private void handleScanRequest(Message message) {
1661        if (startScanNative(freqs, hiddenNetworks, workSource)) {
1710    private boolean startScanNative(final Set<Integer> freqs,
1751        mWifiScanner.startScan(settings, nativeScanListener, workSource);           

複制

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

跳轉到WifiScanner.java中的startscan()函數

808    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
809    public void startScan(ScanSettings settings, ScanListener listener, WorkSource workSource) {
810        Preconditions.checkNotNull(listener, "listener cannot be null");
811        int key = addListener(listener);
812        if (key == INVALID_KEY) return;
813        validateChannel();
814        Bundle scanParams = new Bundle();
815        scanParams.putParcelable(SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
816        scanParams.putParcelable(SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
817        mAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, key, scanParams);
818    }           

複制

frameworks/opt/net/wifi/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java

在DriverStartedState中處理CMD_START_SINGLE_SCAN消息。

class DriverStartedState extends State {
                    case WifiScanner.CMD_START_SINGLE_SCAN:
                                tryToStartNewScan();

        void tryToStartNewScan() {
            if (mScannerImpl.startSingleScan(settings, this)) {           

複制

/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java

case WifiMonitor.SCAN_RESULTS_EVENT:
            case WifiMonitor.SCAN_FAILED_EVENT:
                maybeRegisterNetworkFactory(); 
                setScanResults();
                mIsScanOngoing = false;
                mIsFullScanOngoing = false;
                if (mBufferedScanMsg.size() > 0)
                    sendMessage(mBufferedScanMsg.remove());
                break;           

複制

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

public void connect(WifiConfiguration config, ActionListener listener) {
        if (config == null) throw new IllegalArgumentException("config cannot be null");
        getChannel().sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID,
                putListener(listener), config);
    }           

複制

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java

case WifiManager.CONNECT_NETWORK: {
                    if (checkChangePermissionAndReplyIfNotAuthorized(
                            msg, WifiManager.CONNECT_NETWORK_FAILED)) {
                        WifiConfiguration config = (WifiConfiguration) msg.obj;
                        int networkId = msg.arg1;
                        Slog.d(TAG, "CONNECT "
                                + " nid=" + Integer.toString(networkId)
                                + " uid=" + msg.sendingUid
                                + " name="
                                + mContext.getPackageManager().getNameForUid(msg.sendingUid));
                        if (config != null) {
                            if (DBG) Slog.d(TAG, "Connect with config " + config);
                            /* Command is forwarded to state machine */
                            mWifiStateMachine.sendMessage(Message.obtain(msg));
                        } else if (config == null
                                && networkId != WifiConfiguration.INVALID_NETWORK_ID) {
                            if (DBG) Slog.d(TAG, "Connect with networkId " + networkId);
                            mWifiStateMachine.sendMessage(Message.obtain(msg));
                        } else {
                            Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg);
                            replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED,
                                    WifiManager.INVALID_ARGS);
                        }
                    }
                    break;
                }           

複制

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java

case WifiManager.CONNECT_NETWORK:
                        result = mWifiConfigManager.addOrUpdateNetwork(config, message.sendingUid);

                    broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config);
                    replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED);
                    break;

                case WifiMonitor.NETWORK_CONNECTION_EVENT:
                        transitionTo(mObtainingIpState);           

複制

frameworks/base/services/net/java/android/net/dhcp/DhcpClient.java

在DhcpClient中處理IP位址的擷取。DhcpClient是一個小型的狀态機,

case CMD_START_DHCP:
                    if (mRegisteredForPreDhcpNotification) {
                        transitionTo(mWaitBeforeStartState);
                    } else {
                        transitionTo(mDhcpInitState);
                   }

       public void enter() {
           super.enter();
        mController.sendMessage(CMD_PRE_DHCP_ACTION);
       }           

複制

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java

case DhcpClient.CMD_PRE_DHCP_ACTION:
                    handlePreDhcpSetup();
                    break;

                case DhcpClient.CMD_POST_DHCP_ACTION:
                    mIsAutoRoamOngoing = false;
                    handlePostDhcpSetup();           

複制