[Revert^2] Stop tethering request only if fuzzy-matched to existing request
stopTethering with a TetheringRequest should only stop tethering if there is an existing request (pending or serving) that fuzzy-matches the input and whose UID matches the caller (unless the caller is Settings, which is allowed to remove any request). If there is no existing fuzzy-matched request, return TETHER_ERROR_UNKNOWN_REQUEST. Note: This was originally merged as aosp/3527440 but was reverted due to a dependency CL being reverted. Remerging this on top of the fix for the dependency CL. Reverted changes: /q/submissionid:3541662-revert-3527440-JRJJTQBUFC Bug: 216524590 Test: atest TetheringTest RequestTrackerTest TetheringManagerTest Change-Id: I99dd2433efbb82f3721aa708ab50d198f6fbcb10
This commit is contained in:
parent
8b29d287f5
commit
d093ea69b0
4 changed files with 157 additions and 25 deletions
|
|
@ -239,4 +239,21 @@ public class RequestTracker {
|
||||||
public void removeAllServingRequests(final int type) {
|
public void removeAllServingRequests(final int type) {
|
||||||
mServingRequests.entrySet().removeIf(e -> e.getValue().getTetheringType() == type);
|
mServingRequests.entrySet().removeIf(e -> e.getValue().getTetheringType() == type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an existing (pending or serving) request that fuzzy matches the given request.
|
||||||
|
* Optionally specify matchUid to only return requests with the same uid.
|
||||||
|
*/
|
||||||
|
public TetheringRequest findFuzzyMatchedRequest(
|
||||||
|
@NonNull final TetheringRequest tetheringRequest, boolean matchUid) {
|
||||||
|
List<TetheringRequest> allRequests = new ArrayList<>();
|
||||||
|
allRequests.addAll(getPendingTetheringRequests());
|
||||||
|
allRequests.addAll(mServingRequests.values());
|
||||||
|
for (TetheringRequest request : allRequests) {
|
||||||
|
if (!request.fuzzyMatches(tetheringRequest)) continue;
|
||||||
|
if (matchUid && tetheringRequest.getUid() != request.getUid()) continue;
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -737,26 +737,13 @@ public class Tethering {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTetheringTypePendingOrServing(final int type) {
|
|
||||||
if (mRequestTracker.getNextPendingRequest(type) != null) return true;
|
|
||||||
for (TetherState state : mTetherStates.values()) {
|
|
||||||
// TODO: isCurrentlyServing only starts returning true once the IpServer has processed
|
|
||||||
// the CMD_TETHER_REQUESTED. Ensure that we consider the request to be serving even when
|
|
||||||
// that has not happened yet. This already works if the sync state machine is enabled
|
|
||||||
// (which includes all B+ devices).
|
|
||||||
if (state.isCurrentlyServing() && state.ipServer.interfaceType() == type) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void stopTetheringRequest(@NonNull final TetheringRequest request,
|
void stopTetheringRequest(@NonNull final TetheringRequest request,
|
||||||
@NonNull final IIntResultListener listener) {
|
@NonNull final IIntResultListener listener) {
|
||||||
if (!isTetheringWithSoftApConfigEnabled()) return;
|
if (!isTetheringWithSoftApConfigEnabled()) return;
|
||||||
|
final boolean hasNetworkSettings = hasCallingPermission(NETWORK_SETTINGS);
|
||||||
mHandler.post(() -> {
|
mHandler.post(() -> {
|
||||||
final int type = request.getTetheringType();
|
if (mRequestTracker.findFuzzyMatchedRequest(request, !hasNetworkSettings) != null) {
|
||||||
// TODO: when fuzzy-matching is enabled, check whether any pending request
|
final int type = request.getTetheringType();
|
||||||
// fuzzy-matches this request instead of just checking the type.
|
|
||||||
if (isTetheringTypePendingOrServing(type)) {
|
|
||||||
stopTetheringInternal(type);
|
stopTetheringInternal(type);
|
||||||
// TODO: We should send the success result after the waiting for tethering to
|
// TODO: We should send the success result after the waiting for tethering to
|
||||||
// actually stop.
|
// actually stop.
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ import static android.net.TetheringManager.TETHER_ERROR_INTERNAL_ERROR;
|
||||||
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
|
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
|
||||||
import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
|
import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
|
||||||
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
|
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
|
||||||
|
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_REQUEST;
|
||||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
|
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
|
||||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
|
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
|
||||||
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
|
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
|
||||||
|
|
@ -2779,6 +2780,85 @@ public class TetheringTest {
|
||||||
successListener2.assertHasResult();
|
successListener2.assertHasResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStopTetheringWithMatchingRequest() throws Exception {
|
||||||
|
assumeTrue(isTetheringWithSoftApConfigEnabled());
|
||||||
|
when(mContext.checkCallingOrSelfPermission(NETWORK_SETTINGS)).thenReturn(PERMISSION_DENIED);
|
||||||
|
initTetheringOnTestThread();
|
||||||
|
UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
|
||||||
|
initTetheringUpstream(upstreamState);
|
||||||
|
when(mWifiManager.startTetheredHotspot(null)).thenReturn(true);
|
||||||
|
|
||||||
|
// Enable wifi tethering.
|
||||||
|
SoftApConfiguration softApConfig = new SoftApConfiguration.Builder()
|
||||||
|
.setSsid("SoftApConfig")
|
||||||
|
.build();
|
||||||
|
final TetheringRequest tetheringRequest = new TetheringRequest.Builder(TETHERING_WIFI)
|
||||||
|
.setSoftApConfiguration(softApConfig).build();
|
||||||
|
tetheringRequest.setUid(TEST_CALLER_UID);
|
||||||
|
mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, null);
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
|
||||||
|
// Stop tethering with non-matching config. Should fail with TETHER_ERROR_UNKNOWN_REQUEST.
|
||||||
|
SoftApConfiguration softApConfig2 = new SoftApConfiguration.Builder()
|
||||||
|
.setSsid("SoftApConfig2")
|
||||||
|
.build();
|
||||||
|
IIntResultListener differentConfigListener = mock(IIntResultListener.class);
|
||||||
|
mTethering.stopTetheringRequest(new TetheringRequest.Builder(TETHERING_WIFI)
|
||||||
|
.setSoftApConfiguration(softApConfig2).build(), differentConfigListener);
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
verify(differentConfigListener).onResult(eq(TETHER_ERROR_UNKNOWN_REQUEST));
|
||||||
|
verify(mWifiManager, never()).stopSoftAp();
|
||||||
|
|
||||||
|
// Stop tethering with non-matching UID. Should fail with TETHER_ERROR_UNKNOWN_REQUEST.
|
||||||
|
final TetheringRequest nonMatchingUid = new TetheringRequest.Builder(TETHERING_WIFI)
|
||||||
|
.setSoftApConfiguration(softApConfig).build();
|
||||||
|
IIntResultListener nonMatchingUidListener = mock(IIntResultListener.class);
|
||||||
|
nonMatchingUid.setUid(TEST_CALLER_UID_2);
|
||||||
|
mTethering.stopTetheringRequest(nonMatchingUid, nonMatchingUidListener);
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
verify(nonMatchingUidListener).onResult(eq(TETHER_ERROR_UNKNOWN_REQUEST));
|
||||||
|
verify(mWifiManager, never()).stopSoftAp();
|
||||||
|
|
||||||
|
// Stop tethering with matching request. Should succeed now.
|
||||||
|
IIntResultListener matchingListener = mock(IIntResultListener.class);
|
||||||
|
mTethering.stopTetheringRequest(tetheringRequest, matchingListener);
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
verify(matchingListener).onResult(eq(TETHER_ERROR_NO_ERROR));
|
||||||
|
verify(mWifiManager).stopSoftAp();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStopTetheringWithSettingsPermission() throws Exception {
|
||||||
|
assumeTrue(isTetheringWithSoftApConfigEnabled());
|
||||||
|
initTetheringOnTestThread();
|
||||||
|
UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
|
||||||
|
initTetheringUpstream(upstreamState);
|
||||||
|
when(mWifiManager.startTetheredHotspot(null)).thenReturn(true);
|
||||||
|
|
||||||
|
// Enable wifi tethering.
|
||||||
|
SoftApConfiguration softApConfig = new SoftApConfiguration.Builder()
|
||||||
|
.setSsid("SoftApConfig")
|
||||||
|
.build();
|
||||||
|
final TetheringRequest tetheringRequest = new TetheringRequest.Builder(TETHERING_WIFI)
|
||||||
|
.setSoftApConfiguration(softApConfig).build();
|
||||||
|
tetheringRequest.setUid(TEST_CALLER_UID);
|
||||||
|
mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, null);
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
|
||||||
|
// Stop tethering with non-matching UID and Settings permission. Should succeed.
|
||||||
|
final TetheringRequest nonMatchingUid = new TetheringRequest.Builder(TETHERING_WIFI)
|
||||||
|
.setSoftApConfiguration(softApConfig).build();
|
||||||
|
IIntResultListener nonMatchingUidListener = mock(IIntResultListener.class);
|
||||||
|
nonMatchingUid.setUid(TEST_CALLER_UID_2);
|
||||||
|
when(mContext.checkCallingOrSelfPermission(NETWORK_SETTINGS))
|
||||||
|
.thenReturn(PERMISSION_GRANTED);
|
||||||
|
mTethering.stopTetheringRequest(nonMatchingUid, nonMatchingUidListener);
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
verify(nonMatchingUidListener).onResult(eq(TETHER_ERROR_NO_ERROR));
|
||||||
|
verify(mWifiManager).stopSoftAp();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReportFailCallbackIfOffloadNotSupported() throws Exception {
|
public void testReportFailCallbackIfOffloadNotSupported() throws Exception {
|
||||||
initTetheringOnTestThread();
|
initTetheringOnTestThread();
|
||||||
|
|
|
||||||
|
|
@ -483,25 +483,73 @@ public class TetheringManagerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStopTetheringRequest() throws Exception {
|
public void testStopTetheringRequestNoMatchFailure() throws Exception {
|
||||||
|
assumeTrue(isTetheringWithSoftApConfigEnabled());
|
||||||
|
final TestTetheringEventCallback tetherEventCallback =
|
||||||
|
mCtsTetheringUtils.registerTetheringEventCallback();
|
||||||
|
try {
|
||||||
|
final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
|
||||||
|
mTM.startTethering(new TetheringRequest.Builder(TETHERING_VIRTUAL).build(),
|
||||||
|
c -> c.run(), startTetheringCallback);
|
||||||
|
|
||||||
|
// Stopping a non-matching request should have no effect
|
||||||
|
TetheringRequest nonMatchingRequest = new TetheringRequest.Builder(TETHERING_VIRTUAL)
|
||||||
|
.setInterfaceName("iface")
|
||||||
|
.build();
|
||||||
|
mCtsTetheringUtils.stopTethering(nonMatchingRequest, false /* success */);
|
||||||
|
} finally {
|
||||||
|
mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStopTetheringRequestMatchSuccess() throws Exception {
|
||||||
assumeTrue(isTetheringWithSoftApConfigEnabled());
|
assumeTrue(isTetheringWithSoftApConfigEnabled());
|
||||||
final TestTetheringEventCallback tetherEventCallback =
|
final TestTetheringEventCallback tetherEventCallback =
|
||||||
mCtsTetheringUtils.registerTetheringEventCallback();
|
mCtsTetheringUtils.registerTetheringEventCallback();
|
||||||
try {
|
try {
|
||||||
tetherEventCallback.assumeWifiTetheringSupported(mContext);
|
tetherEventCallback.assumeWifiTetheringSupported(mContext);
|
||||||
|
|
||||||
// stopTethering without any tethering active should fail.
|
SoftApConfiguration softApConfig = new SoftApConfiguration.Builder()
|
||||||
TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build();
|
.setWifiSsid(WifiSsid.fromBytes("This is one config"
|
||||||
mCtsTetheringUtils.stopTethering(request, false /* expectSuccess */);
|
.getBytes(StandardCharsets.UTF_8))).build();
|
||||||
|
mCtsTetheringUtils.startWifiTethering(tetherEventCallback, softApConfig);
|
||||||
|
|
||||||
// Start wifi tethering
|
// Stopping the active request should stop tethering.
|
||||||
mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
|
TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI)
|
||||||
|
.setSoftApConfiguration(softApConfig)
|
||||||
|
.build();
|
||||||
|
mCtsTetheringUtils.stopTethering(request, true /* success */);
|
||||||
|
tetherEventCallback.expectNoTetheringActive();
|
||||||
|
} finally {
|
||||||
|
mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// stopTethering should succeed now that there's a request.
|
@Test
|
||||||
mCtsTetheringUtils.stopTethering(request, true /* expectSuccess */);
|
public void testStopTetheringRequestFuzzyMatchSuccess() throws Exception {
|
||||||
|
assumeTrue(isTetheringWithSoftApConfigEnabled());
|
||||||
|
final TestTetheringEventCallback tetherEventCallback =
|
||||||
|
mCtsTetheringUtils.registerTetheringEventCallback();
|
||||||
|
try {
|
||||||
|
tetherEventCallback.assumeWifiTetheringSupported(mContext);
|
||||||
|
|
||||||
|
SoftApConfiguration softApConfig = new SoftApConfiguration.Builder()
|
||||||
|
.setWifiSsid(WifiSsid.fromBytes("This is one config"
|
||||||
|
.getBytes(StandardCharsets.UTF_8))).build();
|
||||||
|
mCtsTetheringUtils.startWifiTethering(tetherEventCallback, softApConfig);
|
||||||
|
|
||||||
|
// Stopping with a fuzzy matching request should stop tethering.
|
||||||
|
final LinkAddress localAddr = new LinkAddress("192.168.24.5/24");
|
||||||
|
final LinkAddress clientAddr = new LinkAddress("192.168.24.100/24");
|
||||||
|
TetheringRequest fuzzyMatchingRequest = new TetheringRequest.Builder(TETHERING_WIFI)
|
||||||
|
.setSoftApConfiguration(softApConfig)
|
||||||
|
.setShouldShowEntitlementUi(true)
|
||||||
|
.setStaticIpv4Addresses(localAddr, clientAddr)
|
||||||
|
.build();
|
||||||
|
mCtsTetheringUtils.stopTethering(fuzzyMatchingRequest, true /* success */);
|
||||||
tetherEventCallback.expectNoTetheringActive();
|
tetherEventCallback.expectNoTetheringActive();
|
||||||
} finally {
|
} finally {
|
||||||
mCtsTetheringUtils.stopAllTethering();
|
|
||||||
mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
|
mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue