【Android-WIFI】(二) Wifi 扫描

1 扫描服务注册

//frameworks/base/services/java/com/android/server/SystemServer.java
if (context.getPackageManager().hasSystemFeature(
        PackageManager.FEATURE_WIFI)) {
    // Wifi Service must be started first for wifi-related services.
    //...
    t.traceBegin("StartWifiScanning");
    mSystemServiceManager.startServiceFromJar(
            WIFI_SCANNING_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);
    t.traceEnd();
}

在 SystemServer 中注册 并启动 WiFiScanning 服务,创建了 WifiScanningService。

//packages/modules/Wifi/service/java/com/android/server/wifi/scanner/WifiScanningService.java
public WifiScanningService(Context contextBase) {
    super(new WifiContext(contextBase));
    Log.i(TAG, "Creating " + Context.WIFI_SCANNING_SERVICE);
    mHandlerThread = new HandlerThread("WifiScanningService");
    mHandlerThread.start();
    mImpl = new WifiScanningServiceImpl(getContext(), mHandlerThread.getLooper(),
            WifiScannerImpl.DEFAULT_FACTORY,
            getContext().getSystemService(BatteryStatsManager.class),
            WifiInjector.getInstance());
}

@Override
public void onStart() {
    Log.i(TAG, "Publishing " + Context.WIFI_SCANNING_SERVICE);
    publishBinderService(Context.WIFI_SCANNING_SERVICE, mImpl);
}

@Override
public void onBootPhase(int phase) {
    if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
        Log.i(TAG, "Starting " + Context.WIFI_SCANNING_SERVICE);
        mImpl.startService();
    }
}

创建 WifiScanningService 实例对象的时候创建了 WifiScanningServiceImpl,也就是 WifiScanningService 的实际实现类。并且将 WifiScanningServiceImpl 注册到 ServiceManager 中。此处主要还创建了 ScannerImplFactory。

在 PHASE_SYSTEM_SERVICES_READY 阶段,SystemServer 将会通过其内部的 SystemServiceManager 来挨个调用自己管理的系统服务的 onBootPhase,也就包括 WifiScanningService,接下来调用到 WifiServiceScanningImpl 的 startService 方法中。

//packages/modules/Wifi/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
public void startService() {
    mWifiThreadRunner.post(() -> {
        mBackgroundScanStateMachine = new WifiBackgroundScanStateMachine(mLooper);
        mSingleScanStateMachine = new WifiSingleScanStateMachine(mLooper);
        mPnoScanStateMachine = new WifiPnoScanStateMachine(mLooper);

        mBackgroundScanStateMachine.start();
        mSingleScanStateMachine.start();
        mPnoScanStateMachine.start();

        // Create client handler only after StateMachines are ready.
        mClientHandler = new ClientHandler(TAG, mLooper);
    });
}

其中创建了并启动了各种状态机:WifiBackgroundScanStateMachine,WifiSingleScanStateMachine,WifiPnoScanStateMachine。还创建了一个 ClientHandler,用于处理来自 WifiScanner 发过来的消息。

2 启动服务

在 ConcreteClientModeManager 的 ConnectModeState 状态下,创建了 ClientModeImpl 以后,调用了 setRoleInternalAndInvokeCallback。

//packages/modules/Wifi/service/java/com/android/server/wifi/ConcreteClientModeManager.java
private void setRoleInternalAndInvokeCallback(@NonNull RoleChangeInfo roleChangeInfo) {
    if (roleChangeInfo.role == mRole) return;
    if (mRole == null) {
        Log.v(getTag(), "ClientModeManager started in role: " + roleChangeInfo);
        setRoleInternal(roleChangeInfo);
        mModeListener.onStarted(ConcreteClientModeManager.this);
    } else {
        Log.v(getTag(), "ClientModeManager role changed: " + roleChangeInfo);
        setRoleInternal(roleChangeInfo);
        reset();
        mModeListener.onRoleChanged(ConcreteClientModeManager.this);
    }
    if (mClientModeImpl != null) {
        mClientModeImpl.onRoleChanged();
    }
}
//packages/modules/Wifi/service/java/com/android/server/wifi/ActiveModeWarden.java/ClientListener.class
private void onStartedOrRoleChanged(ConcreteClientModeManager clientModeManager) {
    updateClientScanMode();
    updateBatteryStats();
    configureHwForMultiStaIfNecessary();
    if (mExternalRequestListener != null) {
        mExternalRequestListener.onAnswer(clientModeManager);
        mExternalRequestListener = null; // reset after one shot.
    }

    // Report to SarManager
    reportWifiStateToSarManager();
}

