(九十七)Android O WiFi热点 开启流程梳理续(二)
发布日期:2021-06-30 15:25:23 浏览次数:2 分类:技术文章

本文共 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 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;        }

其中有两个比较关键的方法:

  1. mNMService.setIpForwardingEnabled(true);
  2. 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 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);

暂时不知道干嘛的。。。

待续。。。

 

转载地址:https://jiatai.blog.csdn.net/article/details/82956145 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:(九十八)Android O 探讨WiFi先打开后再打开WiFi热点继而改变配置的情况
下一篇:(九十六)Android O activity standard mode 探究

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月12日 15时25分59秒