Merge "Remove --show-annotation FlaggedApi from flagged-apis-droidstubs" into main
diff --git a/OWNERS b/OWNERS
index 988af41..b2176cc 100644
--- a/OWNERS
+++ b/OWNERS
@@ -3,4 +3,3 @@
file:platform/packages/modules/Connectivity:main:/OWNERS_core_networking
per-file **IpSec* = file:platform/frameworks/base:main:/services/core/java/com/android/server/vcn/OWNERS
-per-file **Xfrm* = file:platform/frameworks/base:main:/services/core/java/com/android/server/vcn/OWNERS
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 996ee11..da3b584 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -327,8 +327,10 @@
return mConfig;
}
});
- mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMainSM, mLog,
- TetherMainSM.EVENT_UPSTREAM_CALLBACK);
+ mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mHandler, mLog,
+ (what, obj) -> {
+ mTetherMainSM.sendMessage(TetherMainSM.EVENT_UPSTREAM_CALLBACK, what, 0, obj);
+ });
mForwardedDownstreams = new HashSet<>();
IntentFilter filter = new IntentFilter();
@@ -2732,84 +2734,73 @@
}
}
- private IpServer.Callback makeControlCallback() {
- return new IpServer.Callback() {
- @Override
- public void updateInterfaceState(IpServer who, int state, int lastError) {
- notifyInterfaceStateChange(who, state, lastError);
+ private class ControlCallback extends IpServer.Callback {
+ @Override
+ public void updateInterfaceState(IpServer who, int state, int lastError) {
+ final String iface = who.interfaceName();
+ final TetherState tetherState = mTetherStates.get(iface);
+ if (tetherState != null && tetherState.ipServer.equals(who)) {
+ tetherState.lastState = state;
+ tetherState.lastError = lastError;
+ } else {
+ if (DBG) Log.d(TAG, "got notification from stale iface " + iface);
}
- @Override
- public void updateLinkProperties(IpServer who, LinkProperties newLp) {
- notifyLinkPropertiesChanged(who, newLp);
- }
+ mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, lastError));
- @Override
- public void dhcpLeasesChanged() {
- maybeDhcpLeasesChanged();
+ // If TetherMainSM is in ErrorState, TetherMainSM stays there.
+ // Thus we give a chance for TetherMainSM to recover to InitialState
+ // by sending CMD_CLEAR_ERROR
+ if (lastError == TETHER_ERROR_INTERNAL_ERROR) {
+ mTetherMainSM.sendMessage(TetherMainSM.CMD_CLEAR_ERROR, who);
}
-
- @Override
- public void requestEnableTethering(int tetheringType, boolean enabled) {
- mTetherMainSM.sendMessage(TetherMainSM.EVENT_REQUEST_CHANGE_DOWNSTREAM,
- tetheringType, 0, enabled ? Boolean.TRUE : Boolean.FALSE);
+ int which;
+ switch (state) {
+ case IpServer.STATE_UNAVAILABLE:
+ case IpServer.STATE_AVAILABLE:
+ which = TetherMainSM.EVENT_IFACE_SERVING_STATE_INACTIVE;
+ break;
+ case IpServer.STATE_TETHERED:
+ case IpServer.STATE_LOCAL_ONLY:
+ which = TetherMainSM.EVENT_IFACE_SERVING_STATE_ACTIVE;
+ break;
+ default:
+ Log.wtf(TAG, "Unknown interface state: " + state);
+ return;
}
- };
- }
-
- // TODO: Move into TetherMainSM.
- private void notifyInterfaceStateChange(IpServer who, int state, int error) {
- final String iface = who.interfaceName();
- final TetherState tetherState = mTetherStates.get(iface);
- if (tetherState != null && tetherState.ipServer.equals(who)) {
- tetherState.lastState = state;
- tetherState.lastError = error;
- } else {
- if (DBG) Log.d(TAG, "got notification from stale iface " + iface);
+ mTetherMainSM.sendMessage(which, state, 0, who);
+ sendTetherStateChangedBroadcast();
}
- mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error));
-
- // If TetherMainSM is in ErrorState, TetherMainSM stays there.
- // Thus we give a chance for TetherMainSM to recover to InitialState
- // by sending CMD_CLEAR_ERROR
- if (error == TETHER_ERROR_INTERNAL_ERROR) {
- mTetherMainSM.sendMessage(TetherMainSM.CMD_CLEAR_ERROR, who);
- }
- int which;
- switch (state) {
- case IpServer.STATE_UNAVAILABLE:
- case IpServer.STATE_AVAILABLE:
- which = TetherMainSM.EVENT_IFACE_SERVING_STATE_INACTIVE;
- break;
- case IpServer.STATE_TETHERED:
- case IpServer.STATE_LOCAL_ONLY:
- which = TetherMainSM.EVENT_IFACE_SERVING_STATE_ACTIVE;
- break;
- default:
- Log.wtf(TAG, "Unknown interface state: " + state);
+ @Override
+ public void updateLinkProperties(IpServer who, LinkProperties newLp) {
+ final String iface = who.interfaceName();
+ final int state;
+ final TetherState tetherState = mTetherStates.get(iface);
+ if (tetherState != null && tetherState.ipServer.equals(who)) {
+ state = tetherState.lastState;
+ } else {
+ mLog.log("got notification from stale iface " + iface);
return;
- }
- mTetherMainSM.sendMessage(which, state, 0, who);
- sendTetherStateChangedBroadcast();
- }
+ }
- private void notifyLinkPropertiesChanged(IpServer who, LinkProperties newLp) {
- final String iface = who.interfaceName();
- final int state;
- final TetherState tetherState = mTetherStates.get(iface);
- if (tetherState != null && tetherState.ipServer.equals(who)) {
- state = tetherState.lastState;
- } else {
- mLog.log("got notification from stale iface " + iface);
- return;
+ mLog.log(String.format(
+ "OBSERVED LinkProperties update iface=%s state=%s lp=%s",
+ iface, IpServer.getStateString(state), newLp));
+ final int which = TetherMainSM.EVENT_IFACE_UPDATE_LINKPROPERTIES;
+ mTetherMainSM.sendMessage(which, state, 0, newLp);
}
- mLog.log(String.format(
- "OBSERVED LinkProperties update iface=%s state=%s lp=%s",
- iface, IpServer.getStateString(state), newLp));
- final int which = TetherMainSM.EVENT_IFACE_UPDATE_LINKPROPERTIES;
- mTetherMainSM.sendMessage(which, state, 0, newLp);
+ @Override
+ public void dhcpLeasesChanged() {
+ maybeDhcpLeasesChanged();
+ }
+
+ @Override
+ public void requestEnableTethering(int tetheringType, boolean enabled) {
+ mTetherMainSM.sendMessage(TetherMainSM.EVENT_REQUEST_CHANGE_DOWNSTREAM,
+ tetheringType, 0, enabled ? Boolean.TRUE : Boolean.FALSE);
+ }
}
private boolean hasSystemFeature(final String feature) {
@@ -2851,7 +2842,7 @@
mLog.i("adding IpServer for: " + iface);
final TetherState tetherState = new TetherState(
new IpServer(iface, mHandler, interfaceType, mLog, mNetd, mBpfCoordinator,
- mRoutingCoordinator, makeControlCallback(), mConfig,
+ mRoutingCoordinator, new ControlCallback(), mConfig,
mPrivateAddressCoordinator, mTetheringMetrics,
mDeps.getIpServerDependencies()), isNcm);
mTetherStates.put(iface, tetherState);
@@ -2879,4 +2870,9 @@
} catch (RemoteException e) { }
});
}
+
+ @VisibleForTesting
+ public TetherMainSM getTetherMainSMForTesting() {
+ return mTetherMainSM;
+ }
}
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
index c274165..d02e8e8 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
@@ -35,7 +35,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
-import com.android.internal.util.StateMachine;
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.SdkUtil.LateSdk;
import com.android.net.module.util.SharedLog;
@@ -84,9 +83,9 @@
/**
* Get a reference to the UpstreamNetworkMonitor to be used by tethering.
*/
- public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx, StateMachine target,
- SharedLog log, int what) {
- return new UpstreamNetworkMonitor(ctx, target, log, what);
+ public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx, Handler h,
+ SharedLog log, UpstreamNetworkMonitor.EventListener listener) {
+ return new UpstreamNetworkMonitor(ctx, h, log, listener);
}
/**
diff --git a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
index ac2aa7b..7a05d74 100644
--- a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
+++ b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
@@ -44,7 +44,6 @@
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.StateMachine;
import com.android.net.module.util.SharedLog;
import com.android.networkstack.apishim.ConnectivityManagerShimImpl;
import com.android.networkstack.apishim.common.ConnectivityManagerShim;
@@ -111,9 +110,8 @@
private final Context mContext;
private final SharedLog mLog;
- private final StateMachine mTarget;
private final Handler mHandler;
- private final int mWhat;
+ private final EventListener mEventListener;
private final HashMap<Network, UpstreamNetworkState> mNetworkMap = new HashMap<>();
private HashSet<IpPrefix> mLocalPrefixes;
private ConnectivityManager mCM;
@@ -135,12 +133,11 @@
private Network mDefaultInternetNetwork;
private boolean mPreferTestNetworks;
- public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, SharedLog log, int what) {
+ public UpstreamNetworkMonitor(Context ctx, Handler h, SharedLog log, EventListener listener) {
mContext = ctx;
- mTarget = tgt;
- mHandler = mTarget.getHandler();
+ mHandler = h;
mLog = log.forSubComponent(TAG);
- mWhat = what;
+ mEventListener = listener;
mLocalPrefixes = new HashSet<>();
mIsDefaultCellularUpstream = false;
mCM = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -374,11 +371,12 @@
network, newNc));
}
- mNetworkMap.put(network, new UpstreamNetworkState(
- prev.linkProperties, newNc, network));
+ final UpstreamNetworkState uns =
+ new UpstreamNetworkState(prev.linkProperties, newNc, network);
+ mNetworkMap.put(network, uns);
// TODO: If sufficient information is available to select a more
// preferable upstream, do so now and notify the target.
- notifyTarget(EVENT_ON_CAPABILITIES, network);
+ mEventListener.onUpstreamEvent(EVENT_ON_CAPABILITIES, uns);
}
private @Nullable UpstreamNetworkState updateLinkProperties(@NonNull Network network,
@@ -411,7 +409,7 @@
private void handleLinkProp(Network network, LinkProperties newLp) {
final UpstreamNetworkState ns = updateLinkProperties(network, newLp);
if (ns != null) {
- notifyTarget(EVENT_ON_LINKPROPERTIES, ns);
+ mEventListener.onUpstreamEvent(EVENT_ON_LINKPROPERTIES, ns);
}
}
@@ -438,7 +436,7 @@
// preferable upstream, do so now and notify the target. Likewise,
// if the current upstream network is gone, notify the target of the
// fact that we now have no upstream at all.
- notifyTarget(EVENT_ON_LOST, mNetworkMap.remove(network));
+ mEventListener.onUpstreamEvent(EVENT_ON_LOST, mNetworkMap.remove(network));
}
private void maybeHandleNetworkSwitch(@NonNull Network network) {
@@ -456,14 +454,14 @@
// Default network changed. Update local data and notify tethering.
Log.d(TAG, "New default Internet network: " + network);
mDefaultInternetNetwork = network;
- notifyTarget(EVENT_DEFAULT_SWITCHED, ns);
+ mEventListener.onUpstreamEvent(EVENT_DEFAULT_SWITCHED, ns);
}
private void recomputeLocalPrefixes() {
final HashSet<IpPrefix> localPrefixes = allLocalPrefixes(mNetworkMap.values());
if (!mLocalPrefixes.equals(localPrefixes)) {
mLocalPrefixes = localPrefixes;
- notifyTarget(NOTIFY_LOCAL_PREFIXES, localPrefixes.clone());
+ mEventListener.onUpstreamEvent(NOTIFY_LOCAL_PREFIXES, localPrefixes.clone());
}
}
@@ -502,12 +500,13 @@
// onLinkPropertiesChanged right after this method and mDefaultInternetNetwork will
// be updated then.
//
- // Technically, not updating here isn't necessary, because the notifications to
- // Tethering sent by notifyTarget are messages sent to a state machine running on
- // the same thread as this method, and so cannot arrive until after this method has
- // returned. However, it is not a good idea to rely on that because fact that
- // Tethering uses multiple state machines running on the same thread is a major
- // source of race conditions and something that should be fixed.
+ // Technically, mDefaultInternetNetwork could be updated here, because the
+ // Callback#onChange implementation sends messages to the state machine running
+ // on the same thread as this method. If there is new default network change,
+ // the message cannot arrive until onLinkPropertiesChanged returns.
+ // However, it is not a good idea to rely on that because fact that Tethering uses
+ // multiple state machines running on the same thread is a major source of race
+ // conditions and something that should be fixed.
//
// TODO: is it correct that this code always updates EntitlementManager?
// This code runs when the default network connects or changes capabilities, but the
@@ -551,7 +550,7 @@
mIsDefaultCellularUpstream = false;
mEntitlementMgr.notifyUpstream(false);
Log.d(TAG, "Lost default Internet network: " + network);
- notifyTarget(EVENT_DEFAULT_SWITCHED, null);
+ mEventListener.onUpstreamEvent(EVENT_DEFAULT_SWITCHED, null);
return;
}
@@ -569,14 +568,6 @@
if (cb != null) cm().unregisterNetworkCallback(cb);
}
- private void notifyTarget(int which, Network network) {
- notifyTarget(which, mNetworkMap.get(network));
- }
-
- private void notifyTarget(int which, Object obj) {
- mTarget.sendMessage(mWhat, which, 0, obj);
- }
-
private static class TypeStatePair {
public int type = TYPE_NONE;
public UpstreamNetworkState ns = null;
@@ -698,4 +689,10 @@
public void setPreferTestNetworks(boolean prefer) {
mPreferTestNetworks = prefer;
}
+
+ /** An interface to notify upstream network changes. */
+ public interface EventListener {
+ /** Notify the client of some event */
+ void onUpstreamEvent(int what, Object obj);
+ }
}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
index 01600b8..47ecf58 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -1280,9 +1280,9 @@
final Ipv6DownstreamRule rule = buildTestDownstreamRule(mobileIfIndex, NEIGH_A, MAC_A);
final TetherDownstream6Key key = rule.makeTetherDownstream6Key();
- assertEquals(key.iif, mobileIfIndex);
- assertEquals(key.dstMac, MacAddress.ALL_ZEROS_ADDRESS); // rawip upstream
- assertTrue(Arrays.equals(key.neigh6, NEIGH_A.getAddress()));
+ assertEquals(mobileIfIndex, key.iif);
+ assertEquals(MacAddress.ALL_ZEROS_ADDRESS, key.dstMac); // rawip upstream
+ assertArrayEquals(NEIGH_A.getAddress(), key.neigh6);
// iif (4) + dstMac(6) + padding(2) + neigh6 (16) = 28.
assertEquals(28, key.writeToBytes().length);
}
@@ -1293,12 +1293,12 @@
final Ipv6DownstreamRule rule = buildTestDownstreamRule(mobileIfIndex, NEIGH_A, MAC_A);
final Tether6Value value = rule.makeTether6Value();
- assertEquals(value.oif, DOWNSTREAM_IFINDEX);
- assertEquals(value.ethDstMac, MAC_A);
- assertEquals(value.ethSrcMac, DOWNSTREAM_MAC);
- assertEquals(value.ethProto, ETH_P_IPV6);
- assertEquals(value.pmtu, NetworkStackConstants.ETHER_MTU);
- // oif (4) + ethDstMac (6) + ethSrcMac (6) + ethProto (2) + pmtu (2) = 20.
+ assertEquals(DOWNSTREAM_IFINDEX, value.oif);
+ assertEquals(MAC_A, value.ethDstMac);
+ assertEquals(DOWNSTREAM_MAC, value.ethSrcMac);
+ assertEquals(ETH_P_IPV6, value.ethProto);
+ assertEquals(NetworkStackConstants.ETHER_MTU, value.pmtu);
+ // oif (4) + ethDstMac (6) + ethSrcMac (6) + ethProto (2) + pmtu (2) = 20
assertEquals(20, value.writeToBytes().length);
}
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 6eba590..5877fc5 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -187,7 +187,6 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.util.StateMachine;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.net.module.util.CollectionUtils;
@@ -310,6 +309,7 @@
private BroadcastReceiver mBroadcastReceiver;
private Tethering mTethering;
private TestTetheringEventCallback mTetheringEventCallback;
+ private Tethering.TetherMainSM mTetherMainSM;
private PhoneStateListener mPhoneStateListener;
private InterfaceConfigurationParcel mInterfaceConfiguration;
private TetheringConfiguration mConfig;
@@ -319,6 +319,7 @@
private SoftApCallback mSoftApCallback;
private SoftApCallback mLocalOnlyHotspotCallback;
private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
+ private UpstreamNetworkMonitor.EventListener mEventListener;
private TetheredInterfaceCallbackShim mTetheredInterfaceCallbackShim;
private TestConnectivityManager mCm;
@@ -432,7 +433,6 @@
}
public class MockTetheringDependencies extends TetheringDependencies {
- StateMachine mUpstreamNetworkMonitorSM;
ArrayList<IpServer> mAllDownstreams;
@Override
@@ -456,12 +456,12 @@
}
@Override
- public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
- StateMachine target, SharedLog log, int what) {
+ public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx, Handler h,
+ SharedLog log, UpstreamNetworkMonitor.EventListener listener) {
// Use a real object instead of a mock so that some tests can use a real UNM and some
// can use a mock.
- mUpstreamNetworkMonitorSM = target;
- mUpstreamNetworkMonitor = spy(super.getUpstreamNetworkMonitor(ctx, target, log, what));
+ mEventListener = listener;
+ mUpstreamNetworkMonitor = spy(super.getUpstreamNetworkMonitor(ctx, h, log, listener));
return mUpstreamNetworkMonitor;
}
@@ -688,6 +688,7 @@
private void initTetheringOnTestThread() throws Exception {
mLooper = new TestLooper();
mTethering = new Tethering(mTetheringDependencies);
+ mTetherMainSM = mTethering.getTetherMainSMForTesting();
verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any());
verify(mNetd).registerUnsolicitedEventListener(any());
verifyDefaultNetworkRequestFiled();
@@ -1182,10 +1183,7 @@
initTetheringUpstream(upstreamState);
// Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES.
- mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage(
- Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK,
- UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
- 0,
+ mEventListener.onUpstreamEvent(UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
upstreamState);
mLooper.dispatchAll();
@@ -2713,14 +2711,12 @@
@Test
public void testUpstreamNetworkChanged() throws Exception {
initTetheringOnTestThread();
- final Tethering.TetherMainSM stateMachine = (Tethering.TetherMainSM)
- mTetheringDependencies.mUpstreamNetworkMonitorSM;
final InOrder inOrder = inOrder(mNotificationUpdater);
// Gain upstream.
final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
initTetheringUpstream(upstreamState);
- stateMachine.chooseUpstreamType(true);
+ mTetherMainSM.chooseUpstreamType(true);
mTetheringEventCallback.expectUpstreamChanged(upstreamState.network);
inOrder.verify(mNotificationUpdater)
.onUpstreamCapabilitiesChanged(upstreamState.networkCapabilities);
@@ -2728,7 +2724,7 @@
// Set the upstream with the same network ID but different object and the same capability.
final UpstreamNetworkState upstreamState2 = buildMobileIPv4UpstreamState();
initTetheringUpstream(upstreamState2);
- stateMachine.chooseUpstreamType(true);
+ mTetherMainSM.chooseUpstreamType(true);
// Expect that no upstream change event and capabilities changed event.
mTetheringEventCallback.assertNoUpstreamChangeCallback();
inOrder.verify(mNotificationUpdater, never()).onUpstreamCapabilitiesChanged(any());
@@ -2738,17 +2734,17 @@
assertFalse(upstreamState3.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED));
upstreamState3.networkCapabilities.addCapability(NET_CAPABILITY_VALIDATED);
initTetheringUpstream(upstreamState3);
- stateMachine.chooseUpstreamType(true);
+ mTetherMainSM.chooseUpstreamType(true);
// Expect that no upstream change event and capabilities changed event.
mTetheringEventCallback.assertNoUpstreamChangeCallback();
- stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState3);
+ mTetherMainSM.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState3);
inOrder.verify(mNotificationUpdater)
.onUpstreamCapabilitiesChanged(upstreamState3.networkCapabilities);
// Lose upstream.
initTetheringUpstream(null);
- stateMachine.chooseUpstreamType(true);
+ mTetherMainSM.chooseUpstreamType(true);
mTetheringEventCallback.expectUpstreamChanged(NULL_NETWORK);
inOrder.verify(mNotificationUpdater).onUpstreamCapabilitiesChanged(null);
}
@@ -2756,17 +2752,15 @@
@Test
public void testUpstreamCapabilitiesChanged() throws Exception {
initTetheringOnTestThread();
- final Tethering.TetherMainSM stateMachine = (Tethering.TetherMainSM)
- mTetheringDependencies.mUpstreamNetworkMonitorSM;
final InOrder inOrder = inOrder(mNotificationUpdater);
final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
initTetheringUpstream(upstreamState);
- stateMachine.chooseUpstreamType(true);
+ mTetherMainSM.chooseUpstreamType(true);
inOrder.verify(mNotificationUpdater)
.onUpstreamCapabilitiesChanged(upstreamState.networkCapabilities);
- stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState);
+ mTetherMainSM.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState);
inOrder.verify(mNotificationUpdater)
.onUpstreamCapabilitiesChanged(upstreamState.networkCapabilities);
@@ -2775,7 +2769,7 @@
// Expect that capability is changed with new capability VALIDATED.
assertFalse(upstreamState.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED));
upstreamState.networkCapabilities.addCapability(NET_CAPABILITY_VALIDATED);
- stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState);
+ mTetherMainSM.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState);
inOrder.verify(mNotificationUpdater)
.onUpstreamCapabilitiesChanged(upstreamState.networkCapabilities);
@@ -2784,7 +2778,7 @@
final UpstreamNetworkState upstreamState2 = new UpstreamNetworkState(
upstreamState.linkProperties, upstreamState.networkCapabilities,
new Network(WIFI_NETID));
- stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState2);
+ mTetherMainSM.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState2);
inOrder.verify(mNotificationUpdater, never()).onUpstreamCapabilitiesChanged(any());
}
@@ -2907,11 +2901,7 @@
final String iface, final int transportType) {
final UpstreamNetworkState upstream = buildV4UpstreamState(ipv4Address, network, iface,
transportType);
- mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage(
- Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK,
- UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
- 0,
- upstream);
+ mEventListener.onUpstreamEvent(UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES, upstream);
mLooper.dispatchAll();
}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
index e756bd3..045c0cb 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
@@ -30,10 +30,12 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -51,27 +53,23 @@
import android.net.NetworkRequest;
import android.os.Build;
import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
import android.os.test.TestLooper;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
import com.android.net.module.util.SharedLog;
import com.android.networkstack.tethering.TestConnectivityManager.NetworkRequestInfo;
import com.android.networkstack.tethering.TestConnectivityManager.TestNetworkAgent;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
-import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -84,8 +82,6 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class UpstreamNetworkMonitorTest {
- private static final int EVENT_UNM_UPDATE = 1;
-
private static final boolean INCLUDES = true;
private static final boolean EXCLUDES = false;
@@ -102,12 +98,13 @@
@Mock private EntitlementManager mEntitleMgr;
@Mock private IConnectivityManager mCS;
@Mock private SharedLog mLog;
+ @Mock private UpstreamNetworkMonitor.EventListener mListener;
- private TestStateMachine mSM;
private TestConnectivityManager mCM;
private UpstreamNetworkMonitor mUNM;
private final TestLooper mLooper = new TestLooper();
+ private InOrder mCallbackOrder;
@Before public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -117,17 +114,11 @@
when(mLog.forSubComponent(anyString())).thenReturn(mLog);
when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true);
+ mCallbackOrder = inOrder(mListener);
mCM = spy(new TestConnectivityManager(mContext, mCS));
when(mContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE))).thenReturn(mCM);
- mSM = new TestStateMachine(mLooper.getLooper());
- mUNM = new UpstreamNetworkMonitor(mContext, mSM, mLog, EVENT_UNM_UPDATE);
- }
-
- @After public void tearDown() throws Exception {
- if (mSM != null) {
- mSM.quit();
- mSM = null;
- }
+ mUNM = new UpstreamNetworkMonitor(mContext, new Handler(mLooper.getLooper()), mLog,
+ mListener);
}
@Test
@@ -603,14 +594,17 @@
mCM.makeDefaultNetwork(cellAgent);
mLooper.dispatchAll();
verifyCurrentLinkProperties(cellAgent);
- int messageIndex = mSM.messages.size() - 1;
+ verifyNotifyNetworkCapabilitiesChange(cellAgent.networkCapabilities);
+ verifyNotifyLinkPropertiesChange(cellLp);
+ verifyNotifyDefaultSwitch(cellAgent);
+ verifyNoMoreInteractions(mListener);
addLinkAddresses(cellLp, ipv6Addr1);
mCM.sendLinkProperties(cellAgent, false /* updateDefaultFirst */);
mLooper.dispatchAll();
verifyCurrentLinkProperties(cellAgent);
- verifyNotifyLinkPropertiesChange(messageIndex);
- messageIndex = mSM.messages.size() - 1;
+ verifyNotifyLinkPropertiesChange(cellLp);
+ verifyNoMoreInteractions(mListener);
removeLinkAddresses(cellLp, ipv6Addr1);
addLinkAddresses(cellLp, ipv6Addr2);
@@ -618,7 +612,8 @@
mLooper.dispatchAll();
assertEquals(cellAgent.linkProperties, mUNM.getCurrentPreferredUpstream().linkProperties);
verifyCurrentLinkProperties(cellAgent);
- verifyNotifyLinkPropertiesChange(messageIndex);
+ verifyNotifyLinkPropertiesChange(cellLp);
+ verifyNoMoreInteractions(mListener);
}
private void verifyCurrentLinkProperties(TestNetworkAgent agent) {
@@ -626,12 +621,33 @@
assertEquals(agent.linkProperties, mUNM.getCurrentPreferredUpstream().linkProperties);
}
- private void verifyNotifyLinkPropertiesChange(int lastMessageIndex) {
- assertEquals(UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
- mSM.messages.get(++lastMessageIndex).arg1);
- assertEquals(UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES,
- mSM.messages.get(++lastMessageIndex).arg1);
- assertEquals(lastMessageIndex + 1, mSM.messages.size());
+ private void verifyNotifyNetworkCapabilitiesChange(final NetworkCapabilities cap) {
+ mCallbackOrder.verify(mListener).onUpstreamEvent(
+ eq(UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES),
+ argThat(uns -> uns instanceof UpstreamNetworkState
+ && cap.equals(((UpstreamNetworkState) uns).networkCapabilities)));
+
+ }
+
+ private void verifyNotifyLinkPropertiesChange(final LinkProperties lp) {
+ mCallbackOrder.verify(mListener).onUpstreamEvent(
+ eq(UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES),
+ argThat(uns -> uns instanceof UpstreamNetworkState
+ && lp.equals(((UpstreamNetworkState) uns).linkProperties)));
+
+ mCallbackOrder.verify(mListener).onUpstreamEvent(
+ eq(UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES), any());
+ }
+
+ private void verifyNotifyDefaultSwitch(TestNetworkAgent agent) {
+ mCallbackOrder.verify(mListener).onUpstreamEvent(
+ eq(UpstreamNetworkMonitor.EVENT_DEFAULT_SWITCHED),
+ argThat(uns ->
+ uns instanceof UpstreamNetworkState
+ && agent.networkId.equals(((UpstreamNetworkState) uns).network)
+ && agent.linkProperties.equals(((UpstreamNetworkState) uns).linkProperties)
+ && agent.networkCapabilities.equals(
+ ((UpstreamNetworkState) uns).networkCapabilities)));
}
private void addLinkAddresses(LinkProperties lp, String... addrs) {
@@ -673,33 +689,6 @@
return false;
}
- public static class TestStateMachine extends StateMachine {
- public final ArrayList<Message> messages = new ArrayList<>();
- private final State mLoggingState = new LoggingState();
-
- class LoggingState extends State {
- @Override public void enter() {
- messages.clear();
- }
-
- @Override public void exit() {
- messages.clear();
- }
-
- @Override public boolean processMessage(Message msg) {
- messages.add(msg);
- return true;
- }
- }
-
- public TestStateMachine(Looper looper) {
- super("UpstreamNetworkMonitor.TestStateMachine", looper);
- addState(mLoggingState);
- setInitialState(mLoggingState);
- super.start();
- }
- }
-
static void assertPrefixSet(Set<IpPrefix> prefixes, boolean expectation, String... expected) {
final Set<String> expectedSet = new HashSet<>();
Collections.addAll(expectedSet, expected);
diff --git a/common/flags.aconfig b/common/flags.aconfig
index b85c2fe..ebfa13a 100644
--- a/common/flags.aconfig
+++ b/common/flags.aconfig
@@ -41,3 +41,10 @@
description: "Block network access for apps in a low importance background state"
bug: "304347838"
}
+
+flag {
+ name: "register_nsd_offload_engine"
+ namespace: "android_core_networking"
+ description: "The flag controls the access for registerOffloadEngine API in NsdManager"
+ bug: "294777050"
+}
diff --git a/framework-t/src/android/net/nsd/NsdManager.java b/framework-t/src/android/net/nsd/NsdManager.java
index ef0e34b..dae8914 100644
--- a/framework-t/src/android/net/nsd/NsdManager.java
+++ b/framework-t/src/android/net/nsd/NsdManager.java
@@ -34,10 +34,10 @@
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
+import android.net.ConnectivityThread;
import android.net.Network;
import android.net.NetworkRequest;
import android.os.Handler;
-import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
@@ -632,10 +632,9 @@
*/
public NsdManager(Context context, INsdManager service) {
mContext = context;
-
- HandlerThread t = new HandlerThread("NsdManager");
- t.start();
- mHandler = new ServiceHandler(t.getLooper());
+ // Use a common singleton thread ConnectivityThread to be shared among all nsd tasks.
+ // Instead of launching separate threads to handle tasks from the various instances.
+ mHandler = new ServiceHandler(ConnectivityThread.getInstanceLooper());
try {
mService = service.connect(new NsdCallbackImpl(mHandler), CompatChanges.isChangeEnabled(
diff --git a/framework/Android.bp b/framework/Android.bp
index 68a8cc5..10acbd0 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -94,7 +94,9 @@
"framework-wifi.stubs.module_lib",
],
static_libs: [
- "mdns_aidl_interface-lateststable-java",
+ // Not using the latest stable version because all functions in the latest version of
+ // mdns_aidl_interface are deprecated.
+ "mdns_aidl_interface-V1-java",
"modules-utils-backgroundthread",
"modules-utils-build",
"modules-utils-preconditions",
diff --git a/service/Android.bp b/service/Android.bp
index 76741bc..e2dab9e 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -185,7 +185,7 @@
"androidx.annotation_annotation",
"connectivity-net-module-utils-bpf",
"connectivity_native_aidl_interface-lateststable-java",
- "dnsresolver_aidl_interface-V12-java",
+ "dnsresolver_aidl_interface-V13-java",
"modules-utils-shell-command-handler",
"net-utils-device-common",
"net-utils-device-common-ip",
diff --git a/staticlibs/Android.bp b/staticlibs/Android.bp
index 6325b46..9f1debc 100644
--- a/staticlibs/Android.bp
+++ b/staticlibs/Android.bp
@@ -191,7 +191,7 @@
java_library {
name: "net-utils-device-common-netlink",
srcs: [
- "device/com/android/net/module/util/netlink/*.java",
+ "device/com/android/net/module/util/netlink/**/*.java",
],
sdk_version: "module_current",
min_sdk_version: "30",
diff --git a/staticlibs/device/com/android/net/module/util/netlink/xfrm/OWNERS b/staticlibs/device/com/android/net/module/util/netlink/xfrm/OWNERS
new file mode 100644
index 0000000..97b4da0
--- /dev/null
+++ b/staticlibs/device/com/android/net/module/util/netlink/xfrm/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 1364804
+
+per-file **Xfrm* = file:platform/frameworks/base:main:/services/core/java/com/android/server/vcn/OWNERS
diff --git a/staticlibs/device/com/android/net/module/util/netlink/IpSecStructXfrmAddressT.java b/staticlibs/device/com/android/net/module/util/netlink/xfrm/StructXfrmAddressT.java
similarity index 86%
rename from staticlibs/device/com/android/net/module/util/netlink/IpSecStructXfrmAddressT.java
rename to staticlibs/device/com/android/net/module/util/netlink/xfrm/StructXfrmAddressT.java
index 4c19887..cef1f56 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/IpSecStructXfrmAddressT.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/xfrm/StructXfrmAddressT.java
@@ -13,7 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.net.module.util.netlink;
+package com.android.net.module.util.netlink.xfrm;
+
+import static com.android.net.module.util.NetworkStackConstants.IPV4_ADDR_LEN;
import android.system.OsConstants;
@@ -41,21 +43,19 @@
*
* @hide
*/
-public class IpSecStructXfrmAddressT extends Struct {
- private static final int IPV4_ADDRESS_LEN = 4;
-
+public class StructXfrmAddressT extends Struct {
public static final int STRUCT_SIZE = 16;
@Field(order = 0, type = Type.ByteArray, arraysize = STRUCT_SIZE)
public final byte[] address;
// Constructor that allows Strutc.parse(Class<T>, ByteBuffer) to work
- public IpSecStructXfrmAddressT(@NonNull byte[] address) {
+ public StructXfrmAddressT(@NonNull final byte[] address) {
this.address = address.clone();
}
// Constructor to build a new message
- public IpSecStructXfrmAddressT(@NonNull InetAddress inetAddress) {
+ public StructXfrmAddressT(@NonNull final InetAddress inetAddress) {
this.address = new byte[STRUCT_SIZE];
final byte[] addressBytes = inetAddress.getAddress();
System.arraycopy(addressBytes, 0, address, 0, addressBytes.length);
@@ -67,7 +67,7 @@
if (family == OsConstants.AF_INET6) {
addressBytes = this.address;
} else if (family == OsConstants.AF_INET) {
- addressBytes = new byte[IPV4_ADDRESS_LEN];
+ addressBytes = new byte[IPV4_ADDR_LEN];
System.arraycopy(this.address, 0, addressBytes, 0, addressBytes.length);
} else {
throw new IllegalArgumentException("Invalid IP family " + family);
diff --git a/staticlibs/device/com/android/net/module/util/netlink/IpSecStructXfrmUsersaId.java b/staticlibs/device/com/android/net/module/util/netlink/xfrm/StructXfrmUsersaId.java
similarity index 76%
rename from staticlibs/device/com/android/net/module/util/netlink/IpSecStructXfrmUsersaId.java
rename to staticlibs/device/com/android/net/module/util/netlink/xfrm/StructXfrmUsersaId.java
index 6f7b656..5ebc69c 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/IpSecStructXfrmUsersaId.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/xfrm/StructXfrmUsersaId.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.net.module.util.netlink;
+package com.android.net.module.util.netlink.xfrm;
import androidx.annotation.NonNull;
@@ -40,7 +40,7 @@
*
* @hide
*/
-public class IpSecStructXfrmUsersaId extends Struct {
+public class StructXfrmUsersaId extends Struct {
public static final int STRUCT_SIZE = 24;
@Field(order = 0, type = Type.ByteArray, arraysize = 16)
@@ -55,23 +55,23 @@
@Field(order = 3, type = Type.U8, padding = 1)
public final short proto;
- @Computed private final IpSecStructXfrmAddressT mDestXfrmAddressT;
+ @Computed private final StructXfrmAddressT mDestXfrmAddressT;
// Constructor that allows Strutc.parse(Class<T>, ByteBuffer) to work
- public IpSecStructXfrmUsersaId(
- @NonNull byte[] nestedStructDAddr, long spi, int family, short proto) {
+ public StructXfrmUsersaId(
+ @NonNull final byte[] nestedStructDAddr, long spi, int family, short proto) {
this.nestedStructDAddr = nestedStructDAddr.clone();
this.spi = spi;
this.family = family;
this.proto = proto;
- mDestXfrmAddressT = new IpSecStructXfrmAddressT(this.nestedStructDAddr);
+ mDestXfrmAddressT = new StructXfrmAddressT(this.nestedStructDAddr);
}
// Constructor to build a new message
- public IpSecStructXfrmUsersaId(
- @NonNull InetAddress destAddress, long spi, int family, short proto) {
- this(new IpSecStructXfrmAddressT(destAddress).writeToBytes(), spi, family, proto);
+ public StructXfrmUsersaId(
+ @NonNull final InetAddress destAddress, long spi, int family, short proto) {
+ this(new StructXfrmAddressT(destAddress).writeToBytes(), spi, family, proto);
}
/** Return the destination address */
diff --git a/staticlibs/device/com/android/net/module/util/netlink/IpSecXfrmNetlinkMessage.java b/staticlibs/device/com/android/net/module/util/netlink/xfrm/XfrmNetlinkMessage.java
similarity index 81%
rename from staticlibs/device/com/android/net/module/util/netlink/IpSecXfrmNetlinkMessage.java
rename to staticlibs/device/com/android/net/module/util/netlink/xfrm/XfrmNetlinkMessage.java
index 8ad784b..ee34e57 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/IpSecXfrmNetlinkMessage.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/xfrm/XfrmNetlinkMessage.java
@@ -14,21 +14,24 @@
* limitations under the License.
*/
-package com.android.net.module.util.netlink;
+package com.android.net.module.util.netlink.xfrm;
import androidx.annotation.NonNull;
+import com.android.net.module.util.netlink.NetlinkMessage;
+import com.android.net.module.util.netlink.StructNlMsgHdr;
+
/** Base calss for XFRM netlink messages */
// Developer notes: The Linux kernel includes a number of XFRM structs that are not standard netlink
// attributes (e.g., xfrm_usersa_id). These structs are unlikely to change size, so this XFRM
// netlink message implementation assumes their sizes will remain stable. If any non-attribute
// struct size changes, it should be caught by CTS and then developers should add
// kernel-version-based behvaiours.
-public abstract class IpSecXfrmNetlinkMessage extends NetlinkMessage {
+public abstract class XfrmNetlinkMessage extends NetlinkMessage {
// TODO: STOPSHIP: b/308011229 Remove it when OsConstants.IPPROTO_ESP is exposed
public static final int IPPROTO_ESP = 50;
- public IpSecXfrmNetlinkMessage(@NonNull StructNlMsgHdr header) {
+ public XfrmNetlinkMessage(@NonNull final StructNlMsgHdr header) {
super(header);
}
diff --git a/staticlibs/netd/Android.bp b/staticlibs/netd/Android.bp
index 56565ed..637a938 100644
--- a/staticlibs/netd/Android.bp
+++ b/staticlibs/netd/Android.bp
@@ -225,19 +225,6 @@
}
-java_library {
- name: "mdns_aidl_interface-lateststable-java",
- sdk_version: "module_current",
- min_sdk_version: "30",
- static_libs: [
- "mdns_aidl_interface-V1-java",
- ],
- apex_available: [
- "//apex_available:platform",
- "com.android.tethering",
- ],
-}
-
aidl_interface {
name: "mdns_aidl_interface",
local_include_dir: "binder",
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/IpSecStructXfrmUsersaIdTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/xfrm/StructXfrmUsersaIdTest.java
similarity index 84%
rename from staticlibs/tests/unit/src/com/android/net/module/util/netlink/IpSecStructXfrmUsersaIdTest.java
rename to staticlibs/tests/unit/src/com/android/net/module/util/netlink/xfrm/StructXfrmUsersaIdTest.java
index 4266f68..52fd591 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/IpSecStructXfrmUsersaIdTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/xfrm/StructXfrmUsersaIdTest.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package com.android.net.module.util.netlink;
+package com.android.net.module.util.netlink.xfrm;
-import static com.android.net.module.util.netlink.IpSecXfrmNetlinkMessage.IPPROTO_ESP;
+import static com.android.net.module.util.netlink.xfrm.XfrmNetlinkMessage.IPPROTO_ESP;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -38,7 +38,7 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
-public class IpSecStructXfrmUsersaIdTest {
+public class StructXfrmUsersaIdTest {
private static final String EXPECTED_HEX_STRING =
"C0000201000000000000000000000000" + "7768440002003200";
private static final byte[] EXPECTED_HEX = HexDump.hexStringToByteArray(EXPECTED_HEX_STRING);
@@ -50,8 +50,7 @@
@Test
public void testEncode() throws Exception {
- final IpSecStructXfrmUsersaId struct =
- new IpSecStructXfrmUsersaId(DEST_ADDRESS, SPI, FAMILY, PROTO);
+ final StructXfrmUsersaId struct = new StructXfrmUsersaId(DEST_ADDRESS, SPI, FAMILY, PROTO);
ByteBuffer buffer = ByteBuffer.allocate(EXPECTED_HEX.length);
buffer.order(ByteOrder.nativeOrder());
@@ -65,8 +64,8 @@
final ByteBuffer buffer = ByteBuffer.wrap(EXPECTED_HEX);
buffer.order(ByteOrder.nativeOrder());
- final IpSecStructXfrmUsersaId struct =
- IpSecStructXfrmUsersaId.parse(IpSecStructXfrmUsersaId.class, buffer);
+ final StructXfrmUsersaId struct =
+ StructXfrmUsersaId.parse(StructXfrmUsersaId.class, buffer);
assertEquals(DEST_ADDRESS, struct.getDestAddress());
assertEquals(SPI, struct.spi);
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 778f0c5..58f6d58 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -278,10 +278,8 @@
private static final int MIN_KEEPALIVE_INTERVAL = 10;
private static final int NETWORK_CALLBACK_TIMEOUT_MS = 30_000;
- // Timeout for waiting network to be validated. Set the timeout to 30s, which is more than
- // DNS timeout.
- // TODO(b/252972908): reset the original timer when aosp/2188755 is ramped up.
- private static final int LISTEN_ACTIVITY_TIMEOUT_MS = 30_000;
+ // Timeout for waiting network to be validated.
+ private static final int LISTEN_ACTIVITY_TIMEOUT_MS = 5_000;
private static final int NO_CALLBACK_TIMEOUT_MS = 100;
private static final int NETWORK_REQUEST_TIMEOUT_MS = 3000;
private static final int SOCKET_TIMEOUT_MS = 100;
diff --git a/tests/unit/java/android/net/nsd/NsdManagerTest.java b/tests/unit/java/android/net/nsd/NsdManagerTest.java
index 0965193..550a9ee 100644
--- a/tests/unit/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/unit/java/android/net/nsd/NsdManagerTest.java
@@ -51,6 +51,7 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+@DevSdkIgnoreRunner.MonitorThreadLeak
@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
diff --git a/tests/unit/java/com/android/server/NsdServiceTest.java b/tests/unit/java/com/android/server/NsdServiceTest.java
index 771edb2..ffc8aa1 100644
--- a/tests/unit/java/com/android/server/NsdServiceTest.java
+++ b/tests/unit/java/com/android/server/NsdServiceTest.java
@@ -145,6 +145,7 @@
// TODOs:
// - test client can send requests and receive replies
// - test NSD_ON ENABLE/DISABLED listening
+@DevSdkIgnoreRunner.MonitorThreadLeak
@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
diff --git a/tests/unit/java/com/android/server/connectivity/DnsManagerTest.java b/tests/unit/java/com/android/server/connectivity/DnsManagerTest.java
index 545ed16..afb9abd 100644
--- a/tests/unit/java/com/android/server/connectivity/DnsManagerTest.java
+++ b/tests/unit/java/com/android/server/connectivity/DnsManagerTest.java
@@ -140,7 +140,8 @@
assertResolverOptionsEquals(actual.resolverOptions, expected.resolverOptions);
assertContainsExactly(actual.transportTypes, expected.transportTypes);
assertEquals(actual.meteredNetwork, expected.meteredNetwork);
- assertFieldCountEquals(17, ResolverParamsParcel.class);
+ assertEquals(actual.dohParams, expected.dohParams);
+ assertFieldCountEquals(18, ResolverParamsParcel.class);
}
@Before
@@ -381,6 +382,7 @@
expectedParams.transportTypes = TEST_TRANSPORT_TYPES;
expectedParams.resolverOptions = null;
expectedParams.meteredNetwork = true;
+ expectedParams.dohParams = null;
assertResolverParamsEquals(actualParams, expectedParams);
}
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java
index 331a5b6..5251e2a 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java
@@ -56,6 +56,7 @@
import java.util.concurrent.ScheduledExecutorService;
/** Tests for {@link MdnsDiscoveryManager}. */
+@DevSdkIgnoreRunner.MonitorThreadLeak
@RunWith(DevSdkIgnoreRunner.class)
@DevSdkIgnoreRule.IgnoreUpTo(SC_V2)
public class MdnsDiscoveryManagerTests {
@@ -134,9 +135,10 @@
}
@After
- public void tearDown() {
+ public void tearDown() throws Exception {
if (thread != null) {
thread.quitSafely();
+ thread.join();
}
}
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceCacheTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceCacheTest.kt
index 3cea5cb..b040ab6 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceCacheTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceCacheTest.kt
@@ -49,6 +49,7 @@
private const val TEST_ELAPSED_REALTIME_MS = 123L
private const val DEFAULT_TTL_TIME_MS = 120000L
+@DevSdkIgnoreRunner.MonitorThreadLeak
@RunWith(DevSdkIgnoreRunner::class)
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
class MdnsServiceCacheTest {
@@ -104,6 +105,7 @@
@After
fun tearDown() {
thread.quitSafely()
+ thread.join()
}
private fun makeFlags(isExpiredServicesRemovalEnabled: Boolean = false) =
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java
index 26a3796..7a2e4bf 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java
@@ -87,6 +87,7 @@
import java.util.stream.Stream;
/** Tests for {@link MdnsServiceTypeClient}. */
+@DevSdkIgnoreRunner.MonitorThreadLeak
@RunWith(DevSdkIgnoreRunner.class)
@DevSdkIgnoreRule.IgnoreUpTo(SC_V2)
public class MdnsServiceTypeClientTests {
@@ -230,9 +231,10 @@
}
@After
- public void tearDown() {
+ public void tearDown() throws Exception {
if (thread != null) {
thread.quitSafely();
+ thread.join();
}
}
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitorTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitorTest.kt
index c62a081..3e1dab8 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitorTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitorTest.kt
@@ -27,6 +27,7 @@
private val LINKADDRV4 = LinkAddress("192.0.2.0/24")
private val IFACE_IDX = 32
+@DevSdkIgnoreRunner.MonitorThreadLeak
@RunWith(DevSdkIgnoreRunner::class)
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
internal class SocketNetlinkMonitorTest {
@@ -43,6 +44,7 @@
@After
fun tearDown() {
thread.quitSafely()
+ thread.join()
}
@Test
diff --git a/thread/framework/java/android/net/thread/IThreadNetworkController.aidl b/thread/framework/java/android/net/thread/IThreadNetworkController.aidl
index 51e4d88..89dcd39 100644
--- a/thread/framework/java/android/net/thread/IThreadNetworkController.aidl
+++ b/thread/framework/java/android/net/thread/IThreadNetworkController.aidl
@@ -16,7 +16,6 @@
package android.net.thread;
-import android.net.Network;
import android.net.thread.ActiveOperationalDataset;
import android.net.thread.IActiveOperationalDatasetReceiver;
import android.net.thread.IOperationalDatasetCallback;
diff --git a/thread/framework/java/android/net/thread/ThreadNetworkController.java b/thread/framework/java/android/net/thread/ThreadNetworkController.java
index 5c5fda9..34b0b06 100644
--- a/thread/framework/java/android/net/thread/ThreadNetworkController.java
+++ b/thread/framework/java/android/net/thread/ThreadNetworkController.java
@@ -26,6 +26,7 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.os.Binder;
import android.os.OutcomeReceiver;
import android.os.RemoteException;
@@ -98,7 +99,8 @@
private final Map<OperationalDatasetCallback, OperationalDatasetCallbackProxy>
mOpDatasetCallbackMap = new HashMap<>();
- ThreadNetworkController(@NonNull IThreadNetworkController controllerService) {
+ /** @hide */
+ public ThreadNetworkController(@NonNull IThreadNetworkController controllerService) {
requireNonNull(controllerService, "controllerService cannot be null");
mControllerService = controllerService;
}
@@ -180,12 +182,22 @@
@Override
public void onDeviceRoleChanged(@DeviceRole int deviceRole) {
- mExecutor.execute(() -> mCallback.onDeviceRoleChanged(deviceRole));
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallback.onDeviceRoleChanged(deviceRole));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
@Override
public void onPartitionIdChanged(long partitionId) {
- mExecutor.execute(() -> mCallback.onPartitionIdChanged(partitionId));
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallback.onPartitionIdChanged(partitionId));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
}
@@ -282,13 +294,24 @@
@Override
public void onActiveOperationalDatasetChanged(
@Nullable ActiveOperationalDataset activeDataset) {
- mExecutor.execute(() -> mCallback.onActiveOperationalDatasetChanged(activeDataset));
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallback.onActiveOperationalDatasetChanged(activeDataset));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
@Override
public void onPendingOperationalDatasetChanged(
@Nullable PendingOperationalDataset pendingDataset) {
- mExecutor.execute(() -> mCallback.onPendingOperationalDatasetChanged(pendingDataset));
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(
+ () -> mCallback.onPendingOperationalDatasetChanged(pendingDataset));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
}
@@ -481,7 +504,13 @@
OutcomeReceiver<T, ThreadNetworkException> receiver,
int errorCode,
String errorMsg) {
- executor.execute(() -> receiver.onError(new ThreadNetworkException(errorCode, errorMsg)));
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(
+ () -> receiver.onError(new ThreadNetworkException(errorCode, errorMsg)));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
private static final class ActiveDatasetReceiverProxy
@@ -498,7 +527,12 @@
@Override
public void onSuccess(ActiveOperationalDataset dataset) {
- mExecutor.execute(() -> mResultReceiver.onResult(dataset));
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mResultReceiver.onResult(dataset));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
@Override
@@ -520,7 +554,12 @@
@Override
public void onSuccess() {
- mExecutor.execute(() -> mResultReceiver.onResult(null));
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mResultReceiver.onResult(null));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
@Override
diff --git a/thread/tests/unit/Android.bp b/thread/tests/unit/Android.bp
index 5863673..8092693 100644
--- a/thread/tests/unit/Android.bp
+++ b/thread/tests/unit/Android.bp
@@ -33,11 +33,11 @@
static_libs: [
"androidx.test.ext.junit",
"compatibility-device-util-axt",
- "ctstestrunner-axt",
"framework-connectivity-pre-jarjar",
"framework-connectivity-t-pre-jarjar",
"guava",
"guava-android-testlib",
+ "mockito-target-minus-junit4",
"net-tests-utils",
"truth",
],
@@ -45,6 +45,7 @@
"android.test.base",
"android.test.runner",
],
+ jarjar_rules: ":connectivity-jarjar-rules",
// Test coverage system runs on different devices. Need to
// compile for all architectures.
compile_multilib: "both",
diff --git a/thread/tests/unit/AndroidTest.xml b/thread/tests/unit/AndroidTest.xml
index 663ff74..597c6a8 100644
--- a/thread/tests/unit/AndroidTest.xml
+++ b/thread/tests/unit/AndroidTest.xml
@@ -27,6 +27,7 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.net.thread.unittests" />
+ <option name="hidden-api-checks" value="false"/>
<!-- Ignores tests introduced by guava-android-testlib -->
<option name="exclude-annotation" value="org.junit.Ignore"/>
</test>
diff --git a/thread/tests/unit/src/android/net/thread/ThreadNetworkControllerTest.java b/thread/tests/unit/src/android/net/thread/ThreadNetworkControllerTest.java
new file mode 100644
index 0000000..2f120b2
--- /dev/null
+++ b/thread/tests/unit/src/android/net/thread/ThreadNetworkControllerTest.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.thread;
+
+import static android.net.thread.ThreadNetworkController.DEVICE_ROLE_CHILD;
+import static android.net.thread.ThreadNetworkException.ERROR_UNAVAILABLE;
+import static android.net.thread.ThreadNetworkException.ERROR_UNSUPPORTED_CHANNEL;
+import static android.os.Process.SYSTEM_UID;
+
+import static com.google.common.io.BaseEncoding.base16;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+
+import android.net.thread.IActiveOperationalDatasetReceiver;
+import android.net.thread.IOperationReceiver;
+import android.net.thread.IOperationalDatasetCallback;
+import android.net.thread.IStateCallback;
+import android.net.thread.IThreadNetworkController;
+import android.net.thread.ThreadNetworkController.OperationalDatasetCallback;
+import android.net.thread.ThreadNetworkController.StateCallback;
+import android.os.Binder;
+import android.os.OutcomeReceiver;
+import android.os.Process;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+
+import java.time.Duration;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/** Unit tests for {@link ThreadNetworkController}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public final class ThreadNetworkControllerTest {
+
+ @Mock private IThreadNetworkController mMockService;
+ private ThreadNetworkController mController;
+
+ // A valid Thread Active Operational Dataset generated from OpenThread CLI "dataset new":
+ // Active Timestamp: 1
+ // Channel: 19
+ // Channel Mask: 0x07FFF800
+ // Ext PAN ID: ACC214689BC40BDF
+ // Mesh Local Prefix: fd64:db12:25f4:7e0b::/64
+ // Network Key: F26B3153760F519A63BAFDDFFC80D2AF
+ // Network Name: OpenThread-d9a0
+ // PAN ID: 0xD9A0
+ // PSKc: A245479C836D551B9CA557F7B9D351B4
+ // Security Policy: 672 onrcb
+ private static final byte[] DEFAULT_DATASET_TLVS =
+ base16().decode(
+ "0E080000000000010000000300001335060004001FFFE002"
+ + "08ACC214689BC40BDF0708FD64DB1225F47E0B0510F26B31"
+ + "53760F519A63BAFDDFFC80D2AF030F4F70656E5468726561"
+ + "642D643961300102D9A00410A245479C836D551B9CA557F7"
+ + "B9D351B40C0402A0FFF8");
+
+ private static final ActiveOperationalDataset DEFAULT_DATASET =
+ ActiveOperationalDataset.fromThreadTlvs(DEFAULT_DATASET_TLVS);
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mController = new ThreadNetworkController(mMockService);
+ }
+
+ private static void setBinderUid(int uid) {
+ // TODO: generally, it's not a good practice to depend on the implementation detail to set
+ // a custom UID, but Connectivity, Wifi, UWB and etc modules are using this trick. Maybe
+ // define a interface (e.b. CallerIdentityInjector) for easier mocking.
+ Binder.restoreCallingIdentity((((long) uid) << 32) | Binder.getCallingPid());
+ }
+
+ private static IStateCallback getStateCallback(InvocationOnMock invocation) {
+ return (IStateCallback) invocation.getArguments()[0];
+ }
+
+ private static IOperationReceiver getOperationReceiver(InvocationOnMock invocation) {
+ return (IOperationReceiver) invocation.getArguments()[0];
+ }
+
+ private static IOperationReceiver getJoinReceiver(InvocationOnMock invocation) {
+ return (IOperationReceiver) invocation.getArguments()[1];
+ }
+
+ private static IOperationReceiver getScheduleMigrationReceiver(InvocationOnMock invocation) {
+ return (IOperationReceiver) invocation.getArguments()[1];
+ }
+
+ private static IActiveOperationalDatasetReceiver getCreateDatasetReceiver(
+ InvocationOnMock invocation) {
+ return (IActiveOperationalDatasetReceiver) invocation.getArguments()[1];
+ }
+
+ private static IOperationalDatasetCallback getOperationalDatasetCallback(
+ InvocationOnMock invocation) {
+ return (IOperationalDatasetCallback) invocation.getArguments()[0];
+ }
+
+ @Test
+ public void registerStateCallback_callbackIsInvokedWithCallingAppIdentity() throws Exception {
+ setBinderUid(SYSTEM_UID);
+ doAnswer(
+ invoke -> {
+ getStateCallback(invoke).onDeviceRoleChanged(DEVICE_ROLE_CHILD);
+ return null;
+ })
+ .when(mMockService)
+ .registerStateCallback(any(IStateCallback.class));
+ AtomicInteger callbackUid = new AtomicInteger(0);
+ StateCallback callback = state -> callbackUid.set(Binder.getCallingUid());
+
+ try {
+ mController.registerStateCallback(Runnable::run, callback);
+
+ assertThat(callbackUid.get()).isNotEqualTo(SYSTEM_UID);
+ assertThat(callbackUid.get()).isEqualTo(Process.myUid());
+ } finally {
+ mController.unregisterStateCallback(callback);
+ }
+ }
+
+ @Test
+ public void registerOperationalDatasetCallback_callbackIsInvokedWithCallingAppIdentity()
+ throws Exception {
+ setBinderUid(SYSTEM_UID);
+ doAnswer(
+ invoke -> {
+ getOperationalDatasetCallback(invoke)
+ .onActiveOperationalDatasetChanged(null);
+ getOperationalDatasetCallback(invoke)
+ .onPendingOperationalDatasetChanged(null);
+ return null;
+ })
+ .when(mMockService)
+ .registerOperationalDatasetCallback(any(IOperationalDatasetCallback.class));
+ AtomicInteger activeCallbackUid = new AtomicInteger(0);
+ AtomicInteger pendingCallbackUid = new AtomicInteger(0);
+ OperationalDatasetCallback callback =
+ new OperationalDatasetCallback() {
+ @Override
+ public void onActiveOperationalDatasetChanged(
+ ActiveOperationalDataset dataset) {
+ activeCallbackUid.set(Binder.getCallingUid());
+ }
+
+ @Override
+ public void onPendingOperationalDatasetChanged(
+ PendingOperationalDataset dataset) {
+ pendingCallbackUid.set(Binder.getCallingUid());
+ }
+ };
+
+ try {
+ mController.registerOperationalDatasetCallback(Runnable::run, callback);
+
+ assertThat(activeCallbackUid.get()).isNotEqualTo(SYSTEM_UID);
+ assertThat(activeCallbackUid.get()).isEqualTo(Process.myUid());
+ assertThat(pendingCallbackUid.get()).isNotEqualTo(SYSTEM_UID);
+ assertThat(pendingCallbackUid.get()).isEqualTo(Process.myUid());
+ } finally {
+ mController.unregisterOperationalDatasetCallback(callback);
+ }
+ }
+
+ @Test
+ public void createRandomizedDataset_callbackIsInvokedWithCallingAppIdentity() throws Exception {
+ setBinderUid(SYSTEM_UID);
+ AtomicInteger successCallbackUid = new AtomicInteger(0);
+ AtomicInteger errorCallbackUid = new AtomicInteger(0);
+
+ doAnswer(
+ invoke -> {
+ getCreateDatasetReceiver(invoke).onSuccess(DEFAULT_DATASET);
+ return null;
+ })
+ .when(mMockService)
+ .createRandomizedDataset(anyString(), any(IActiveOperationalDatasetReceiver.class));
+ mController.createRandomizedDataset(
+ "TestNet",
+ Runnable::run,
+ dataset -> successCallbackUid.set(Binder.getCallingUid()));
+ doAnswer(
+ invoke -> {
+ getCreateDatasetReceiver(invoke).onError(ERROR_UNSUPPORTED_CHANNEL, "");
+ return null;
+ })
+ .when(mMockService)
+ .createRandomizedDataset(anyString(), any(IActiveOperationalDatasetReceiver.class));
+ mController.createRandomizedDataset(
+ "TestNet",
+ Runnable::run,
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(ActiveOperationalDataset dataset) {}
+
+ @Override
+ public void onError(ThreadNetworkException e) {
+ errorCallbackUid.set(Binder.getCallingUid());
+ }
+ });
+
+ assertThat(successCallbackUid.get()).isNotEqualTo(SYSTEM_UID);
+ assertThat(successCallbackUid.get()).isEqualTo(Process.myUid());
+ assertThat(errorCallbackUid.get()).isNotEqualTo(SYSTEM_UID);
+ assertThat(errorCallbackUid.get()).isEqualTo(Process.myUid());
+ }
+
+ @Test
+ public void join_callbackIsInvokedWithCallingAppIdentity() throws Exception {
+ setBinderUid(SYSTEM_UID);
+ AtomicInteger successCallbackUid = new AtomicInteger(0);
+ AtomicInteger errorCallbackUid = new AtomicInteger(0);
+
+ doAnswer(
+ invoke -> {
+ getJoinReceiver(invoke).onSuccess();
+ return null;
+ })
+ .when(mMockService)
+ .join(any(ActiveOperationalDataset.class), any(IOperationReceiver.class));
+ mController.join(
+ DEFAULT_DATASET,
+ Runnable::run,
+ v -> successCallbackUid.set(Binder.getCallingUid()));
+ doAnswer(
+ invoke -> {
+ getJoinReceiver(invoke).onError(ERROR_UNAVAILABLE, "");
+ return null;
+ })
+ .when(mMockService)
+ .join(any(ActiveOperationalDataset.class), any(IOperationReceiver.class));
+ mController.join(
+ DEFAULT_DATASET,
+ Runnable::run,
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Void unused) {}
+
+ @Override
+ public void onError(ThreadNetworkException e) {
+ errorCallbackUid.set(Binder.getCallingUid());
+ }
+ });
+
+ assertThat(successCallbackUid.get()).isNotEqualTo(SYSTEM_UID);
+ assertThat(successCallbackUid.get()).isEqualTo(Process.myUid());
+ assertThat(errorCallbackUid.get()).isNotEqualTo(SYSTEM_UID);
+ assertThat(errorCallbackUid.get()).isEqualTo(Process.myUid());
+ }
+
+ @Test
+ public void scheduleMigration_callbackIsInvokedWithCallingAppIdentity() throws Exception {
+ setBinderUid(SYSTEM_UID);
+ final PendingOperationalDataset pendingDataset =
+ new PendingOperationalDataset(
+ DEFAULT_DATASET,
+ new OperationalDatasetTimestamp(100, 0, false),
+ Duration.ZERO);
+ AtomicInteger successCallbackUid = new AtomicInteger(0);
+ AtomicInteger errorCallbackUid = new AtomicInteger(0);
+
+ doAnswer(
+ invoke -> {
+ getScheduleMigrationReceiver(invoke).onSuccess();
+ return null;
+ })
+ .when(mMockService)
+ .scheduleMigration(
+ any(PendingOperationalDataset.class), any(IOperationReceiver.class));
+ mController.scheduleMigration(
+ pendingDataset, Runnable::run, v -> successCallbackUid.set(Binder.getCallingUid()));
+ doAnswer(
+ invoke -> {
+ getScheduleMigrationReceiver(invoke).onError(ERROR_UNAVAILABLE, "");
+ return null;
+ })
+ .when(mMockService)
+ .scheduleMigration(
+ any(PendingOperationalDataset.class), any(IOperationReceiver.class));
+ mController.scheduleMigration(
+ pendingDataset,
+ Runnable::run,
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Void unused) {}
+
+ @Override
+ public void onError(ThreadNetworkException e) {
+ errorCallbackUid.set(Binder.getCallingUid());
+ }
+ });
+
+ assertThat(successCallbackUid.get()).isNotEqualTo(SYSTEM_UID);
+ assertThat(successCallbackUid.get()).isEqualTo(Process.myUid());
+ assertThat(errorCallbackUid.get()).isNotEqualTo(SYSTEM_UID);
+ assertThat(errorCallbackUid.get()).isEqualTo(Process.myUid());
+ }
+
+ @Test
+ public void leave_callbackIsInvokedWithCallingAppIdentity() throws Exception {
+ setBinderUid(SYSTEM_UID);
+ AtomicInteger successCallbackUid = new AtomicInteger(0);
+ AtomicInteger errorCallbackUid = new AtomicInteger(0);
+
+ doAnswer(
+ invoke -> {
+ getOperationReceiver(invoke).onSuccess();
+ return null;
+ })
+ .when(mMockService)
+ .leave(any(IOperationReceiver.class));
+ mController.leave(Runnable::run, v -> successCallbackUid.set(Binder.getCallingUid()));
+ doAnswer(
+ invoke -> {
+ getOperationReceiver(invoke).onError(ERROR_UNAVAILABLE, "");
+ return null;
+ })
+ .when(mMockService)
+ .leave(any(IOperationReceiver.class));
+ mController.leave(
+ Runnable::run,
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Void unused) {}
+
+ @Override
+ public void onError(ThreadNetworkException e) {
+ errorCallbackUid.set(Binder.getCallingUid());
+ }
+ });
+
+ assertThat(successCallbackUid.get()).isNotEqualTo(SYSTEM_UID);
+ assertThat(successCallbackUid.get()).isEqualTo(Process.myUid());
+ assertThat(errorCallbackUid.get()).isNotEqualTo(SYSTEM_UID);
+ assertThat(errorCallbackUid.get()).isEqualTo(Process.myUid());
+ }
+}