ConcreClientManager 内部的状态机状态转换成 ConnectModeState 时,通过 setRoleInternalAndInvokeCallback 调用到 ModeListener,由于此时是 Client 模式,所以这里的 Listener 是 ClientListener。如果是启动 WiFi 则回调到 onStart,如果是 role 切换则回调到 onRoleChanged。onStart 和 onRoleChanged 都会调用到 onStartedOrRoleChanged。

//packages/modules/Wifi/service/java/com/android/server/wifi/ActiveModeWarden.java
private void updateClientScanMode() {
    boolean scanEnabled = hasAnyClientModeManager();
    boolean scanningForHiddenNetworksEnabled;

    if (mContext.getResources().getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) {
        scanningForHiddenNetworksEnabled = hasAnyClientModeManager();
    } else {
        scanningForHiddenNetworksEnabled = hasAnyClientModeManagerInConnectivityRole();
    }
    mScanRequestProxy.enableScanning(scanEnabled, scanningForHiddenNetworksEnabled);
}

基于 ClientMode 来更新 ScanMode。接着启动扫描,这里传入的两个参数都是 true。

//packages/modules/Wifi/service/java/com/android/server/wifi/ScanRequestProxy.java
public void enableScanning(boolean enable, boolean enableScanningForHiddenNetworks) {
    if (enable) {
        enableScanningInternal(true);
        mScanningForHiddenNetworksEnabled = enableScanningForHiddenNetworks;
        Log.i(TAG, "Scanning for hidden networks is "
                + (enableScanningForHiddenNetworks ? "enabled" : "disabled"));
    } else {
        enableScanningInternal(false);
    }
    mScanningEnabled = enable;
}

private void enableScanningInternal(boolean enable) {
    if (!retrieveWifiScannerIfNecessary()) {
        Log.e(TAG, "Failed to retrieve wifiscanner");
        return;
    }
    mWifiScanner.setScanningEnabled(enable);
    sendScanAvailableBroadcast(mContext, enable);
    if (!enable) clearScanResults();
    Log.i(TAG, "Scanning is " + (enable ? "enabled" : "disabled"));
}

private void sendScanAvailableBroadcast(Context context, boolean available) {
    Log.d(TAG, "Sending scan available broadcast: " + available);
    final Intent intent = new Intent(WifiManager.ACTION_WIFI_SCAN_AVAILABILITY_CHANGED);
    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
    intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, available);
    context.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}

//packages/modules/Wifi/framework/java/android/net/wifi/WifiScanner.java
public void setScanningEnabled(boolean enable) {
    validateChannel();
    mAsyncChannel.sendMessage(enable ? CMD_ENABLE : CMD_DISABLE, Process.myTid(),
            Binder.getCallingPid(), mContext.getOpPackageName());
}

enableScanning 先是调用 WifiScanner 的 setScanningEnabled 方法来启动扫描。接着调用 sendScanAvailableBroadcast 发送一个扫描可用的的广播。WifiScanner 中的 setScanningEnabled 方法主要是向内部的 AsyncChannel 发送了一个 CMD_ENABLE。AsyncChannel 的对端是 WifiScanneingServiceImpl,所以由 ClientHandler 来处理这个消息。

//packages/modules/Wifi/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java/ClientHandler.class
case WifiScanner.CMD_ENABLE:
    Log.i(TAG, "Received a request to enable scanning, UID = " + msg.sendingUid);
    setupScannerImpls();
    mBackgroundScanStateMachine.sendMessage(Message.obtain(msg));
    mSingleScanStateMachine.sendMessage(Message.obtain(msg));
    mPnoScanStateMachine.sendMessage(Message.obtain(msg));
    mLastCallerInfoManager.put(LastCallerInfoManager.SCANNING_ENABLED, msg.arg1,
            msg.sendingUid, msg.arg2, (String) msg.obj, true);
    break;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值