Merge "Creating interface name to index tracking for Bpf Maps." into main
diff --git a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
index 2f9c3bc..0a66f01 100644
--- a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -37,7 +37,6 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
-import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -1259,44 +1258,6 @@
return sj.toString();
}
- @SuppressLint("UnflaggedApi")
- private static boolean supportsInterfaceName(int tetheringType) {
- // TODO: Check the interface name for TETHERING_WIFI and TETHERING_WIFI_P2P once
- // they're actually used.
- // Suppress lint for TETHERING_VIRTUAL since this method is only used internally.
- return tetheringType == TETHERING_VIRTUAL;
- }
-
- private static boolean supportsConcurrentConnectivityScopes(int tetheringType) {
- // Currently, only WIFI supports simultaneous local and global connectivity.
- // This can't happen for REQUEST_TYPE_EXPLICIT requests, because
- // TetheringRequest.Builder will not allow building an explicit TetheringRequest
- // with TETHERING_WIFI and CONNECTIVITY_SCOPE_LOCAL, but when local-only hotspot
- // is running, there is a REQUEST_TYPE_IMPLICIT request in the serving request list.
- return tetheringType == TETHERING_WIFI;
- }
-
- /**
- * Returns true if the other TetheringRequest "fuzzy" matches this one. This is used
- * internally to match tracked requests with external requests from API calls, and to reject
- * additional requests that the link layer has no capacity for.
- * @hide
- */
- public boolean fuzzyMatches(final TetheringRequest other) {
- if (other == null) return false;
- final int type = getTetheringType();
- if (type != other.getTetheringType()) return false;
- if (supportsInterfaceName(type)
- && !TextUtils.equals(getInterfaceName(), other.getInterfaceName())) {
- return false;
- }
- if (supportsConcurrentConnectivityScopes(type)
- && getConnectivityScope() != other.getConnectivityScope()) {
- return false;
- }
- return true;
- }
-
/**
* @hide
*/
@@ -1318,8 +1279,6 @@
public boolean equalsIgnoreUidPackage(TetheringRequest otherRequest) {
TetheringRequestParcel parcel = getParcel();
TetheringRequestParcel otherParcel = otherRequest.getParcel();
- // Note: Changes here should also be reflected in fuzzyMatches(TetheringRequest) when
- // appropriate.
return parcel.requestType == otherParcel.requestType
&& parcel.tetheringType == otherParcel.tetheringType
&& Objects.equals(parcel.localIPv4Address, otherParcel.localIPv4Address)
diff --git a/Tethering/src/android/net/ip/IpServer.java b/Tethering/src/android/net/ip/IpServer.java
index 70a3442..d0ba431 100644
--- a/Tethering/src/android/net/ip/IpServer.java
+++ b/Tethering/src/android/net/ip/IpServer.java
@@ -415,6 +415,12 @@
return mIpv4PrefixRequest;
}
+ /** The TetheringRequest the IpServer started with. */
+ @Nullable
+ public TetheringRequest getTetheringRequest() {
+ return mTetheringRequest;
+ }
+
/**
* Get the latest list of DHCP leases that was reported. Must be called on the IpServer looper
* thread.
diff --git a/Tethering/src/com/android/networkstack/tethering/RequestTracker.java b/Tethering/src/com/android/networkstack/tethering/RequestTracker.java
index 9c61716..3ebe4f7 100644
--- a/Tethering/src/com/android/networkstack/tethering/RequestTracker.java
+++ b/Tethering/src/com/android/networkstack/tethering/RequestTracker.java
@@ -19,8 +19,6 @@
import static com.android.networkstack.tethering.util.TetheringUtils.createPlaceholderRequest;
import android.net.TetheringManager.TetheringRequest;
-import android.net.ip.IpServer;
-import android.util.ArrayMap;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -30,7 +28,6 @@
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
/**
* Helper class to keep track of tethering requests.
@@ -39,17 +36,29 @@
* layer to start.
* 2) When the link layer is up, use {@link #getOrCreatePendingRequest(int)} to get a request to
* start IP serving with.
- * 3) Remove pending request with {@link #removePendingRequest(TetheringRequest)}.
+ * 3) Remove all pending requests with {@link #removeAllPendingRequests(int)}.
* Note: This class is not thread-safe.
+ * TODO: Add the pending IIntResultListeners at the same time as the pending requests, and
+ * call them when we get the tether result.
+ * TODO: Add support for multiple Bluetooth requests before the PAN service connects instead of
+ * using a separate mPendingPanRequestListeners.
+ * TODO: Add support for fuzzy-matched requests.
*/
public class RequestTracker {
private static final String TAG = RequestTracker.class.getSimpleName();
- @NonNull
- private final boolean mUseFuzzyMatching;
+ private class PendingRequest {
+ @NonNull
+ private final TetheringRequest mTetheringRequest;
- public RequestTracker(boolean useFuzzyMatching) {
- mUseFuzzyMatching = useFuzzyMatching;
+ private PendingRequest(@NonNull TetheringRequest tetheringRequest) {
+ mTetheringRequest = tetheringRequest;
+ }
+
+ @NonNull
+ TetheringRequest getTetheringRequest() {
+ return mTetheringRequest;
+ }
}
public enum AddResult {
@@ -60,51 +69,24 @@
/**
* Failure indicating that the request could not be added due to a request of the same type
* with conflicting parameters already pending. If so, we must stop tethering for the
- * pending request before trying to add the result again. Only returned on V-.
+ * pending request before trying to add the result again.
*/
- FAILURE_DUPLICATE_REQUEST_RESTART,
- /**
- * Failure indicating that the request could not be added due to a fuzzy-matched request
- * already pending or serving. Only returned on B+.
- */
- FAILURE_DUPLICATE_REQUEST_ERROR,
+ FAILURE_CONFLICTING_PENDING_REQUEST
}
/**
- * List of pending requests added by {@link #addPendingRequest(TetheringRequest)}
- * There can be only one per type, since we remove every request of the
- * same type when we add a request.
+ * List of pending requests added by {@link #addPendingRequest(TetheringRequest)}. There can be
+ * only one per type, since we remove every request of the same type when we add a request.
*/
- private final List<TetheringRequest> mPendingRequests = new ArrayList<>();
- /**
- * List of serving requests added by
- * {@link #promoteRequestToServing(IpServer, TetheringRequest)}.
- */
- private final Map<IpServer, TetheringRequest> mServingRequests = new ArrayMap<>();
+ private final List<PendingRequest> mPendingRequests = new ArrayList<>();
@VisibleForTesting
List<TetheringRequest> getPendingTetheringRequests() {
- return new ArrayList<>(mPendingRequests);
- }
-
- /**
- * Adds a pending request or fails with FAILURE_CONFLICTING_REQUEST_FAIL if the request
- * fuzzy-matches an existing request (either pending or serving).
- */
- public AddResult addPendingRequestFuzzyMatched(@NonNull final TetheringRequest newRequest) {
- List<TetheringRequest> existingRequests = new ArrayList<>();
- existingRequests.addAll(mServingRequests.values());
- existingRequests.addAll(mPendingRequests);
- for (TetheringRequest request : existingRequests) {
- if (request.fuzzyMatches(newRequest)) {
- Log.i(TAG, "Cannot add pending request due to existing fuzzy-matched "
- + "request: " + request);
- return AddResult.FAILURE_DUPLICATE_REQUEST_ERROR;
- }
+ List<TetheringRequest> requests = new ArrayList<>();
+ for (PendingRequest pendingRequest : mPendingRequests) {
+ requests.add(pendingRequest.getTetheringRequest());
}
-
- mPendingRequests.add(newRequest);
- return AddResult.SUCCESS;
+ return requests;
}
/**
@@ -113,12 +95,9 @@
* layer comes up. The result of the add operation will be returned as an AddResult code.
*/
public AddResult addPendingRequest(@NonNull final TetheringRequest newRequest) {
- if (mUseFuzzyMatching) {
- return addPendingRequestFuzzyMatched(newRequest);
- }
-
// Check the existing requests to see if it is OK to add the new request.
- for (TetheringRequest existingRequest : mPendingRequests) {
+ for (PendingRequest request : mPendingRequests) {
+ TetheringRequest existingRequest = request.getTetheringRequest();
if (existingRequest.getTetheringType() != newRequest.getTetheringType()) {
continue;
}
@@ -126,7 +105,7 @@
// Can't add request if there's a request of the same type with different
// parameters.
if (!existingRequest.equalsIgnoreUidPackage(newRequest)) {
- return AddResult.FAILURE_DUPLICATE_REQUEST_RESTART;
+ return AddResult.FAILURE_CONFLICTING_PENDING_REQUEST;
}
}
@@ -134,7 +113,7 @@
// conflicting parameters above, so these would have been equivalent anyway (except for
// UID).
removeAllPendingRequests(newRequest.getTetheringType());
- mPendingRequests.add(newRequest);
+ mPendingRequests.add(new PendingRequest(newRequest));
return AddResult.SUCCESS;
}
@@ -166,8 +145,10 @@
*/
@Nullable
public TetheringRequest getNextPendingRequest(int type) {
- for (TetheringRequest request : mPendingRequests) {
- if (request.getTetheringType() == type) return request;
+ for (PendingRequest pendingRequest : mPendingRequests) {
+ TetheringRequest tetheringRequest =
+ pendingRequest.getTetheringRequest();
+ if (tetheringRequest.getTetheringType() == type) return tetheringRequest;
}
return null;
}
@@ -177,83 +158,7 @@
*
* @param type Tethering type
*/
- public void removeAllPendingRequests(final int type) {
- mPendingRequests.removeIf(r -> r.getTetheringType() == type);
- }
-
- /**
- * Removes a specific pending request.
- *
- * Note: For V-, this will be the same as removeAllPendingRequests to align with historical
- * behavior.
- *
- * @param request Request to be removed
- */
- public void removePendingRequest(@NonNull TetheringRequest request) {
- if (!mUseFuzzyMatching) {
- // Remove all requests of the same type to match the historical behavior.
- removeAllPendingRequests(request.getTetheringType());
- return;
- }
-
- mPendingRequests.removeIf(r -> r.equals(request));
- }
-
- /**
- * Removes a tethering request from the pending list and promotes it to serving with the
- * IpServer that is using it.
- * Note: If mUseFuzzyMatching is false, then the request will be removed from the pending list,
- * but it will not be added to serving list.
- */
- public void promoteRequestToServing(@NonNull final IpServer ipServer,
- @NonNull final TetheringRequest tetheringRequest) {
- removePendingRequest(tetheringRequest);
- if (!mUseFuzzyMatching) return;
- mServingRequests.put(ipServer, tetheringRequest);
- }
-
-
- /**
- * Returns the serving request tied to the given IpServer, or null if there is none.
- * Note: If mUseFuzzyMatching is false, then this will always return null.
- */
- @Nullable
- public TetheringRequest getServingRequest(@NonNull final IpServer ipServer) {
- return mServingRequests.get(ipServer);
- }
-
- /**
- * Removes the serving request tied to the given IpServer.
- * Note: If mUseFuzzyMatching is false, then this is a no-op since serving requests are unused
- * for that configuration.
- */
- public void removeServingRequest(@NonNull final IpServer ipServer) {
- mServingRequests.remove(ipServer);
- }
-
- /**
- * Removes all serving requests of the given tethering type.
- *
- * @param type Tethering type
- */
- public void removeAllServingRequests(final int 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;
+ public void removeAllPendingRequests(int type) {
+ mPendingRequests.removeIf(r -> r.getTetheringRequest().getTetheringType() == type);
}
}
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 59f05ed..1a26658 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -43,7 +43,6 @@
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
import static android.net.TetheringManager.TETHERING_WIGIG;
import static android.net.TetheringManager.TETHER_ERROR_BLUETOOTH_SERVICE_PENDING;
-import static android.net.TetheringManager.TETHER_ERROR_DUPLICATE_REQUEST;
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_SERVICE_UNAVAIL;
@@ -68,8 +67,6 @@
import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-import static com.android.networkstack.tethering.RequestTracker.AddResult.FAILURE_DUPLICATE_REQUEST_ERROR;
-import static com.android.networkstack.tethering.RequestTracker.AddResult.FAILURE_DUPLICATE_REQUEST_RESTART;
import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_FORCE_USB_FUNCTIONS;
import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE;
import static com.android.networkstack.tethering.UpstreamNetworkMonitor.isCellular;
@@ -312,7 +309,7 @@
mLooper = mDeps.makeTetheringLooper();
mNotificationUpdater = mDeps.makeNotificationUpdater(mContext, mLooper);
mTetheringMetrics = mDeps.makeTetheringMetrics(mContext);
- mRequestTracker = new RequestTracker(isTetheringWithSoftApConfigEnabled());
+ mRequestTracker = new RequestTracker();
mTetherStates = new ArrayMap<>();
mConnectedClientsTracker = new ConnectedClientsTracker();
@@ -463,7 +460,6 @@
return mSettingsObserver;
}
- // TODO: Replace with SdkLevel.isAtLeastB() once the feature is fully implemented.
boolean isTetheringWithSoftApConfigEnabled() {
return SdkLevel.isAtLeastB() && Flags.tetheringWithSoftApConfig();
}
@@ -708,16 +704,9 @@
RequestTracker.AddResult result = mRequestTracker.addPendingRequest(request);
// If tethering is already pending with a conflicting request, stop tethering before
// starting.
- if (result == FAILURE_DUPLICATE_REQUEST_RESTART) {
+ if (result == RequestTracker.AddResult.FAILURE_CONFLICTING_PENDING_REQUEST) {
stopTetheringInternal(type); // Also removes the request from the tracker.
mRequestTracker.addPendingRequest(request);
- } else if (result == FAILURE_DUPLICATE_REQUEST_ERROR) {
- // Reject any fuzzy matched request.
- // TODO: Add a CTS test to verify back-to-back start/stop calls succeed. This must
- // be for a non-Wifi type, since Wifi will reject the start calls if it hasn't
- // brought down the SoftAP yet.
- sendTetherResult(listener, TETHER_ERROR_DUPLICATE_REQUEST);
- return;
}
if (request.isExemptFromEntitlementCheck()) {
@@ -737,28 +726,39 @@
});
}
+ 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.
+ if (state.isCurrentlyServing() && state.ipServer.interfaceType() == type) return true;
+ }
+ return false;
+ }
+
void stopTetheringRequest(@NonNull final TetheringRequest request,
@NonNull final IIntResultListener listener) {
if (!isTetheringWithSoftApConfigEnabled()) return;
- final boolean hasNetworkSettings = hasCallingPermission(NETWORK_SETTINGS);
mHandler.post(() -> {
- if (mRequestTracker.findFuzzyMatchedRequest(request, !hasNetworkSettings) != null) {
- final int type = request.getTetheringType();
+ final int type = request.getTetheringType();
+ if (isTetheringTypePendingOrServing(type)) {
stopTetheringInternal(type);
- // TODO: We should send the success result after the waiting for tethering to
- // actually stop.
- sendTetherResult(listener, TETHER_ERROR_NO_ERROR);
+ try {
+ listener.onResult(TETHER_ERROR_NO_ERROR);
+ } catch (RemoteException ignored) { }
return;
}
// Request doesn't match any active requests, ignore.
- sendTetherResult(listener, TETHER_ERROR_UNKNOWN_REQUEST);
+ try {
+ listener.onResult(TETHER_ERROR_UNKNOWN_REQUEST);
+ } catch (RemoteException ignored) { }
});
}
void stopTetheringInternal(int type) {
mRequestTracker.removeAllPendingRequests(type);
- mRequestTracker.removeAllServingRequests(type);
// Using a placeholder here is ok since none of the disable APIs use the request for
// anything. We simply need the tethering type to know which link layer to poke for removal.
@@ -802,25 +802,21 @@
// The result of Bluetooth tethering will be sent after the pan service connects.
if (result == TETHER_ERROR_BLUETOOTH_SERVICE_PENDING) return;
- sendTetherResultAndRemoveOnError(request, listener, result);
+ sendTetherResult(listener, result, type);
}
- private void sendTetherResult(final IIntResultListener listener, final int result) {
+ private void sendTetherResult(final IIntResultListener listener, final int result,
+ final int type) {
if (listener != null) {
try {
listener.onResult(result);
- } catch (RemoteException e) {
- }
+ } catch (RemoteException e) { }
}
- }
- private void sendTetherResultAndRemoveOnError(TetheringRequest request,
- final IIntResultListener listener, final int result) {
- sendTetherResult(listener, result);
-
+ // If changing tethering fail, remove corresponding request
+ // no matter who trigger the start/stop.
if (result != TETHER_ERROR_NO_ERROR) {
- mRequestTracker.removePendingRequest(request);
- final int type = request.getTetheringType();
+ mRequestTracker.removeAllPendingRequests(type);
mTetheringMetrics.updateErrorCode(type, result);
mTetheringMetrics.sendReport(type);
}
@@ -866,7 +862,8 @@
// the service just to stop tethering since tethering is not started. Just remove
// any pending request to enable tethering, and notify them that they have failed.
if (mPendingPanRequestListener != null) {
- sendTetherResult(mPendingPanRequestListener, TETHER_ERROR_SERVICE_UNAVAIL);
+ sendTetherResult(mPendingPanRequestListener, TETHER_ERROR_SERVICE_UNAVAIL,
+ TETHERING_BLUETOOTH);
}
mPendingPanRequestListener = null;
return TETHER_ERROR_NO_ERROR;
@@ -907,10 +904,7 @@
if (mPendingPanRequestListener != null) {
final int result = setBluetoothTetheringSettings(mBluetoothPan,
true /* enable */);
- sendTetherResultAndRemoveOnError(
- mRequestTracker.getOrCreatePendingRequest(TETHERING_BLUETOOTH),
- mPendingPanRequestListener,
- result);
+ sendTetherResult(mPendingPanRequestListener, result, TETHERING_BLUETOOTH);
}
mPendingPanRequestListener = null;
});
@@ -924,10 +918,8 @@
mIsConnected = false;
if (mPendingPanRequestListener != null) {
- sendTetherResultAndRemoveOnError(
- mRequestTracker.getOrCreatePendingRequest(TETHERING_BLUETOOTH),
- mPendingPanRequestListener,
- TETHER_ERROR_SERVICE_UNAVAIL);
+ sendTetherResult(mPendingPanRequestListener, TETHER_ERROR_SERVICE_UNAVAIL,
+ TETHERING_BLUETOOTH);
}
mPendingPanRequestListener = null;
mBluetoothIfaceRequest = null;
@@ -1101,7 +1093,9 @@
final int type = ifaceNameToType(iface);
if (type == TETHERING_INVALID) {
Log.e(TAG, "Ignoring call to legacy tether for unknown iface " + iface);
- sendTetherResult(listener, TETHER_ERROR_UNKNOWN_IFACE);
+ try {
+ listener.onResult(TETHER_ERROR_UNKNOWN_IFACE);
+ } catch (RemoteException e) { }
}
TetheringRequest request = mRequestTracker.getNextPendingRequest(type);
@@ -1138,7 +1132,9 @@
// Do nothing
break;
}
- sendTetherResult(listener, result);
+ try {
+ listener.onResult(result);
+ } catch (RemoteException e) { }
}
/**
@@ -1171,9 +1167,11 @@
Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring");
return TETHER_ERROR_UNAVAIL_IFACE;
}
- mRequestTracker.promoteRequestToServing(tetherState.ipServer, request);
// NOTE: If a CMD_TETHER_REQUESTED message is already in the IpServer's queue but not yet
// processed, this will be a no-op and it will not return an error.
+ //
+ // This code cannot race with untether() because they both run on the handler thread.
+ mRequestTracker.removeAllPendingRequests(request.getTetheringType());
tetherState.ipServer.enable(request);
if (request.getRequestType() == REQUEST_TYPE_PLACEHOLDER) {
TerribleErrorLog.logTerribleError(TetheringStatsLog::write,
@@ -1193,7 +1191,10 @@
return;
}
mHandler.post(() -> {
- sendTetherResult(listener, legacyUntetherInternal(iface));
+ try {
+ listener.onResult(legacyUntetherInternal(iface));
+ } catch (RemoteException e) {
+ }
});
}
@@ -1208,7 +1209,7 @@
Log.e(TAG, "Tried to untether an inactive iface :" + iface + ", ignoring");
return TETHER_ERROR_UNAVAIL_IFACE;
}
- ensureIpServerUnwanted(tetherState.ipServer);
+ tetherState.ipServer.unwanted();
return TETHER_ERROR_NO_ERROR;
}
@@ -1288,12 +1289,7 @@
final TetherState tetherState = mTetherStates.valueAt(i);
final int type = tetherState.ipServer.interfaceType();
final String iface = mTetherStates.keyAt(i);
- // Note: serving requests are only populated on B+. B+ also uses the sync state
- // machine by default. This ensures that the serving request is (correctly) populated
- // after the IpServer enters the available state and before it enters the serving
- // state.
- final TetheringRequest request =
- mRequestTracker.getServingRequest(tetherState.ipServer);
+ final TetheringRequest request = tetherState.ipServer.getTetheringRequest();
final boolean includeSoftApConfig = request != null && cookie != null
&& (cookie.uid == request.getUid() || cookie.hasSystemPrivilege);
final TetheringInterface tetheringIface = new TetheringInterface(type, iface,
@@ -1615,7 +1611,7 @@
private void disableWifiIpServingCommon(int tetheringType, String ifname) {
if (!TextUtils.isEmpty(ifname) && mTetherStates.containsKey(ifname)) {
- ensureIpServerUnwanted(mTetherStates.get(ifname).ipServer);
+ mTetherStates.get(ifname).ipServer.unwanted();
return;
}
@@ -1632,7 +1628,7 @@
for (int i = 0; i < mTetherStates.size(); i++) {
final IpServer ipServer = mTetherStates.valueAt(i).ipServer;
if (ipServer.interfaceType() == tetheringType) {
- ensureIpServerUnwanted(ipServer);
+ ipServer.unwanted();
return;
}
}
@@ -1779,7 +1775,9 @@
void setUsbTethering(boolean enable, IIntResultListener listener) {
mHandler.post(() -> {
- sendTetherResult(listener, setUsbTethering(enable));
+ try {
+ listener.onResult(setUsbTethering(enable));
+ } catch (RemoteException e) { }
});
}
@@ -2906,9 +2904,6 @@
tetherState.lastState = state;
tetherState.lastError = lastError;
} else {
- // Note: Even if an IpServer exists for this iface, it may be different from "who"
- // if a new IpServer fills the gap before the IpServer.STATE_UNAVAILABLE transition.
- // TODO: remove this comment once the sync state machine is enabled everywhere.
if (DBG) Log.d(TAG, "got notification from stale iface " + iface);
}
@@ -2923,19 +2918,7 @@
int which;
switch (state) {
case IpServer.STATE_UNAVAILABLE:
- which = TetherMainSM.EVENT_IFACE_SERVING_STATE_INACTIVE;
- break;
case IpServer.STATE_AVAILABLE:
- if (lastError != TETHER_ERROR_NO_ERROR) {
- // IpServer transitioned from an enabled state (STATE_TETHERED or
- // STATE_LOCAL_ONLY) back to STATE_AVAILABLE due to an error, so make sure
- // we remove the serving request from RequestTracker.
- // TODO: don't continue to use IpServers after they have hit an error, and
- // instead move them to STATE_UNAVAILABLE. This code can then
- // unconditionally remove the serving request whenever the IpServer enters
- // STATE_UNAVAILABLE.
- mRequestTracker.removeServingRequest(who);
- }
which = TetherMainSM.EVENT_IFACE_SERVING_STATE_INACTIVE;
break;
case IpServer.STATE_TETHERED:
@@ -3031,18 +3014,11 @@
final TetherState tetherState = mTetherStates.get(iface);
if (tetherState == null) return;
- mRequestTracker.removeServingRequest(tetherState.ipServer);
tetherState.ipServer.stop();
mLog.i("removing IpServer for: " + iface);
mTetherStates.remove(iface);
}
- private void ensureIpServerUnwanted(final IpServer ipServer) {
- mLog.i("unrequesting IpServer: " + ipServer);
- mRequestTracker.removeServingRequest(ipServer);
- ipServer.unwanted();
- }
-
private static String[] copy(String[] strarray) {
return Arrays.copyOf(strarray, strarray.length);
}
@@ -3050,7 +3026,9 @@
void setPreferTestNetworks(final boolean prefer, IIntResultListener listener) {
mHandler.post(() -> {
mUpstreamNetworkMonitor.setPreferTestNetworks(prefer);
- sendTetherResult(listener, TETHER_ERROR_NO_ERROR);
+ try {
+ listener.onResult(TETHER_ERROR_NO_ERROR);
+ } catch (RemoteException e) { }
});
}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/RequestTrackerTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/RequestTrackerTest.java
index 086f2d2..e00e9f0 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/RequestTrackerTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/RequestTrackerTest.java
@@ -18,22 +18,19 @@
import static android.net.TetheringManager.TETHERING_USB;
import static android.net.TetheringManager.TETHERING_WIFI;
-import static android.net.TetheringManager.TETHERING_VIRTUAL;
import static com.android.networkstack.tethering.util.TetheringUtils.createPlaceholderRequest;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.mock;
-
import android.net.TetheringManager.TetheringRequest;
-import android.net.ip.IpServer;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.networkstack.tethering.RequestTracker.AddResult;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -42,10 +39,13 @@
public class RequestTrackerTest {
private RequestTracker mRequestTracker;
+ @Before
+ public void setUp() {
+ mRequestTracker = new RequestTracker();
+ }
+
@Test
public void testNoRequestsAdded_noPendingRequests() {
- mRequestTracker = new RequestTracker(false);
-
assertThat(mRequestTracker.getNextPendingRequest(TETHERING_WIFI)).isNull();
assertThat(mRequestTracker.getOrCreatePendingRequest(TETHERING_WIFI))
.isEqualTo(createPlaceholderRequest(TETHERING_WIFI));
@@ -53,7 +53,6 @@
@Test
public void testAddRequest_successResultAndBecomesNextPending() {
- mRequestTracker = new RequestTracker(false);
final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build();
final AddResult result = mRequestTracker.addPendingRequest(request);
@@ -65,7 +64,6 @@
@Test
public void testAddRequest_equalRequestExists_successResultAndBecomesNextPending() {
- mRequestTracker = new RequestTracker(false);
final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build();
mRequestTracker.addPendingRequest(request);
@@ -79,7 +77,6 @@
@Test
public void testAddRequest_equalButDifferentUidRequest_successResultAndBecomesNextPending() {
- mRequestTracker = new RequestTracker(false);
final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build();
request.setUid(1000);
request.setPackageName("package");
@@ -97,8 +94,7 @@
}
@Test
- public void testAddRequest_conflictingPendingRequest_returnsFailureConflictingRequestRestart() {
- mRequestTracker = new RequestTracker(false);
+ public void testAddConflictingRequest_returnsFailureConflictingPendingRequest() {
final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build();
final TetheringRequest conflictingRequest = new TetheringRequest.Builder(TETHERING_WIFI)
.setExemptFromEntitlementCheck(true).build();
@@ -106,139 +102,13 @@
final AddResult result = mRequestTracker.addPendingRequest(conflictingRequest);
- assertThat(result).isEqualTo(AddResult.FAILURE_DUPLICATE_REQUEST_RESTART);
+ assertThat(result).isEqualTo(AddResult.FAILURE_CONFLICTING_PENDING_REQUEST);
assertThat(mRequestTracker.getNextPendingRequest(TETHERING_WIFI)).isEqualTo(request);
assertThat(mRequestTracker.getOrCreatePendingRequest(TETHERING_WIFI)).isEqualTo(request);
}
@Test
- public void testAddRequest_noExistingRequestsFuzzyMatching_returnsSuccess() {
- mRequestTracker = new RequestTracker(true);
- final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build();
-
- final AddResult result = mRequestTracker.addPendingRequest(request);
-
- assertThat(result).isEqualTo(AddResult.SUCCESS);
- assertThat(mRequestTracker.getNextPendingRequest(TETHERING_WIFI)).isEqualTo(request);
- assertThat(mRequestTracker.getOrCreatePendingRequest(TETHERING_WIFI)).isEqualTo(request);
- }
-
- @Test
- public void testAddRequest_conflictingPendingRequestFuzzyMatching_returnsFailure() {
- mRequestTracker = new RequestTracker(true);
- final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build();
- final TetheringRequest conflictingRequest = new TetheringRequest.Builder(TETHERING_WIFI)
- .setExemptFromEntitlementCheck(true).build();
- mRequestTracker.addPendingRequest(request);
-
- final AddResult result = mRequestTracker.addPendingRequest(conflictingRequest);
-
- assertThat(result).isEqualTo(AddResult.FAILURE_DUPLICATE_REQUEST_ERROR);
- assertThat(mRequestTracker.getNextPendingRequest(TETHERING_WIFI)).isEqualTo(request);
- assertThat(mRequestTracker.getOrCreatePendingRequest(TETHERING_WIFI)).isEqualTo(request);
- }
-
- @Test
- public void testAddRequest_conflictingServingRequestFuzzyMatching_returnsFailure() {
- mRequestTracker = new RequestTracker(true);
- final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build();
- final TetheringRequest conflictingRequest = new TetheringRequest.Builder(TETHERING_WIFI)
- .setExemptFromEntitlementCheck(true).build();
- mRequestTracker.promoteRequestToServing(mock(IpServer.class), request);
-
- final AddResult result = mRequestTracker.addPendingRequest(conflictingRequest);
-
- assertThat(result).isEqualTo(AddResult.FAILURE_DUPLICATE_REQUEST_ERROR);
- assertThat(mRequestTracker.getNextPendingRequest(TETHERING_WIFI)).isNull();
- assertThat(mRequestTracker.getOrCreatePendingRequest(TETHERING_WIFI))
- .isEqualTo(createPlaceholderRequest(TETHERING_WIFI));
- }
-
- @Test
- public void testAddRequest_nonMatchingPendingRequestFuzzyMatching_returnsSuccess() {
- mRequestTracker = new RequestTracker(true);
- final TetheringRequest request = new TetheringRequest.Builder(TETHERING_VIRTUAL).build();
- final TetheringRequest nonFuzzyMatched = new TetheringRequest.Builder(TETHERING_VIRTUAL)
- .setInterfaceName("iface")
- .build();
- mRequestTracker.addPendingRequest(request);
-
- final AddResult result = mRequestTracker.addPendingRequest(nonFuzzyMatched);
-
- assertThat(result).isEqualTo(AddResult.SUCCESS);
- // Next request is still the first, but verify RequestTracker contains the second request by
- // seeing if it rejects anything matching the second request
- assertThat(mRequestTracker.getNextPendingRequest(TETHERING_VIRTUAL)).isEqualTo(request);
- assertThat(mRequestTracker.getOrCreatePendingRequest(TETHERING_VIRTUAL))
- .isEqualTo(request);
- assertThat(mRequestTracker.addPendingRequestFuzzyMatched(nonFuzzyMatched))
- .isEqualTo(AddResult.FAILURE_DUPLICATE_REQUEST_ERROR);
- }
-
- @Test
- public void testAddRequest_nonMatchingServingRequestFuzzyMatching_returnsSuccess() {
- mRequestTracker = new RequestTracker(true);
- final TetheringRequest request = new TetheringRequest.Builder(TETHERING_VIRTUAL).build();
- final TetheringRequest nonFuzzyMatched = new TetheringRequest.Builder(TETHERING_VIRTUAL)
- .setInterfaceName("iface")
- .build();
- mRequestTracker.promoteRequestToServing(mock(IpServer.class), request);
-
- final AddResult result = mRequestTracker.addPendingRequest(nonFuzzyMatched);
-
- assertThat(result).isEqualTo(AddResult.SUCCESS);
- assertThat(mRequestTracker.getNextPendingRequest(TETHERING_VIRTUAL))
- .isEqualTo(nonFuzzyMatched);
- assertThat(mRequestTracker.getOrCreatePendingRequest(TETHERING_VIRTUAL))
- .isEqualTo(nonFuzzyMatched);
- }
-
- @Test
- public void testRemovePendingRequest_removesAllPendingRequestsOfType() {
- mRequestTracker = new RequestTracker(false);
- final TetheringRequest request1 = new TetheringRequest.Builder(TETHERING_WIFI).build();
- request1.setUid(1000);
- request1.setPackageName("package");
- mRequestTracker.addPendingRequest(request1);
- final TetheringRequest request2 = new TetheringRequest.Builder(TETHERING_WIFI).build();
- request2.setUid(2000);
- request2.setPackageName("package2");
-
- mRequestTracker.removePendingRequest(request2);
-
- // Verify request1 isn't pending even though we tried to remove a different request
- assertThat(mRequestTracker.getNextPendingRequest(TETHERING_WIFI)).isNull();
- assertThat(mRequestTracker.getOrCreatePendingRequest(TETHERING_WIFI))
- .isEqualTo(createPlaceholderRequest(TETHERING_WIFI));
- }
-
- @Test
- public void testRemovePendingRequest_fuzzyMatching_onlyTheEqualRequestIsRemoved() {
- mRequestTracker = new RequestTracker(true);
- final TetheringRequest request1 = new TetheringRequest.Builder(TETHERING_VIRTUAL).build();
- final TetheringRequest request2 = new TetheringRequest.Builder(TETHERING_VIRTUAL)
- .setInterfaceName("iface")
- .build();
- mRequestTracker.addPendingRequest(request1);
- mRequestTracker.addPendingRequest(request2);
-
- mRequestTracker.removePendingRequest(request2);
-
- // Verify request1 is still pending.
- assertThat(mRequestTracker.getNextPendingRequest(TETHERING_VIRTUAL)).isEqualTo(request1);
- assertThat(mRequestTracker.getOrCreatePendingRequest(TETHERING_VIRTUAL))
- .isEqualTo(request1);
- assertThat(mRequestTracker.addPendingRequestFuzzyMatched(request1))
- .isEqualTo(AddResult.FAILURE_DUPLICATE_REQUEST_ERROR);
- // Verify we've removed request2 by checking if it can be added back without
- // FAILURE_CONFLICTING_REQUEST_FAIL.
- assertThat(mRequestTracker.addPendingRequestFuzzyMatched(request2))
- .isEqualTo(AddResult.SUCCESS);
- }
-
- @Test
public void testRemoveAllPendingRequests_noPendingRequestsLeft() {
- mRequestTracker = new RequestTracker(false);
final TetheringRequest firstRequest = new TetheringRequest.Builder(TETHERING_WIFI).build();
firstRequest.setUid(1000);
firstRequest.setPackageName("package");
@@ -257,7 +127,6 @@
@Test
public void testRemoveAllPendingRequests_differentTypeExists_doesNotRemoveDifferentType() {
- mRequestTracker = new RequestTracker(false);
final TetheringRequest differentType = new TetheringRequest.Builder(TETHERING_USB).build();
mRequestTracker.addPendingRequest(differentType);
@@ -267,61 +136,4 @@
assertThat(mRequestTracker.getOrCreatePendingRequest(TETHERING_USB))
.isEqualTo(differentType);
}
-
- @Test
- public void testPromoteRequestToServing_requestIsntPendingAnymore() {
- mRequestTracker = new RequestTracker(false);
- final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build();
- mRequestTracker.addPendingRequest(request);
-
- mRequestTracker.promoteRequestToServing(mock(IpServer.class), request);
-
- assertThat(mRequestTracker.getNextPendingRequest(TETHERING_WIFI)).isNull();
- assertThat(mRequestTracker.getOrCreatePendingRequest(TETHERING_WIFI))
- .isEqualTo(createPlaceholderRequest(TETHERING_WIFI));
- }
-
- @Test
- public void testPromoteRequestToServing_fuzzyMatching_requestIsntPendingAnymore() {
- mRequestTracker = new RequestTracker(true);
- final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build();
- mRequestTracker.addPendingRequest(request);
-
- mRequestTracker.promoteRequestToServing(mock(IpServer.class), request);
-
- assertThat(mRequestTracker.getNextPendingRequest(TETHERING_WIFI)).isNull();
- assertThat(mRequestTracker.getOrCreatePendingRequest(TETHERING_WIFI))
- .isEqualTo(createPlaceholderRequest(TETHERING_WIFI));
- }
-
- @Test
- public void testRemoveServingRequest_fuzzyMatching_requestCanBeAddedAgain() {
- mRequestTracker = new RequestTracker(true);
- final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build();
- mRequestTracker.addPendingRequest(request);
- IpServer ipServer = mock(IpServer.class);
- mRequestTracker.promoteRequestToServing(ipServer, request);
-
- mRequestTracker.removeServingRequest(ipServer);
-
- AddResult result = mRequestTracker.addPendingRequest(request);
- assertThat(result).isEqualTo(AddResult.SUCCESS);
- assertThat(mRequestTracker.getNextPendingRequest(TETHERING_WIFI)).isEqualTo(request);
- assertThat(mRequestTracker.getOrCreatePendingRequest(TETHERING_WIFI)).isEqualTo(request);
- }
-
- @Test
- public void testRemoveAllServingRequests_fuzzyMatching_requestCanBeAddedAgain() {
- mRequestTracker = new RequestTracker(true);
- final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build();
- mRequestTracker.addPendingRequest(request);
- mRequestTracker.promoteRequestToServing(mock(IpServer.class), request);
-
- mRequestTracker.removeAllServingRequests(TETHERING_WIFI);
-
- AddResult result = mRequestTracker.addPendingRequest(request);
- assertThat(result).isEqualTo(AddResult.SUCCESS);
- assertThat(mRequestTracker.getNextPendingRequest(TETHERING_WIFI)).isEqualTo(request);
- assertThat(mRequestTracker.getOrCreatePendingRequest(TETHERING_WIFI)).isEqualTo(request);
- }
}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index 8ecaec9..2a22c6d 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -50,18 +50,15 @@
import static android.net.TetheringManager.TETHERING_VIRTUAL;
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
-import static android.net.TetheringManager.TETHER_ERROR_DUPLICATE_REQUEST;
import static android.net.TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;
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_SERVICE_UNAVAIL;
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_STARTED;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
-import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
@@ -96,7 +93,6 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.notNull;
@@ -201,7 +197,6 @@
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.modules.utils.build.SdkLevel;
-import com.android.net.flags.Flags;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.InterfaceParams;
import com.android.net.module.util.PrivateAddressCoordinator;
@@ -313,7 +308,8 @@
@Mock private TetheringMetrics mTetheringMetrics;
@Mock private PrivateAddressCoordinator.Dependencies mPrivateAddressCoordinatorDependencies;
- private MockIpServerDependencies mIpServerDependencies;
+ private final MockIpServerDependencies mIpServerDependencies =
+ spy(new MockIpServerDependencies());
private final MockTetheringDependencies mTetheringDependencies =
new MockTetheringDependencies();
@@ -400,9 +396,6 @@
}
public class MockIpServerDependencies extends IpServer.Dependencies {
-
- private int mOnDhcpServerCreatedResult = STATUS_SUCCESS;
-
@Override
public DadProxy getDadProxy(
Handler handler, InterfaceParams ifParams) {
@@ -444,7 +437,7 @@
DhcpServerCallbacks cb) {
new Thread(() -> {
try {
- cb.onDhcpServerCreated(mOnDhcpServerCreatedResult, mDhcpServer);
+ cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
} catch (RemoteException e) {
fail(e.getMessage());
}
@@ -455,10 +448,6 @@
IpNeighborMonitor.NeighborEventConsumer c) {
return mIpNeighborMonitor;
}
-
- public void setOnDhcpServerCreatedResult(final int result) {
- mOnDhcpServerCreatedResult = result;
- }
}
public class MockTetheringDependencies extends TetheringDependencies {
@@ -719,7 +708,6 @@
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)).thenReturn(true);
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)).thenReturn(true);
- mIpServerDependencies = spy(new MockIpServerDependencies());
}
// In order to interact with syncSM from the test, tethering must be created in test thread.
@@ -2437,7 +2425,7 @@
@Test
public void testSoftApConfigInTetheringEventCallback() throws Exception {
- assumeTrue(isTetheringWithSoftApConfigEnabled());
+ assumeTrue(SdkLevel.isAtLeastV());
when(mContext.checkCallingOrSelfPermission(NETWORK_SETTINGS))
.thenReturn(PERMISSION_DENIED);
when(mContext.checkCallingOrSelfPermission(NETWORK_STACK))
@@ -2494,12 +2482,14 @@
// Enable wifi tethering
mBinderCallingUid = TEST_CALLER_UID;
mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, null);
- mLooper.dispatchAll();
mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
mLooper.dispatchAll();
- // Netd "up" event should not trigger a state change callback in B+.
- callback.assertNoStateChangeCallback();
+ if (SdkLevel.isAtLeastB()) {
+ // Starting in B, ignore the interfaceStatusChanged
+ callback.assertNoStateChangeCallback();
+ }
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
+ mLooper.dispatchAll();
// Verify we see Available -> Tethered states
assertArrayEquals(new TetheringInterface[] {wifiIfaceWithoutConfig},
callback.pollTetherStatesChanged().availableList);
@@ -2517,15 +2507,20 @@
callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STARTED);
// Disable wifi tethering
- mTethering.stopTethering(TETHERING_WIFI);
mLooper.dispatchAll();
- sendWifiApStateChanged(WIFI_AP_STATE_DISABLED, TEST_WLAN_IFNAME,
+ mTethering.stopTethering(TETHERING_WIFI);
+ sendWifiApStateChanged(WIFI_AP_STATE_DISABLED);
+ if (isAtLeastT()) {
+ // After T, tethering doesn't support WIFI_AP_STATE_DISABLED with null interface name.
+ callback.assertNoStateChangeCallback();
+ sendWifiApStateChanged(WIFI_AP_STATE_DISABLED, TEST_WLAN_IFNAME,
IFACE_IP_MODE_TETHERED);
- assertArrayEquals(new TetheringInterface[] {wifiIfaceWithoutConfig},
+ }
+ assertArrayEquals(new TetheringInterface[] {wifiIfaceWithConfig},
callback.pollTetherStatesChanged().availableList);
assertArrayEquals(new TetheringInterface[] {wifiIfaceWithoutConfig},
differentCallback.pollTetherStatesChanged().availableList);
- assertArrayEquals(new TetheringInterface[] {wifiIfaceWithoutConfig},
+ assertArrayEquals(new TetheringInterface[] {wifiIfaceWithConfig},
settingsCallback.pollTetherStatesChanged().availableList);
mLooper.dispatchAll();
callback.expectUpstreamChanged(NULL_NETWORK);
@@ -2533,332 +2528,6 @@
callback.assertNoCallback();
}
- private boolean isTetheringWithSoftApConfigEnabled() {
- return SdkLevel.isAtLeastB() && Flags.tetheringWithSoftApConfig();
- }
-
- @Test
- public void testFuzzyMatchedWifiCannotBeAdded() throws Exception {
- assumeTrue(isTetheringWithSoftApConfigEnabled());
- initTetheringOnTestThread();
- TestTetheringEventCallback callback = new TestTetheringEventCallback();
- SoftApConfiguration softApConfig = new SoftApConfiguration.Builder().setWifiSsid(
- WifiSsid.fromBytes("SoftApConfig".getBytes(StandardCharsets.UTF_8))).build();
- final TetheringInterface wifiIfaceWithoutConfig = new TetheringInterface(
- TETHERING_WIFI, TEST_WLAN_IFNAME, null);
- final TetheringInterface wifiIfaceWithConfig = new TetheringInterface(
- TETHERING_WIFI, TEST_WLAN_IFNAME, softApConfig);
-
- // Register callback before running any tethering.
- mTethering.registerTetheringEventCallback(callback);
- mLooper.dispatchAll();
- callback.expectTetheredClientChanged(Collections.emptyList());
- callback.expectUpstreamChanged(NULL_NETWORK);
- callback.expectConfigurationChanged(
- mTethering.getTetheringConfiguration().toStableParcelable());
- assertTetherStatesNotNullButEmpty(callback.pollTetherStatesChanged());
- callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
- UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
- initTetheringUpstream(upstreamState);
-
- // Start wifi tethering but don't trigger the link layer event yet.
- mBinderCallingUid = TEST_CALLER_UID;
- final TetheringRequest tetheringRequest = new TetheringRequest.Builder(TETHERING_WIFI)
- .setSoftApConfiguration(softApConfig).build();
- tetheringRequest.setUid(TEST_CALLER_UID);
- ResultListener successListener = new ResultListener(TETHER_ERROR_NO_ERROR);
- when(mWifiManager.startTetheredHotspot(null)).thenReturn(true);
- mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, successListener);
- mLooper.dispatchAll();
- successListener.assertHasResult();
-
- // Try starting wifi tethering with various fuzzy-matching requests and verify we get
- // TETHER_ERROR_DUPLICATE_REQUEST.
-
- // Different static IP addresses
- final TetheringRequest differentIpAddr = new TetheringRequest.Builder(TETHERING_WIFI)
- .setSoftApConfiguration(softApConfig)
- .setStaticIpv4Addresses(new LinkAddress("192.168.0.123/24"),
- new LinkAddress("192.168.0.42/24"))
- .build();
- differentIpAddr.setUid(TEST_CALLER_UID);
- ResultListener differentIpAddrListener = new ResultListener(TETHER_ERROR_DUPLICATE_REQUEST);
- mTethering.startTethering(differentIpAddr, TEST_CALLER_PKG, differentIpAddrListener);
- mLooper.dispatchAll();
- verify(mWifiManager, times(1)).startTetheredHotspot(any());
- verify(mWifiManager, never()).stopSoftAp();
- differentIpAddrListener.assertHasResult();
-
- // Different UID
- final TetheringRequest differentUid = new TetheringRequest.Builder(TETHERING_WIFI)
- .setSoftApConfiguration(softApConfig).build();
- differentUid.setUid(TEST_CALLER_UID + 1);
- ResultListener differentUidListener = new ResultListener(TETHER_ERROR_DUPLICATE_REQUEST);
- mTethering.startTethering(differentUid, TEST_CALLER_PKG, differentUidListener);
- mLooper.dispatchAll();
- differentUidListener.assertHasResult();
- verify(mWifiManager, times(1)).startTetheredHotspot(any());
- verify(mWifiManager, never()).stopSoftAp();
-
- // Mock the link layer event to start IP serving and verify we still get
- // TETHER_ERROR_DUPLICATE_REQUEST even though the request is no longer pending and is
- // already serving.
- sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
- assertArrayEquals(new TetheringInterface[] {wifiIfaceWithoutConfig},
- callback.pollTetherStatesChanged().availableList);
- assertArrayEquals(new TetheringInterface[] {wifiIfaceWithConfig},
- callback.pollTetherStatesChanged().tetheredList);
- callback.expectUpstreamChanged(upstreamState.network);
- callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STARTED);
- differentIpAddrListener = new ResultListener(TETHER_ERROR_DUPLICATE_REQUEST);
- differentUidListener = new ResultListener(TETHER_ERROR_DUPLICATE_REQUEST);
- mTethering.startTethering(differentIpAddr, TEST_CALLER_PKG, differentIpAddrListener);
- mTethering.startTethering(differentUid, TEST_CALLER_PKG, differentUidListener);
- mLooper.dispatchAll();
- differentIpAddrListener.assertHasResult();
- differentUidListener.assertHasResult();
- verify(mWifiManager, times(1)).startTetheredHotspot(any());
- verify(mWifiManager, never()).stopSoftAp();
- }
-
- @Test
- public void testFuzzyMatchedWifiCanBeAddedAfterIpServerStopped() throws Exception {
- assumeTrue(isTetheringWithSoftApConfigEnabled());
- when(mWifiManager.startTetheredHotspot(null)).thenReturn(true);
- initTetheringOnTestThread();
-
- // Start wifi tethering and mock the ap state change.
- SoftApConfiguration softApConfig = new SoftApConfiguration.Builder().setWifiSsid(
- WifiSsid.fromBytes("SoftApConfig".getBytes(StandardCharsets.UTF_8))).build();
- final TetheringRequest tetheringRequest = new TetheringRequest.Builder(TETHERING_WIFI)
- .setSoftApConfiguration(softApConfig).build();
- ResultListener successListener = new ResultListener(TETHER_ERROR_NO_ERROR);
- mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, successListener);
- mLooper.dispatchAll();
- successListener.assertHasResult();
- sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
-
- // Starting wifi again will cause TETHER_ERROR_DUPLICATE_REQUEST
- ResultListener failureListener = new ResultListener(TETHER_ERROR_DUPLICATE_REQUEST);
- mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, failureListener);
- mLooper.dispatchAll();
- failureListener.assertHasResult();
-
- // Trigger Netd callback to stop the IpServer
- mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, false);
-
- // We should be able to request the same Wifi again
- ResultListener successListener2 = new ResultListener(TETHER_ERROR_DUPLICATE_REQUEST);
- mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, successListener2);
- mLooper.dispatchAll();
- successListener2.assertHasResult();
- }
-
- @Test
- public void testFuzzyMatchedWifiCanBeAddedAfterIpServerUnwanted() throws Exception {
- assumeTrue(isTetheringWithSoftApConfigEnabled());
- when(mWifiManager.startTetheredHotspot(null)).thenReturn(true);
- initTetheringOnTestThread();
-
- // Start wifi tethering and mock the ap state change.
- SoftApConfiguration softApConfig = new SoftApConfiguration.Builder().setWifiSsid(
- WifiSsid.fromBytes("SoftApConfig".getBytes(StandardCharsets.UTF_8))).build();
- final TetheringRequest tetheringRequest = new TetheringRequest.Builder(TETHERING_WIFI)
- .setSoftApConfiguration(softApConfig).build();
- ResultListener successListener = new ResultListener(TETHER_ERROR_NO_ERROR);
- mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, successListener);
- mLooper.dispatchAll();
- successListener.assertHasResult();
- sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
-
- // Starting wifi again will cause TETHER_ERROR_DUPLICATE_REQUEST
- ResultListener failureListener = new ResultListener(TETHER_ERROR_DUPLICATE_REQUEST);
- mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, failureListener);
- mLooper.dispatchAll();
- failureListener.assertHasResult();
-
- // Trigger wifi ap state change to tell IpServer it's unwanted.
- sendWifiApStateChanged(WIFI_AP_STATE_DISABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
-
- // We should be able to request the same Wifi again
- ResultListener successListener2 = new ResultListener(TETHER_ERROR_NO_ERROR);
- mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, successListener2);
- mLooper.dispatchAll();
- successListener2.assertHasResult();
- }
-
- @Test
- public void testFuzzyMatchedWifiCanBeAddedAfterIpServerError() throws Exception {
- assumeTrue(isTetheringWithSoftApConfigEnabled());
- when(mWifiManager.startTetheredHotspot(null)).thenReturn(true);
- initTetheringOnTestThread();
-
- // Set up the DHCP server to fail creation.
- mIpServerDependencies.setOnDhcpServerCreatedResult(STATUS_UNKNOWN_ERROR);
-
- // Start wifi tethering and mock the ap state change.
- SoftApConfiguration softApConfig = new SoftApConfiguration.Builder().setWifiSsid(
- WifiSsid.fromBytes("SoftApConfig".getBytes(StandardCharsets.UTF_8))).build();
- final TetheringRequest tetheringRequest = new TetheringRequest.Builder(TETHERING_WIFI)
- .setSoftApConfiguration(softApConfig).build();
- ResultListener successListener = new ResultListener(TETHER_ERROR_NO_ERROR);
- mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, successListener);
- mLooper.dispatchAll();
- successListener.assertHasResult();
- sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
-
- // We should be able to request the same Wifi again since the DHCP server transitioned the
- // IpServer back to InitialState.
- ResultListener successListener2 = new ResultListener(TETHER_ERROR_NO_ERROR);
- mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, successListener2);
- mLooper.dispatchAll();
- successListener2.assertHasResult();
- }
-
- @Test
- public void testFuzzyMatchedWifiCanBeAddedAfterStoppingPendingRequest() throws Exception {
- assumeTrue(isTetheringWithSoftApConfigEnabled());
- when(mWifiManager.startTetheredHotspot(null)).thenReturn(true);
- initTetheringOnTestThread();
-
- // Start wifi tethering but keep the request pending by not sending the ap state change.
- SoftApConfiguration softApConfig = new SoftApConfiguration.Builder().setWifiSsid(
- WifiSsid.fromBytes("SoftApConfig".getBytes(StandardCharsets.UTF_8))).build();
- final TetheringRequest tetheringRequest = new TetheringRequest.Builder(TETHERING_WIFI)
- .setSoftApConfiguration(softApConfig).build();
- ResultListener successListener = new ResultListener(TETHER_ERROR_NO_ERROR);
- mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, successListener);
- mLooper.dispatchAll();
- successListener.assertHasResult();
-
- // Starting wifi again will cause TETHER_ERROR_DUPLICATE_REQUEST
- ResultListener failureListener = new ResultListener(TETHER_ERROR_DUPLICATE_REQUEST);
- mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, failureListener);
- mLooper.dispatchAll();
- failureListener.assertHasResult();
-
- // Stop Wifi tethering.
- mTethering.stopTethering(TETHERING_WIFI);
-
- // We should be able to request the same Wifi again
- ResultListener successListener2 = new ResultListener(TETHER_ERROR_NO_ERROR);
- mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, successListener2);
- mLooper.dispatchAll();
- successListener2.assertHasResult();
- }
-
- @Test
- public void testFuzzyMatchedWifiCanBeAddedAfterStoppingServingRequest() throws Exception {
- assumeTrue(isTetheringWithSoftApConfigEnabled());
- when(mWifiManager.startTetheredHotspot(null)).thenReturn(true);
- initTetheringOnTestThread();
-
- // Start wifi tethering and mock the ap state change.
- SoftApConfiguration softApConfig = new SoftApConfiguration.Builder().setWifiSsid(
- WifiSsid.fromBytes("SoftApConfig".getBytes(StandardCharsets.UTF_8))).build();
- final TetheringRequest tetheringRequest = new TetheringRequest.Builder(TETHERING_WIFI)
- .setSoftApConfiguration(softApConfig).build();
- ResultListener successListener = new ResultListener(TETHER_ERROR_NO_ERROR);
- mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, successListener);
- mLooper.dispatchAll();
- successListener.assertHasResult();
- sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
-
- // Starting wifi again will cause TETHER_ERROR_DUPLICATE_REQUEST
- ResultListener failureListener = new ResultListener(TETHER_ERROR_DUPLICATE_REQUEST);
- mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, failureListener);
- mLooper.dispatchAll();
- failureListener.assertHasResult();
-
- // Stop Wifi tethering.
- mTethering.stopTethering(TETHERING_WIFI);
-
- // We should be able to request the same Wifi again
- ResultListener successListener2 = new ResultListener(TETHER_ERROR_NO_ERROR);
- mTethering.startTethering(tetheringRequest, TEST_CALLER_PKG, successListener2);
- mLooper.dispatchAll();
- 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
public void testReportFailCallbackIfOffloadNotSupported() throws Exception {
initTetheringOnTestThread();
@@ -3125,8 +2794,7 @@
}
@Test
- public void testMultipleStartTetheringLegacy() throws Exception {
- assumeFalse(isTetheringWithSoftApConfigEnabled());
+ public void testMultipleStartTethering() throws Exception {
initTetheringOnTestThread();
final LinkAddress serverLinkAddr = new LinkAddress("192.168.20.1/24");
final LinkAddress clientLinkAddr = new LinkAddress("192.168.20.42/24");
@@ -3907,7 +3575,6 @@
@Test
public void testStartBluetoothTetheringFailsWhenTheresAnExistingRequestWaitingForPanService()
throws Exception {
- assumeFalse(isTetheringWithSoftApConfigEnabled());
initTetheringOnTestThread();
mockBluetoothSettings(true /* bluetoothOn */, true /* tetheringOn */);
diff --git a/staticlibs/testutils/host/python/apf_utils.py b/staticlibs/testutils/host/python/apf_utils.py
index 49ffad6..c2ad18e 100644
--- a/staticlibs/testutils/host/python/apf_utils.py
+++ b/staticlibs/testutils/host/python/apf_utils.py
@@ -18,6 +18,7 @@
from mobly.controllers import android_device
from mobly.controllers.android_device_lib.adb import AdbError
from net_tests_utils.host.python import adb_utils, assert_utils
+import functools
class PatternNotFoundException(Exception):
@@ -400,6 +401,20 @@
f" {expected_version}",
)
+def at_least_B():
+ def decorator(test_function):
+ @functools.wraps(test_function)
+ def wrapper(self, *args, **kwargs):
+ asserts.abort_class_if(
+ (not hasattr(self, 'client')) or (not hasattr(self.client, 'isAtLeastB')),
+ "client device is not B+"
+ )
+
+ asserts.abort_class_if(not self.client.isAtLeastB(), "not B+")
+ return test_function(self, *args, **kwargs)
+ return wrapper
+ return decorator
+
class AdbOutputHandler:
def __init__(self, ad, cmd):
self._ad = ad
diff --git a/staticlibs/testutils/host/python/multi_devices_test_base.py b/staticlibs/testutils/host/python/multi_devices_test_base.py
index 677329a..72bac0c 100644
--- a/staticlibs/testutils/host/python/multi_devices_test_base.py
+++ b/staticlibs/testutils/host/python/multi_devices_test_base.py
@@ -53,3 +53,4 @@
raise_on_exception=True,
)
self.client = self.clientDevice.connectivity_multi_devices_snippet
+ self.server = self.serverDevice.connectivity_multi_devices_snippet
diff --git a/tests/cts/multidevices/Android.bp b/tests/cts/multidevices/Android.bp
index c730b86..00fb934 100644
--- a/tests/cts/multidevices/Android.bp
+++ b/tests/cts/multidevices/Android.bp
@@ -29,6 +29,7 @@
libs: [
"absl-py",
"mobly",
+ "scapy",
"net-tests-utils-host-python-common",
],
test_suites: [
diff --git a/tests/cts/multidevices/apfv6_test.py b/tests/cts/multidevices/apfv6_test.py
index fc732d2..61f1bfc 100644
--- a/tests/cts/multidevices/apfv6_test.py
+++ b/tests/cts/multidevices/apfv6_test.py
@@ -13,6 +13,8 @@
# limitations under the License.
from mobly import asserts
+from scapy.layers.inet import IP, ICMP
+from scapy.layers.l2 import Ether
from net_tests_utils.host.python import apf_test_base, apf_utils, adb_utils, assert_utils, packet_utils
APFV6_VERSION = 6000
@@ -82,3 +84,18 @@
self.send_packet_and_expect_reply_received(
arp_request, "DROPPED_ARP_REQUEST_REPLIED", arp_reply
)
+
+ @apf_utils.at_least_B()
+ def test_ipv4_icmp_echo_request_offload(self):
+ eth = Ether(src=self.server_mac_address, dst=self.client_mac_address)
+ ip = IP(src=self.server_ipv4_addresses[0], dst=self.client_ipv4_addresses[0])
+ icmp = ICMP(id=1, seq=123)
+ echo_request = bytes(eth/ip/icmp/b"hello").hex()
+
+ eth = Ether(src=self.client_mac_address, dst=self.server_mac_address)
+ ip = IP(src=self.client_ipv4_addresses[0], dst=self.server_ipv4_addresses[0])
+ icmp = ICMP(type=0, id=1, seq=123)
+ expected_echo_reply = bytes(eth/ip/icmp/b"hello").hex()
+ self.send_packet_and_expect_reply_received(
+ echo_request, "DROPPED_IPV4_PING_REQUEST_REPLIED", expected_echo_reply
+ )
\ No newline at end of file
diff --git a/tests/cts/multidevices/snippet/ConnectivityMultiDevicesSnippet.kt b/tests/cts/multidevices/snippet/ConnectivityMultiDevicesSnippet.kt
index 252052e..e1c6bf1 100644
--- a/tests/cts/multidevices/snippet/ConnectivityMultiDevicesSnippet.kt
+++ b/tests/cts/multidevices/snippet/ConnectivityMultiDevicesSnippet.kt
@@ -33,6 +33,8 @@
import android.net.wifi.WifiInfo
import android.net.wifi.WifiManager
import android.net.wifi.WifiSsid
+import android.os.Build.VERSION.CODENAME
+import android.os.Build.VERSION.SDK_INT
import androidx.test.platform.app.InstrumentationRegistry
import com.android.compatibility.common.util.PropertyUtil
import com.android.modules.utils.build.SdkLevel
@@ -62,6 +64,17 @@
cbHelper.unregisterAll()
}
+ private fun isAtLeastPreReleaseCodename(codeName: String): Boolean {
+ // Special case "REL", which means the build is not a pre-release build.
+ if ("REL".equals(CODENAME)) {
+ return false
+ }
+
+ // Otherwise lexically compare them. Return true if the build codename is equal to or
+ // greater than the requested codename.
+ return CODENAME.compareTo(codeName) >= 0
+ }
+
@Rpc(description = "Check whether the device has wifi feature.")
fun hasWifiFeature() = pm.hasSystemFeature(FEATURE_WIFI)
@@ -77,6 +90,11 @@
@Rpc(description = "Return whether the Sdk level is at least V.")
fun isAtLeastV() = SdkLevel.isAtLeastV()
+ @Rpc(description = "Check whether the device is at least B.")
+ fun isAtLeastB(): Boolean {
+ return SDK_INT >= 36 || (SDK_INT == 35 && isAtLeastPreReleaseCodename("Baklava"))
+ }
+
@Rpc(description = "Return the API level that the VSR requirement must be fulfilled.")
fun getVsrApiLevel() = PropertyUtil.getVsrApiLevel()
diff --git a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
index ed6107b..e645f67 100644
--- a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
+++ b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
@@ -32,7 +32,6 @@
import static android.net.TetheringManager.TETHERING_VIRTUAL;
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
-import static android.net.TetheringManager.TETHER_ERROR_DUPLICATE_REQUEST;
import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
@@ -235,30 +234,6 @@
}
- @Test
- public void testStartTetheringDuplicateRequestRejected() throws Exception {
- assumeTrue(isTetheringWithSoftApConfigEnabled());
- final TestTetheringEventCallback tetherEventCallback =
- mCtsTetheringUtils.registerTetheringEventCallback();
- try {
- tetherEventCallback.assumeWifiTetheringSupported(mContext);
- tetherEventCallback.expectNoTetheringActive();
-
- final String[] wifiRegexs = mTM.getTetherableWifiRegexs();
- mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
- mTetherChangeReceiver.expectTethering(true /* active */, wifiRegexs);
-
- final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
- runAsShell(TETHER_PRIVILEGED, () -> {
- mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(),
- c -> c.run() /* executor */, startTetheringCallback);
- startTetheringCallback.expectTetheringFailed(TETHER_ERROR_DUPLICATE_REQUEST);
- });
- } finally {
- mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
- }
- }
-
private SoftApConfiguration createSoftApConfiguration(@NonNull String ssid) {
SoftApConfiguration config;
if (SdkLevel.isAtLeastT()) {
@@ -405,20 +380,17 @@
tetherEventCallback.assumeWifiTetheringSupported(mContext);
tetherEventCallback.expectNoTetheringActive();
- SoftApConfiguration softApConfig = isTetheringWithSoftApConfigEnabled()
- ? createSoftApConfiguration("SSID") : null;
+ SoftApConfiguration softApConfig = createSoftApConfiguration("SSID");
final TetheringInterface tetheredIface =
mCtsTetheringUtils.startWifiTethering(tetherEventCallback, softApConfig);
assertNotNull(tetheredIface);
- if (isTetheringWithSoftApConfigEnabled()) {
- assertEquals(softApConfig, tetheredIface.getSoftApConfiguration());
- }
+ assertEquals(softApConfig, tetheredIface.getSoftApConfiguration());
+ final String wifiTetheringIface = tetheredIface.getInterface();
mCtsTetheringUtils.stopWifiTethering(tetherEventCallback);
if (!SdkLevel.isAtLeastB()) {
- final String wifiTetheringIface = tetheredIface.getInterface();
try {
final int ret = runAsShell(TETHER_PRIVILEGED,
() -> mTM.tether(wifiTetheringIface));
@@ -483,73 +455,25 @@
}
@Test
- 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 {
+ public void testStopTetheringRequest() 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);
+ // stopTethering without any tethering active should fail.
+ TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build();
+ mCtsTetheringUtils.stopTethering(request, false /* expectSuccess */);
- // Stopping the active request should stop tethering.
- TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI)
- .setSoftApConfiguration(softApConfig)
- .build();
- mCtsTetheringUtils.stopTethering(request, true /* success */);
+ // Start wifi tethering
+ mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
+
+ // stopTethering should succeed now that there's a request.
+ mCtsTetheringUtils.stopTethering(request, true /* expectSuccess */);
tetherEventCallback.expectNoTetheringActive();
} finally {
- mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
- }
- }
-
- @Test
- 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();
- } finally {
+ mCtsTetheringUtils.stopAllTethering();
mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
}
}