Remove mPublicSync. am: 94311aa902 am: c0f1bed8c5

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/1678387

Change-Id: Ie173e954e3ed27aebb73ebe2baefe3eff1c52556
This commit is contained in:
Lorenzo Colitti
2021-05-12 10:55:44 +00:00
committed by Automerger Merge Worker
4 changed files with 236 additions and 293 deletions

View File

@@ -128,7 +128,6 @@ import android.util.SparseArray;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.MessageUtils;
@@ -218,9 +217,6 @@ public class Tethering {
private final SparseArray<TetheringRequestParcel> mActiveTetheringRequests =
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 ArrayMap<String, TetherState> mTetherStates;
private final BroadcastReceiver mStateReceiver;
@@ -246,8 +242,6 @@ public class Tethering {
private final BpfCoordinator mBpfCoordinator;
private final PrivateAddressCoordinator mPrivateAddressCoordinator;
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 InterfaceSet mCurrentUpstreamIfaceSet;
@@ -261,11 +255,8 @@ public class Tethering {
private String mWifiP2pTetherInterface = null;
private int mOffloadStatus = TETHER_HARDWARE_OFFLOAD_STOPPED;
@GuardedBy("mPublicSync")
private EthernetManager.TetheredInterfaceRequest mEthernetIfaceRequest;
@GuardedBy("mPublicSync")
private String mConfiguredEthernetIface;
@GuardedBy("mPublicSync")
private EthernetCallback mEthernetCallback;
public Tethering(TetheringDependencies deps) {
@@ -276,8 +267,6 @@ public class Tethering {
mLooper = mDeps.getTetheringLooper();
mNotificationUpdater = mDeps.getNotificationUpdater(mContext, mLooper);
mPublicSync = new Object();
mTetherStates = new ArrayMap<>();
mConnectedClientsTracker = new ConnectedClientsTracker();
@@ -504,7 +493,6 @@ public class Tethering {
// Never called directly: only called from interfaceLinkStateChanged.
// See NetlinkHandler.cpp: notifyInterfaceChanged.
if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
synchronized (mPublicSync) {
if (up) {
maybeTrackNewInterfaceLocked(iface);
} else {
@@ -520,7 +508,6 @@ public class Tethering {
}
}
}
}
void interfaceLinkStateChanged(String iface, boolean up) {
interfaceStatusChanged(iface, up);
@@ -547,17 +534,13 @@ public class Tethering {
void interfaceAdded(String iface) {
if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
synchronized (mPublicSync) {
maybeTrackNewInterfaceLocked(iface);
}
}
void interfaceRemoved(String iface) {
if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
synchronized (mPublicSync) {
stopTrackingInterfaceLocked(iface);
}
}
void startTethering(final TetheringRequestParcel request, final IIntResultListener listener) {
mHandler.post(() -> {
@@ -641,7 +624,6 @@ public class Tethering {
private int setWifiTethering(final boolean enable) {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mPublicSync) {
final WifiManager mgr = getWifiManager();
if (mgr == null) {
mLog.e("setWifiTethering: failed to get WifiManager!");
@@ -652,7 +634,6 @@ public class Tethering {
mWifiTetherRequested = enable;
return TETHER_ERROR_NO_ERROR;
}
}
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -703,7 +684,6 @@ public class Tethering {
private int setEthernetTethering(final boolean enable) {
final EthernetManager em = (EthernetManager) mContext.getSystemService(
Context.ETHERNET_SERVICE);
synchronized (mPublicSync) {
if (enable) {
if (mEthernetCallback != null) {
Log.d(TAG, "Ethernet tethering already started");
@@ -715,7 +695,6 @@ public class Tethering {
} else {
stopEthernetTetheringLocked();
}
}
return TETHER_ERROR_NO_ERROR;
}
@@ -734,7 +713,6 @@ public class Tethering {
private class EthernetCallback implements EthernetManager.TetheredInterfaceCallback {
@Override
public void onAvailable(String iface) {
synchronized (mPublicSync) {
if (this != mEthernetCallback) {
// Ethernet callback arrived after Ethernet tethering stopped. Ignore.
return;
@@ -743,11 +721,9 @@ public class Tethering {
changeInterfaceState(iface, getRequestedState(TETHERING_ETHERNET));
mConfiguredEthernetIface = iface;
}
}
@Override
public void onUnavailable() {
synchronized (mPublicSync) {
if (this != mEthernetCallback) {
// onAvailable called after stopping Ethernet tethering.
return;
@@ -755,7 +731,6 @@ public class Tethering {
stopEthernetTetheringLocked();
}
}
}
void tether(String iface, int requestedState, final IIntResultListener listener) {
mHandler.post(() -> {
@@ -767,7 +742,6 @@ public class Tethering {
private int tether(String iface, int requestedState) {
if (DBG) Log.d(TAG, "Tethering " + iface);
synchronized (mPublicSync) {
TetherState tetherState = mTetherStates.get(iface);
if (tetherState == null) {
Log.e(TAG, "Tried to Tether an unknown iface: " + iface + ", ignoring");
@@ -782,8 +756,7 @@ public class Tethering {
// 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.
//
// This code cannot race with untether() because they both synchronize on mPublicSync.
// TODO: reexamine the threading and messaging model to totally remove mPublicSync.
// This code cannot race with untether() because they both run on the handler thread.
final int type = tetherState.ipServer.interfaceType();
final TetheringRequestParcel request = mActiveTetheringRequests.get(type, null);
if (request != null) {
@@ -793,19 +766,18 @@ public class Tethering {
request);
return TETHER_ERROR_NO_ERROR;
}
}
void untether(String iface, final IIntResultListener listener) {
mHandler.post(() -> {
try {
listener.onResult(untether(iface));
} catch (RemoteException e) { }
} catch (RemoteException e) {
}
});
}
int untether(String iface) {
if (DBG) Log.d(TAG, "Untethering " + iface);
synchronized (mPublicSync) {
TetherState tetherState = mTetherStates.get(iface);
if (tetherState == null) {
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);
return TETHER_ERROR_NO_ERROR;
}
}
void untetherAll() {
stopTethering(TETHERING_WIFI);
@@ -828,17 +799,16 @@ public class Tethering {
stopTethering(TETHERING_ETHERNET);
}
int getLastTetherError(String iface) {
synchronized (mPublicSync) {
@VisibleForTesting
int getLastErrorForTest(String iface) {
TetherState tetherState = mTetherStates.get(iface);
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");
return TETHER_ERROR_UNKNOWN_IFACE;
}
return tetherState.lastError;
}
}
private boolean isProvisioningNeededButUnavailable() {
return isTetherProvisioningRequired() && !doesEntitlementPackageExist();
@@ -894,7 +864,6 @@ public class Tethering {
mTetherStatesParcel = new TetherStatesParcel();
int downstreamTypesMask = DOWNSTREAM_NONE;
synchronized (mPublicSync) {
for (int i = 0; i < mTetherStates.size(); i++) {
TetherState tetherState = mTetherStates.valueAt(i);
String iface = mTetherStates.keyAt(i);
@@ -916,7 +885,6 @@ public class Tethering {
tetherList.add(iface);
}
}
}
mTetherStatesParcel.availableList = availableList.toArray(new String[0]);
mTetherStatesParcel.tetheredList = tetherList.toArray(new String[0]);
@@ -1012,7 +980,6 @@ public class Tethering {
// functions are ready to use.
//
// For more explanation, see b/62552150 .
synchronized (Tethering.this.mPublicSync) {
if (!usbConnected && mRndisEnabled) {
// Turn off tethering if it was enabled and there is a disconnect.
tetherMatchingInterfaces(IpServer.STATE_AVAILABLE, TETHERING_USB);
@@ -1027,14 +994,12 @@ public class Tethering {
}
mRndisEnabled = usbConfigured && rndisEnabled;
}
}
private void handleWifiApAction(Intent intent) {
final int curState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
final String ifname = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME);
final int ipmode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, IFACE_IP_MODE_UNSPECIFIED);
synchronized (Tethering.this.mPublicSync) {
switch (curState) {
case WifiManager.WIFI_AP_STATE_ENABLING:
// We can see this state on the way to both enabled and failure states.
@@ -1052,7 +1017,6 @@ public class Tethering {
break;
}
}
}
private boolean isGroupOwner(WifiP2pGroup group) {
return group != null && group.isGroupOwner()
@@ -1071,7 +1035,6 @@ public class Tethering {
Log.d(TAG, "WifiP2pAction: P2pInfo: " + p2pInfo + " Group: " + group);
}
synchronized (Tethering.this.mPublicSync) {
// if no group is formed, bring it down if needed.
if (p2pInfo == null || !p2pInfo.groupFormed) {
disableWifiP2pIpServingLockedIfNeeded(mWifiP2pTetherInterface);
@@ -1097,7 +1060,6 @@ public class Tethering {
mWifiP2pTetherInterface = group.getInterface();
enableWifiIpServingLocked(mWifiP2pTetherInterface, IFACE_IP_MODE_LOCAL_ONLY);
}
}
private void handleUserRestrictionAction() {
mTetheringRestriction.onUserRestrictionsChanged();
@@ -1131,14 +1093,14 @@ public class Tethering {
@VisibleForTesting
protected static class UserRestrictionActionListener {
private final UserManager mUserMgr;
private final Tethering mWrapper;
private final Tethering mTethering;
private final TetheringNotificationUpdater mNotificationUpdater;
public boolean mDisallowTethering;
public UserRestrictionActionListener(@NonNull UserManager um, @NonNull Tethering wrapper,
public UserRestrictionActionListener(@NonNull UserManager um, @NonNull Tethering tethering,
@NonNull TetheringNotificationUpdater updater) {
mUserMgr = um;
mWrapper = wrapper;
mTethering = tethering;
mNotificationUpdater = updater;
mDisallowTethering = false;
}
@@ -1165,13 +1127,13 @@ public class Tethering {
return;
}
if (mWrapper.isTetheringActive()) {
if (mTethering.isTetheringActive()) {
// Restricted notification is shown when tethering function is disallowed on
// user's device.
mNotificationUpdater.notifyTetheringDisabledByRestriction();
// Untether from all downstreams since tethering is disallowed.
mWrapper.untetherAll();
mTethering.untetherAll();
}
// TODO(b/148139325): send tetheringSupported on restriction change
}
@@ -1332,55 +1294,53 @@ public class Tethering {
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 + ")");
UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
if (usbManager == null) {
mLog.e("setUsbTethering: failed to get UsbManager!");
return TETHER_ERROR_SERVICE_UNAVAIL;
}
synchronized (mPublicSync) {
usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_RNDIS
: UsbManager.FUNCTION_NONE);
}
return TETHER_ERROR_NO_ERROR;
}
private int setNcmTethering(boolean enable) {
if (VDBG) Log.d(TAG, "setNcmTethering(" + enable + ")");
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;
}
// TODO review API - figure out how to delete these entirely.
String[] getTetheredIfaces() {
ArrayList<String> list = new ArrayList<String>();
synchronized (mPublicSync) {
for (int i = 0; i < mTetherStates.size(); i++) {
TetherState tetherState = mTetherStates.valueAt(i);
if (tetherState.lastState == IpServer.STATE_TETHERED) {
list.add(mTetherStates.keyAt(i));
}
}
}
return list.toArray(new String[list.size()]);
}
String[] getTetherableIfaces() {
String[] getTetherableIfacesForTest() {
ArrayList<String> list = new ArrayList<String>();
synchronized (mPublicSync) {
for (int i = 0; i < mTetherStates.size(); i++) {
TetherState tetherState = mTetherStates.valueAt(i);
if (tetherState.lastState == IpServer.STATE_AVAILABLE) {
list.add(mTetherStates.keyAt(i));
}
}
}
return list.toArray(new String[list.size()]);
}
@@ -1390,30 +1350,14 @@ public class Tethering {
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) {
mLog.log(state.getName() + " got " + sMagicDecoderRing.get(what, Integer.toString(what)));
}
private boolean upstreamWanted() {
if (!mForwardedDownstreams.isEmpty()) return true;
synchronized (mPublicSync) {
return mWifiTetherRequested;
}
}
// Needed because the canonical source of upstream truth is just the
// upstream interface set, |mCurrentUpstreamIfaceSet|.
@@ -2308,7 +2252,6 @@ public class Tethering {
mEntitlementMgr.dump(pw);
pw.decreaseIndent();
synchronized (mPublicSync) {
pw.println("Tether state:");
pw.increaseIndent();
for (int i = 0; i < mTetherStates.size(); i++) {
@@ -2338,7 +2281,6 @@ public class Tethering {
pw.println("Upstream wanted: " + upstreamWanted());
pw.println("Current upstream interface(s): " + mCurrentUpstreamIfaceSet);
pw.decreaseIndent();
}
pw.println("Hardware offload:");
pw.increaseIndent();
@@ -2439,7 +2381,6 @@ public class Tethering {
// TODO: Move into TetherMainSM.
private void notifyInterfaceStateChange(IpServer who, int state, int error) {
final String iface = who.interfaceName();
synchronized (mPublicSync) {
final TetherState tetherState = mTetherStates.get(iface);
if (tetherState != null && tetherState.ipServer.equals(who)) {
tetherState.lastState = state;
@@ -2447,7 +2388,6 @@ public class Tethering {
} else {
if (DBG) Log.d(TAG, "got notification from stale iface " + iface);
}
}
mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error));
@@ -2478,7 +2418,6 @@ public class Tethering {
private void notifyLinkPropertiesChanged(IpServer who, LinkProperties newLp) {
final String iface = who.interfaceName();
final int state;
synchronized (mPublicSync) {
final TetherState tetherState = mTetherStates.get(iface);
if (tetherState != null && tetherState.ipServer.equals(who)) {
state = tetherState.lastState;
@@ -2486,7 +2425,6 @@ public class Tethering {
mLog.log("got notification from stale iface " + iface);
return;
}
}
mLog.log(String.format(
"OBSERVED LinkProperties update iface=%s state=%s lp=%s",

View File

@@ -121,9 +121,7 @@ public class TetheringService extends Service {
IIntResultListener listener) {
if (checkAndNotifyCommonError(callerPkg, callingAttributionTag, listener)) return;
try {
listener.onResult(mTethering.setUsbTethering(enable));
} catch (RemoteException e) { }
mTethering.setUsbTethering(enable, listener);
}
@Override

View File

@@ -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 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.Mockito.doAnswer;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -214,11 +217,15 @@ public final class TetheringServiceTest {
}
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,
TEST_ATTRIBUTION_TAG, result);
verify(mTethering).isTetheringSupported();
verify(mTethering).setUsbTethering(true /* enable */);
verify(mTethering).setUsbTethering(eq(true) /* enable */, any(IIntResultListener.class));
result.assertResult(TETHER_ERROR_NO_ERROR);
}

View File

@@ -941,7 +941,7 @@ public class TetheringTest {
verifyNoMoreInteractions(mWifiManager);
// Asking for the last error after the per-interface state machine
// 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);
// Asking for the last error after the per-interface state machine
// 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().
@@ -1942,7 +1942,7 @@ public class TetheringTest {
// There are 2 IpServer state change events: STATE_AVAILABLE -> STATE_LOCAL_ONLY
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
// is being removed.
@@ -1961,7 +1961,7 @@ public class TetheringTest {
verifyNoMoreInteractions(mNetd);
// Asking for the last error after the per-interface state machine
// 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(
@@ -1991,7 +1991,7 @@ public class TetheringTest {
verifyNoMoreInteractions(mNetd);
// Asking for the last error after the per-interface state machine
// 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
@@ -2022,7 +2022,7 @@ public class TetheringTest {
verify(mNetd, never()).networkAddInterface(INetd.LOCAL_NET_ID, TEST_P2P_IFNAME);
verify(mNetd, never()).ipfwdEnableForwarding(TETHERING_NAME);
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
public void workingWifiP2pGroupOwnerLegacyModeWithIfaceChanged() throws Exception {
@@ -2387,10 +2387,10 @@ public class TetheringTest {
mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
sendUsbBroadcast(true, true, true, TETHERING_USB);
assertContains(Arrays.asList(mTethering.getTetherableIfaces()), TEST_USB_IFNAME);
assertContains(Arrays.asList(mTethering.getTetherableIfaces()), TEST_ETH_IFNAME);
assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastTetherError(TEST_USB_IFNAME));
assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastTetherError(TEST_ETH_IFNAME));
assertContains(Arrays.asList(mTethering.getTetherableIfacesForTest()), TEST_USB_IFNAME);
assertContains(Arrays.asList(mTethering.getTetherableIfacesForTest()), TEST_ETH_IFNAME);
assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastErrorForTest(TEST_USB_IFNAME));
assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastErrorForTest(TEST_ETH_IFNAME));
}
@Test