当前位置: 首页 > news >正文

东莞seo网站建设公司湛江网站搜索引擎推广

东莞seo网站建设公司,湛江网站搜索引擎推广,点石嘉业北京网站建设公司,软件跟网站开发的区别Android R WiFi热点流程浅析 Android上的WiFi SoftAp功能是用户常用的功能之一#xff0c;它能让我们分享手机的网络给其他设备使用。 那Android系统是如何实现SoftAp的呢#xff0c;这里在FWK层面做一个简要的流程分析#xff0c;供自己记录和大家参考。 以Android R版本为… Android R WiFi热点流程浅析 Android上的WiFi SoftAp功能是用户常用的功能之一它能让我们分享手机的网络给其他设备使用。 那Android系统是如何实现SoftAp的呢这里在FWK层面做一个简要的流程分析供自己记录和大家参考。 以Android R版本为例我们知道Android大部分的系统FWK服务都在SystemServer中启动SoftAp的Service也不例外 /*** Use with {link #getSystemService(String)} to retrieve a {link android.net.TetheringManager}* for managing tethering functions.* hide* see android.net.TetheringManager*/SystemApipublic static final String TETHERING_SERVICE tethering;private static final String TETHERING_CONNECTOR_CLASS android.net.ITetheringConnector;/*** Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.*/private void startOtherServices(NonNull TimingsTraceAndSlog t) {t.traceBegin(startOtherServices);......t.traceBegin(StartTethering);try {// TODO: hide implementation details, b/146312721.ConnectivityModuleConnector.getInstance().startModuleService(TETHERING_CONNECTOR_CLASS,PERMISSION_MAINLINE_NETWORK_STACK, service - {ServiceManager.addService(Context.TETHERING_SERVICE, service,false /* allowIsolated */,DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);});} catch (Throwable e) {reportWtf(starting Tethering, e);}t.traceEnd();......} 这里借助了ConnectivityModuleConnector工具类的startModuleService()函数去启动、绑定服务 /*** Start a module running in the network stack or system_server process. Should be called only* once for each module per device startup.** pThis method will start a networking module either in the network stack* process, or inside the system server on devices that do not support the corresponding* mainline network . The corresponding networking module services binder* object will then be delivered asynchronously via the provided {link ModuleServiceCallback}.** param serviceIntentBaseAction Base action to use for constructing the intent needed to* bind to the corresponding module.* param servicePermissionName Permission to be held by the corresponding module.*/public void startModuleService(NonNull String serviceIntentBaseAction,NonNull String servicePermissionName,NonNull ModuleServiceCallback callback) {log(Starting networking module serviceIntentBaseAction);final PackageManager pm mContext.getPackageManager();// Try to bind in-process if the device was shipped with an in-process versionIntent intent mDeps.getModuleServiceIntent(pm, serviceIntentBaseAction,servicePermissionName, true /* inSystemProcess */);// Otherwise use the updatable module versionif (intent null) {intent mDeps.getModuleServiceIntent(pm, serviceIntentBaseAction,servicePermissionName, false /* inSystemProcess */);log(Starting networking module in network_stack process);} else {log(Starting networking module in system_server process);}if (intent null) {maybeCrashWithTerribleFailure(Could not resolve the networking module, null);return;}final String packageName intent.getComponent().getPackageName();// Start the network stack. The service will be added to the service manager by the// corresponding client in ModuleServiceCallback.onModuleServiceConnected().if (!mContext.bindServiceAsUser(intent, new ModuleServiceConnection(packageName, callback),Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {maybeCrashWithTerribleFailure(Could not bind to networking module in-process, or in app with intent, packageName);return;}log(Networking module service start requested);}private class ModuleServiceConnection implements ServiceConnection {NonNullprivate final String mPackageName;NonNullprivate final ModuleServiceCallback mModuleServiceCallback;private ModuleServiceConnection(NonNull String packageName,NonNull ModuleServiceCallback moduleCallback) {mPackageName packageName;mModuleServiceCallback moduleCallback;}Overridepublic void onServiceConnected(ComponentName name, IBinder service) {logi(Networking module service connected);mModuleServiceCallback.onModuleServiceConnected(service);}Overridepublic void onServiceDisconnected(ComponentName name) {// onServiceDisconnected is not being called on device shutdown, so this method being// called always indicates a bad state for the system server.// This code path is only run by the system server: only the system server binds// to the NetworkStack as a service. Other processes get the NetworkStack from// the ServiceManager.maybeCrashWithTerribleFailure(Lost network stack, mPackageName);}} 结合代码可知就是通过bindService()启动一个服务并通过一个lambda表达式在服务connect成功之后进行服务注册的过程它绑定的服务的filter是android.net.ITetheringConnector。 在源码中该服务定义在frameworks\base\packages\Tethering\AndroidManifest.xml中 manifest xmlns:androidhttp://schemas.android.com/apk/res/androidpackagecom.android.networkstack.tetheringandroid:sharedUserIdandroid.uid.networkstackuses-sdk android:minSdkVersion29 android:targetSdkVersion29 /!-- Permissions must be defined here, and not in the base manifest, as the tetheringrunning in the system server process does not need any permission, and havingprivileged permissions added would cause crashes on startup unless they are alsoadded to the privileged permissions whitelist for that package. --uses-permission android:nameandroid.permission.ACCESS_NETWORK_STATE /uses-permission android:nameandroid.permission.BLUETOOTH /uses-permission android:nameandroid.permission.BLUETOOTH_PRIVILEGED /uses-permission android:nameandroid.permission.BROADCAST_STICKY /uses-permission android:nameandroid.permission.CHANGE_NETWORK_STATE /uses-permission android:nameandroid.permission.MANAGE_USB /uses-permission android:nameandroid.permission.MODIFY_PHONE_STATE /uses-permission android:nameandroid.permission.READ_DEVICE_CONFIG /uses-permission android:nameandroid.permission.READ_NETWORK_USAGE_HISTORY /uses-permission android:nameandroid.permission.READ_PHONE_STATE/uses-permission android:nameandroid.permission.TETHER_PRIVILEGED /uses-permission android:nameandroid.permission.UPDATE_APP_OPS_STATS /uses-permission android:nameandroid.permission.UPDATE_DEVICE_STATS /uses-permission android:nameandroid.permission.WRITE_SETTINGS /protected-broadcast android:namecom.android.server.connectivity.tethering.DISABLE_TETHERING /applicationandroid:processcom.android.networkstack.processandroid:extractNativeLibsfalseandroid:persistenttrueservice android:namecom.android.networkstack.tethering.TetheringServiceandroid:permissionandroid.permission.MAINLINE_NETWORK_STACKandroid:exportedtrueintent-filteraction android:nameandroid.net.ITetheringConnector//intent-filter/service/application /manifest它对应的Service是TetheringServiceTethering.apk封装了网络共享相关的主要服务实现它的使用类似于Bluetooth.apk被bind service拉起随后运行继续看TetheringService /** Copyright (C) 2019 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the License);* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an AS IS BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package com.android.networkstack.tethering;/*** Android service used to manage tethering.** pThe service returns a binder for the system server to communicate with the tethering.*/ public class TetheringService extends Service {private static final String TAG TetheringService.class.getSimpleName();private TetheringConnector mConnector;Overridepublic void onCreate() {final TetheringDependencies deps makeTetheringDependencies();// The Tethering object needs a fully functional context to start, so this cant be done// in the constructor.mConnector new TetheringConnector(makeTethering(deps), TetheringService.this);}/*** Make a reference to Tethering object.*/VisibleForTestingpublic Tethering makeTethering(TetheringDependencies deps) {System.loadLibrary(tetherutilsjni);return new Tethering(deps);}NonNullOverridepublic IBinder onBind(Intent intent) {return mConnector;}private static class TetheringConnector extends ITetheringConnector.Stub {private final TetheringService mService;private final Tethering mTethering;TetheringConnector(Tethering tether, TetheringService service) {mTethering tether;mService service;}} }/** hide */ oneway interface ITetheringConnector {void tether(String iface, String callerPkg, IIntResultListener receiver);void untether(String iface, String callerPkg, IIntResultListener receiver);void setUsbTethering(boolean enable, String callerPkg, IIntResultListener receiver);void startTethering(in TetheringRequestParcel request, String callerPkg,IIntResultListener receiver);void stopTethering(int type, String callerPkg, IIntResultListener receiver);void requestLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,boolean showEntitlementUi, String callerPkg);void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);void isTetheringSupported(String callerPkg, IIntResultListener receiver);void stopAllTethering(String callerPkg, IIntResultListener receiver); }TetheringService主要实现了AIDL ITetheringConnector定义的业务接口根据function名称可以很清晰的知道它主要针对的是网络共享。服务启动成功会以tethering的名字注册进系统中其他需要使用的组件就可以很容易的向Android查询、获取它。 Tethering组件正常启动之后就是APP使用它了我们以CarSetting为例 /*** Fragment to host tethering-related preferences.*/ SearchIndexable public class WifiTetherFragment extends SettingsFragment {private TetheringManager mTetheringManager;private void startTethering() {mTetheringManager.startTethering(ConnectivityManager.TETHERING_WIFI,ConcurrentUtils.DIRECT_EXECUTOR,new TetheringManager.StartTetheringCallback() {Overridepublic void onTetheringFailed(final int result) {mTetherSwitch.setChecked(false);mTetherSwitch.setEnabled(true);}});}private void stopTethering() {mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI);}private void restartTethering() {stopTethering();mRestartBooked true;}} WifiTetherFragment是实现开关热点的Fragment可知它会调用TetherManager::startTethering()去开启WiFi共享TetheringManager内部通过ITetheringConnector实现具体功能类似于WifiManager /*** Starts tethering and runs tether provisioning for the given type if needed. If provisioning* fails, stopTethering will be called automatically.** pWithout {link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will* fail if a tethering entitlement check is required.** param request a {link TetheringRequest} which can specify the preferred configuration.* param executor {link Executor} to specify the thread upon which the callback of* TetheringRequest will be invoked.* param callback A callback that will be called to indicate the success status of the* tethering start request.*/RequiresPermission(anyOf {android.Manifest.permission.TETHER_PRIVILEGED,android.Manifest.permission.WRITE_SETTINGS})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() {Overridepublic 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, listener));}/*** Starts tethering and runs tether provisioning for the given type if needed. If provisioning* fails, stopTethering will be called automatically.** pWithout {link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will* fail if a tethering entitlement check is required.** param type The tethering type, on of the {code TetheringManager#TETHERING_*} constants.* param executor {link Executor} to specify the thread upon which the callback of* TetheringRequest will be invoked.* hide*/RequiresPermission(anyOf {android.Manifest.permission.TETHER_PRIVILEGED,android.Manifest.permission.WRITE_SETTINGS})SystemApi(client MODULE_LIBRARIES)public void startTethering(int type, NonNull final Executor executor,NonNull final StartTetheringCallback callback) {startTethering(new TetheringRequest.Builder(type).build(), executor, callback);} 从前述可知传入的Tethering type是ConnectivityManager.TETHERING_WIFI直接看TetheringService private final Tethering mTethering;Overridepublic void startTethering(TetheringRequestParcel request, String callerPkg,IIntResultListener listener) {if (checkAndNotifyCommonError(callerPkg,request.exemptFromEntitlementCheck /* onlyAllowPrivileged */,listener)) {return;}m Tethering是一个包含各种网络共享业务逻辑的实现类比如BT网络共享、USB网络共享以及我们这里关注的WiFi网络共享 /**** This class holds much of the business logic to allow Android devices* to act as IP gateways via USB, BT, and WiFi interfaces.*/ public class Tethering {public Tethering(TetheringDependencies deps) {......startStateMachineUpdaters();}/*** Start to register callbacks.* Call this function when tethering is ready to handle callback events.*/private void startStateMachineUpdaters() {try {mNetd.registerUnsolicitedEventListener(mNetdCallback);} catch (RemoteException e) {mLog.e(Unable to register netd UnsolicitedEventListener);}mCarrierConfigChange.startListening();mContext.getSystemService(TelephonyManager.class).listen(mActiveDataSubIdListener,PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);IntentFilter filter new IntentFilter();filter.addAction(UsbManager.ACTION_USB_STATE);filter.addAction(CONNECTIVITY_ACTION);filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);filter.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED);filter.addAction(ACTION_RESTRICT_BACKGROUND_CHANGED);mContext.registerReceiver(mStateReceiver, filter, null, mHandler);final IntentFilter noUpstreamFilter new IntentFilter();noUpstreamFilter.addAction(TetheringNotificationUpdater.ACTION_DISABLE_TETHERING);mContext.registerReceiver(mStateReceiver, noUpstreamFilter, PERMISSION_MAINLINE_NETWORK_STACK, mHandler);final WifiManager wifiManager getWifiManager();if (wifiManager ! null) {wifiManager.registerSoftApCallback(mExecutor, new TetheringSoftApCallback());}startTrackDefaultNetwork();}private class StateReceiver extends BroadcastReceiver {Overridepublic void onReceive(Context content, Intent intent) {final String action intent.getAction();if (action null) return;if (action.equals(UsbManager.ACTION_USB_STATE)) {handleUsbAction(intent);} else if (action.equals(CONNECTIVITY_ACTION)) {handleConnectivityAction(intent);} else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {handleWifiApAction(intent);} else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) {handleWifiP2pAction(intent);} else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {mLog.log(OBSERVED configuration changed);updateConfiguration();} else if (action.equals(UserManager.ACTION_USER_RESTRICTIONS_CHANGED)) {mLog.log(OBSERVED user restrictions changed);handleUserRestrictionAction();} else if (action.equals(ACTION_RESTRICT_BACKGROUND_CHANGED)) {mLog.log(OBSERVED data saver changed);handleDataSaverChanged();} else if (action.equals(TetheringNotificationUpdater.ACTION_DISABLE_TETHERING)) {untetherAll();}}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);});}/*** Enables or disables tethering for the given type. If provisioning is required, it will* schedule provisioning rechecks for the specified interface.*/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 {synchronized (mPublicSync) {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;}} 从构造函数可知它监听了WifiManager.WIFI_AP_STATE_CHANGED_ACTION AP状态改变的广播这让它有了在驱动创建成功SoftAp iface后为它配置IP的能力这个后面再介绍。根据startTethering()的调用逻辑发现它调用了 WifiManager.startTetheredHotspot()WifiManager我们应该很熟悉 /*** This class provides the primary API for managing all aspects of Wi-Fi* connectivity.* p* On releases before {link android.os.Build.VERSION_CODES#N}, this object* should only be obtained from an {linkplain Context#getApplicationContext()* application context}, and not from any other derived context to avoid memory* leaks within the calling process.* p* It deals with several categories of items:* /p* ul* liThe list of configured networks. The list can be viewed and updated, and* attributes of individual entries can be modified./li* liThe currently active Wi-Fi network, if any. Connectivity can be* established or torn down, and dynamic information about the state of the* network can be queried./li* liResults of access point scans, containing enough information to make* decisions about what access point to connect to./li* liIt defines the names of various Intent actions that are broadcast upon* any sort of change in Wi-Fi state.* /ul* p* This is the API to use when performing Wi-Fi specific operations. To perform* operations that pertain to network connectivity at an abstract level, use* {link android.net.ConnectivityManager}.* /p*/ SystemService(Context.WIFI_SERVICE) public class WifiManager {/*** Start Soft AP (hotspot) mode for tethering purposes with the specified configuration.* Note that starting Soft AP mode may disable station mode operation if the device does not* support concurrency.* param softApConfig A valid SoftApConfiguration specifying the configuration of the SAP,* or null to use the persisted Soft AP configuration that was previously* set using {link #setSoftApConfiguration(softApConfiguration)}.* return {code true} if the operation succeeded, {code false} otherwise** hide*/SystemApiRequiresPermission(anyOf {android.Manifest.permission.NETWORK_STACK,NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})public boolean startTetheredHotspot(Nullable SoftApConfiguration softApConfig) {try {return mService.startTetheredHotspot(softApConfig);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}}/*** WifiService handles remote WiFi operation requests by implementing* the IWifiManager interface.*/ public class WifiServiceImpl extends BaseWifiService {/*** see {link android.net.wifi.WifiManager#startTetheredHotspot(SoftApConfiguration)}* param softApConfig SSID, security and channel details as part of SoftApConfiguration* return {code true} if softap start was triggered* throws SecurityException if the caller does not have permission to start softap*/Overridepublic boolean startTetheredHotspot(Nullable SoftApConfiguration softApConfig) {// NETWORK_STACK is a signature only permission.enforceNetworkStackPermission();mLog.info(startTetheredHotspot uid%).c(Binder.getCallingUid()).flush();if (!mTetheredSoftApTracker.setEnablingIfAllowed()) {mLog.err(Tethering is already active.).flush();return false;}if (!mWifiThreadRunner.call(() - mActiveModeWarden.canRequestMoreSoftApManagers(), false)) {// Take down LOHS if it is up.mLohsSoftApTracker.stopAll();}if (!startSoftApInternal(new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, softApConfig,mTetheredSoftApTracker.getSoftApCapability()))) {mTetheredSoftApTracker.setFailedWhileEnabling();return false;}return true;}/*** Internal method to start softap mode. Callers of this method should have already checked* proper permissions beyond the NetworkStack permission.*/private boolean startSoftApInternal(SoftApModeConfiguration apConfig) {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)|| !validateSoftApBand(softApConfig.getBand()))) {Log.e(TAG, Invalid SoftApConfiguration);return false;}mActiveModeWarden.startSoftAp(apConfig);return true;}} 主要的首先创建了一个目标共享MODE为WifiManager.IFACE_IP_MODE_TETHERED的SoftApModeConfiguration对象它描述了我们对开启的热点的配置信息随后调用ActiveModeWarden.startSoftAp(): /*** This class provides the implementation for different WiFi operating modes.*/ public class ActiveModeWarden {/*** WifiController is the class used to manage wifi state for various operating* modes (normal, airplane, wifi hotspot, etc.).*/private class WifiController extends StateMachine {WifiController() {super(TAG, mLooper);DefaultState defaultState new DefaultState();addState(defaultState); {addState(mDisabledState, defaultState);addState(mEnabledState, defaultState);}setLogRecSize(100);setLogOnlyTransitions(false);}Overridepublic void start() {if (shouldEnableSta()) {startClientModeManager();setInitialState(mEnabledState);} else {setInitialState(mDisabledState);}super.start();}class DefaultState extends State {}class EnabledState extends BaseState {private boolean mIsDisablingDueToAirplaneMode;Overridepublic void enter() {log(EnabledState.enter());super.enter();if (!hasAnyModeManager()) {Log.e(TAG, Entered EnabledState, but no active mode managers);}mIsDisablingDueToAirplaneMode false;}Overridepublic void exit() {log(EnabledState.exit());if (hasAnyModeManager()) {Log.e(TAG, Existing EnabledState, but has active mode managers);}super.exit();}Overridepublic boolean processMessageFiltered(Message msg) {switch (msg.what) {case CMD_WIFI_TOGGLED:case CMD_SCAN_ALWAYS_MODE_CHANGED:if (shouldEnableSta()) {if (hasAnyClientModeManager()) {switchAllClientModeManagers();} else {startClientModeManager();}} else {stopAllClientModeManagers();}break;case CMD_SET_AP:// note: CMD_SET_AP is handled/dropped in ECM mode - will not start hereif (msg.arg1 1) {startSoftApModeManager((SoftApModeConfiguration) msg.obj);} else {stopSoftApModeManagers(msg.arg2);}break;case CMD_AIRPLANE_TOGGLED:// airplane mode toggled on is handled in the default stateif (mSettingsStore.isAirplaneModeOn()) {mIsDisablingDueToAirplaneMode true;return NOT_HANDLED;} else {if (mIsDisablingDueToAirplaneMode) {// Previous airplane mode toggle on is being processed, defer the// message toggle off until previous processing is completed.// Once previous airplane mode toggle is complete, we should// transition to DisabledState. There, we will process the deferred// airplane mode toggle message to disable airplane mode.deferMessage(msg);} else {// when airplane mode is toggled off, but wifi is on, we can keep it// onlog(airplane mode toggled - and airplane mode is off. return handled);}return HANDLED;}case CMD_AP_STOPPED:case CMD_AP_START_FAILURE:if (!hasAnyModeManager()) {if (shouldEnableSta()) {log(SoftAp disabled, start client mode);startClientModeManager();} else {log(SoftAp mode disabled, return to DisabledState);transitionTo(mDisabledState);}} else {log(AP disabled, remain in EnabledState.);}break;case CMD_STA_START_FAILURE:case CMD_STA_STOPPED:// Client mode stopped. Head to Disabled to wait for next command if there// no active mode managers.if (!hasAnyModeManager()) {log(STA disabled, return to DisabledState.);transitionTo(mDisabledState);} else {log(STA disabled, remain in EnabledState.);}break;case CMD_RECOVERY_RESTART_WIFI:final String bugTitle;final String bugDetail;if (msg.arg1 SelfRecovery.REASON_STRINGS.length msg.arg1 0) {bugDetail SelfRecovery.REASON_STRINGS[msg.arg1];bugTitle Wi-Fi BugReport: bugDetail;} else {bugDetail ;bugTitle Wi-Fi BugReport;}if (msg.arg1 ! SelfRecovery.REASON_LAST_RESORT_WATCHDOG) {mHandler.post(() - mClientModeImpl.takeBugReport(bugTitle, bugDetail));}log(Recovery triggered, disable wifi);deferMessage(obtainMessage(CMD_DEFERRED_RECOVERY_RESTART_WIFI));shutdownWifi();// onStopped will move the state machine to DisabledState.break;default:return NOT_HANDLED;}return HANDLED;}}class DisabledState extends BaseState {Overridepublic void enter() {log(DisabledState.enter());super.enter();if (hasAnyModeManager()) {Log.e(TAG, Entered DisabledState, but has active mode managers);}}Overridepublic void exit() {log(DisabledState.exit());super.exit();}Overridepublic boolean processMessageFiltered(Message msg) {switch (msg.what) {case CMD_WIFI_TOGGLED:case CMD_SCAN_ALWAYS_MODE_CHANGED:if (shouldEnableSta()) {startClientModeManager();transitionTo(mEnabledState);}break;case CMD_SET_AP:// note: CMD_SET_AP is handled/dropped in ECM mode - will not start hereif (msg.arg1 1) {startSoftApModeManager((SoftApModeConfiguration) msg.obj);transitionTo(mEnabledState);}break;case CMD_RECOVERY_RESTART_WIFI:log(Recovery triggered, already in disabled state);// intentional fallthroughcase CMD_DEFERRED_RECOVERY_RESTART_WIFI:// wait mRecoveryDelayMillis for letting driver clean reset.sendMessageDelayed(CMD_RECOVERY_RESTART_WIFI_CONTINUE,readWifiRecoveryDelay());break;case CMD_RECOVERY_RESTART_WIFI_CONTINUE:if (shouldEnableSta()) {startClientModeManager();transitionTo(mEnabledState);}break;default:return NOT_HANDLED;}return HANDLED;}}}/** Starts SoftAp. */public void startSoftAp(SoftApModeConfiguration softApConfig) {mWifiController.sendMessage(WifiController.CMD_SET_AP, 1, 0, softApConfig);}} 经常接触Wifi或者BT Framework框架的打工人应该很熟悉StateMachine的流程了这里不再介绍相关的流程只关注开启热点的处理流程startSoftAp()的操作只是发送了WifiController.CMD_SET_AP命令让状态机处理开启的流程假设这是我们第一次开热点也是只开热点DisabledState状态处理该cmd case CMD_SET_AP: // note: CMD_SET_AP is handled/dropped in ECM mode - will not start here if (msg.arg1 1) {startSoftApModeManager((SoftApModeConfiguration) msg.obj);transitionTo(mEnabledState); }/*** Method to enable soft ap for wifi hotspot.** The supplied SoftApModeConfiguration includes the target softap WifiConfiguration (or null if* the persisted config is to be used) and the target operating mode (ex,* {link WifiManager#IFACE_IP_MODE_TETHERED} {link WifiManager#IFACE_IP_MODE_LOCAL_ONLY}).** param softApConfig SoftApModeConfiguration for the hostapd softap*/private void startSoftApModeManager(NonNull SoftApModeConfiguration softApConfig) {Log.d(TAG, Starting SoftApModeManager config softApConfig.getSoftApConfiguration());Preconditions.checkState(softApConfig.getTargetMode() IFACE_IP_MODE_LOCAL_ONLY|| softApConfig.getTargetMode() IFACE_IP_MODE_TETHERED);WifiManager.SoftApCallback callback softApConfig.getTargetMode() IFACE_IP_MODE_LOCAL_ONLY? mLohsCallback : mSoftApCallback;SoftApListener listener new SoftApListener();ActiveModeManager manager mWifiInjector.makeSoftApManager(listener, callback, softApConfig);listener.setActiveModeManager(manager);manager.start();manager.setRole(getRoleForSoftApIpMode(softApConfig.getTargetMode()));mActiveModeManagers.add(manager);}private ActiveModeManager.Role int getRoleForSoftApIpMode(int ipMode) {return ipMode IFACE_IP_MODE_TETHERED? ActiveModeManager.ROLE_SOFTAP_TETHERED : ActiveModeManager.ROLE_SOFTAP_LOCAL_ONLY;} 创建SoftApManager并调用其start()因为之前我们创建的MODE是IFACE_IP_MODE_TETHERED所以给SoftApManager set的role这里是ROLE_SOFTAP_TETHERED随后进入EnabledState。我们看SoftApManager它是一个管理WiFi AP mode管理类 /*** Manage WiFi in AP mode.* The internal state machine runs under the ClientModeImpl handler thread context.*/ public class SoftApManager implements ActiveModeManager {/*** Listener for soft AP events.*/private final SoftApListener mSoftApListener new SoftApListener() {Overridepublic void onFailure() {mStateMachine.sendMessage(SoftApStateMachine.CMD_FAILURE);}Overridepublic void onConnectedClientsChanged(NativeWifiClient client, boolean isConnected) {if (client ! null) {mStateMachine.sendMessage(SoftApStateMachine.CMD_ASSOCIATED_STATIONS_CHANGED,isConnected ? 1 : 0, 0, client);} else {Log.e(TAG, onConnectedClientsChanged: Invalid type returned);}}Overridepublic void onSoftApChannelSwitched(int frequency,WifiAnnotations.Bandwidth int bandwidth) {mStateMachine.sendMessage(SoftApStateMachine.CMD_SOFT_AP_CHANNEL_SWITCHED, frequency, bandwidth);}};public SoftApManager(NonNull WifiContext context,NonNull Looper looper,NonNull FrameworkFacade framework,NonNull WifiNative wifiNative,String countryCode,NonNull Listener listener,NonNull WifiManager.SoftApCallback callback,NonNull WifiApConfigStore wifiApConfigStore,NonNull SoftApModeConfiguration apConfig,NonNull WifiMetrics wifiMetrics,NonNull SarManager sarManager,NonNull BaseWifiDiagnostics wifiDiagnostics) {mStateMachine new SoftApStateMachine(looper);}/*** Start soft AP, as configured in the constructor.*/Overridepublic void start() {mStateMachine.sendMessage(SoftApStateMachine.CMD_START);}private class SoftApStateMachine extends StateMachine {private final State mIdleState new IdleState();private final State mStartedState new StartedState();private final InterfaceCallback mWifiNativeInterfaceCallback new InterfaceCallback() {Overridepublic void onDestroyed(String ifaceName) {if (mApInterfaceName ! null mApInterfaceName.equals(ifaceName)) {sendMessage(CMD_INTERFACE_DESTROYED);}}Overridepublic void onUp(String ifaceName) {if (mApInterfaceName ! null mApInterfaceName.equals(ifaceName)) {sendMessage(CMD_INTERFACE_STATUS_CHANGED, 1);}}Overridepublic void onDown(String ifaceName) {if (mApInterfaceName ! null mApInterfaceName.equals(ifaceName)) {sendMessage(CMD_INTERFACE_STATUS_CHANGED, 0);}}};SoftApStateMachine(Looper looper) {super(TAG, looper);addState(mIdleState);addState(mStartedState);setInitialState(mIdleState);start();}private class IdleState extends State {}private class StartedState extends State {}}} SoftApManager内部包含一个小的状态机SoftApStateMachine它只有两个状态Idle状态是初始状态它处理发来的SoftApStateMachine.CMD_START private class IdleState extends State {Overridepublic void enter() {}Overridepublic boolean processMessage(Message message) {switch (message.what) {case CMD_START:mApInterfaceName mWifiNative.setupInterfaceForSoftApMode(mWifiNativeInterfaceCallback);if (TextUtils.isEmpty(mApInterfaceName)) {Log.e(TAG, setup failure when creating ap interface.);updateApState(WifiManager.WIFI_AP_STATE_FAILED,WifiManager.WIFI_AP_STATE_DISABLED,WifiManager.SAP_START_FAILURE_GENERAL);mWifiMetrics.incrementSoftApStartResult(false, WifiManager.SAP_START_FAILURE_GENERAL);mModeListener.onStartFailure();break;}mSoftApNotifier.dismissSoftApShutDownTimeoutExpiredNotification();updateApState(WifiManager.WIFI_AP_STATE_ENABLING,WifiManager.WIFI_AP_STATE_DISABLED, 0);int result startSoftAp();if (result ! SUCCESS) {int failureReason WifiManager.SAP_START_FAILURE_GENERAL;if (result ERROR_NO_CHANNEL) {failureReason WifiManager.SAP_START_FAILURE_NO_CHANNEL;} else if (result ERROR_UNSUPPORTED_CONFIGURATION) {failureReason WifiManager.SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION;}updateApState(WifiManager.WIFI_AP_STATE_FAILED,WifiManager.WIFI_AP_STATE_ENABLING,failureReason);stopSoftAp();mWifiMetrics.incrementSoftApStartResult(false, failureReason);mModeListener.onStartFailure();break;}transitionTo(mStartedState);break;} }/*** Start a soft AP instance as configured.** return integer result code*/private int startSoftAp() {SoftApConfiguration config mApConfig.getSoftApConfiguration();if (config null || config.getSsid() null) {Log.e(TAG, Unable to start soft AP without valid configuration);return ERROR_GENERIC;}Log.d(TAG, band config.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(config);boolean acsEnabled mCurrentSoftApCapability.areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD);result ApConfigUtil.updateApChannelConfig(mWifiNative, mContext.getResources(), mCountryCode, localConfigBuilder, config,acsEnabled);if (result ! SUCCESS) {Log.e(TAG, Failed to update AP band and channel);return result;}if (config.isHiddenSsid()) {Log.d(TAG, SoftAP is a hidden network);}if (!ApConfigUtil.checkSupportAllConfiguration(config, mCurrentSoftApCapability)) {Log.d(TAG, Unsupported Configuration detect! config config);return ERROR_UNSUPPORTED_CONFIGURATION;}if (!mWifiNative.startSoftAp(mApInterfaceName,localConfigBuilder.build(), mSoftApListener)) {Log.e(TAG, Soft AP start failed);return ERROR_GENERIC;}mWifiDiagnostics.startLogging(mApInterfaceName);mStartTimestamp FORMATTER.format(new Date(System.currentTimeMillis()));Log.d(TAG, Soft AP is started );return SUCCESS;}主要的 1、WifiNative.setupInterfaceForSoftApMode():创建一个供AP MODE使用的interface它的状态由mWifiNativeInterfaceCallback回调管理. 2、SoftApManager.startSoftAp():按配置信息在HAL/Driver层创建一个管理Soft ap的instance它的状态由SoftApListener回调管理 如果都调用成功进入StartedState private class StartedState extends State {private WakeupMessage mSoftApTimeoutMessage;private void scheduleTimeoutMessage() {if (!mTimeoutEnabled || mConnectedClients.size() ! 0) {cancelTimeoutMessage();return;}long timeout mApConfig.getSoftApConfiguration().getShutdownTimeoutMillis();if (timeout 0) {timeout mDefaultShutDownTimeoutMills;}mSoftApTimeoutMessage.schedule(SystemClock.elapsedRealtime() timeout);Log.d(TAG, Timeout message scheduled, delay timeout);}Overridepublic void enter() {mIfaceIsUp false;mIfaceIsDestroyed false;onUpChanged(mWifiNative.isInterfaceUp(mApInterfaceName));Handler handler mStateMachine.getHandler();mSoftApTimeoutMessage new WakeupMessage(mContext, handler,SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG,SoftApStateMachine.CMD_NO_ASSOCIATED_STATIONS_TIMEOUT);mSarManager.setSapWifiState(WifiManager.WIFI_AP_STATE_ENABLED);Log.d(TAG, Resetting connected clients on start);mConnectedClients.clear();mEverReportMetricsForMaxClient false;scheduleTimeoutMessage();} } 进入StartedState::enter()时比较重要的是此时会设置一个默认600000ms(10min)的timeout超时机制如果此时间段一直没有设备连接该AP就会自动关闭AP。 整个开启AP的过程都会有对外通知当前AP状态改变的广播发送 /*** Update AP state.** param newState new AP state* param currentState current AP state* param reason Failure reason if the new AP state is in failure state*/private void updateApState(int newState, int currentState, int reason) {mSoftApCallback.onStateChanged(newState, reason);//send the AP state change broadcastfinal Intent intent new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, newState);intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, currentState);if (newState WifiManager.WIFI_AP_STATE_FAILED) {//only set reason number when softAP start failedintent.putExtra(WifiManager.EXTRA_WIFI_AP_FAILURE_REASON, reason);}intent.putExtra(WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME, mApInterfaceName);intent.putExtra(WifiManager.EXTRA_WIFI_AP_MODE, mApConfig.getTargetMode());mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);} 假设我们正常开启了热点此时也会发送AP开启成功的广播。回到前面介绍Tethering的内容它内部监听了该广播 private class StateReceiver extends BroadcastReceiver {Overridepublic void onReceive(Context content, Intent intent) {final String action intent.getAction();if (action null) return;if (action.equals(UsbManager.ACTION_USB_STATE)) {handleUsbAction(intent);} else if (action.equals(CONNECTIVITY_ACTION)) {handleConnectivityAction(intent);} else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {handleWifiApAction(intent);} else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) {handleWifiP2pAction(intent);} else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {mLog.log(OBSERVED configuration changed);updateConfiguration();} else if (action.equals(UserManager.ACTION_USER_RESTRICTIONS_CHANGED)) {mLog.log(OBSERVED user restrictions changed);handleUserRestrictionAction();} else if (action.equals(ACTION_RESTRICT_BACKGROUND_CHANGED)) {mLog.log(OBSERVED data saver changed);handleDataSaverChanged();} else if (action.equals(TetheringNotificationUpdater.ACTION_DISABLE_TETHERING)) {untetherAll();}}private void handleWifiApAction(Intent intent) {final int curState intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);final String ifname intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME);final int ipmode intent.getIntExtra(EXTRA_WIFI_AP_MODE, IFACE_IP_MODE_UNSPECIFIED);synchronized (Tethering.this.mPublicSync) {switch (curState) {case WifiManager.WIFI_AP_STATE_ENABLING:// We can see this state on the way to both enabled and failure states.break;case WifiManager.WIFI_AP_STATE_ENABLED:enableWifiIpServingLocked(ifname, ipmode);break;case WifiManager.WIFI_AP_STATE_DISABLING:// We can see this state on the way to disabled.break;case WifiManager.WIFI_AP_STATE_DISABLED:case WifiManager.WIFI_AP_STATE_FAILED:default:disableWifiIpServingLocked(ifname, curState);break;}}} }private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {// Map wifiIpMode values to IpServer.Callback serving states, inferring// from mWifiTetherRequested as a final best guess.final int ipServingMode;switch (wifiIpMode) {case IFACE_IP_MODE_TETHERED:ipServingMode IpServer.STATE_TETHERED;break;case IFACE_IP_MODE_LOCAL_ONLY:ipServingMode IpServer.STATE_LOCAL_ONLY;break;default:mLog.e(Cannot enable IP serving in unknown WiFi mode: wifiIpMode);return;}if (!TextUtils.isEmpty(ifname)) {maybeTrackNewInterfaceLocked(ifname);changeInterfaceState(ifname, ipServingMode);} else {mLog.e(String.format(Cannot enable IP serving in mode %s on missing interface name,ipServingMode));}} 根据前面的说明此处会调用Tethering.enableWifiIpServingLocked()主要的处理有改变ipServerMode的值为IpServer.STATE_TETHERED以及如下两个函数 private void maybeTrackNewInterfaceLocked(final String iface) {// If we dont care about this type of interface, ignore.final int interfaceType ifaceNameToType(iface);if (interfaceType TETHERING_INVALID) {mLog.log(iface is not a tetherable iface, ignoring);return;}maybeTrackNewInterfaceLocked(iface, interfaceType);}private void maybeTrackNewInterfaceLocked(final String iface, int interfaceType) {// If we have already started a TISM for this interface, skip.if (mTetherStates.containsKey(iface)) {mLog.log(active iface ( iface ) reported as added, ignoring);return;}mLog.log(adding TetheringInterfaceStateMachine for: iface);final TetherState tetherState new TetherState(new IpServer(iface, mLooper, interfaceType, mLog, mNetd, mBpfCoordinator,makeControlCallback(), mConfig.enableLegacyDhcpServer,mConfig.isBpfOffloadEnabled(), mPrivateAddressCoordinator,mDeps.getIpServerDependencies()));mTetherStates.put(iface, tetherState);tetherState.ipServer.start();}private void changeInterfaceState(String ifname, int requestedState) {final int result;switch (requestedState) {case IpServer.STATE_UNAVAILABLE:case IpServer.STATE_AVAILABLE:result untether(ifname);break;case IpServer.STATE_TETHERED:case IpServer.STATE_LOCAL_ONLY:result tether(ifname, requestedState);break;default:Log.wtf(TAG, Unknown interface state: requestedState);return;}if (result ! TETHER_ERROR_NO_ERROR) {Log.e(TAG, unable start or stop tethering on iface ifname);return;}} 这里两个个函数的内容分别介绍首先maybeTrackNewInterfaceLocked() private void maybeTrackNewInterfaceLocked(final String iface, int interfaceType) {// If we have already started a TISM for this interface, skip.if (mTetherStates.containsKey(iface)) {mLog.log(active iface ( iface ) reported as added, ignoring);return;}mLog.log(adding TetheringInterfaceStateMachine for: iface);final TetherState tetherState new TetherState(new IpServer(iface, mLooper, interfaceType, mLog, mNetd, mBpfCoordinator,makeControlCallback(), mConfig.enableLegacyDhcpServer,mConfig.isBpfOffloadEnabled(), mPrivateAddressCoordinator,mDeps.getIpServerDependencies()));mTetherStates.put(iface, tetherState);tetherState.ipServer.start();} 1、它为每个iface创建了TetherState对象并保存一个Map里 2、同时创建了IpServer类型实例并调用了IpServer.start()它是给AP配置的IP地址的来源 /*** Provides the interface to IP-layer serving functionality for a given network* interface, e.g. for tethering or local-only hotspot mode.** hide*/ public class IpServer extends StateMachine {/** IpServer callback. */public static class Callback {/*** Notify that |who| has changed its tethering state.** param who the calling instance of IpServer* param state one of STATE_** param lastError one of TetheringManager.TETHER_ERROR_**/public void updateInterfaceState(IpServer who, int state, int lastError) { }/*** Notify that |who| has new LinkProperties.** param who the calling instance of IpServer* param newLp the new LinkProperties to report*/public void updateLinkProperties(IpServer who, LinkProperties newLp) { }/*** Notify that the DHCP leases changed in one of the IpServers.*/public void dhcpLeasesChanged() { }/*** Request Tethering change.** param tetheringType the downstream type of this IpServer.* param enabled enable or disable tethering.*/public void requestEnableTethering(int tetheringType, boolean enabled) { }}private final State mInitialState;private final State mLocalHotspotState;private final State mTetheredState;private final State mUnavailableState;private final State mWaitingForRestartState;private LinkAddress mIpv4Address;// TODO: Add a dependency object to pass the data members or variables from the tethering// object. It helps to reduce the arguments of the constructor.public IpServer(String ifaceName, Looper looper, int interfaceType, SharedLog log,INetd netd, NonNull BpfCoordinator coordinator, Callback callback,boolean usingLegacyDhcp, boolean usingBpfOffload,PrivateAddressCoordinator addressCoordinator, Dependencies deps) {mInitialState new InitialState();mLocalHotspotState new LocalHotspotState();mTetheredState new TetheredState();mUnavailableState new UnavailableState();mWaitingForRestartState new WaitingForRestartState();addState(mInitialState);addState(mLocalHotspotState);addState(mTetheredState);addState(mWaitingForRestartState, mTetheredState);addState(mUnavailableState);setInitialState(mInitialState);}class InitialState extends State {}class BaseServingState extends State {}class LocalHotspotState extends BaseServingState{}class TetheredState extends BaseServingState {}/*** This state is terminal for the per interface state machine. At this* point, the master state machine should have removed this interface* specific state machine from its list of possible recipients of* tethering requests. The state machine itself will hang around until* the garbage collector finds it.*/class UnavailableState extends State {Overridepublic void enter() {mIpNeighborMonitor.stop();mLastError TetheringManager.TETHER_ERROR_NO_ERROR;sendInterfaceState(STATE_UNAVAILABLE);}}class WaitingForRestartState extends State {Overridepublic boolean processMessage(Message message) {logMessage(this, message.what);switch (message.what) {case CMD_TETHER_UNREQUESTED:transitionTo(mInitialState);mLog.i(Untethered (unrequested) and restarting mIfaceName);mCallback.requestEnableTethering(mInterfaceType, true /* enabled */);break;case CMD_INTERFACE_DOWN:transitionTo(mUnavailableState);mLog.i(Untethered (interface down) and restarting mIfaceName);mCallback.requestEnableTethering(mInterfaceType, true /* enabled */);break;default:return false;}return true;}} } IpServer也是一个小状态机它主要是计算IP地址并在对应的iface进行地址配置这样我们ifconfig查看网卡信息时才能看到配置的信息。IpServer.start()启动之后处理暂时告一段落. 接着看Tethering.changeInterfaceState() private void changeInterfaceState(String ifname, int requestedState) {final int result;switch (requestedState) {case IpServer.STATE_UNAVAILABLE:case IpServer.STATE_AVAILABLE:result untether(ifname);break;case IpServer.STATE_TETHERED:case IpServer.STATE_LOCAL_ONLY:result tether(ifname, requestedState);break;default:Log.wtf(TAG, Unknown interface state: requestedState);return;}if (result ! TETHER_ERROR_NO_ERROR) {Log.e(TAG, unable start or stop tethering on iface ifname);return;}} 根据前面的Mode我们进入Tethering.tether() private int tether(String iface, int requestedState) {if (DBG) Log.d(TAG, Tethering iface);synchronized (mPublicSync) {TetherState tetherState mTetherStates.get(iface);if (tetherState null) {Log.e(TAG, Tried to Tether an unknown iface: iface , ignoring);return TETHER_ERROR_UNKNOWN_IFACE;}// Ignore the error status of the interface. If the interface is available,// the errors are referring to past tethering attempts anyway.if (tetherState.lastState ! IpServer.STATE_AVAILABLE) {Log.e(TAG, Tried to Tether an unavailable iface: iface , ignoring);return TETHER_ERROR_UNAVAIL_IFACE;}// NOTE: If a CMD_TETHER_REQUESTED message is already in the TISMs queue but not yet// processed, this will be a no-op and it will not return an error.//// This code cannot race with untether() because they both synchronize on mPublicSync.// TODO: reexamine the threading and messaging model to totally remove mPublicSync.final int type tetherState.ipServer.interfaceType();final TetheringRequestParcel request mActiveTetheringRequests.get(type, null);if (request ! null) {mActiveTetheringRequests.delete(type);}tetherState.ipServer.sendMessage(IpServer.CMD_TETHER_REQUESTED, requestedState, 0,request);return TETHER_ERROR_NO_ERROR;}} 主要向IpServer这个StateMachine发送CMD_TETHER_REQUESTED cmd它的初始状态是InitialState它处理此消息 class InitialState extends State {Overridepublic void enter() {sendInterfaceState(STATE_AVAILABLE);}Overridepublic boolean processMessage(Message message) {logMessage(this, message.what);switch (message.what) {case CMD_TETHER_REQUESTED:mLastError TetheringManager.TETHER_ERROR_NO_ERROR;switch (message.arg1) {case STATE_LOCAL_ONLY:maybeConfigureStaticIp((TetheringRequestParcel) message.obj);transitionTo(mLocalHotspotState);break;case STATE_TETHERED:maybeConfigureStaticIp((TetheringRequestParcel) message.obj);transitionTo(mTetheredState);break;default:mLog.e(Invalid tethering interface serving state specified.);}break;case CMD_INTERFACE_DOWN:transitionTo(mUnavailableState);break;case CMD_IPV6_TETHER_UPDATE:updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1);break;default:return NOT_HANDLED;}return HANDLED;}}private void maybeConfigureStaticIp(final TetheringRequestParcel request) {// Ignore static address configuration if they are invalid or null. In theory, static// addresses should not be invalid here because TetheringManager do not allow caller to// specify invalid static address configuration.if (request null || request.localIPv4Address null|| request.staticClientAddress null || !checkStaticAddressConfiguration(request.localIPv4Address, request.staticClientAddress)) {return;}mStaticIpv4ServerAddr request.localIPv4Address;mStaticIpv4ClientAddr request.staticClientAddress;}// Handling errors in BaseServingState.enter() by transitioning is// problematic because transitioning during a multi-state jump yields// a Log.wtf(). Ultimately, there should be only one ServingState,// and forwarding and NAT rules should be handled by a coordinating// functional element outside of IpServer.class TetheredState extends BaseServingState {Overridepublic void enter() {super.enter();if (mLastError ! TetheringManager.TETHER_ERROR_NO_ERROR) {transitionTo(mInitialState);}if (DBG) Log.d(TAG, Tethered mIfaceName);sendInterfaceState(STATE_TETHERED);}Overridepublic void exit() {cleanupUpstream();super.exit();}private void cleanupUpstream() {if (mUpstreamIfaceSet null) return;for (String ifname : mUpstreamIfaceSet.ifnames) cleanupUpstreamInterface(ifname);mUpstreamIfaceSet null;clearIpv6ForwardingRules();}private void cleanupUpstreamInterface(String upstreamIface) {// Note that we dont care about errors here.// Sometimes interfaces are gone before we get// to remove their rules, which generates errors.// Just do the best we can.try {mNetd.ipfwdRemoveInterfaceForward(mIfaceName, upstreamIface);} catch (RemoteException | ServiceSpecificException e) {mLog.e(Exception in ipfwdRemoveInterfaceForward: e.toString());}try {mNetd.tetherRemoveForward(mIfaceName, upstreamIface);} catch (RemoteException | ServiceSpecificException e) {mLog.e(Exception in disableNat: e.toString());}}Overridepublic boolean processMessage(Message message) {if (super.processMessage(message)) return true;logMessage(this, message.what);switch (message.what) {case CMD_TETHER_REQUESTED:mLog.e(CMD_TETHER_REQUESTED while already tethering.);break;case CMD_TETHER_CONNECTION_CHANGED:final InterfaceSet newUpstreamIfaceSet (InterfaceSet) message.obj;if (noChangeInUpstreamIfaceSet(newUpstreamIfaceSet)) {if (VDBG) Log.d(TAG, Connection changed noop - dropping);break;}if (newUpstreamIfaceSet null) {cleanupUpstream();break;}for (String removed : upstreamInterfacesRemoved(newUpstreamIfaceSet)) {cleanupUpstreamInterface(removed);}final SetString added upstreamInterfacesAdd(newUpstreamIfaceSet);// This makes the call to cleanupUpstream() in the error// path for any interface neatly cleanup all the interfaces.mUpstreamIfaceSet newUpstreamIfaceSet;for (String ifname : added) {try {mNetd.tetherAddForward(mIfaceName, ifname);mNetd.ipfwdAddInterfaceForward(mIfaceName, ifname);} catch (RemoteException | ServiceSpecificException e) {mLog.e(Exception enabling NAT: e.toString());cleanupUpstream();mLastError TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR;transitionTo(mInitialState);return true;}}break;case CMD_NEIGHBOR_EVENT:handleNeighborEvent((NeighborEvent) message.obj);break;default:return false;}return true;}private boolean noChangeInUpstreamIfaceSet(InterfaceSet newIfaces) {if (mUpstreamIfaceSet null newIfaces null) return true;if (mUpstreamIfaceSet ! null newIfaces ! null) {return mUpstreamIfaceSet.equals(newIfaces);}return false;}private SetString upstreamInterfacesRemoved(InterfaceSet newIfaces) {if (mUpstreamIfaceSet null) return new HashSet();final HashSetString removed new HashSet(mUpstreamIfaceSet.ifnames);removed.removeAll(newIfaces.ifnames);return removed;}private SetString upstreamInterfacesAdd(InterfaceSet newIfaces) {final HashSetString added new HashSet(newIfaces.ifnames);if (mUpstreamIfaceSet ! null) added.removeAll(mUpstreamIfaceSet.ifnames);return added;}}class BaseServingState extends State {Overridepublic void enter() {if (!startIPv4()) {mLastError TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;return;}try {NetdUtils.tetherInterface(mNetd, mIfaceName, asIpPrefix(mIpv4Address));} catch (RemoteException | ServiceSpecificException | IllegalStateException e) {mLog.e(Error Tethering, e);mLastError TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;return;}if (!startIPv6()) {mLog.e(Failed to startIPv6);// TODO: Make this a fatal error once Bluetooth IPv6 is sorted.return;}}Overridepublic void exit() {// Note that at this point, were leaving the tethered state. We can fail any// of these operations, but it doesnt really change that we have to try them// all in sequence.stopIPv6();try {NetdUtils.untetherInterface(mNetd, mIfaceName);} catch (RemoteException | ServiceSpecificException e) {mLastError TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;mLog.e(Failed to untether interface: e);}stopIPv4();resetLinkProperties();} maybeConfigureStaticIp()主要是根据传入的config信息初始化一下变量以便后续配置为设定的static ip这里假设没有指定IP直接进入mTetheredState根据StateMachine的切换逻辑首先执行父状态的enter()其中 /** Internals. */private boolean startIPv4() {return configureIPv4(true);}private boolean configureIPv4(boolean enabled) {if (VDBG) Log.d(TAG, configureIPv4( enabled ));if (enabled) {mIpv4Address requestIpv4Address();}if (mIpv4Address null) {mLog.e(No available ipv4 address);return false;}if (mInterfaceType TetheringManager.TETHERING_BLUETOOTH) {// BT configures the interface elsewhere: only start DHCP.// TODO: make all tethering types behave the same way, and delete the bluetooth// code that calls into NetworkManagementService directly.return configureDhcp(enabled, mIpv4Address, null /* clientAddress */);}final IpPrefix ipv4Prefix asIpPrefix(mIpv4Address);final Boolean setIfaceUp;if (mInterfaceType TetheringManager.TETHERING_WIFI|| mInterfaceType TetheringManager.TETHERING_WIFI_P2P|| mInterfaceType TetheringManager.TETHERING_ETHERNET|| mInterfaceType TetheringManager.TETHERING_WIGIG) {// The WiFi and Ethernet stack has ownership of the interface up/down state.// It is unclear whether the Bluetooth or USB stacks will manage their own// state.setIfaceUp null;} else {setIfaceUp enabled;}if (!mInterfaceCtrl.setInterfaceConfiguration(mIpv4Address, setIfaceUp)) {mLog.e(Error configuring interface);if (!enabled) stopDhcp();return false;}if (enabled) {mLinkProperties.addLinkAddress(mIpv4Address);mLinkProperties.addRoute(getDirectConnectedRoute(mIpv4Address));} else {mLinkProperties.removeLinkAddress(mIpv4Address);mLinkProperties.removeRoute(getDirectConnectedRoute(mIpv4Address));}return configureDhcp(enabled, mIpv4Address, mStaticIpv4ClientAddr);}private LinkAddress requestIpv4Address() {if (mStaticIpv4ServerAddr ! null) return mStaticIpv4ServerAddr;if (mInterfaceType TetheringManager.TETHERING_BLUETOOTH) {return new LinkAddress(BLUETOOTH_IFACE_ADDR);}return mPrivateAddressCoordinator.requestDownstreamAddress(this);}private boolean configureDhcp(boolean enable, final LinkAddress serverAddr,final LinkAddress clientAddr) {if (enable) {return startDhcp(serverAddr, clientAddr);} else {stopDhcp();return true;}}private boolean startDhcp(final LinkAddress serverLinkAddr, final LinkAddress clientLinkAddr) {if (mUsingLegacyDhcp) {return true;}final Inet4Address addr (Inet4Address) serverLinkAddr.getAddress();final Inet4Address clientAddr clientLinkAddr null ? null :(Inet4Address) clientLinkAddr.getAddress();final DhcpServingParamsParcel params makeServingParams(addr /* defaultRouter */,addr /* dnsServer */, serverLinkAddr, clientAddr);mDhcpServerStartIndex;mDeps.makeDhcpServer(mIfaceName, params, new DhcpServerCallbacksImpl(mDhcpServerStartIndex));return true;}这里我们没指定static Ip就会通过requestIpv4Address()函数获取一个随机的IP地址(基本是xxx.xxx.xxx.xxx/netmask)获取到地址后紧接着就是去设置和通过DHCP为interface配置IP了。 之后就是通过Netd配置iface因为这类网络共享需要一些路由配置这部分要由Netd的内部负责处理 NetdUtils.tetherInterface(mNetd, mIfaceName, asIpPrefix(mIpv4Address)); 随后进入TetheredState。 这样SoftAp的开启的流程就粗略的过了一遍至于大家工作中有跟其他细致流程相关的可以根据这个流程进行自己的开发与分析了。
http://www.hkea.cn/news/14482986/

