Merge "Prepare for refactoring wifi ipserver start/stop" into tm-dev

This commit is contained in:
TreeHugger Robot
2022-05-20 09:53:13 +00:00
committed by Android (Google) Code Review
2 changed files with 77 additions and 40 deletions

View File

@@ -1288,7 +1288,7 @@ public class Tethering {
// Finally bring up serving on the new interface // Finally bring up serving on the new interface
mWifiP2pTetherInterface = group.getInterface(); mWifiP2pTetherInterface = group.getInterface();
enableWifiIpServing(mWifiP2pTetherInterface, IFACE_IP_MODE_LOCAL_ONLY); enableWifiP2pIpServing(mWifiP2pTetherInterface);
} }
private void handleUserRestrictionAction() { private void handleUserRestrictionAction() {
@@ -1379,20 +1379,22 @@ public class Tethering {
changeInterfaceState(ifname, ipServingMode); changeInterfaceState(ifname, ipServingMode);
} }
private void disableWifiIpServingCommon(int tetheringType, String ifname, int apState) { private void disableWifiIpServingCommon(int tetheringType, String ifname) {
mLog.log("Canceling WiFi tethering request -" if (!TextUtils.isEmpty(ifname) && mTetherStates.containsKey(ifname)) {
+ " type=" + tetheringType mTetherStates.get(ifname).ipServer.unwanted();
+ " interface=" + ifname return;
+ " state=" + apState);
if (!TextUtils.isEmpty(ifname)) {
final TetherState ts = mTetherStates.get(ifname);
if (ts != null) {
ts.ipServer.unwanted();
return;
}
} }
if (SdkLevel.isAtLeastT()) {
mLog.e("Tethering no longer handle untracked interface after T: " + ifname);
return;
}
// Attempt to guess the interface name before T. Pure AOSP code should never enter here
// because WIFI_AP_STATE_CHANGED intent always include ifname and it should be tracked
// by mTetherStates. In case OEMs have some modification in wifi side which pass null
// or empty ifname. Before T, tethering allow to disable the first wifi ipServer if
// given ifname don't match any tracking ipServer.
for (int i = 0; i < mTetherStates.size(); i++) { for (int i = 0; i < mTetherStates.size(); i++) {
final IpServer ipServer = mTetherStates.valueAt(i).ipServer; final IpServer ipServer = mTetherStates.valueAt(i).ipServer;
if (ipServer.interfaceType() == tetheringType) { if (ipServer.interfaceType() == tetheringType) {
@@ -1400,7 +1402,6 @@ public class Tethering {
return; return;
} }
} }
mLog.log("Error disabling Wi-Fi IP serving; " mLog.log("Error disabling Wi-Fi IP serving; "
+ (TextUtils.isEmpty(ifname) ? "no interface name specified" + (TextUtils.isEmpty(ifname) ? "no interface name specified"
: "specified interface: " + ifname)); : "specified interface: " + ifname));
@@ -1409,20 +1410,39 @@ public class Tethering {
private void disableWifiIpServing(String ifname, int apState) { private void disableWifiIpServing(String ifname, int apState) {
// Regardless of whether we requested this transition, the AP has gone // Regardless of whether we requested this transition, the AP has gone
// down. Don't try to tether again unless we're requested to do so. // down. Don't try to tether again unless we're requested to do so.
// TODO: Remove this altogether, once Wi-Fi reliably gives us an
// interface name with every broadcast.
mWifiTetherRequested = false; mWifiTetherRequested = false;
disableWifiIpServingCommon(TETHERING_WIFI, ifname, apState); mLog.log("Canceling WiFi tethering request - interface=" + ifname + " state=" + apState);
disableWifiIpServingCommon(TETHERING_WIFI, ifname);
}
private void enableWifiP2pIpServing(String ifname) {
if (TextUtils.isEmpty(ifname)) {
mLog.e("Cannot enable P2P IP serving with invalid interface");
return;
}
// After T, tethering always trust the iface pass by state change intent. This allow
// tethering to deprecate tetherable p2p regexs after T.
final int type = SdkLevel.isAtLeastT() ? TETHERING_WIFI_P2P : ifaceNameToType(ifname);
if (!checkTetherableType(type)) {
mLog.e(ifname + " is not a tetherable iface, ignoring");
return;
}
enableIpServing(type, ifname, IpServer.STATE_LOCAL_ONLY);
} }
private void disableWifiP2pIpServingIfNeeded(String ifname) { private void disableWifiP2pIpServingIfNeeded(String ifname) {
if (TextUtils.isEmpty(ifname)) return; if (TextUtils.isEmpty(ifname)) return;
disableWifiIpServingCommon(TETHERING_WIFI_P2P, ifname, /* fake */ 0); mLog.log("Canceling P2P tethering request - interface=" + ifname);
disableWifiIpServingCommon(TETHERING_WIFI_P2P, ifname);
} }
private void enableWifiIpServing(String ifname, int wifiIpMode) { private void enableWifiIpServing(String ifname, int wifiIpMode) {
mLog.log("request WiFi tethering - interface=" + ifname + " state=" + wifiIpMode);
// Map wifiIpMode values to IpServer.Callback serving states, inferring // Map wifiIpMode values to IpServer.Callback serving states, inferring
// from mWifiTetherRequested as a final "best guess". // from mWifiTetherRequested as a final "best guess".
final int ipServingMode; final int ipServingMode;
@@ -1438,13 +1458,18 @@ public class Tethering {
return; return;
} }
// After T, tethering always trust the iface pass by state change intent. This allow
// tethering to deprecate tetherable wifi regexs after T.
final int type = SdkLevel.isAtLeastT() ? TETHERING_WIFI : ifaceNameToType(ifname);
if (!checkTetherableType(type)) {
mLog.e(ifname + " is not a tetherable iface, ignoring");
return;
}
if (!TextUtils.isEmpty(ifname)) { if (!TextUtils.isEmpty(ifname)) {
ensureIpServerStarted(ifname); enableIpServing(type, ifname, ipServingMode);
changeInterfaceState(ifname, ipServingMode);
} else { } else {
mLog.e(String.format( mLog.e("Cannot enable IP serving on missing interface name");
"Cannot enable IP serving in mode %s on missing interface name",
ipServingMode));
} }
} }
@@ -2715,23 +2740,28 @@ public class Tethering {
mTetherMainSM.sendMessage(which, state, 0, newLp); mTetherMainSM.sendMessage(which, state, 0, newLp);
} }
private boolean hasSystemFeature(final String feature) {
return mContext.getPackageManager().hasSystemFeature(feature);
}
private boolean checkTetherableType(int type) {
if ((type == TETHERING_WIFI || type == TETHERING_WIGIG)
&& !hasSystemFeature(PackageManager.FEATURE_WIFI)) {
return false;
}
if (type == TETHERING_WIFI_P2P && !hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)) {
return false;
}
return type != TETHERING_INVALID;
}
private void ensureIpServerStarted(final String iface) { private void ensureIpServerStarted(final String iface) {
// If we don't care about this type of interface, ignore. // If we don't care about this type of interface, ignore.
final int interfaceType = ifaceNameToType(iface); final int interfaceType = ifaceNameToType(iface);
if (interfaceType == TETHERING_INVALID) { if (!checkTetherableType(interfaceType)) {
mLog.log(iface + " is not a tetherable iface, ignoring"); mLog.log(iface + " is used for " + interfaceType + " which is not tetherable");
return;
}
final PackageManager pm = mContext.getPackageManager();
if ((interfaceType == TETHERING_WIFI || interfaceType == TETHERING_WIGIG)
&& !pm.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
mLog.log(iface + " is not tetherable, because WiFi feature is disabled");
return;
}
if (interfaceType == TETHERING_WIFI_P2P
&& !pm.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)) {
mLog.log(iface + " is not tetherable, because WiFi Direct feature is disabled");
return; return;
} }

View File

@@ -57,6 +57,7 @@ import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY; import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED; import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED; import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
import static android.system.OsConstants.RT_SCOPE_UNIVERSE; import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -936,7 +937,7 @@ public class TetheringTest {
// Emulate externally-visible WifiManager effects, when hotspot mode // Emulate externally-visible WifiManager effects, when hotspot mode
// is being torn down. // is being torn down.
sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED); sendWifiApStateChanged(WIFI_AP_STATE_DISABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
mTethering.interfaceRemoved(TEST_WLAN_IFNAME); mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
mLooper.dispatchAll(); mLooper.dispatchAll();
@@ -1509,7 +1510,7 @@ public class TetheringTest {
// Emulate externally-visible WifiManager effects, when tethering mode // Emulate externally-visible WifiManager effects, when tethering mode
// is being torn down. // is being torn down.
sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED); sendWifiApStateChanged(WIFI_AP_STATE_DISABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
mTethering.interfaceRemoved(TEST_WLAN_IFNAME); mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
mLooper.dispatchAll(); mLooper.dispatchAll();
@@ -1903,7 +1904,13 @@ public class TetheringTest {
mTethering.unregisterTetheringEventCallback(callback); mTethering.unregisterTetheringEventCallback(callback);
mLooper.dispatchAll(); mLooper.dispatchAll();
mTethering.stopTethering(TETHERING_WIFI); mTethering.stopTethering(TETHERING_WIFI);
sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED); sendWifiApStateChanged(WIFI_AP_STATE_DISABLED);
if (isAtLeastT()) {
// After T, tethering doesn't support WIFI_AP_STATE_DISABLED with null interface name.
callback2.assertNoStateChangeCallback();
sendWifiApStateChanged(WIFI_AP_STATE_DISABLED, TEST_WLAN_IFNAME,
IFACE_IP_MODE_TETHERED);
}
tetherState = callback2.pollTetherStatesChanged(); tetherState = callback2.pollTetherStatesChanged();
assertArrayEquals(tetherState.availableList, new TetheringInterface[] {wifiIface}); assertArrayEquals(tetherState.availableList, new TetheringInterface[] {wifiIface});
mLooper.dispatchAll(); mLooper.dispatchAll();