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
     
    
- 
    
     
    
    
     
       */
     
    
- 
    
     
    
    
         
      @SystemApi
     
    
- 
    
     
    
    
         
      public 
      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.
     
    
- 
    
     
    
    
     
       *
     
    
- 
    
     
    
    
     
       * <p>This 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 service's 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 version
     
    
- 
    
     
    
    
             
      Intent 
      intent 
      = mDeps.getModuleServiceIntent(pm, serviceIntentBaseAction,
     
    
- 
    
     
    
    
     
                      servicePermissionName, 
      true 
      /* inSystemProcess */);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
             
      // Otherwise use the updatable module version
     
    
- 
    
     
    
    
             
      if (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 {
     
    
- 
    
     
    
    
             
      @NonNull
     
    
- 
    
     
    
    
             
      private 
      final String mPackageName;
     
    
- 
    
     
    
    
             
      @NonNull
     
    
- 
    
     
    
    
             
      private 
      final ModuleServiceCallback mModuleServiceCallback;
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
             
      private 
      ModuleServiceConnection
      (
     
    
- 
    
     
    
    
                     
      @NonNull String packageName,
     
    
- 
    
     
    
    
                     
      @NonNull ModuleServiceCallback moduleCallback) {
     
    
- 
    
     
    
    
     
                  mPackageName = packageName;
     
    
- 
    
     
    
    
     
                  mModuleServiceCallback = moduleCallback;
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
             
      @Override
     
    
- 
    
     
    
    
             
      public 
      void 
      onServiceConnected
      (ComponentName name, IBinder service) {
     
    
- 
    
     
    
    
     
                  logi(
      "Networking module service connected");
     
    
- 
    
     
    
    
     
                  mModuleServiceCallback.onModuleServiceConnected(service);
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
             
      @Override
     
    
- 
    
     
    
    
             
      public 
      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:android="http://schemas.android.com/apk/res/android"
     
    
- 
    
     
    
    
               
      package=
      "com.android.networkstack.tethering"
     
    
- 
    
     
    
    
               
      android:sharedUserId=
      "android.uid.networkstack">
     
    
- 
    
     
    
    
         
      <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      <!-- Permissions must be defined here, and not in the base manifest, as the tethering
     
    
- 
    
     
    
    
     
       running in the system server process does not need any permission, and having
     
    
- 
    
     
    
    
     
       privileged permissions added would cause crashes on startup unless they are also
     
    
- 
    
     
    
    
     
       added to the privileged permissions whitelist for that package. -->
     
    
- 
    
     
    
    
         
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     
    
- 
    
     
    
    
         
      <uses-permission android:name="android.permission.BLUETOOTH" />
     
    
- 
    
     
    
    
         
      <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
     
    
- 
    
     
    
    
         
      <uses-permission android:name="android.permission.BROADCAST_STICKY" />
     
    
- 
    
     
    
    
         
      <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
     
    
- 
    
     
    
    
         
      <uses-permission android:name="android.permission.MANAGE_USB" />
     
    
- 
    
     
    
    
         
      <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
     
    
- 
    
     
    
    
         
      <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
     
    
- 
    
     
    
    
         
      <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
     
    
- 
    
     
    
    
         
      <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
     
    
- 
    
     
    
    
         
      <uses-permission android:name="android.permission.TETHER_PRIVILEGED" />
     
    
- 
    
     
    
    
         
      <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
     
    
- 
    
     
    
    
         
      <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
     
    
- 
    
     
    
    
         
      <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      <protected-broadcast android:name="com.android.server.connectivity.tethering.DISABLE_TETHERING" />
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      <application
     
    
- 
    
     
    
    
             
      android:process=
      "com.android.networkstack.process"
     
    
- 
    
     
    
    
             
      android:extractNativeLibs=
      "false"
     
    
- 
    
     
    
    
             
      android:persistent=
      "true">
     
    
- 
    
     
    
    
             
      <service android:name="com.android.networkstack.tethering.TetheringService"
     
    
- 
    
     
    
    
                      
      android:permission=
      "android.permission.MAINLINE_NETWORK_STACK"
     
    
- 
    
     
    
    
                      
      android:exported=
      "true">
     
    
- 
    
     
    
    
                 
      <intent-filter>
     
    
- 
    
     
    
    
                     
      <action android:name="android.net.ITetheringConnector"/>
     
    
- 
    
     
    
    
                 
      </intent-filter>
     
    
- 
    
     
    
    
             
      </service>
     
    
- 
    
     
    
    
         
      </application>
     
    
- 
    
     
    
    
     
      </manifest>
     
    
 它对应的Service是TetheringService,Tethering.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.
     
    
- 
    
     
    
    
     
       *
     
    
- 
    
     
    
    
     
       * 
      <p>The 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;
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
          @Override
     
    
- 
    
     
    
    
     
          public void onCreate() {
     
    
- 
    
     
    
    
     
              final TetheringDependencies deps = makeTetheringDependencies();
     
    
- 
    
     
    
    
     
              // The Tethering object needs a fully functional context to start, so this can't be done
     
    
- 
    
     
    
    
     
              // in the constructor.
     
    
- 
    
     
    
    
     
              mConnector = new TetheringConnector(makeTethering(deps), TetheringService.this);
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
          /**
     
    
- 
    
     
    
    
     
           * Make a reference to Tethering object.
     
    
- 
    
     
    
    
     
           */
     
    
- 
    
     
    
    
     
          @VisibleForTesting
     
    
- 
    
     
    
    
     
          public Tethering makeTethering(TetheringDependencies deps) {
     
    
- 
    
     
    
    
     
              System.loadLibrary("tetherutilsjni");
     
    
- 
    
     
    
    
     
              return new Tethering(deps);
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
          @NonNull
     
    
- 
    
     
    
    
     
          @Override
     
    
- 
    
     
    
    
     
          public 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() {
     
    
- 
    
     
    
    
     
                          @Override
     
    
- 
    
     
    
    
     
                          public 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.
     
    
- 
    
     
    
    
     
           *
     
    
- 
    
     
    
    
     
           * 
      <p>Without {@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() {
     
    
- 
    
     
    
    
     
                  @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, listener));
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
          /**
     
    
- 
    
     
    
    
     
           * Starts tethering and runs tether provisioning for the given type if needed. If provisioning
     
    
- 
    
     
    
    
     
           * fails, stopTethering will be called automatically.
     
    
- 
    
     
    
    
     
           *
     
    
- 
    
     
    
    
     
           * 
      <p>Without {@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;
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public 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 {
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public 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>
     
    
- 
    
     
    
    
     
       * 
      <li>The list of configured networks. The list can be viewed and updated, and
     
    
- 
    
     
    
    
     
       * attributes of individual entries can be modified.
      </li>
     
    
- 
    
     
    
    
     
       * 
      <li>The 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>
     
    
- 
    
     
    
    
     
       * 
      <li>Results of access point scans, containing enough information to make
     
    
- 
    
     
    
    
     
       * decisions about what access point to connect to.
      </li>
     
    
- 
    
     
    
    
     
       * 
      <li>It 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
     
    
- 
    
     
    
    
     
           */
     
    
- 
    
     
    
    
     
          @SystemApi
     
    
- 
    
     
    
    
     
          @RequiresPermission(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
     
    
- 
    
     
    
    
     
           */
     
    
- 
    
     
    
    
     
          @Override
     
    
- 
    
     
    
    
     
          public 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);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public void start() {
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
                  if (shouldEnableSta()) {
     
    
- 
    
     
    
    
     
                      startClientModeManager();
     
    
- 
    
     
    
    
     
                      setInitialState(mEnabledState);
     
    
- 
    
     
    
    
     
                  } else {
     
    
- 
    
     
    
    
     
                      setInitialState(mDisabledState);
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
                  super.start();
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
              class DefaultState extends State {
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
              class EnabledState extends BaseState {
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
                  private boolean mIsDisablingDueToAirplaneMode;
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
                  @Override
     
    
- 
    
     
    
    
     
                  public void enter() {
     
    
- 
    
     
    
    
     
                      log("EnabledState.enter()");
     
    
- 
    
     
    
    
     
                      super.enter();
     
    
- 
    
     
    
    
     
                      if (!hasAnyModeManager()) {
     
    
- 
    
     
    
    
     
                          Log.e(TAG, "Entered EnabledState, but no active mode managers");
     
    
- 
    
     
    
    
     
                      }
     
    
- 
    
     
    
    
     
                      mIsDisablingDueToAirplaneMode = false;
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
                  @Override
     
    
- 
    
     
    
    
     
                  public void exit() {
     
    
- 
    
     
    
    
     
                      log("EnabledState.exit()");
     
    
- 
    
     
    
    
     
                      if (hasAnyModeManager()) {
     
    
- 
    
     
    
    
     
                          Log.e(TAG, "Existing EnabledState, but has active mode managers");
     
    
- 
    
     
    
    
     
                      }
     
    
- 
    
     
    
    
     
                      super.exit();
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
                  @Override
     
    
- 
    
     
    
    
     
                  public 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 here
     
    
- 
    
     
    
    
     
                              if (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 state
     
    
- 
    
     
    
    
     
                              if (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
     
    
- 
    
     
    
    
     
                                      // on
     
    
- 
    
     
    
    
     
                                      log("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 {
     
    
- 
    
     
    
    
     
                  @Override
     
    
- 
    
     
    
    
     
                  public void enter() {
     
    
- 
    
     
    
    
     
                      log("DisabledState.enter()");
     
    
- 
    
     
    
    
     
                      super.enter();
     
    
- 
    
     
    
    
     
                      if (hasAnyModeManager()) {
     
    
- 
    
     
    
    
     
                          Log.e(TAG, "Entered DisabledState, but has active mode managers");
     
    
- 
    
     
    
    
     
                      }
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
                  @Override
     
    
- 
    
     
    
    
     
                  public void exit() {
     
    
- 
    
     
    
    
     
                      log("DisabledState.exit()");
     
    
- 
    
     
    
    
     
                      super.exit();
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
                  @Override
     
    
- 
    
     
    
    
     
                  public 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 here
     
    
- 
    
     
    
    
     
                              if (msg.arg1 == 1) {
     
    
- 
    
     
    
    
     
                                  startSoftApModeManager((SoftApModeConfiguration) msg.obj);
     
    
- 
    
     
    
    
     
                                  transitionTo(mEnabledState);
     
    
- 
    
     
    
    
     
                              }
     
    
- 
    
     
    
    
     
                              break;
     
    
- 
    
     
    
    
     
                          case CMD_RECOVERY_RESTART_WIFI:
     
    
- 
    
     
    
    
     
                              log("Recovery triggered, already in disabled state");
     
    
- 
    
     
    
    
     
                              // intentional fallthrough
     
    
- 
    
     
    
    
     
                          case 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() {
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public void onFailure() {
     
    
- 
    
     
    
    
     
                  mStateMachine.sendMessage(SoftApStateMachine.CMD_FAILURE);
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public 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");
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public 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.
     
    
- 
    
     
    
    
     
           */
     
    
- 
    
     
    
    
     
          @Override
     
    
- 
    
     
    
    
     
          public 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() {
     
    
- 
    
     
    
    
     
                  @Override
     
    
- 
    
     
    
    
     
                  public void onDestroyed(String ifaceName) {
     
    
- 
    
     
    
    
     
                      if (mApInterfaceName != null && mApInterfaceName.equals(ifaceName)) {
     
    
- 
    
     
    
    
     
                          sendMessage(CMD_INTERFACE_DESTROYED);
     
    
- 
    
     
    
    
     
                      }
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
                  @Override
     
    
- 
    
     
    
    
     
                  public void onUp(String ifaceName) {
     
    
- 
    
     
    
    
     
                      if (mApInterfaceName != null && mApInterfaceName.equals(ifaceName)) {
     
    
- 
    
     
    
    
     
                          sendMessage(CMD_INTERFACE_STATUS_CHANGED, 1);
     
    
- 
    
     
    
    
     
                      }
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
                  @Override
     
    
- 
    
     
    
    
     
                  public 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 {
     
    
- 
    
     
    
    
     
                  @Override
     
    
- 
    
     
    
    
     
                  public void enter() {
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
                  @Override
     
    
- 
    
     
    
    
     
                  public 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);
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
     
                  @Override
     
    
- 
    
     
    
    
     
                  public 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 broadcast
     
    
- 
    
     
    
    
     
              final 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 failed
     
    
- 
    
     
    
    
     
                  intent.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 {
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public 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 don't 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 {
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public void enter() {
     
    
- 
    
     
    
    
     
                  mIpNeighborMonitor.stop();
     
    
- 
    
     
    
    
     
                  mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
     
    
- 
    
     
    
    
     
                  sendInterfaceState(STATE_UNAVAILABLE);
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
          class WaitingForRestartState extends State {
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public 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 TISM's 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 {
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public void enter() {
     
    
- 
    
     
    
    
     
                  sendInterfaceState(STATE_AVAILABLE);
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public 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 {
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public void enter() {
     
    
- 
    
     
    
    
     
                  super.enter();
     
    
- 
    
     
    
    
     
                  if (mLastError != TetheringManager.TETHER_ERROR_NO_ERROR) {
     
    
- 
    
     
    
    
     
                      transitionTo(mInitialState);
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
                  if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
     
    
- 
    
     
    
    
     
                  sendInterfaceState(STATE_TETHERED);
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public 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 don't 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());
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public 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 Set
      <String> 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 Set
      <String> upstreamInterfacesRemoved(InterfaceSet newIfaces) {
     
    
- 
    
     
    
    
     
                  if (mUpstreamIfaceSet == null) return new HashSet
      <>();
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
                  final HashSet
      <String> removed = new HashSet
      <>(mUpstreamIfaceSet.ifnames);
     
    
- 
    
     
    
    
     
                  removed.removeAll(newIfaces.ifnames);
     
    
- 
    
     
    
    
     
                  return removed;
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
              private Set
      <String> upstreamInterfacesAdd(InterfaceSet newIfaces) {
     
    
- 
    
     
    
    
     
                  final HashSet
      <String> added = new HashSet
      <>(newIfaces.ifnames);
     
    
- 
    
     
    
    
     
                  if (mUpstreamIfaceSet != null) added.removeAll(mUpstreamIfaceSet.ifnames);
     
    
- 
    
     
    
    
     
                  return added;
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
          class BaseServingState extends State {
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public 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;
     
    
- 
    
     
    
    
     
                  }
     
    
- 
    
     
    
    
     
              }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
              @Override
     
    
- 
    
     
    
    
     
              public void exit() {
     
    
- 
    
     
    
    
     
                  // Note that at this point, we're leaving the tethered state.  We can fail any
     
    
- 
    
     
    
    
     
                  // of these operations, but it doesn't 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的开启的流程就粗略的过了一遍,至于大家工作中有跟其他细致流程相关的,可以根据这个流程进行自己的开发与分析了。
转载:https://blog.csdn.net/csdn_of_coder/article/details/129098947
 
					