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;