Remove mPublicSync.
This is no longer necessary as all the methods that take it are
running on on the handler thread, either in Tethering itself or
on the state machine thread in IpServer, which runs on the same
thread as Tethering.
Specifically:
- interfaceStatusChanged, interfaceAdded, interfaceRemoved,
interfaceLinkStateChanged: run from mNetdCallback, which always
posts them to mHandler.
- setWifiTethering: only called by enableTetheringInternal, which
is called by the following:
- startTethering, stopTethering: via lambda posted to mHandler
- IpServerCallback#requestEnableTethering: called by IpServer
while processing a command.
- setEthernetTethering: only called by enableTetheringInternal.
- EthernetCallback: runs on mExecutor, which posts to mHandler.
- getLastTetherError: only used by the test. Renamed to
getLastErrorForTest to ensure no other callers.
- sendTetherStateChangedBroadcast: called only by
notifyInterfaceStateChange, which is called only by
- IpServerCallback#updateInterfaceState, which is called only
by sendInterfaceState, which is called by various IpServer
state enter methods.
- notifyLinkPropertiesChanged: called only by
IpServerCallback#updateLinkProperties, which is only called by
IpServer#sendLinkProperties, which is only called by:
- Code that processes CMD_IPV6_TETHER_UPDATE
- IpServer#handleNewPrefixRequest: only called when processing
CMD_NEW_PREFIX_REQUEST.
- IpServer#sendInterfaceState (see above)
- handleWifiApAction, handleWifiP2pAction: only called by
mStateReceiver, which runs on the handler thread
- tether(String, int): called by:
- tether(String, IIntResultListener): posted to mHandler
- changeInterfaceState: called by:
- EthernetCallback (see above)
- enableWifiIpServingLocked: called by handleWifiApAction and
handleWifiP2pAction (see above)
- tetherMatchingInterfaces: only called by handleUsbAction,
which is run from mStateReceiver on the handler thread.
- untether(String): called by:
- untether(String, IIntResultListener): posted to mHandler
- changeInterfaceState (see above)
- setUsbTethering: called by:
- setUsbTethering(boolean, IIntResultListener): posted to mHandler
- enableTetheringInternal (see above)
- setNcmTethering: called by enableTetheringInternal (see above)
- getTetheredIfaces: called only by TetheringTest. Renamed to
getTetheredIfacesForTest to ensure no other callers.
- getErroredIfaces: unused, deleted in this CL
- getTetheredIfaces: called by:
- isTetheringActive: called by onUserRestrictionsChanged, which
is only called by mStateReceiver
- TetheringTest
- dump(): changed to run on handler thread
- upstreamWanted: called by
- TetherModeAliveState#enter
- TetherModeAliveState#updateUpstreamWanted, which is called
only by TetherModeAliveState#processMessage.
Test: atest TetheringCoverageTests
Test: enabled/disabled hotspot, USB tethering
Change-Id: Id49d33f027b8df4c97fda480ff239c0ba90bb96a
This commit is contained in:
@@ -128,7 +128,6 @@ import android.util.SparseArray;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.util.IndentingPrintWriter;
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
import com.android.internal.util.MessageUtils;
|
import com.android.internal.util.MessageUtils;
|
||||||
@@ -218,9 +217,6 @@ public class Tethering {
|
|||||||
private final SparseArray<TetheringRequestParcel> mActiveTetheringRequests =
|
private final SparseArray<TetheringRequestParcel> mActiveTetheringRequests =
|
||||||
new SparseArray<>();
|
new SparseArray<>();
|
||||||
|
|
||||||
// used to synchronize public access to members
|
|
||||||
// TODO(b/153621704): remove mPublicSync to make Tethering lock free
|
|
||||||
private final Object mPublicSync;
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final ArrayMap<String, TetherState> mTetherStates;
|
private final ArrayMap<String, TetherState> mTetherStates;
|
||||||
private final BroadcastReceiver mStateReceiver;
|
private final BroadcastReceiver mStateReceiver;
|
||||||
@@ -246,8 +242,6 @@ public class Tethering {
|
|||||||
private final BpfCoordinator mBpfCoordinator;
|
private final BpfCoordinator mBpfCoordinator;
|
||||||
private final PrivateAddressCoordinator mPrivateAddressCoordinator;
|
private final PrivateAddressCoordinator mPrivateAddressCoordinator;
|
||||||
private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID;
|
private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID;
|
||||||
// All the usage of mTetheringEventCallback should run in the same thread.
|
|
||||||
private ITetheringEventCallback mTetheringEventCallback = null;
|
|
||||||
|
|
||||||
private volatile TetheringConfiguration mConfig;
|
private volatile TetheringConfiguration mConfig;
|
||||||
private InterfaceSet mCurrentUpstreamIfaceSet;
|
private InterfaceSet mCurrentUpstreamIfaceSet;
|
||||||
@@ -261,11 +255,8 @@ public class Tethering {
|
|||||||
private String mWifiP2pTetherInterface = null;
|
private String mWifiP2pTetherInterface = null;
|
||||||
private int mOffloadStatus = TETHER_HARDWARE_OFFLOAD_STOPPED;
|
private int mOffloadStatus = TETHER_HARDWARE_OFFLOAD_STOPPED;
|
||||||
|
|
||||||
@GuardedBy("mPublicSync")
|
|
||||||
private EthernetManager.TetheredInterfaceRequest mEthernetIfaceRequest;
|
private EthernetManager.TetheredInterfaceRequest mEthernetIfaceRequest;
|
||||||
@GuardedBy("mPublicSync")
|
|
||||||
private String mConfiguredEthernetIface;
|
private String mConfiguredEthernetIface;
|
||||||
@GuardedBy("mPublicSync")
|
|
||||||
private EthernetCallback mEthernetCallback;
|
private EthernetCallback mEthernetCallback;
|
||||||
|
|
||||||
public Tethering(TetheringDependencies deps) {
|
public Tethering(TetheringDependencies deps) {
|
||||||
@@ -276,8 +267,6 @@ public class Tethering {
|
|||||||
mLooper = mDeps.getTetheringLooper();
|
mLooper = mDeps.getTetheringLooper();
|
||||||
mNotificationUpdater = mDeps.getNotificationUpdater(mContext, mLooper);
|
mNotificationUpdater = mDeps.getNotificationUpdater(mContext, mLooper);
|
||||||
|
|
||||||
mPublicSync = new Object();
|
|
||||||
|
|
||||||
mTetherStates = new ArrayMap<>();
|
mTetherStates = new ArrayMap<>();
|
||||||
mConnectedClientsTracker = new ConnectedClientsTracker();
|
mConnectedClientsTracker = new ConnectedClientsTracker();
|
||||||
|
|
||||||
@@ -504,7 +493,6 @@ public class Tethering {
|
|||||||
// Never called directly: only called from interfaceLinkStateChanged.
|
// Never called directly: only called from interfaceLinkStateChanged.
|
||||||
// See NetlinkHandler.cpp: notifyInterfaceChanged.
|
// See NetlinkHandler.cpp: notifyInterfaceChanged.
|
||||||
if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
|
if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
|
||||||
synchronized (mPublicSync) {
|
|
||||||
if (up) {
|
if (up) {
|
||||||
maybeTrackNewInterfaceLocked(iface);
|
maybeTrackNewInterfaceLocked(iface);
|
||||||
} else {
|
} else {
|
||||||
@@ -520,7 +508,6 @@ public class Tethering {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void interfaceLinkStateChanged(String iface, boolean up) {
|
void interfaceLinkStateChanged(String iface, boolean up) {
|
||||||
interfaceStatusChanged(iface, up);
|
interfaceStatusChanged(iface, up);
|
||||||
@@ -547,17 +534,13 @@ public class Tethering {
|
|||||||
|
|
||||||
void interfaceAdded(String iface) {
|
void interfaceAdded(String iface) {
|
||||||
if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
|
if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
|
||||||
synchronized (mPublicSync) {
|
|
||||||
maybeTrackNewInterfaceLocked(iface);
|
maybeTrackNewInterfaceLocked(iface);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void interfaceRemoved(String iface) {
|
void interfaceRemoved(String iface) {
|
||||||
if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
|
if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
|
||||||
synchronized (mPublicSync) {
|
|
||||||
stopTrackingInterfaceLocked(iface);
|
stopTrackingInterfaceLocked(iface);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void startTethering(final TetheringRequestParcel request, final IIntResultListener listener) {
|
void startTethering(final TetheringRequestParcel request, final IIntResultListener listener) {
|
||||||
mHandler.post(() -> {
|
mHandler.post(() -> {
|
||||||
@@ -641,7 +624,6 @@ public class Tethering {
|
|||||||
private int setWifiTethering(final boolean enable) {
|
private int setWifiTethering(final boolean enable) {
|
||||||
final long ident = Binder.clearCallingIdentity();
|
final long ident = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
synchronized (mPublicSync) {
|
|
||||||
final WifiManager mgr = getWifiManager();
|
final WifiManager mgr = getWifiManager();
|
||||||
if (mgr == null) {
|
if (mgr == null) {
|
||||||
mLog.e("setWifiTethering: failed to get WifiManager!");
|
mLog.e("setWifiTethering: failed to get WifiManager!");
|
||||||
@@ -652,7 +634,6 @@ public class Tethering {
|
|||||||
mWifiTetherRequested = enable;
|
mWifiTetherRequested = enable;
|
||||||
return TETHER_ERROR_NO_ERROR;
|
return TETHER_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(ident);
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
@@ -703,7 +684,6 @@ public class Tethering {
|
|||||||
private int setEthernetTethering(final boolean enable) {
|
private int setEthernetTethering(final boolean enable) {
|
||||||
final EthernetManager em = (EthernetManager) mContext.getSystemService(
|
final EthernetManager em = (EthernetManager) mContext.getSystemService(
|
||||||
Context.ETHERNET_SERVICE);
|
Context.ETHERNET_SERVICE);
|
||||||
synchronized (mPublicSync) {
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
if (mEthernetCallback != null) {
|
if (mEthernetCallback != null) {
|
||||||
Log.d(TAG, "Ethernet tethering already started");
|
Log.d(TAG, "Ethernet tethering already started");
|
||||||
@@ -715,7 +695,6 @@ public class Tethering {
|
|||||||
} else {
|
} else {
|
||||||
stopEthernetTetheringLocked();
|
stopEthernetTetheringLocked();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return TETHER_ERROR_NO_ERROR;
|
return TETHER_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,7 +713,6 @@ public class Tethering {
|
|||||||
private class EthernetCallback implements EthernetManager.TetheredInterfaceCallback {
|
private class EthernetCallback implements EthernetManager.TetheredInterfaceCallback {
|
||||||
@Override
|
@Override
|
||||||
public void onAvailable(String iface) {
|
public void onAvailable(String iface) {
|
||||||
synchronized (mPublicSync) {
|
|
||||||
if (this != mEthernetCallback) {
|
if (this != mEthernetCallback) {
|
||||||
// Ethernet callback arrived after Ethernet tethering stopped. Ignore.
|
// Ethernet callback arrived after Ethernet tethering stopped. Ignore.
|
||||||
return;
|
return;
|
||||||
@@ -743,11 +721,9 @@ public class Tethering {
|
|||||||
changeInterfaceState(iface, getRequestedState(TETHERING_ETHERNET));
|
changeInterfaceState(iface, getRequestedState(TETHERING_ETHERNET));
|
||||||
mConfiguredEthernetIface = iface;
|
mConfiguredEthernetIface = iface;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUnavailable() {
|
public void onUnavailable() {
|
||||||
synchronized (mPublicSync) {
|
|
||||||
if (this != mEthernetCallback) {
|
if (this != mEthernetCallback) {
|
||||||
// onAvailable called after stopping Ethernet tethering.
|
// onAvailable called after stopping Ethernet tethering.
|
||||||
return;
|
return;
|
||||||
@@ -755,7 +731,6 @@ public class Tethering {
|
|||||||
stopEthernetTetheringLocked();
|
stopEthernetTetheringLocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void tether(String iface, int requestedState, final IIntResultListener listener) {
|
void tether(String iface, int requestedState, final IIntResultListener listener) {
|
||||||
mHandler.post(() -> {
|
mHandler.post(() -> {
|
||||||
@@ -767,7 +742,6 @@ public class Tethering {
|
|||||||
|
|
||||||
private int tether(String iface, int requestedState) {
|
private int tether(String iface, int requestedState) {
|
||||||
if (DBG) Log.d(TAG, "Tethering " + iface);
|
if (DBG) Log.d(TAG, "Tethering " + iface);
|
||||||
synchronized (mPublicSync) {
|
|
||||||
TetherState tetherState = mTetherStates.get(iface);
|
TetherState tetherState = mTetherStates.get(iface);
|
||||||
if (tetherState == null) {
|
if (tetherState == null) {
|
||||||
Log.e(TAG, "Tried to Tether an unknown iface: " + iface + ", ignoring");
|
Log.e(TAG, "Tried to Tether an unknown iface: " + iface + ", ignoring");
|
||||||
@@ -782,8 +756,7 @@ public class Tethering {
|
|||||||
// NOTE: If a CMD_TETHER_REQUESTED message is already in the TISM's queue but not yet
|
// NOTE: If a CMD_TETHER_REQUESTED message is already in the TISM's queue but not yet
|
||||||
// processed, this will be a no-op and it will not return an error.
|
// processed, this will be a no-op and it will not return an error.
|
||||||
//
|
//
|
||||||
// This code cannot race with untether() because they both synchronize on mPublicSync.
|
// This code cannot race with untether() because they both run on the handler thread.
|
||||||
// TODO: reexamine the threading and messaging model to totally remove mPublicSync.
|
|
||||||
final int type = tetherState.ipServer.interfaceType();
|
final int type = tetherState.ipServer.interfaceType();
|
||||||
final TetheringRequestParcel request = mActiveTetheringRequests.get(type, null);
|
final TetheringRequestParcel request = mActiveTetheringRequests.get(type, null);
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
@@ -793,19 +766,18 @@ public class Tethering {
|
|||||||
request);
|
request);
|
||||||
return TETHER_ERROR_NO_ERROR;
|
return TETHER_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void untether(String iface, final IIntResultListener listener) {
|
void untether(String iface, final IIntResultListener listener) {
|
||||||
mHandler.post(() -> {
|
mHandler.post(() -> {
|
||||||
try {
|
try {
|
||||||
listener.onResult(untether(iface));
|
listener.onResult(untether(iface));
|
||||||
} catch (RemoteException e) { }
|
} catch (RemoteException e) {
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
int untether(String iface) {
|
int untether(String iface) {
|
||||||
if (DBG) Log.d(TAG, "Untethering " + iface);
|
if (DBG) Log.d(TAG, "Untethering " + iface);
|
||||||
synchronized (mPublicSync) {
|
|
||||||
TetherState tetherState = mTetherStates.get(iface);
|
TetherState tetherState = mTetherStates.get(iface);
|
||||||
if (tetherState == null) {
|
if (tetherState == null) {
|
||||||
Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
|
Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
|
||||||
@@ -818,7 +790,6 @@ public class Tethering {
|
|||||||
tetherState.ipServer.sendMessage(IpServer.CMD_TETHER_UNREQUESTED);
|
tetherState.ipServer.sendMessage(IpServer.CMD_TETHER_UNREQUESTED);
|
||||||
return TETHER_ERROR_NO_ERROR;
|
return TETHER_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void untetherAll() {
|
void untetherAll() {
|
||||||
stopTethering(TETHERING_WIFI);
|
stopTethering(TETHERING_WIFI);
|
||||||
@@ -828,17 +799,16 @@ public class Tethering {
|
|||||||
stopTethering(TETHERING_ETHERNET);
|
stopTethering(TETHERING_ETHERNET);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getLastTetherError(String iface) {
|
@VisibleForTesting
|
||||||
synchronized (mPublicSync) {
|
int getLastErrorForTest(String iface) {
|
||||||
TetherState tetherState = mTetherStates.get(iface);
|
TetherState tetherState = mTetherStates.get(iface);
|
||||||
if (tetherState == null) {
|
if (tetherState == null) {
|
||||||
Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface
|
Log.e(TAG, "Tried to getLastErrorForTest on an unknown iface :" + iface
|
||||||
+ ", ignoring");
|
+ ", ignoring");
|
||||||
return TETHER_ERROR_UNKNOWN_IFACE;
|
return TETHER_ERROR_UNKNOWN_IFACE;
|
||||||
}
|
}
|
||||||
return tetherState.lastError;
|
return tetherState.lastError;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isProvisioningNeededButUnavailable() {
|
private boolean isProvisioningNeededButUnavailable() {
|
||||||
return isTetherProvisioningRequired() && !doesEntitlementPackageExist();
|
return isTetherProvisioningRequired() && !doesEntitlementPackageExist();
|
||||||
@@ -894,7 +864,6 @@ public class Tethering {
|
|||||||
mTetherStatesParcel = new TetherStatesParcel();
|
mTetherStatesParcel = new TetherStatesParcel();
|
||||||
|
|
||||||
int downstreamTypesMask = DOWNSTREAM_NONE;
|
int downstreamTypesMask = DOWNSTREAM_NONE;
|
||||||
synchronized (mPublicSync) {
|
|
||||||
for (int i = 0; i < mTetherStates.size(); i++) {
|
for (int i = 0; i < mTetherStates.size(); i++) {
|
||||||
TetherState tetherState = mTetherStates.valueAt(i);
|
TetherState tetherState = mTetherStates.valueAt(i);
|
||||||
String iface = mTetherStates.keyAt(i);
|
String iface = mTetherStates.keyAt(i);
|
||||||
@@ -916,7 +885,6 @@ public class Tethering {
|
|||||||
tetherList.add(iface);
|
tetherList.add(iface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mTetherStatesParcel.availableList = availableList.toArray(new String[0]);
|
mTetherStatesParcel.availableList = availableList.toArray(new String[0]);
|
||||||
mTetherStatesParcel.tetheredList = tetherList.toArray(new String[0]);
|
mTetherStatesParcel.tetheredList = tetherList.toArray(new String[0]);
|
||||||
@@ -1012,7 +980,6 @@ public class Tethering {
|
|||||||
// functions are ready to use.
|
// functions are ready to use.
|
||||||
//
|
//
|
||||||
// For more explanation, see b/62552150 .
|
// For more explanation, see b/62552150 .
|
||||||
synchronized (Tethering.this.mPublicSync) {
|
|
||||||
if (!usbConnected && mRndisEnabled) {
|
if (!usbConnected && mRndisEnabled) {
|
||||||
// Turn off tethering if it was enabled and there is a disconnect.
|
// Turn off tethering if it was enabled and there is a disconnect.
|
||||||
tetherMatchingInterfaces(IpServer.STATE_AVAILABLE, TETHERING_USB);
|
tetherMatchingInterfaces(IpServer.STATE_AVAILABLE, TETHERING_USB);
|
||||||
@@ -1027,14 +994,12 @@ public class Tethering {
|
|||||||
}
|
}
|
||||||
mRndisEnabled = usbConfigured && rndisEnabled;
|
mRndisEnabled = usbConfigured && rndisEnabled;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void handleWifiApAction(Intent intent) {
|
private void handleWifiApAction(Intent intent) {
|
||||||
final int curState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
|
final int curState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
|
||||||
final String ifname = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME);
|
final String ifname = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME);
|
||||||
final int ipmode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, IFACE_IP_MODE_UNSPECIFIED);
|
final int ipmode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, IFACE_IP_MODE_UNSPECIFIED);
|
||||||
|
|
||||||
synchronized (Tethering.this.mPublicSync) {
|
|
||||||
switch (curState) {
|
switch (curState) {
|
||||||
case WifiManager.WIFI_AP_STATE_ENABLING:
|
case WifiManager.WIFI_AP_STATE_ENABLING:
|
||||||
// We can see this state on the way to both enabled and failure states.
|
// We can see this state on the way to both enabled and failure states.
|
||||||
@@ -1052,7 +1017,6 @@ public class Tethering {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isGroupOwner(WifiP2pGroup group) {
|
private boolean isGroupOwner(WifiP2pGroup group) {
|
||||||
return group != null && group.isGroupOwner()
|
return group != null && group.isGroupOwner()
|
||||||
@@ -1071,7 +1035,6 @@ public class Tethering {
|
|||||||
Log.d(TAG, "WifiP2pAction: P2pInfo: " + p2pInfo + " Group: " + group);
|
Log.d(TAG, "WifiP2pAction: P2pInfo: " + p2pInfo + " Group: " + group);
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (Tethering.this.mPublicSync) {
|
|
||||||
// if no group is formed, bring it down if needed.
|
// if no group is formed, bring it down if needed.
|
||||||
if (p2pInfo == null || !p2pInfo.groupFormed) {
|
if (p2pInfo == null || !p2pInfo.groupFormed) {
|
||||||
disableWifiP2pIpServingLockedIfNeeded(mWifiP2pTetherInterface);
|
disableWifiP2pIpServingLockedIfNeeded(mWifiP2pTetherInterface);
|
||||||
@@ -1097,7 +1060,6 @@ public class Tethering {
|
|||||||
mWifiP2pTetherInterface = group.getInterface();
|
mWifiP2pTetherInterface = group.getInterface();
|
||||||
enableWifiIpServingLocked(mWifiP2pTetherInterface, IFACE_IP_MODE_LOCAL_ONLY);
|
enableWifiIpServingLocked(mWifiP2pTetherInterface, IFACE_IP_MODE_LOCAL_ONLY);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void handleUserRestrictionAction() {
|
private void handleUserRestrictionAction() {
|
||||||
mTetheringRestriction.onUserRestrictionsChanged();
|
mTetheringRestriction.onUserRestrictionsChanged();
|
||||||
@@ -1131,14 +1093,14 @@ public class Tethering {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected static class UserRestrictionActionListener {
|
protected static class UserRestrictionActionListener {
|
||||||
private final UserManager mUserMgr;
|
private final UserManager mUserMgr;
|
||||||
private final Tethering mWrapper;
|
private final Tethering mTethering;
|
||||||
private final TetheringNotificationUpdater mNotificationUpdater;
|
private final TetheringNotificationUpdater mNotificationUpdater;
|
||||||
public boolean mDisallowTethering;
|
public boolean mDisallowTethering;
|
||||||
|
|
||||||
public UserRestrictionActionListener(@NonNull UserManager um, @NonNull Tethering wrapper,
|
public UserRestrictionActionListener(@NonNull UserManager um, @NonNull Tethering tethering,
|
||||||
@NonNull TetheringNotificationUpdater updater) {
|
@NonNull TetheringNotificationUpdater updater) {
|
||||||
mUserMgr = um;
|
mUserMgr = um;
|
||||||
mWrapper = wrapper;
|
mTethering = tethering;
|
||||||
mNotificationUpdater = updater;
|
mNotificationUpdater = updater;
|
||||||
mDisallowTethering = false;
|
mDisallowTethering = false;
|
||||||
}
|
}
|
||||||
@@ -1165,13 +1127,13 @@ public class Tethering {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mWrapper.isTetheringActive()) {
|
if (mTethering.isTetheringActive()) {
|
||||||
// Restricted notification is shown when tethering function is disallowed on
|
// Restricted notification is shown when tethering function is disallowed on
|
||||||
// user's device.
|
// user's device.
|
||||||
mNotificationUpdater.notifyTetheringDisabledByRestriction();
|
mNotificationUpdater.notifyTetheringDisabledByRestriction();
|
||||||
|
|
||||||
// Untether from all downstreams since tethering is disallowed.
|
// Untether from all downstreams since tethering is disallowed.
|
||||||
mWrapper.untetherAll();
|
mTethering.untetherAll();
|
||||||
}
|
}
|
||||||
// TODO(b/148139325): send tetheringSupported on restriction change
|
// TODO(b/148139325): send tetheringSupported on restriction change
|
||||||
}
|
}
|
||||||
@@ -1332,55 +1294,53 @@ public class Tethering {
|
|||||||
return copy(mConfig.tetherableBluetoothRegexs);
|
return copy(mConfig.tetherableBluetoothRegexs);
|
||||||
}
|
}
|
||||||
|
|
||||||
int setUsbTethering(boolean enable) {
|
void setUsbTethering(boolean enable, IIntResultListener listener) {
|
||||||
|
mHandler.post(() -> {
|
||||||
|
try {
|
||||||
|
listener.onResult(setUsbTethering(enable));
|
||||||
|
} catch (RemoteException e) { }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private int setUsbTethering(boolean enable) {
|
||||||
if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
|
if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
|
||||||
UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
|
UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
|
||||||
if (usbManager == null) {
|
if (usbManager == null) {
|
||||||
mLog.e("setUsbTethering: failed to get UsbManager!");
|
mLog.e("setUsbTethering: failed to get UsbManager!");
|
||||||
return TETHER_ERROR_SERVICE_UNAVAIL;
|
return TETHER_ERROR_SERVICE_UNAVAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (mPublicSync) {
|
|
||||||
usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_RNDIS
|
usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_RNDIS
|
||||||
: UsbManager.FUNCTION_NONE);
|
: UsbManager.FUNCTION_NONE);
|
||||||
}
|
|
||||||
return TETHER_ERROR_NO_ERROR;
|
return TETHER_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int setNcmTethering(boolean enable) {
|
private int setNcmTethering(boolean enable) {
|
||||||
if (VDBG) Log.d(TAG, "setNcmTethering(" + enable + ")");
|
if (VDBG) Log.d(TAG, "setNcmTethering(" + enable + ")");
|
||||||
UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
|
UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
|
||||||
synchronized (mPublicSync) {
|
usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_NCM : UsbManager.FUNCTION_NONE);
|
||||||
usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_NCM
|
|
||||||
: UsbManager.FUNCTION_NONE);
|
|
||||||
}
|
|
||||||
return TETHER_ERROR_NO_ERROR;
|
return TETHER_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO review API - figure out how to delete these entirely.
|
// TODO review API - figure out how to delete these entirely.
|
||||||
String[] getTetheredIfaces() {
|
String[] getTetheredIfaces() {
|
||||||
ArrayList<String> list = new ArrayList<String>();
|
ArrayList<String> list = new ArrayList<String>();
|
||||||
synchronized (mPublicSync) {
|
|
||||||
for (int i = 0; i < mTetherStates.size(); i++) {
|
for (int i = 0; i < mTetherStates.size(); i++) {
|
||||||
TetherState tetherState = mTetherStates.valueAt(i);
|
TetherState tetherState = mTetherStates.valueAt(i);
|
||||||
if (tetherState.lastState == IpServer.STATE_TETHERED) {
|
if (tetherState.lastState == IpServer.STATE_TETHERED) {
|
||||||
list.add(mTetherStates.keyAt(i));
|
list.add(mTetherStates.keyAt(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return list.toArray(new String[list.size()]);
|
return list.toArray(new String[list.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] getTetherableIfaces() {
|
String[] getTetherableIfacesForTest() {
|
||||||
ArrayList<String> list = new ArrayList<String>();
|
ArrayList<String> list = new ArrayList<String>();
|
||||||
synchronized (mPublicSync) {
|
|
||||||
for (int i = 0; i < mTetherStates.size(); i++) {
|
for (int i = 0; i < mTetherStates.size(); i++) {
|
||||||
TetherState tetherState = mTetherStates.valueAt(i);
|
TetherState tetherState = mTetherStates.valueAt(i);
|
||||||
if (tetherState.lastState == IpServer.STATE_AVAILABLE) {
|
if (tetherState.lastState == IpServer.STATE_AVAILABLE) {
|
||||||
list.add(mTetherStates.keyAt(i));
|
list.add(mTetherStates.keyAt(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return list.toArray(new String[list.size()]);
|
return list.toArray(new String[list.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1390,30 +1350,14 @@ public class Tethering {
|
|||||||
return mConfig.legacyDhcpRanges;
|
return mConfig.legacyDhcpRanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] getErroredIfaces() {
|
|
||||||
ArrayList<String> list = new ArrayList<String>();
|
|
||||||
synchronized (mPublicSync) {
|
|
||||||
for (int i = 0; i < mTetherStates.size(); i++) {
|
|
||||||
TetherState tetherState = mTetherStates.valueAt(i);
|
|
||||||
if (tetherState.lastError != TETHER_ERROR_NO_ERROR) {
|
|
||||||
list.add(mTetherStates.keyAt(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list.toArray(new String[list.size()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logMessage(State state, int what) {
|
private void logMessage(State state, int what) {
|
||||||
mLog.log(state.getName() + " got " + sMagicDecoderRing.get(what, Integer.toString(what)));
|
mLog.log(state.getName() + " got " + sMagicDecoderRing.get(what, Integer.toString(what)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean upstreamWanted() {
|
private boolean upstreamWanted() {
|
||||||
if (!mForwardedDownstreams.isEmpty()) return true;
|
if (!mForwardedDownstreams.isEmpty()) return true;
|
||||||
|
|
||||||
synchronized (mPublicSync) {
|
|
||||||
return mWifiTetherRequested;
|
return mWifiTetherRequested;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Needed because the canonical source of upstream truth is just the
|
// Needed because the canonical source of upstream truth is just the
|
||||||
// upstream interface set, |mCurrentUpstreamIfaceSet|.
|
// upstream interface set, |mCurrentUpstreamIfaceSet|.
|
||||||
@@ -2308,7 +2252,6 @@ public class Tethering {
|
|||||||
mEntitlementMgr.dump(pw);
|
mEntitlementMgr.dump(pw);
|
||||||
pw.decreaseIndent();
|
pw.decreaseIndent();
|
||||||
|
|
||||||
synchronized (mPublicSync) {
|
|
||||||
pw.println("Tether state:");
|
pw.println("Tether state:");
|
||||||
pw.increaseIndent();
|
pw.increaseIndent();
|
||||||
for (int i = 0; i < mTetherStates.size(); i++) {
|
for (int i = 0; i < mTetherStates.size(); i++) {
|
||||||
@@ -2338,7 +2281,6 @@ public class Tethering {
|
|||||||
pw.println("Upstream wanted: " + upstreamWanted());
|
pw.println("Upstream wanted: " + upstreamWanted());
|
||||||
pw.println("Current upstream interface(s): " + mCurrentUpstreamIfaceSet);
|
pw.println("Current upstream interface(s): " + mCurrentUpstreamIfaceSet);
|
||||||
pw.decreaseIndent();
|
pw.decreaseIndent();
|
||||||
}
|
|
||||||
|
|
||||||
pw.println("Hardware offload:");
|
pw.println("Hardware offload:");
|
||||||
pw.increaseIndent();
|
pw.increaseIndent();
|
||||||
@@ -2439,7 +2381,6 @@ public class Tethering {
|
|||||||
// TODO: Move into TetherMainSM.
|
// TODO: Move into TetherMainSM.
|
||||||
private void notifyInterfaceStateChange(IpServer who, int state, int error) {
|
private void notifyInterfaceStateChange(IpServer who, int state, int error) {
|
||||||
final String iface = who.interfaceName();
|
final String iface = who.interfaceName();
|
||||||
synchronized (mPublicSync) {
|
|
||||||
final TetherState tetherState = mTetherStates.get(iface);
|
final TetherState tetherState = mTetherStates.get(iface);
|
||||||
if (tetherState != null && tetherState.ipServer.equals(who)) {
|
if (tetherState != null && tetherState.ipServer.equals(who)) {
|
||||||
tetherState.lastState = state;
|
tetherState.lastState = state;
|
||||||
@@ -2447,7 +2388,6 @@ public class Tethering {
|
|||||||
} else {
|
} else {
|
||||||
if (DBG) Log.d(TAG, "got notification from stale iface " + iface);
|
if (DBG) Log.d(TAG, "got notification from stale iface " + iface);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error));
|
mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error));
|
||||||
|
|
||||||
@@ -2478,7 +2418,6 @@ public class Tethering {
|
|||||||
private void notifyLinkPropertiesChanged(IpServer who, LinkProperties newLp) {
|
private void notifyLinkPropertiesChanged(IpServer who, LinkProperties newLp) {
|
||||||
final String iface = who.interfaceName();
|
final String iface = who.interfaceName();
|
||||||
final int state;
|
final int state;
|
||||||
synchronized (mPublicSync) {
|
|
||||||
final TetherState tetherState = mTetherStates.get(iface);
|
final TetherState tetherState = mTetherStates.get(iface);
|
||||||
if (tetherState != null && tetherState.ipServer.equals(who)) {
|
if (tetherState != null && tetherState.ipServer.equals(who)) {
|
||||||
state = tetherState.lastState;
|
state = tetherState.lastState;
|
||||||
@@ -2486,7 +2425,6 @@ public class Tethering {
|
|||||||
mLog.log("got notification from stale iface " + iface);
|
mLog.log("got notification from stale iface " + iface);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mLog.log(String.format(
|
mLog.log(String.format(
|
||||||
"OBSERVED LinkProperties update iface=%s state=%s lp=%s",
|
"OBSERVED LinkProperties update iface=%s state=%s lp=%s",
|
||||||
|
|||||||
@@ -121,9 +121,7 @@ public class TetheringService extends Service {
|
|||||||
IIntResultListener listener) {
|
IIntResultListener listener) {
|
||||||
if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
|
if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
|
||||||
|
|
||||||
try {
|
mTethering.setUsbTethering(enable, listener);
|
||||||
listener.onResult(mTethering.setUsbTethering(enable));
|
|
||||||
} catch (RemoteException e) { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -25,7 +25,10 @@ import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERM
|
|||||||
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
|
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.doAnswer;
|
||||||
import static org.mockito.Mockito.reset;
|
import static org.mockito.Mockito.reset;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
@@ -214,11 +217,15 @@ public final class TetheringServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void runSetUsbTethering(final TestTetheringResult result) throws Exception {
|
private void runSetUsbTethering(final TestTetheringResult result) throws Exception {
|
||||||
when(mTethering.setUsbTethering(true /* enable */)).thenReturn(TETHER_ERROR_NO_ERROR);
|
doAnswer((invocation) -> {
|
||||||
|
final IIntResultListener listener = invocation.getArgument(1);
|
||||||
|
listener.onResult(TETHER_ERROR_NO_ERROR);
|
||||||
|
return null;
|
||||||
|
}).when(mTethering).setUsbTethering(anyBoolean(), any(IIntResultListener.class));
|
||||||
mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG,
|
mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG,
|
||||||
TEST_ATTRIBUTION_TAG, result);
|
TEST_ATTRIBUTION_TAG, result);
|
||||||
verify(mTethering).isTetheringSupported();
|
verify(mTethering).isTetheringSupported();
|
||||||
verify(mTethering).setUsbTethering(true /* enable */);
|
verify(mTethering).setUsbTethering(eq(true) /* enable */, any(IIntResultListener.class));
|
||||||
result.assertResult(TETHER_ERROR_NO_ERROR);
|
result.assertResult(TETHER_ERROR_NO_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -941,7 +941,7 @@ public class TetheringTest {
|
|||||||
verifyNoMoreInteractions(mWifiManager);
|
verifyNoMoreInteractions(mWifiManager);
|
||||||
// Asking for the last error after the per-interface state machine
|
// Asking for the last error after the per-interface state machine
|
||||||
// has been reaped yields an unknown interface error.
|
// has been reaped yields an unknown interface error.
|
||||||
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
|
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastErrorForTest(TEST_WLAN_IFNAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1474,7 +1474,7 @@ public class TetheringTest {
|
|||||||
verifyNoMoreInteractions(mWifiManager);
|
verifyNoMoreInteractions(mWifiManager);
|
||||||
// Asking for the last error after the per-interface state machine
|
// Asking for the last error after the per-interface state machine
|
||||||
// has been reaped yields an unknown interface error.
|
// has been reaped yields an unknown interface error.
|
||||||
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
|
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastErrorForTest(TEST_WLAN_IFNAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Test with and without interfaceStatusChanged().
|
// TODO: Test with and without interfaceStatusChanged().
|
||||||
@@ -1942,7 +1942,7 @@ public class TetheringTest {
|
|||||||
// There are 2 IpServer state change events: STATE_AVAILABLE -> STATE_LOCAL_ONLY
|
// There are 2 IpServer state change events: STATE_AVAILABLE -> STATE_LOCAL_ONLY
|
||||||
verify(mNotificationUpdater, times(2)).onDownstreamChanged(DOWNSTREAM_NONE);
|
verify(mNotificationUpdater, times(2)).onDownstreamChanged(DOWNSTREAM_NONE);
|
||||||
|
|
||||||
assertEquals(TETHER_ERROR_NO_ERROR, mTethering.getLastTetherError(TEST_P2P_IFNAME));
|
assertEquals(TETHER_ERROR_NO_ERROR, mTethering.getLastErrorForTest(TEST_P2P_IFNAME));
|
||||||
|
|
||||||
// Emulate externally-visible WifiP2pManager effects, when wifi p2p group
|
// Emulate externally-visible WifiP2pManager effects, when wifi p2p group
|
||||||
// is being removed.
|
// is being removed.
|
||||||
@@ -1961,7 +1961,7 @@ public class TetheringTest {
|
|||||||
verifyNoMoreInteractions(mNetd);
|
verifyNoMoreInteractions(mNetd);
|
||||||
// Asking for the last error after the per-interface state machine
|
// Asking for the last error after the per-interface state machine
|
||||||
// has been reaped yields an unknown interface error.
|
// has been reaped yields an unknown interface error.
|
||||||
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
|
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastErrorForTest(TEST_P2P_IFNAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void workingWifiP2pGroupClient(
|
private void workingWifiP2pGroupClient(
|
||||||
@@ -1991,7 +1991,7 @@ public class TetheringTest {
|
|||||||
verifyNoMoreInteractions(mNetd);
|
verifyNoMoreInteractions(mNetd);
|
||||||
// Asking for the last error after the per-interface state machine
|
// Asking for the last error after the per-interface state machine
|
||||||
// has been reaped yields an unknown interface error.
|
// has been reaped yields an unknown interface error.
|
||||||
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
|
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastErrorForTest(TEST_P2P_IFNAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -2022,7 +2022,7 @@ public class TetheringTest {
|
|||||||
verify(mNetd, never()).networkAddInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
|
verify(mNetd, never()).networkAddInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
|
||||||
verify(mNetd, never()).ipfwdEnableForwarding(TETHERING_NAME);
|
verify(mNetd, never()).ipfwdEnableForwarding(TETHERING_NAME);
|
||||||
verify(mNetd, never()).tetherStartWithConfiguration(any());
|
verify(mNetd, never()).tetherStartWithConfiguration(any());
|
||||||
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
|
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastErrorForTest(TEST_P2P_IFNAME));
|
||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
public void workingWifiP2pGroupOwnerLegacyModeWithIfaceChanged() throws Exception {
|
public void workingWifiP2pGroupOwnerLegacyModeWithIfaceChanged() throws Exception {
|
||||||
@@ -2387,10 +2387,10 @@ public class TetheringTest {
|
|||||||
|
|
||||||
mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
|
mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
|
||||||
sendUsbBroadcast(true, true, true, TETHERING_USB);
|
sendUsbBroadcast(true, true, true, TETHERING_USB);
|
||||||
assertContains(Arrays.asList(mTethering.getTetherableIfaces()), TEST_USB_IFNAME);
|
assertContains(Arrays.asList(mTethering.getTetherableIfacesForTest()), TEST_USB_IFNAME);
|
||||||
assertContains(Arrays.asList(mTethering.getTetherableIfaces()), TEST_ETH_IFNAME);
|
assertContains(Arrays.asList(mTethering.getTetherableIfacesForTest()), TEST_ETH_IFNAME);
|
||||||
assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastTetherError(TEST_USB_IFNAME));
|
assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastErrorForTest(TEST_USB_IFNAME));
|
||||||
assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastTetherError(TEST_ETH_IFNAME));
|
assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastErrorForTest(TEST_ETH_IFNAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user