Android共享热点IP问题引发的“血案”

今天一朋友问Android手机的Wi-Fi共享热点IP能不能修改,他那边一直是192.168.43.,自己记得在设置里面没有这个选项,便回复了他不能修改。后来猜测Android源码可能为了刻意避开常用局域网路由器192.168.0/1/2.段,特意设置的其他网段,但会不会存在与基站代理在一个网段后冲突自我协调的机制呢?(当然这个可能性很低,一般基站的代理服务器分配的都是10.*段的内网地址),既然有了这个问题,那索性看看源码怎么设置的。

涉水

首先想到的是到StackOverFlow上看看有没有相关问题,搜索得之,

http://stackoverflow.com/a/31238229/4865380

确实有人提到修改Hotspot网关的问题,给出的具体源码是在WiFiStateMachine.java中硬编码了192.168.43.1这个网关地址,这就解释了为什么共享出去的IP地址都是192.168.43.*了。手机用户想修改它,duang然是不可能了。

挣扎

从AOSP的master中去查找上文提到的platform/framework/base/wifi/java/android/net/WiFiStateMachine.java却消失了踪影,寻寻觅觅发现已经被移到platform/framework/opt/net/wifi/service/java/com/android/server/wifi/WiFiStateMachine.java。一看就对源码分析不熟悉,这些模块搬家的消息都不知道,其实从5.0之后opt/net/wifi之后就有了,部分代码被迁移到这里。

但是,但是,这个文件里面再也没有发现startTethering()方法,而且硬编码的代码也被移除了,难道5.0之后热点网关IP的配置又被更改了?继续跟踪文件diff发现有一次提交提到AP:

https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/d4f347f7de30834317dd1561dc806eccb1c4f277

Integrate SoftApManager to WifiStateMachine
   
Refactor WifiStateMachine to use SoftApManager for managing soft AP
instance.  This consolidate all soft AP related states in WifiStateMachine
to a single SoftApState.
   
While there, fix number of existing issues in WifiController:
- fix a possible race condition in WifiController where it will
 transition to a new state before AP is completely stopped.  Currently it is
 being worked around in WifiStateMachine by having the soft AP states defer
 the commands that might be issued during this race window.  This doesn't
 really scale and not really clear to the reader.  Fix it by only transition
 out of ApEnabledState when AP is completely stopped.
- fix a bug in WifiController where it doesn't transition out of
 ApEnabledState when AP is stopped internally (either tether notification
 timed out or WiFi becomes untethered), results in WifiController and
 WifiStateMachine being out of sync.
- fix couple unintentional fall through case statements.
   
Bug: 26876260
TEST=run frameworks-wifi test
TEST=run autotests
   
Change-Id: I1d12690b51265dacd087f22f601b7b0ea0a1082e

这次提交说明有关于AP热点配置在WiFiStateMachine.java中的代码被迁移到SoftAPManager,然后通过SoftAPManager来集成,同时也提到了AP这块代码放在WiFiStateMachine代码不够清晰。

继续挣扎

既然知道了代码迁移过程,那就需要跟着去寻找SoftAPManager。这个文件和WiFiStateMachine.java在同一包下,打开文件一看还是没有发现对于IP地址的硬编码部分,只能再次寻求log,这个文件的修改历史记录比较少,其中最老的一条对应于上文提到的AP状态管理通过SoftAPManager。通过历史查看这次修改发现了从WiFiStateMachine.java迁移过来的硬编码IP地址的代码。既然在创建时代码还存在,那么次新一条的历史记录就更加让人着迷了:

Remove all knowledge of tethering from SoftApManager
   
This logic has moved into Tethering and TetherInterfaceStatemachine,
where it probably always belonged.
   
Bug: 29054780
Test: WiFi tethering continues to work on angler
     `runtest frameworks-wifi` passes.
   
Change-Id: Ifff78ea540929fde4abea65716e1f659da2ecfec

时隔上次迁移到SoftAPManager.java的三个月后,这块逻辑又要被搬家了,归宿就是Tether模块,这么一波三折到底是Android源码,修改的简直是猝不及防。

上岸

上面提交记录中,提到的Tethering&TetherInterfaceStateMachine在platform/frameworks/base/services/core/java/com/android/server/connectivity/下面,关于硬编码的部分被迁移到TetherInterfaceStateMachine.java

private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129";
private static final String WIFI_HOST_IFACE_ADDR = "192.168.43.1";
   
private boolean configureIfaceIp(boolean enabled) {
   if (VDBG) Log.d(TAG, "configureIfaceIp(" + enabled + ")");
   String ipAsString = null;
   int prefixLen = 0;
   if (mInterfaceType == ConnectivityManager.TETHERING_USB) {
       ipAsString = USB_NEAR_IFACE_ADDR;
       prefixLen = USB_PREFIX_LENGTH;
   } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
       ipAsString = WIFI_HOST_IFACE_ADDR;
       prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
   } else {
       // Nothing to do, BT does this elsewhere.
       return true;
   }
   ......
}

硬编码IP的方式并没有改变,至此终于将代码的变化追踪完了,结果还是一套硬编码方式。当然乐在于真正找到了答案。