赞
踩
版本Android-13.0.0_r3
在Settings中打开热点 点击事件开始
按钮初始化
/packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSettings.java
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (mUnavailable) {
return;
}
// Assume we are in a SettingsActivity. This is only safe because we currently use
// SettingsActivity as base for all preference fragments.
final SettingsActivity activity = (SettingsActivity) getActivity();
final SettingsMainSwitchBar switchBar = activity.getSwitchBar();
switchBar.setTitle(getContext().getString(R.string.use_wifi_hotsopt_main_switch_title));
mSwitchBarController = new WifiTetherSwitchBarController(activity, switchBar);
getSettingsLifecycle().addObserver(mSwitchBarController);
switchBar.show();
}
获取activity and switchBar,设置switchBar的Title。new WifiTetherSwitchBarController来进行控制控件。最后show显示。
来看WifiTetherSwitchBarController方法
/packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
//构造函数
WifiTetherSwitchBarController(Context context, SettingsMainSwitchBar switchBar) {
mContext = context;
mSwitchBar = switchBar;
mSwitch = mSwitchBar.getSwitch();
mDataSaverBackend = new DataSaverBackend(context);
mConnectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mSwitchBar.setChecked(mWifiManager.getWifiApState() == WIFI_AP_STATE_ENABLED);
updateWifiSwitch();
}
@Override
public void onStart() {
mDataSaverBackend.addListener(this);
mSwitchBar.addOnSwitchChangeListener(this);
mContext.registerReceiver(mReceiver, WIFI_INTENT_FILTER,
Context.RECEIVER_EXPORTED_UNAUDITED);
}
@Override
public void onSwitchChanged(Switch switchView, boolean isChecked) {
// Filter out unnecessary callbacks when switch is disabled.
if (!switchView.isEnabled()) return;
if (isChecked) {
startTether();
} else {
stopTether();
}
}
void startTether() {
if (isWifiApActivated()) return;
mSwitchBar.setEnabled(false);
mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,
mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
}
final ConnectivityManager.OnStartTetheringCallback mOnStartTetheringCallback =
new ConnectivityManager.OnStartTetheringCallback() {
@Override
public void onTetheringFailed() {
super.onTetheringFailed();
Log.e(TAG, "Failed to start Wi-Fi Tethering.");
handleWifiApStateChanged(mWifiManager.getWifiApState());
}
};
在这个WifiTetherSwitchBarController方法中为按钮设置了点击事件,执行的方法是startTether(),开始了开启热点的相关流程。
startTether()中if (isWifiApActivated()) return;当前状态是不是WIFI_AP_STATE_ENABLED and WIFI_AP_STATE_ENABLING,true直接return。
mSwitchBar.setEnabled(false);禁用控件
下来调用ConnectivityManager中的startTethering()
/packages/modules/Connectivity/framework/src/android/net/ConnectivityManager.java
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) {
command.run();
} else {
handler.post(command);
}
}
};
final StartTetheringCallback tetheringCallback = new StartTetheringCallback() {
@Override
public void onTetheringStarted() {
callback.onTetheringStarted();
}
@Override
public void onTetheringFailed(final int error) {
callback.onTetheringFailed();
}
};
final TetheringRequest request = new TetheringRequest.Builder(type)
.setShouldShowEntitlementUi(showProvisioningUi).build();
getTetheringManager().startTethering(request, executor, tetheringCallback);
}
又进入到getTetheringManager().startTethering(request, executor, tetheringCallback);
/packages/modules/Connectivity/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
//如果需要,启动绑定并运行给定类型的绑定配置。如果配置失败,stopTethering将被自动调用。
@RequiresPermission(anyOf = {
android.Manifest.permission.TETHER_PRIVILEGED,
android.Manifest.permission.WRITE_SETTINGS
})
//Executor:指定调用TetheringRequest回调函数的线程。
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(); //Success
} else {
callback.onTetheringFailed(resultCode); //Failed
}
});
}
};
getConnector(c -> c.startTethering(request.getParcel(), callerPkg,
getAttributionTag(), listener));
}
//ConnectorConsumer是一个接口,所以consumer.onConnectorAvailable(connector)就相当于调用了
//connector.startTethering()。ITetheringConnector connector 是一个aidl 接口,跨进程到
//TetheringService.java
private void getConnector(ConnectorConsumer consumer) {
final ITetheringConnector connector;
synchronized (mConnectorWaitQueue) {
connector = mConnector;
if (connector == null) {
mConnectorWaitQueue.add(consumer);
return;
}
}
try {
consumer.onConnectorAvailable(connector);
} catch (RemoteException e) {
throw new IllegalStateException(e);
}
}
//aidl接口---》TetheringService.java
private interface ConnectorConsumer {
void onConnectorAvailable(ITetheringConnector connector) throws RemoteException;
}
/packages/modules/Connectivity/Tethering/src/com/android/networkstack/tethering/TetheringService.java
@Override
public void startTethering(TetheringRequestParcel request, String callerPkg,
String callingAttributionTag, IIntResultListener listener) {
if (checkAndNotifyCommonError(callerPkg,
callingAttributionTag,
request.exemptFromEntitlementCheck /* onlyAllowPrivileged */,
listener)) {
return;
}
mTethering.startTethering(request, listener);
}
这里又调到mTethering.startTethering(request, listener); mTethering—》Tethering
/packages/modules/Connectivity/Tethering/src/com/android/networkstack/tethering/Tethering.java
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;
}
开启热点执行TETHERING_WIFI类型,在setWifiTethering方法中getWifiManager,然后再调用WifiManager 中的startTetheredHotspot传参数是个null。
这个参数代表着在开启热点时,会根据配置文件的内容决定开启热点的参数。这个配置文件在手机的data/misc/apexdata/com.android.wifi/ 下面。一个是热点,一个是WiFi
WifiConfigStore.xml WifiConfigStoreSoftAp.xml
/packages/modules/Wifi/framework/java/android/net/wifi/WifiManager.java
@SystemApi
@RequiresPermission(anyOf = {
android.Manifest.permission.NETWORK_STACK,
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
})
public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig) {
try {
return mService.startTetheredHotspot(softApConfig, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
这里就是打开热点的一个API,SoftApConfiguration 是nullmService—》WifiServiceImpl.startTetheredHotspot()
/packages/modules/Wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
@Override
public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig,
@NonNull String packageName) {
// NETWORK_STACK is a signature only permission.
enforceNetworkStackPermission();
int callingUid = Binder.getCallingUid();
mWifiPermissionsUtil.checkPackage(callingUid, packageName);
// If user restriction is set, cannot start softap
if (mWifiTetheringDisallowed) {
mLog.err("startTetheredHotspot with user restriction: not permitted").flush();
return false;
}
mLog.info("startTetheredHotspot uid=%").c(callingUid).flush();
// TODO: b/233363886, handle timeout in general way.
if (!checkSetEnablingIfAllowed()) {
return false;
}
WorkSource requestorWs = new WorkSource(callingUid, packageName);
if (!mWifiThreadRunner.call(
() -> mActiveModeWarden.canRequestMoreSoftApManagers(requestorWs), false)) {
// Take down LOHS if it is up.
mLohsSoftApTracker.stopAll();
}
if (!startSoftApInternal(new SoftApModeConfiguration(
WifiManager.IFACE_IP_MODE_TETHERED, softApConfig,
mTetheredSoftApTracker.getSoftApCapability()), requestorWs)) {
mTetheredSoftApTracker.setFailedWhileEnabling();
return false;
}
mLastCallerInfoManager.put(WifiManager.API_TETHERED_HOTSPOT, Process.myTid(),
callingUid, Binder.getCallingPid(), packageName, true);
return true;
}
Check一些权限然后执行到startSoftApInternal
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;
}
进入到ActiveModeWarden中的startSoftAp
/packages/modules/Wifi/service/java/com/android/server/wifi/ActiveModeWarden.java
/** Starts SoftAp. */
public void startSoftAp(SoftApModeConfiguration softApConfig, WorkSource requestorWs) {
mWifiController.sendMessage(WifiController.CMD_SET_AP, 1, 0,
Pair.create(softApConfig, requestorWs));
}
在startSoftAp方法中发送一条消息(CMD_SET_AP),在ActiveModeWarden的内部类EnabledState中处理
@Override
public boolean processMessageFiltered(Message msg) {
...
case CMD_SET_AP:
// note: CMD_SET_AP is handled/dropped in ECM mode - will not start here
if (msg.arg1 == 1) {
Pair<SoftApModeConfiguration, WorkSource> softApConfigAndWs = (Pair) msg.obj;
startSoftApModeManager(softApConfigAndWs.first, softApConfigAndWs.second);
} else {
stopSoftApModeManagers(msg.arg2);
}
break;
...
}
private void startSoftApModeManager(
@NonNull SoftApModeConfiguration softApConfig, @NonNull WorkSource requestorWs) {
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(
new SoftApListener(), callback, softApConfig, requestorWs,
getRoleForSoftApIpMode(softApConfig.getTargetMode()), mVerboseLoggingEnabled);
mSoftApManagers.add(manager);
}
Callback回调方法是mLohsCallback。然后通过WifiInjector new了一个softApManager
/packages/modules/Wifi/service/java/com/android/server/wifi/WifiInjector.java
public SoftApManager makeSoftApManager(
@NonNull ActiveModeManager.Listener<SoftApManager> listener,
@NonNull WifiServiceImpl.SoftApCallbackInternal callback,
@NonNull SoftApModeConfiguration config,
@NonNull WorkSource requestorWs,
@NonNull ActiveModeManager.SoftApRole role,
boolean verboseLoggingEnabled) {
return new SoftApManager(mContext, mWifiHandlerThread.getLooper(),
mFrameworkFacade, mWifiNative, mCoexManager, makeBatteryManager(),
mCountryCode.getCountryCode(), listener, callback, mWifiApConfigStore,
config, mWifiMetrics, mSarManager, mWifiDiagnostics,
new SoftApNotifier(mContext, mFrameworkFacade, mWifiNotificationManager),
mCmiMonitor, mActiveModeWarden, mClock.getElapsedSinceBootMillis(),
requestorWs, role, verboseLoggingEnabled);
}
========================================================================
此构造函数有点长,直接在里面进行注释
/packages/modules/Wifi/service/java/com/android/server/wifi/SoftApManager.java
public SoftApManager(
@NonNull WifiContext context,
@NonNull Looper looper,
@NonNull FrameworkFacade framework,
@NonNull WifiNative wifiNative,
@NonNull CoexManager coexManager,
@NonNull BatteryManager batteryManager,
String countryCode,
@NonNull Listener<SoftApManager> listener,
@NonNull WifiServiceImpl.SoftApCallbackInternal callback,
@NonNull WifiApConfigStore wifiApConfigStore,
@NonNull SoftApModeConfiguration apConfig,
@NonNull WifiMetrics wifiMetrics,
@NonNull SarManager sarManager,
@NonNull WifiDiagnostics wifiDiagnostics,
@NonNull SoftApNotifier softApNotifier,
@NonNull ClientModeImplMonitor cmiMonitor,
@NonNull ActiveModeWarden activeModeWarden,
long id,
@NonNull WorkSource requestorWs,
@NonNull SoftApRole role,
boolean verboseLoggingEnabled) {
mContext = context;
mFrameworkFacade = framework;
mSoftApNotifier = softApNotifier;
mWifiNative = wifiNative;
mCoexManager = coexManager;
mBatteryManager = batteryManager;
if (SdkLevel.isAtLeastS()) {
mCoexListener = new CoexListener() {
@Override
public void onCoexUnsafeChannelsChanged() {
if (mCurrentSoftApConfiguration == null) {
return;
}
mStateMachine.sendMessage(
SoftApStateMachine.CMD_SAFE_CHANNEL_FREQUENCY_CHANGED);
}
};
} else {
mCoexListener = null;
}
mCountryCode = countryCode;
mModeListener = listener;
mSoftApCallback = callback;
mWifiApConfigStore = wifiApConfigStore;
mCurrentSoftApConfiguration = apConfig.getSoftApConfiguration();
mCurrentSoftApCapability = apConfig.getCapability();
//传递的是null,这里就会从WifiApConfigStore中AP获取相关的配置
// null is a valid input and means we use the user-configured tethering settings.
if (mCurrentSoftApConfiguration == null) {
mCurrentSoftApConfiguration = mWifiApConfigStore.getApConfiguration();
// may still be null if we fail to load the default config
}
// Store mode configuration before update the configuration.
mOriginalModeConfiguration = new SoftApModeConfiguration(apConfig.getTargetMode(),
mCurrentSoftApConfiguration, mCurrentSoftApCapability);
if (mCurrentSoftApConfiguration != null) {
mIsUnsetBssid = mCurrentSoftApConfiguration.getBssid() == null;
if (mCurrentSoftApCapability.areFeaturesSupported(
SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION)) {
mCurrentSoftApConfiguration = mWifiApConfigStore.randomizeBssidIfUnset(
mContext, mCurrentSoftApConfiguration);
}
}
mWifiMetrics = wifiMetrics;
mSarManager = sarManager;
mWifiDiagnostics = wifiDiagnostics;
//在这里创建了状态机stateMachine,它有两个状态:mIdleState\mStartedState
mStateMachine = new SoftApStateMachine(looper);
configureInternalConfiguration();
mDefaultShutdownTimeoutMillis = mContext.getResources().getInteger(
R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds);
mDefaultShutdownIdleInstanceInBridgedModeTimeoutMillis = mContext.getResources().getInteger(
R.integer
.config_wifiFrameworkSoftApShutDownIdleInstanceInBridgedModeTimeoutMillisecond);
mIsDisableShutDownBridgedModeIdleInstanceTimerWhenCharging = mContext.getResources()
.getBoolean(R.bool
.config_wifiFrameworkSoftApDisableBridgedModeShutdownIdleInstanceWhenCharging);
mCmiMonitor = cmiMonitor;
mActiveModeWarden = activeModeWarden;
mCmiMonitor.registerListener(new ClientModeImplListener() {
@Override
public void onL2Connected(@NonNull ConcreteClientModeManager clientModeManager) {
SoftApManager.this.onL2Connected(clientModeManager);
}
});
updateSafeChannelFrequencyList();
mId = id;
mRole = role;
enableVerboseLogging(verboseLoggingEnabled);
//这里发送一条消息CMD_START让状态机stateMachine中的mIdleState来处理
mStateMachine.sendMessage(SoftApStateMachine.CMD_START, requestorWs);
}
======================================================================================
case CMD_START:
...
int result = startSoftAp();
transitionTo(mStartedState);
break;
========================================================================
这里主要是调用startSoftAp()方法,然后让stateMachine状态机从mIdleState切换到mStartedState。
我们来看看startSoftAp()
/**
* Start a soft AP instance as configured.
*
* @return integer result code
*/
private int startSoftAp() {
Log.d(getTag(), "startSoftAp: band " + mCurrentSoftApConfiguration.getBand()
+ " iface " + mApInterfaceName + " country " + mCountryCode);
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;
}
if (!mWifiNative.startSoftAp(mApInterfaceName,
localConfigBuilder.build(),
mOriginalModeConfiguration.getTargetMode() == WifiManager.IFACE_IP_MODE_TETHERED,
mSoftApHalCallback)) {
Log.e(getTag(), "Soft AP start failed");
return ERROR_GENERIC;
}
mWifiDiagnostics.startLogging(mApInterfaceName);
mStartTimestamp = FORMATTER.format(new Date(System.currentTimeMillis()));
Log.d(getTag(), "Soft AP is started ");
return SUCCESS;
}
从配置中获取Band and channel,进行一些配置上的判断。主要是调用mWifiNative.startSoftAp()方法
public boolean startSoftAp(
@NonNull String ifaceName, SoftApConfiguration config, boolean isMetered,
SoftApHalCallback callback) {
if (mHostapdHal.isApInfoCallbackSupported()) {
if (!mHostapdHal.registerApCallback(ifaceName, callback)) {
Log.e(TAG, "Failed to register ap hal event callback");
return false;
}
} else {
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;
}
}
if (!mHostapdHal.addAccessPoint(ifaceName, config, isMetered, callback::onFailure)) {
Log.e(TAG, "Failed to add acccess point");
mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();
return false;
}
return true;
}
/packages/modules/Wifi/service/java/com/android/server/wifi/HostapdHal.java
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);
}
}
添加并启动一个AccessPoint,调用HAL层的方法;IHostapdHal HAL interface object
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。