前言:从之前WiFi的连接流程可以知道WiFi最后一步会和服务端进行dhcp以获取ip地址,那么WiFi热点开启的时候应该也要配置相关dhcp属性,以供后续WiFi连接的时候ip分配,根据这块流程继续梳理。
01-01 08:01:26.451 840 862 D Tethering: interfaceStatusChanged wlan0, true
01-01 08:01:26.545 840 985 D SoftApManager: startMonitoring
01-01 08:01:26.545 840 985 D SoftApManager: mConnectedToHostapd true
01-01 08:01:26.546 840 985 D WifiStateMachine: setWifiApState: enabled
01-01 08:01:26.548 840 986 D WifiStateMachine: SoftApState !CMD_GET_SUPPORTED_FEATURES uid=1000 rt=87950/87950 0 0
01-01 08:01:26.548 840 986 E WifiStateMachine: Error! unhandled message{ when=-2ms what=131133 target=com.android.internal.util.StateMachine$SmHandler }
01-01 08:01:26.548 840 986 D WifiStateMachine: DefaultState !CMD_GET_SUPPORTED_FEATURES uid=1000 rt=87951/87951 0 0
01-01 08:01:26.552 840 863 D Tethering: Tethering wlan0
01-01 08:01:26.583 840 863 D Tethering: sendTetherStateChangedBroadcast avail=[] local_only=[] tether=[wlan0] error=[]
01-01 08:01:26.590 840 986 D WifiStateMachine: SoftApState !CMD_AP_GET_CONNECTED_STATION_DETAIL uid=1000 rt=87992/87992 0 0
01-01 08:01:26.593 840 986 D WifiStateMachine: SoftApState !CMD_AP_GET_BLOCK_STATION_DETAIL uid=1000 rt=87995/87995 0 0
01-01 08:01:26.593 840 986 D SoftApManager: Get Soft AP Blocked Station
01-01 08:01:26.601 840 863 D Tethering: Tether Mode requested by name=wlan0 state=TetheredState
01-01 08:01:26.616 639 713 D TetherController: Starting tethering services
01-01 08:01:26.625 639 713 D TetherController: Tethering services running
先看这一句log
01-01 08:01:26.451 840 862 D Tethering: interfaceStatusChanged wlan0, true
tether百度翻译是用绳子拴住(牲畜)( tether的过去式和过去分词 )
这句log虽然有点没头没尾,主要由于对supplicant的hostapd初始化没有系统学习和梳理,先看framework吧。
@Override
public void interfaceStatusChanged(String iface, boolean up) {
// Never called directly: only called from interfaceLinkStateChanged.
// See NetlinkHandler.cpp:71.
if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
synchronized (mPublicSync) {
if (up) {
maybeTrackNewInterfaceLocked(iface);
} else {
if (ifaceNameToType(iface) == TETHERING_BLUETOOTH) {
stopTrackingInterfaceLocked(iface);
} else {
// Ignore usb0 down after enabling RNDIS.
// We will handle disconnect in interfaceRemoved.
// Similarly, ignore interface down for WiFi. We monitor WiFi AP status
// through the WifiManager.WIFI_AP_STATE_CHANGED_ACTION intent.
if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
}
}
}
}
看下注释,解释了这个方法是被NetlinkHandler.cpp进行回调的,这边后续梳理,待续。
jiatai@jiatai:~/expand/aosp/aosp/system$ vim +71 ./netd/server/NetlinkHandler.cpp
void NetlinkHandler::onEvent(NetlinkEvent *evt) {
接着往下看up为true,调用maybeTrackNewInterfaceLocked
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 TetherInterfaceStateMachine(
iface, mLooper, interfaceType, mLog, mNMService, mStatsService,
makeControlCallback(iface), mDeps));
mTetherStates.put(iface, tetherState);
tetherState.stateMachine.start();
}
这边新起了一个状态机,应该是用来管理wlan0 各个状态的变化。
看一下这个状态机方法,可以看到一系列和网络配置相关的接口。
构造方法如下
public TetherInterfaceStateMachine(
String ifaceName, Looper looper, int interfaceType, SharedLog log,
INetworkManagementService nMService, INetworkStatsService statsService,
IControlsTethering tetherController,
TetheringDependencies deps) {
super(ifaceName, looper);
mLog = log.forSubComponent(ifaceName);
mNMService = nMService;
mNetd = deps.getNetdService();
mStatsService = statsService;
mTetherController = tetherController;
mInterfaceCtrl = new InterfaceController(ifaceName, nMService, mNetd, mLog);
mIfaceName = ifaceName;
mInterfaceType = interfaceType;
mLinkProperties = new LinkProperties();
mDeps = deps;
resetLinkProperties();
mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
mServingMode = IControlsTethering.STATE_AVAILABLE;
mInitialState = new InitialState();
mLocalHotspotState = new LocalHotspotState();
mTetheredState = new TetheredState();
mUnavailableState = new UnavailableState();
addState(mInitialState);
addState(mLocalHotspotState);
addState(mTetheredState);
addState(mUnavailableState);
setInitialState(mInitialState);
}
有四个状态,分别是
其中InitialState为初始状态,看下InitialState状态:
class InitialState extends State {
@Override
public void enter() {
sendInterfaceState(IControlsTethering.STATE_AVAILABLE);
}
@Override
public boolean processMessage(Message message) {
logMessage(this, message.what);
switch (message.what) {
case CMD_TETHER_REQUESTED:
mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
switch (message.arg1) {
case IControlsTethering.STATE_LOCAL_ONLY:
transitionTo(mLocalHotspotState);
break;
case IControlsTethering.STATE_TETHERED:
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);
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
}
看下sendInterfaceState
private void sendInterfaceState(int newInterfaceState) {
mServingMode = newInterfaceState;
mTetherController.updateInterfaceState(
TetherInterfaceStateMachine.this, newInterfaceState, mLastError);
sendLinkProperties();
}
private void sendLinkProperties() {
mTetherController.updateLinkProperties(
TetherInterfaceStateMachine.this, new LinkProperties(mLinkProperties));
}
其中mTetherController对应于Tethering传递进来的如下对象
private IControlsTethering makeControlCallback(String ifname) {
return new IControlsTethering() {
@Override
public void updateInterfaceState(
TetherInterfaceStateMachine who, int state, int lastError) {
notifyInterfaceStateChange(ifname, who, state, lastError);
}
@Override
public void updateLinkProperties(
TetherInterfaceStateMachine who, LinkProperties newLp) {
notifyLinkPropertiesChanged(ifname, who, newLp);
}
};
}
继而调用
// TODO: Move into TetherMasterSM.
private void notifyInterfaceStateChange(
String iface, TetherInterfaceStateMachine who, int state, int error) {
synchronized (mPublicSync) {
final TetherState tetherState = mTetherStates.get(iface);
if (tetherState != null && tetherState.stateMachine.equals(who)) {
tetherState.lastState = state;
tetherState.lastError = error;
} else {
if (DBG) Log.d(TAG, "got notification from stale iface " + iface);
}
}
mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error));
try {
// Notify that we're tethering (or not) this interface.
// This is how data saver for instance knows if the user explicitly
// turned on tethering (thus keeping us from being in data saver mode).
mPolicyManager.onTetheringChanged(iface, state == IControlsTethering.STATE_TETHERED);
} catch (RemoteException e) {
// Not really very much we can do here.
}
// If TetherMasterSM is in ErrorState, TetherMasterSM stays there.
// Thus we give a chance for TetherMasterSM to recover to InitialState
// by sending CMD_CLEAR_ERROR
if (error == TETHER_ERROR_MASTER_ERROR) {
mTetherMasterSM.sendMessage(TetherMasterSM.CMD_CLEAR_ERROR, who);
}
int which;
switch (state) {
case IControlsTethering.STATE_UNAVAILABLE:
case IControlsTethering.STATE_AVAILABLE:
which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_INACTIVE;
break;
case IControlsTethering.STATE_TETHERED:
case IControlsTethering.STATE_LOCAL_ONLY:
which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_ACTIVE;
break;
default:
Log.wtf(TAG, "Unknown interface state: " + state);
return;
}
mTetherMasterSM.sendMessage(which, state, 0, who);
sendTetherStateChangedBroadcast();
}
TetherMastartSM进行处理EVENT_IFACE_SERVING_STATE_INACTIVE消息
class InitialState extends State {
@Override
public boolean processMessage(Message message) {
logMessage(this, message.what);
switch (message.what) {
case EVENT_IFACE_SERVING_STATE_ACTIVE:
TetherInterfaceStateMachine who = (TetherInterfaceStateMachine) message.obj;
if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
handleInterfaceServingStateActive(message.arg1, who);
transitionTo(mTetherModeAliveState);
break;
case EVENT_IFACE_SERVING_STATE_INACTIVE:
who = (TetherInterfaceStateMachine) message.obj;
if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
handleInterfaceServingStateInactive(who);
break;
case EVENT_IFACE_UPDATE_LINKPROPERTIES:
// Silently ignore these for now.
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
}
private void handleInterfaceServingStateInactive(TetherInterfaceStateMachine who) {
mNotifyList.remove(who);
mIPv6TetheringCoordinator.removeActiveDownstream(who);
mOffload.excludeDownstreamInterface(who.interfaceName());
mForwardedDownstreams.remove(who);
// If this is a Wi-Fi interface, tell WifiManager of any errors.
if (who.interfaceType() == TETHERING_WIFI) {
if (who.lastError() != TETHER_ERROR_NO_ERROR) {
getWifiManager().updateInterfaceIpState(
who.interfaceName(), IFACE_IP_MODE_CONFIGURATION_ERROR);
}
}
}
这边只是初始化的。
再看一下这句log:
01-01 08:01:26.546 840 985 D WifiStateMachine: setWifiApState: enabled
01-01 08:01:26.552 840 863 D Tethering: Tethering wlan0
Tethering接收到了wifiap打开的消息,进行后续处理。
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(Intent.ACTION_CONFIGURATION_CHANGED)) {
mLog.log("OBSERVED configuration changed");
updateConfiguration();
}
}
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_DISABLED:
case WifiManager.WIFI_AP_STATE_DISABLING:
case WifiManager.WIFI_AP_STATE_FAILED:
default:
disableWifiIpServingLocked(ifname, curState);
break;
}
}
}
}
private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {
// Map wifiIpMode values to IControlsTethering serving states, inferring
// from mWifiTetherRequested as a final "best guess".
final int ipServingMode;
switch (wifiIpMode) {
case IFACE_IP_MODE_TETHERED:
ipServingMode = IControlsTethering.STATE_TETHERED;
break;
case IFACE_IP_MODE_LOCAL_ONLY:
ipServingMode = IControlsTethering.STATE_LOCAL_ONLY;
break;
default:
mLog.e("Cannot enable IP serving in unknown WiFi mode: " + wifiIpMode);
return;
}
if (!TextUtils.isEmpty(ifname)) {
maybeTrackNewInterfaceLocked(ifname, TETHERING_WIFI);
changeInterfaceState(ifname, ipServingMode);
} else {
mLog.e(String.format(
"Cannot enable IP serving in mode %s on missing interface name",
ipServingMode));
}
}
private void changeInterfaceState(String ifname, int requestedState) {
final int result;
switch (requestedState) {
case IControlsTethering.STATE_UNAVAILABLE:
case IControlsTethering.STATE_AVAILABLE:
result = untether(ifname);
break;
case IControlsTethering.STATE_TETHERED:
case IControlsTethering.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;
}
}
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 != IControlsTethering.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.
//
// TODO: reexamine the threading and messaging model.
tetherState.stateMachine.sendMessage(
TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, requestedState);
return TETHER_ERROR_NO_ERROR;
}
}
向TetherInterfaceStateMachine发出消息,InitialState进行处理
class InitialState extends State {
@Override
public void enter() {
sendInterfaceState(IControlsTethering.STATE_AVAILABLE);
}
@Override
public boolean processMessage(Message message) {
logMessage(this, message.what);
switch (message.what) {
case CMD_TETHER_REQUESTED:
mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
switch (message.arg1) {
case IControlsTethering.STATE_LOCAL_ONLY:
transitionTo(mLocalHotspotState);
break;
case IControlsTethering.STATE_TETHERED:
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);
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
}
先假定mode为IControlsTethering.STATE_TETHERED,切换到TetheredState状态(其实一般打开WiFi热点 mode确实是,mode是打开的时候传进来的startSoftApInternal(wifiConfig, WifiManager.IFACE_IP_MODE_TETHERED),详见WifiServiceImpl startSoftAp方法)
// 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 TetherInterfaceStateMachine.
class TetheredState extends BaseServingState {
@Override
public void enter() {
super.enter();
if (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
transitionTo(mInitialState);
}
if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
sendInterfaceState(IControlsTethering.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;
}
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 {
// About to tear down NAT; gather remaining statistics.
mStatsService.forceUpdate();
} catch (Exception e) {
if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString());
}
try {
mNMService.stopInterfaceForwarding(mIfaceName, upstreamIface);
} catch (Exception e) {
if (VDBG) Log.e(TAG, "Exception in removeInterfaceForward: " + e.toString());
}
try {
mNMService.disableNat(mIfaceName, upstreamIface);
} catch (Exception e) {
if (VDBG) Log.e(TAG, "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 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 {
mNMService.enableNat(mIfaceName, ifname);
mNMService.startInterfaceForwarding(mIfaceName, ifname);
} catch (Exception e) {
mLog.e("Exception enabling NAT: " + e);
cleanupUpstream();
mLastError = ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
transitionTo(mInitialState);
return true;
}
}
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 upstreamInterfacesRemoved(InterfaceSet newIfaces) {
if (mUpstreamIfaceSet == null) return new HashSet<>();
final HashSet removed = new HashSet<>(mUpstreamIfaceSet.ifnames);
removed.removeAll(newIfaces.ifnames);
return removed;
}
private Set upstreamInterfacesAdd(InterfaceSet newIfaces) {
final HashSet added = new HashSet<>(newIfaces.ifnames);
if (mUpstreamIfaceSet != null) added.removeAll(mUpstreamIfaceSet.ifnames);
return added;
}
}
先看下enter内,先调用它的父类方法的enter方法,开始启动ipv4等等
class BaseServingState extends State {
@Override
public void enter() {
if (!startIPv4()) {
mLastError = ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR;
return;
}
try {
mNMService.tetherInterface(mIfaceName);
} catch (Exception e) {
mLog.e("Error Tethering: " + e);
mLastError = ConnectivityManager.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;
}
继而回调Tethering的notifyInterfaceStateChange方法
case IControlsTethering.STATE_TETHERED:
case IControlsTethering.STATE_LOCAL_ONLY:
which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_ACTIVE;
break;
default:
Log.wtf(TAG, "Unknown interface state: " + state);
return;
}
mTetherMasterSM.sendMessage(which, state, 0, who);
发送EVENT_IFACE_SERVING_STATE_ACTIVE消息
class InitialState extends State {
@Override
public boolean processMessage(Message message) {
logMessage(this, message.what);
switch (message.what) {
case EVENT_IFACE_SERVING_STATE_ACTIVE:
TetherInterfaceStateMachine who = (TetherInterfaceStateMachine) message.obj;
if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
handleInterfaceServingStateActive(message.arg1, who);
transitionTo(mTetherModeAliveState);
break;
先看下handleInterfaceServingStateActive方法
private void handleInterfaceServingStateActive(int mode, TetherInterfaceStateMachine who) {
if (mNotifyList.indexOf(who) < 0) {
mNotifyList.add(who);
mIPv6TetheringCoordinator.addActiveDownstream(who, mode);
}
if (mode == IControlsTethering.STATE_TETHERED) {
// No need to notify OffloadController just yet as there are no
// "offload-able" prefixes to pass along. This will handled
// when the TISM informs Tethering of its LinkProperties.
mForwardedDownstreams.add(who);
} else {
mOffload.excludeDownstreamInterface(who.interfaceName());
mForwardedDownstreams.remove(who);
}
// If this is a Wi-Fi interface, notify WifiManager of the active serving state.
if (who.interfaceType() == TETHERING_WIFI) {
final WifiManager mgr = getWifiManager();
final String iface = who.interfaceName();
switch (mode) {
case IControlsTethering.STATE_TETHERED:
mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_TETHERED);
break;
case IControlsTethering.STATE_LOCAL_ONLY:
mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_LOCAL_ONLY);
break;
default:
Log.wtf(TAG, "Unknown active serving mode: " + mode);
break;
}
}
}
继而调用到WifiServiceImpl
private void updateInterfaceIpStateInternal(String ifaceName, int mode) {
// update interface IP state related to tethering and hotspot
synchronized (mLocalOnlyHotspotRequests) {
// update the mode tracker here - we clear out state below
Integer previousMode = WifiManager.IFACE_IP_MODE_UNSPECIFIED;
if (ifaceName != null) {
previousMode = mIfaceIpModes.put(ifaceName, mode);
}
Slog.d(TAG, "updateInterfaceIpState: ifaceName=" + ifaceName + " mode=" + mode
+ " previous mode= " + previousMode);
switch (mode) {
case WifiManager.IFACE_IP_MODE_LOCAL_ONLY:
// first make sure we have registered requests.. otherwise clean up
if (mLocalOnlyHotspotRequests.isEmpty()) {
// we don't have requests... stop the hotspot
stopSoftAp();
updateInterfaceIpStateInternal(null, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
return;
}
// LOHS is ready to go! Call our registered requestors!
sendHotspotStartedMessageToAllLOHSRequestInfoEntriesLocked();
break;
case WifiManager.IFACE_IP_MODE_TETHERED:
// we have tethered an interface. we don't really act on this now other than if
// we have LOHS requests, and this is an issue. return incompatible mode for
// onFailed for the registered requestors since this can result from a race
// between a tether request and a hotspot request (tethering wins).
sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(
LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE);
break;
/**
* Helper method to send a HOTSPOT_FAILED message to all registered LocalOnlyHotspotRequest
* callers and clear the registrations.
*
* Callers should already hold the mLocalOnlyHotspotRequests lock.
*/
private void sendHotspotFailedMessageToAllLOHSRequestInfoEntriesLocked(int arg1) {
for (LocalOnlyHotspotRequestInfo requestor : mLocalOnlyHotspotRequests.values()) {
try {
requestor.sendHotspotFailedMessage(arg1);
requestor.unlinkDeathRecipient();
} catch (RemoteException e) {
// This will be cleaned up by binder death handling
}
}
// Since all callers were notified, now clear the registrations.
mLocalOnlyHotspotRequests.clear();
}
依据
01-01 08:01:26.607 840 985 D WifiService: updateInterfaceIpState: ifaceName=wlan0 mode=1 previous mode= null
可以判断出mode确实为WifiManager.IFACE_IP_MODE_TETHERED
之后Tethering切换到TetherModeAliveState
class TetherModeAliveState extends State {
boolean mUpstreamWanted = false;
boolean mTryCell = true;
@Override
public void enter() {
// If turning on master tether settings fails, we have already
// transitioned to an error state; exit early.
if (!turnOnMasterTetherSettings()) {
return;
}
mSimChange.startListening();
mUpstreamNetworkMonitor.start(mDeps.getDefaultNetworkRequest());
// TODO: De-duplicate with updateUpstreamWanted() below.
if (upstreamWanted()) {
mUpstreamWanted = true;
mOffload.start();
chooseUpstreamType(true);
mTryCell = false;
}
}
先看下turnOnMasterTetherSettings
protected boolean turnOnMasterTetherSettings() {
final TetheringConfiguration cfg = mConfig;
try {
mNMService.setIpForwardingEnabled(true);
} catch (Exception e) {
mLog.e(e);
transitionTo(mSetIpForwardingEnabledErrorState);
return false;
}
// TODO: Randomize DHCPv4 ranges, especially in hotspot mode.
try {
// TODO: Find a more accurate method name (startDHCPv4()?).
mNMService.startTethering(cfg.dhcpRanges);
} catch (Exception e) {
try {
mNMService.stopTethering();
mNMService.startTethering(cfg.dhcpRanges);
} catch (Exception ee) {
mLog.e(ee);
transitionTo(mStartTetheringErrorState);
return false;
}
}
mLog.log("SET master tether settings: ON");
return true;
}
其中有两个比较关键的方法:
其中dhcpRanges默认值为
// USB is 192.168.42.1 and 255.255.255.0
// Wifi is 192.168.43.1 and 255.255.255.0
// BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
// with 255.255.255.0
// P2P is 192.168.49.1 and 255.255.255.0
private static final String[] DHCP_DEFAULT_RANGE = {
"192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
"192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
"192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
"192.168.48.2", "192.168.48.254", "192.168.49.2", "192.168.49.254",
};
调用到NetworkManagerService的如下方法:
mConnector.execute本质上是通过socket与netd进行通信。
@Override
public void setIpForwardingEnabled(boolean enable) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
mConnector.execute("ipfwd", enable ? "enable" : "disable", "tethering");
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
}
@Override
public void startTethering(String[] dhcpRange) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
// cmd is "tether start first_start first_stop second_start second_stop ..."
// an odd number of addrs will fail
final Command cmd = new Command("tether", "start");
for (String d : dhcpRange) {
cmd.appendArg(d);
}
try {
mConnector.execute(cmd);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
}
netd详细请参考:https://blog.csdn.net/xiaokeweng/article/details/8130218
命令会下发到netd由system/netd/server/CommandListener.cpp进行处理,其中tether命令处理如下。
CommandListener::TetherCmd::TetherCmd() :
NetdCommand("tether") {
}
int CommandListener::TetherCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
int rc = 0;
if (argc < 2) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
return 0;
}
if (!strcmp(argv[1], "stop")) {
rc = gCtls->tetherCtrl.stopTethering();
} else if (!strcmp(argv[1], "status")) {
char *tmp = NULL;
asprintf(&tmp, "Tethering services %s",
(gCtls->tetherCtrl.isTetheringStarted() ? "started" : "stopped"));
cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
free(tmp);
return 0;
} else if (argc == 3) {
if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
for (const auto &ifname : gCtls->tetherCtrl.getTetheredInterfaceList()) {
cli->sendMsg(ResponseCode::TetherInterfaceListResult, ifname.c_str(), false);
}
} else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
char netIdStr[UINT32_STRLEN];
snprintf(netIdStr, sizeof(netIdStr), "%u", gCtls->tetherCtrl.getDnsNetId());
cli->sendMsg(ResponseCode::TetherDnsFwdNetIdResult, netIdStr, false);
for (const auto &fwdr : gCtls->tetherCtrl.getDnsForwarders()) {
cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, fwdr.c_str(), false);
}
}
} else {
/*
* These commands take a minimum of 4 arguments
*/
if (argc < 4) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
return 0;
}
if (!strcmp(argv[1], "start")) {
if (argc % 2 == 1) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
return 0;
}
const int num_addrs = argc - 2;
// TODO: consider moving this validation into TetherController.
struct in_addr tmp_addr;
for (int arg_index = 2; arg_index < argc; arg_index++) {
if (!inet_aton(argv[arg_index], &tmp_addr)) {
cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
return 0;
}
}
rc = gCtls->tetherCtrl.startTethering(num_addrs, &(argv[2]));
} else if (!strcmp(argv[1], "interface")) {
if (!strcmp(argv[2], "add")) {
rc = gCtls->tetherCtrl.tetherInterface(argv[3]);
} else if (!strcmp(argv[2], "remove")) {
rc = gCtls->tetherCtrl.untetherInterface(argv[3]);
/* else if (!strcmp(argv[2], "list")) handled above */
} else {
cli->sendMsg(ResponseCode::CommandParameterError,
"Unknown tether interface operation", false);
return 0;
}
} else if (!strcmp(argv[1], "dns")) {
if (!strcmp(argv[2], "set")) {
if (argc < 5) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
return 0;
}
unsigned netId = stringToNetId(argv[3]);
rc = gCtls->tetherCtrl.setDnsForwarders(netId, &argv[4], argc - 4);
/* else if (!strcmp(argv[2], "list")) handled above */
} else {
cli->sendMsg(ResponseCode::CommandParameterError,
"Unknown tether interface operation", false);
return 0;
}
} else {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
return 0;
}
}
if (!rc) {
cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
} else {
cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
}
return 0;
}
这边暂时不继续追了,重新回到TetherModeAliveState的enter方法
class TetherModeAliveState extends State {
boolean mUpstreamWanted = false;
boolean mTryCell = true;
@Override
public void enter() {
// If turning on master tether settings fails, we have already
// transitioned to an error state; exit early.
if (!turnOnMasterTetherSettings()) {
return;
}
mSimChange.startListening();
mUpstreamNetworkMonitor.start(mDeps.getDefaultNetworkRequest());
// TODO: De-duplicate with updateUpstreamWanted() below.
if (upstreamWanted()) {
mUpstreamWanted = true;
mOffload.start();
chooseUpstreamType(true);
mTryCell = false;
}
}
看下chooseUpstreamType这个方法
protected void chooseUpstreamType(boolean tryCell) {
// We rebuild configuration on ACTION_CONFIGURATION_CHANGED, but we
// do not currently know how to watch for changes in DUN settings.
maybeUpdateConfiguration();
final TetheringConfiguration config = mConfig;
final NetworkState ns = (config.chooseUpstreamAutomatically)
? mUpstreamNetworkMonitor.getCurrentPreferredUpstream()
: mUpstreamNetworkMonitor.selectPreferredUpstreamType(
config.preferredUpstreamIfaceTypes);
if (ns == null) {
if (tryCell) {
mUpstreamNetworkMonitor.registerMobileNetworkRequest();
// We think mobile should be coming up; don't set a retry.
} else {
sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
}
}
mUpstreamNetworkMonitor.setCurrentUpstream((ns != null) ? ns.network : null);
setUpstreamNetwork(ns);
}
protected void setUpstreamNetwork(NetworkState ns) {
InterfaceSet ifaces = null;
if (ns != null) {
// Find the interface with the default IPv4 route. It may be the
// interface described by linkProperties, or one of the interfaces
// stacked on top of it.
mLog.i("Looking for default routes on: " + ns.linkProperties);
ifaces = TetheringInterfaceUtils.getTetheringInterfaces(ns);
mLog.i("Found upstream interface(s): " + ifaces);
}
if (ifaces != null) {
setDnsForwarders(ns.network, ns.linkProperties);
}
notifyDownstreamsOfNewUpstreamIface(ifaces);
if (ns != null && pertainsToCurrentUpstream(ns)) {
// If we already have NetworkState for this network update it immediately.
handleNewUpstreamNetworkState(ns);
} else if (mCurrentUpstreamIfaceSet == null) {
// There are no available upstream networks.
handleNewUpstreamNetworkState(null);
}
}
protected void setDnsForwarders(final Network network, final LinkProperties lp) {
// TODO: Set v4 and/or v6 DNS per available connectivity.
String[] dnsServers = mConfig.defaultIPv4DNS;
final Collection dnses = lp.getDnsServers();
// TODO: Properly support the absence of DNS servers.
if (dnses != null && !dnses.isEmpty()) {
// TODO: remove this invocation of NetworkUtils.makeStrings().
dnsServers = NetworkUtils.makeStrings(dnses);
}
try {
mNMService.setDnsForwarders(network, dnsServers);
mLog.log(String.format(
"SET DNS forwarders: network=%s dnsServers=%s",
network, Arrays.toString(dnsServers)));
} catch (Exception e) {
// TODO: Investigate how this can fail and what exactly
// happens if/when such failures occur.
mLog.e("setting DNS forwarders failed, " + e);
transitionTo(mSetDnsForwardersErrorState);
}
}
设置dns,默认duns服务器为
private final String[] DEFAULT_IPV4_DNS = {"8.8.4.4", "8.8.8.8"};
setDns完了之后会调用notifyDownstreamsOfNewUpstreamIface
protected void notifyDownstreamsOfNewUpstreamIface(InterfaceSet ifaces) {
mCurrentUpstreamIfaceSet = ifaces;
for (TetherInterfaceStateMachine sm : mNotifyList) {
sm.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED, ifaces);
}
}
触使TetherInterfaceStateMachine$TetheredState来处理
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 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 {
mNMService.enableNat(mIfaceName, ifname);
mNMService.startInterfaceForwarding(mIfaceName, ifname);
} catch (Exception e) {
mLog.e("Exception enabling NAT: " + e);
cleanupUpstream();
mLastError = ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
transitionTo(mInitialState);
return true;
}
}
break;
继续调用NMS的
mNMService.enableNat(mIfaceName, ifname);
mNMService.startInterfaceForwarding(mIfaceName, ifname);
暂时不知道干嘛的。。。
待续。。。