本文共 44156 字,大约阅读时间需要 147 分钟。
前言:从之前WiFi的连接流程可以知道WiFi最后一步会和服务端进行dhcp以获取ip地址,那么WiFi热点开启的时候应该也要配置相关dhcp属性,以供后续WiFi连接的时候ip分配,根据这块流程继续梳理。
1. log
01-01 08:01:26.451 840 862 D Tethering: interfaceStatusChanged wlan0, true01-01 08:01:26.545 840 985 D SoftApManager: startMonitoring01-01 08:01:26.545 840 985 D SoftApManager: mConnectedToHostapd true01-01 08:01:26.546 840 985 D WifiStateMachine: setWifiApState: enabled01-01 08:01:26.548 840 986 D WifiStateMachine: SoftApState !CMD_GET_SUPPORTED_FEATURES uid=1000 rt=87950/87950 0 001-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 001-01 08:01:26.552 840 863 D Tethering: Tethering wlan001-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 001-01 08:01:26.593 840 986 D WifiStateMachine: SoftApState !CMD_AP_GET_BLOCK_STATION_DETAIL uid=1000 rt=87995/87995 0 001-01 08:01:26.593 840 986 D SoftApManager: Get Soft AP Blocked Station01-01 08:01:26.601 840 863 D Tethering: Tether Mode requested by name=wlan0 state=TetheredState01-01 08:01:26.616 639 713 D TetherController: Starting tethering services01-01 08:01:26.625 639 713 D TetherController: Tethering services running
2.流程梳理
先看这一句log
01-01 08:01:26.451 840 862 D Tethering: interfaceStatusChanged wlan0, true
tether百度翻译是用绳子拴住(牲畜)( tether的过去式和过去分词 )
这句log虽然有点没头没尾,主要由于对supplicant的hostapd初始化没有系统学习和梳理,先看framework吧。
2.1 Tethering
@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 各个状态的变化。
2.2 TetherInterfaceStateMachine
看一下这个状态机方法,可以看到一系列和网络配置相关的接口。
构造方法如下
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
- LocalHotspotState
- TetheredState
- UnavailableState
其中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: enabled01-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 Setadded = 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; }
其中有两个比较关键的方法:
- mNMService.setIpForwardingEnabled(true);
- mNMService.startTethering(cfg.dhcpRanges);
其中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详细请参考:
命令会下发到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 Collectiondnses = 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 Setadded = 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);暂时不知道干嘛的。。。
待续。。。
转载地址:https://jiatai.blog.csdn.net/article/details/82956145 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!