基于Android S 代码:http://aospxref.com/android-13.0.0_r3/
界面代码:http://aospxref.com/android-13.0.0_r3/xref/packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java#onSwitchChanged
onSwitchChanged —> startTether()
void startTether() {
if (isWifiApActivated()) return;
mSwitchBar.setEnabled(false);
mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */, ---> 继续看
mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
}
http://aospxref.com/android-13.0.0_r3/xref/packages/modules/Connectivity/framework/src/android/net/ConnectivityManager.java#2892
public void startTethering(int type, boolean showProvisioningUi,
final OnStartTetheringCallback callback, Handler handler) {
Objects.requireNonNull(callback, "OnStartTetheringCallback cannot be null.");
// 创建一个执行器,用于在合适的线程上执行回调任务
final Executor executor = new Executor() {
@Override
public void execute(Runnable command) {
if (handler == null) {
// 如果没有传入 Handler,则直接运行任务
command.run();
} else {
// 如果传入了 Handler,则在主线程上执行任务
handler.post(command);
}
}
};
// 创建一个 StartTetheringCallback 对象,用于接收启动网络共享的回调事件
final StartTetheringCallback tetheringCallback = new StartTetheringCallback() {
@Override
public void onTetheringStarted() {
// 当网络共享启动时,调用传入的回调对象的相应方法
callback.onTetheringStarted();
}
@Override
public void onTetheringFailed(final int error) {
// 当网络共享启动失败时,调用传入的回调对象的相应方法
callback.onTetheringFailed();
}
};
// 构建一个 TetheringRequest 对象,用于描述网络共享的请求参数
final TetheringRequest request = new TetheringRequest.Builder(type)
.setShouldShowEntitlementUi(showProvisioningUi).build();
// 获取 TetheringManager 对象,并调用其 startTethering() 方法启动网络共享
getTetheringManager().startTethering(request, executor, tetheringCallback);
}
/packages/modules/Connectivity/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
public void startTethering(@NonNull final TetheringRequest request,
@NonNull final Executor executor, @NonNull final StartTetheringCallback callback) {
final String callerPkg = mContext.getOpPackageName();
Log.i(TAG, "startTethering caller:" + callerPkg);
final IIntResultListener listener = new IIntResultListener.Stub() {
@Override
public void onResult(final int resultCode) {
executor.execute(() -> {
if (resultCode == TETHER_ERROR_NO_ERROR) {
callback.onTetheringStarted();
} else {
callback.onTetheringFailed(resultCode);
}
});
}
};
getConnector(c -> c.startTethering(request.getParcel(), callerPkg,
getAttributionTag(), listener));
}
http://aospxref.com/android-13.0.0_r3/xref/packages/modules/Connectivity/Tethering/src/com/android/networkstack/tethering/TetheringService.java#startTethering
然后调用到:http://aospxref.com/android-13.0.0_r3/xref/packages/modules/Connectivity/Tethering/src/com/android/networkstack/tethering/Tethering.java#startTethering
void startTethering(final TetheringRequestParcel request, final IIntResultListener listener) {
mHandler.post(() -> {
final TetheringRequestParcel unfinishedRequest = mActiveTetheringRequests.get(
request.tetheringType);
// If tethering is already enabled with a different request,
// disable before re-enabling.
if (unfinishedRequest != null
&& !TetheringUtils.isTetheringRequestEquals(unfinishedRequest, request)) {
enableTetheringInternal(request.tetheringType, false /* disabled */, null);
mEntitlementMgr.stopProvisioningIfNeeded(request.tetheringType);
}
mActiveTetheringRequests.put(request.tetheringType, request);
if (request.exemptFromEntitlementCheck) {
mEntitlementMgr.setExemptedDownstreamType(request.tetheringType);
} else {
mEntitlementMgr.startProvisioningIfNeeded(request.tetheringType,
request.showProvisioningUi);
}
enableTetheringInternal(request.tetheringType, true /* enabled */, listener);
});
}
private void enableTetheringInternal(int type, boolean enable,
final IIntResultListener listener) {
int result = TETHER_ERROR_NO_ERROR;
switch (type) {
case TETHERING_WIFI: ---> 这里我们是这种 类型
result = setWifiTethering(enable);
break;
case TETHERING_USB:
result = setUsbTethering(enable);
break;
case TETHERING_BLUETOOTH:
setBluetoothTethering(enable, listener);
break;
case TETHERING_NCM:
result = setNcmTethering(enable);
break;
case TETHERING_ETHERNET:
result = setEthernetTethering(enable);
break;
default:
Log.w(TAG, "Invalid tether type.");
result = TETHER_ERROR_UNKNOWN_TYPE;
}
// The result of Bluetooth tethering will be sent by #setBluetoothTethering.
if (type != TETHERING_BLUETOOTH) {
sendTetherResult(listener, result, type);
}
}
private int setWifiTethering(final boolean enable) {
final long ident = Binder.clearCallingIdentity();
try {
final WifiManager mgr = getWifiManager();
if (mgr == null) {
mLog.e("setWifiTethering: failed to get WifiManager!");
return TETHER_ERROR_SERVICE_UNAVAIL;
}
if ((enable && mgr.startTetheredHotspot(null /* use existing softap config */)) ---> 看这个
|| (!enable && mgr.stopSoftAp())) {
mWifiTetherRequested = enable;
return TETHER_ERROR_NO_ERROR;
}
} finally {
Binder.restoreCallingIdentity(ident);
}
return TETHER_ERROR_INTERNAL_ERROR;
}
http://aospxref.com/android-13.0.0_r3/xref/packages/modules/Wifi/framework/java/android/net/wifi/WifiManager.java#4644
http://aospxref.com/android-13.0.0_r3/xref/packages/modules/Wifi/service/java/com/android/server/wifi/WifiServiceImpl.java#1572
一步步调用下来,最终处理在WifiServiceImpl中这里省略掉部分代码,只看流程相关的:
public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig, @NonNull String packageName) {
if (!startSoftApInternal(new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, softApConfig,
mTetheredSoftApTracker.getSoftApCapability()), requestorWs)) {
mTetheredSoftApTracker.setFailedWhileEnabling();
return false;
}
}
private boolean startSoftApInternal(SoftApModeConfiguration apConfig, WorkSource requestorWs) {
int uid = Binder.getCallingUid();
boolean privileged = isSettingsOrSuw(Binder.getCallingPid(), uid);
mLog.trace("startSoftApInternal uid=% mode=%")
.c(uid).c(apConfig.getTargetMode()).flush();
// null wifiConfig is a meaningful input for CMD_SET_AP; it means to use the persistent
// AP config.
SoftApConfiguration softApConfig = apConfig.getSoftApConfiguration();
if (softApConfig != null
&& (!WifiApConfigStore.validateApWifiConfiguration(
softApConfig, privileged, mContext))) {
Log.e(TAG, "Invalid SoftApConfiguration");
return false;
}
mActiveModeWarden.startSoftAp(apConfig, requestorWs);
return true;
}
http://aospxref.com/android-13.0.0_r3/xref/packages/modules/Wifi/service/java/com/android/server/wifi/ActiveModeWarden.java#startSoftAp
public void startSoftAp(SoftApModeConfiguration softApConfig, WorkSource requestorWs) {
mWifiController.sendMessage(WifiController.CMD_SET_AP, 1, 0,
Pair.create(softApConfig, requestorWs));
}
初始状态是取决于目前是什么模式:
if (role == ROLE_CLIENT_PRIMARY) { ---> client 模式
startPrimaryClientModeManager(mLastPrimaryClientModeManagerRequestorWs);
setInitialState(mEnabledState);
} else if (role == ROLE_CLIENT_SCAN_ONLY) { ---> 后台扫描模式
startScanOnlyClientModeManager(mLastScanOnlyClientModeManagerRequestorWs);
setInitialState(mEnabledState);
} else {
setInitialState(mDisabledState);
}
无论是哪种模式,最终都是调用这个方法:
private void startSoftApModeManager( @NonNull SoftApModeConfiguration softApConfig, @NonNull WorkSource requestorWs) {
//SoftApModeConfiguration不能为null,但是这里的softapConfiguration为null,因为上面我们传配置的时候初始化为null
Log.d(TAG, "Starting SoftApModeManager config = " + softApConfig.getSoftApConfiguration());
Preconditions.checkState(softApConfig.getTargetMode() == IFACE_IP_MODE_LOCAL_ONLY
|| softApConfig.getTargetMode() == IFACE_IP_MODE_TETHERED);
WifiServiceImpl.SoftApCallbackInternal callback =
softApConfig.getTargetMode() == IFACE_IP_MODE_LOCAL_ONLY
? mLohsCallback : mSoftApCallback;
SoftApManager manager = mWifiInjector.makeSoftApManager( ---> 创建一个SoftApManager
new SoftApListener(), callback, softApConfig, requestorWs,
getRoleForSoftApIpMode(softApConfig.getTargetMode()), mVerboseLoggingEnabled);
mSoftApManagers.add(manager);
}
看下创建new的地方:http://aospxref.com/android-13.0.0_r3/xref/packages/modules/Wifi/service/java/com/android/server/wifi/SoftApManager.java#SoftApManager
public SoftApManager(…………
部分代码省略,只看几个和流程相关的地方
mCurrentSoftApConfiguration = apConfig.getSoftApConfiguration(); ---> 刚说过,这里面是null
if (mCurrentSoftApConfiguration == null) {
mCurrentSoftApConfiguration = mWifiApConfigStore.getApConfiguration(); ---> 拿默认配置,我们常修改热点名就是这个方法里面
}
// 重新打包成 SoftApModeConfiguration,因为现在SoftApConfiguration不为null了,当然前提是获取默认配置成功
mOriginalModeConfiguration = new SoftApModeConfiguration(apConfig.getTargetMode(),
mCurrentSoftApConfiguration, mCurrentSoftApCapability);
mStateMachine.sendMessage(SoftApStateMachine.CMD_START, requestorWs);
处理这个消息:CMD_START ,初始化状态是 setInitialState(mIdleState),在setInitialState状态机中处理,代码有点多,具体的大家细看代码,这里记录些总要的:
private class IdleState extends State {
// 初始化接口
mApInterfaceName = mWifiNative.setupInterfaceForSoftApMode( mWifiNativeInterfaceCallback, mRequestorWs,mCurrentSoftApConfiguration.getBand(), isBridgeRequired(),SoftApManager.this);
// 更新状态
updateApState(WifiManager.WIFI_AP_STATE_ENABLING,WifiManager.WIFI_AP_STATE_DISABLED, 0);
//接口初始化没问题就开始启动了
int result = startSoftAp();
private int startSoftAp() {
Log.d(getTag(), "startSoftAp: band " + mCurrentSoftApConfiguration.getBand()
+ " iface " + mApInterfaceName + " country " + mCountryCode);
// 设置mac地址
int result = setMacAddress();
if (result != SUCCESS) {
return result;
}
// 设置国家码
result = setCountryCode();
if (result != SUCCESS) {
return result;
}
// Make a copy of configuration for updating AP band and channel.
SoftApConfiguration.Builder localConfigBuilder =
new SoftApConfiguration.Builder(mCurrentSoftApConfiguration);
// 更新热点的频段和信道配置
result = ApConfigUtil.updateApChannelConfig(
mWifiNative, mCoexManager, mContext.getResources(), mCountryCode,
localConfigBuilder, mCurrentSoftApConfiguration, mCurrentSoftApCapability);
if (result != SUCCESS) {
Log.e(getTag(), "Failed to update AP band and channel");
return result;
}
// 当前热点是否设置为隐藏网络
if (mCurrentSoftApConfiguration.isHiddenSsid()) {
Log.d(getTag(), "SoftAP is a hidden network");
}
// 当前热点的配置是否被支持
if (!ApConfigUtil.checkSupportAllConfiguration(
mCurrentSoftApConfiguration, mCurrentSoftApCapability)) {
Log.d(getTag(), "Unsupported Configuration detect! config = "
+ mCurrentSoftApConfiguration);
return ERROR_UNSUPPORTED_CONFIGURATION;
}
// 继续调用,启动 SoftAP
if (!mWifiNative.startSoftAp(mApInterfaceName,
localConfigBuilder.build(),
mOriginalModeConfiguration.getTargetMode() == WifiManager.IFACE_IP_MODE_TETHERED,
mSoftApHalCallback)) {
Log.e(getTag(), "Soft AP start failed");
return ERROR_GENERIC;
}
// 启动 Wi-Fi 诊断日志记录,将日志写入与热点接口名称相关的文件中
mWifiDiagnostics.startLogging(mApInterfaceName);
// 记录了 Soft AP 启动的时间戳
mStartTimestamp = FORMATTER.format(new Date(System.currentTimeMillis()));
Log.d(getTag(), "Soft AP is started ");
return SUCCESS;
}
http://aospxref.com/android-13.0.0_r3/xref/packages/modules/Wifi/service/java/com/android/server/wifi/WifiNative.java#startSoftAp
public boolean startSoftAp(@NonNull String ifaceName, SoftApConfiguration config, boolean isMetered,SoftApHalCallback callback) {
// 检查是否支持 AP 信息回调
if (mHostapdHal.isApInfoCallbackSupported()) {
// 使用 Hostapd HAL 注册 AP HAL 事件回调
if (!mHostapdHal.registerApCallback(ifaceName, callback)) {
Log.e(TAG, "Failed to register ap hal event callback");
return false;
}
} else {
// 使用 Wificond 注册 AP HAL 事件回调
SoftApHalCallbackFromWificond softApHalCallbackFromWificond =
new SoftApHalCallbackFromWificond(ifaceName, callback);
if (!mWifiCondManager.registerApCallback(ifaceName,
Runnable::run, softApHalCallbackFromWificond)) {
Log.e(TAG, "Failed to register ap hal event callback from wificond");
return false;
}
}
// 添加访问点配置到 Hostapd HAL
if (!mHostapdHal.addAccessPoint(ifaceName, config, isMetered, callback::onFailure)) {
Log.e(TAG, "Failed to add acccess point");
mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();
return false;
}
return true;
}
http://aospxref.com/android-13.0.0_r3/xref/packages/modules/Wifi/service/java/com/android/server/wifi/HostapdHal.java#addAccessPoint
public boolean addAccessPoint(@NonNull String ifaceName, @NonNull SoftApConfiguration config,
boolean isMetered, @NonNull Runnable onFailureListener) {
synchronized (mLock) {
String methodStr = "addAccessPoint";
if (mIHostapd == null) {
return handleNullIHostapd(methodStr);
}
return mIHostapd.addAccessPoint(ifaceName, config, isMetered, onFailureListener);
}
}
这里注意下 mIHostapd 具体是哪个, mIHostapd = createIHostapdHalMockable(),这里面有两个IHostapd可以提供:
protected IHostapdHal createIHostapdHalMockable() {
synchronized (mLock) {
// Prefer AIDL implementation if service is declared.
if (HostapdHalAidlImp.serviceDeclared()) { ---> T版本之后支持
Log.i(TAG, "Initializing hostapd using AIDL implementation.");
return new HostapdHalAidlImp(mContext, mEventHandler);
} else if (HostapdHalHidlImp.serviceDeclared()) { ---> 目前看的是S版本的代码
Log.i(TAG, "Initializing hostapd using HIDL implementation.");
return new HostapdHalHidlImp(mContext, mEventHandler);
}
Log.e(TAG, "No HIDL or AIDL service available for hostapd.");
return null;
}
}
所以这里是走的 HostapdHalHidlImp 类去添加一个 access point:http://aospxref.com/android-13.0.0_r3/xref/packages/modules/Wifi/service/java/com/android/server/wifi/HostapdHalHidlImp.java#addAccessPoint
根据硬件版本调用不同的接口实现
public boolean addAccessPoint(@NonNull String ifaceName, @NonNull SoftApConfiguration config,
boolean isMetered, @NonNull Runnable onFailureListener) {
synchronized (mLock) {
final String methodStr = "addAccessPoint";
IHostapd.IfaceParams ifaceParamsV1_0 = prepareIfaceParamsV1_0(ifaceName, config);
android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams nwParamsV1_2 =
prepareNetworkParamsV1_2(config);
if (nwParamsV1_2 == null) return false;
if (!checkHostapdAndLogFailure(methodStr)) return false;
try {
HostapdStatus status;
if (!isV1_1()) {
// V1_0 case
status = mIHostapd.addAccessPoint(ifaceParamsV1_0, nwParamsV1_2.V1_0);
if (!checkStatusAndLogFailure(status, methodStr)) {
return false;
}
} else {
android.hardware.wifi.hostapd.V1_1.IHostapd.IfaceParams ifaceParamsV1_1 =
prepareIfaceParamsV1_1(ifaceParamsV1_0, config);
if (!isV1_2()) {
// V1_1 case
android.hardware.wifi.hostapd.V1_1.IHostapd iHostapdV1_1 =
getHostapdMockableV1_1();
if (iHostapdV1_1 == null) return false;
status = iHostapdV1_1.addAccessPoint_1_1(ifaceParamsV1_1,
nwParamsV1_2.V1_0);
if (!checkStatusAndLogFailure(status, methodStr)) {
return false;
}
} else {
// V1_2 & V1_3 case
android.hardware.wifi.hostapd.V1_2.HostapdStatus status12;
android.hardware.wifi.hostapd.V1_2.IHostapd.IfaceParams ifaceParamsV1_2 =
prepareIfaceParamsV1_2(ifaceParamsV1_1, config);
if (!isV1_3()) {
// V1_2 case
android.hardware.wifi.hostapd.V1_2.IHostapd iHostapdV1_2 =
getHostapdMockableV1_2();
if (iHostapdV1_2 == null) return false;
status12 = iHostapdV1_2.addAccessPoint_1_2(ifaceParamsV1_2,
nwParamsV1_2);
} else {
// V1_3 case
android.hardware.wifi.hostapd.V1_3
.IHostapd.NetworkParams nwParamsV1_3 =
new android.hardware.wifi.hostapd.V1_3
.IHostapd.NetworkParams();
nwParamsV1_3.V1_2 = nwParamsV1_2;
nwParamsV1_3.isMetered = isMetered;
android.hardware.wifi.hostapd.V1_3.IHostapd.IfaceParams ifaceParams1_3 =
prepareIfaceParamsV1_3(ifaceParamsV1_2, config);
android.hardware.wifi.hostapd.V1_3.IHostapd iHostapdV1_3 =
getHostapdMockableV1_3();
if (iHostapdV1_3 == null) return false;
status12 = iHostapdV1_3.addAccessPoint_1_3(ifaceParams1_3,
nwParamsV1_3);
}
if (!checkStatusAndLogFailure12(status12, methodStr)) {
return false;
}
}
}
mSoftApFailureListeners.put(ifaceName, onFailureListener);
return true;
} catch (IllegalArgumentException e) {
Log.e(TAG, "Unrecognized apBand: " + config.getBand());
return false;
} catch (RemoteException e) {
handleRemoteException(e, methodStr);
return false;
}
}
}
具体走的是哪个版本的,可以自己看下含有厂商的基线,比如MTK的实现就是1.3版本的,路径如下:/external/wpa_supplicant_8/hostapd/hidl/1.3/hostapd.cpp,这里面实现了。