相关文章:

  • 学网站开发多久做视频网站都需要什么软件下载
  • 阿里云网站建设里云官网模版html最简单的代码
  • 建立网站链接结构的基本方式是网络营销ppt课件
  • 江门网站推广设计古德设计网gooood官网
  • 免费地方门户网站源码国际网站建设工具
  • 专业建站网网站运营推广江西住房和城乡建设厅网站
  • 公司网站自己可以学习优化吗广州越秀区租房
  • 网站建设五站合一15年做啥网站致富
  • 织梦网站安装视频教程app和网站开发的成本
  • 山东网站建设口碑好汉邦未来网站开发有限公司
  • 摄影学习网站网页模板之家
  • 做高清图的网站东莞网络推广运营平台
  • 北京网站建设有限公司学网站开发 优帮云
  • 以net结尾的网站中国最新新闻摘抄
  • wordpress网站网速慢国内最好用免费建站系统
  • 石林彝族网站建设wordpress api 中文文档下载
  • 江苏省和住房城乡建设厅网站wordpress单页面静态
  • 网站上传该怎么做亚马逊入驻费用及条件
  • 上海建工网站债权债务交易网站开发
  • 网站主机提供商浙江省建设局网站
  • 小说阅读网站开发怎么做英文的网站
  • 理财产品网站开发文档营销网站特点
  • 南京网站制作设计百度推广代理商名单
  • 自己可以自己做公司的网站吗平面设计师作品网站
  • 电子商务网站开发步骤邯郸公司做网站
  • 建设公司网站需要多少钱中国域名注册中心
  • 网站模板建站教程视频做空比特币网站
  • 易语言 做的网站做网站需要去哪里备案
  • 做网站项目的流程驻马店百度seo
  • ppt做杂志模板下载网站有哪些教你免费申请个人平台