Snap for 6406367 from 65693396631e855393b7cfc90e6464a60c25fa67 to rvc-release

Change-Id: I7a4382baf03b7d5a199ded709947fe5ece3426b1
This commit is contained in:
android-build-team Robot
2020-04-18 01:05:44 +00:00
5 changed files with 268 additions and 17 deletions

View File

@@ -2093,6 +2093,20 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
}
private void enforceNetworkFactoryOrSettingsPermission() {
enforceAnyPermissionOf(
android.Manifest.permission.NETWORK_SETTINGS,
android.Manifest.permission.NETWORK_FACTORY,
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
}
private void enforceNetworkFactoryOrTestNetworksPermission() {
enforceAnyPermissionOf(
android.Manifest.permission.MANAGE_TEST_NETWORKS,
android.Manifest.permission.NETWORK_FACTORY,
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
}
private boolean checkSettingsPermission() {
return checkAnyPermissionOf(
android.Manifest.permission.NETWORK_SETTINGS,
@@ -2722,7 +2736,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
break;
}
case NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED: {
handleUpdateLinkProperties(nai, (LinkProperties) msg.obj);
LinkProperties newLp = (LinkProperties) msg.obj;
processLinkPropertiesFromAgent(nai, newLp);
handleUpdateLinkProperties(nai, newLp);
break;
}
case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {
@@ -5681,7 +5697,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
@Override
public int registerNetworkProvider(Messenger messenger, String name) {
enforceNetworkFactoryPermission();
enforceNetworkFactoryOrSettingsPermission();
NetworkProviderInfo npi = new NetworkProviderInfo(name, messenger,
null /* asyncChannel */, nextNetworkProviderId(),
() -> unregisterNetworkProvider(messenger));
@@ -5691,7 +5707,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
@Override
public void unregisterNetworkProvider(Messenger messenger) {
enforceNetworkFactoryPermission();
enforceNetworkFactoryOrSettingsPermission();
mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_PROVIDER, messenger));
}
@@ -5711,7 +5727,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
@Override
public void declareNetworkRequestUnfulfillable(NetworkRequest request) {
enforceNetworkFactoryPermission();
if (request.hasTransport(TRANSPORT_TEST)) {
enforceNetworkFactoryOrTestNetworksPermission();
} else {
enforceNetworkFactoryPermission();
}
mHandler.post(() -> handleReleaseNetworkRequest(request, Binder.getCallingUid(), true));
}
@@ -5817,7 +5837,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
LinkProperties lp = new LinkProperties(linkProperties);
lp.ensureDirectlyConnectedRoutes();
// TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
// satisfies mDefaultRequest.
final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
@@ -5825,8 +5845,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig),
this, mNetd, mDnsResolver, mNMS, providerId);
// Make sure the network capabilities reflect what the agent info says.
// Make sure the LinkProperties and NetworkCapabilities reflect what the agent info says.
nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc));
processLinkPropertiesFromAgent(nai, nai.linkProperties);
final String extraInfo = networkInfo.getExtraInfo();
final String name = TextUtils.isEmpty(extraInfo)
? nai.networkCapabilities.getSsid() : extraInfo;
@@ -5864,6 +5887,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
updateUids(nai, null, nai.networkCapabilities);
}
private void processLinkPropertiesFromAgent(NetworkAgentInfo nai, LinkProperties lp) {
lp.ensureDirectlyConnectedRoutes();
}
private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties newLp,
@NonNull LinkProperties oldLp) {
int netId = networkAgent.network.netId;
@@ -6391,13 +6418,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Ignore updates for disconnected networks
return;
}
// newLp is already a defensive copy.
newLp.ensureDirectlyConnectedRoutes();
if (VDBG || DDBG) {
log("Update of LinkProperties for " + nai.toShortString()
+ "; created=" + nai.created
+ "; everConnected=" + nai.everConnected);
}
// TODO: eliminate this defensive copy after confirming that updateLinkProperties does not
// modify its oldLp parameter.
updateLinkProperties(nai, newLp, new LinkProperties(nai.linkProperties));
}

View File

@@ -81,6 +81,9 @@ public class Nat464Xlat extends BaseNetworkObserver {
RUNNING, // start() called, and the stacked iface is known to be up.
}
/** NAT64 prefix currently in use. Only valid in STARTING or RUNNING states. */
private IpPrefix mNat64PrefixInUse;
/** NAT64 prefix (if any) discovered from DNS via RFC 7050. */
private IpPrefix mNat64PrefixFromDns;
private String mBaseIface;
private String mIface;
@@ -178,9 +181,10 @@ public class Nat464Xlat extends BaseNetworkObserver {
return;
}
mNat64PrefixInUse = getNat64Prefix();
String addrStr = null;
try {
addrStr = mNetd.clatdStart(baseIface, getNat64Prefix().toString());
addrStr = mNetd.clatdStart(baseIface, mNat64PrefixInUse.toString());
} catch (RemoteException | ServiceSpecificException e) {
Slog.e(TAG, "Error starting clatd on " + baseIface + ": " + e);
}
@@ -211,12 +215,13 @@ public class Nat464Xlat extends BaseNetworkObserver {
} catch (RemoteException | IllegalStateException e) {
Slog.e(TAG, "Error unregistering clatd observer on " + mBaseIface + ": " + e);
}
mNat64PrefixInUse = null;
mIface = null;
mBaseIface = null;
if (requiresClat(mNetwork)) {
mState = State.DISCOVERING;
} else {
stopPrefixDiscovery();
stopPrefixDiscovery(); // Enters IDLE state.
}
}
@@ -274,19 +279,32 @@ public class Nat464Xlat extends BaseNetworkObserver {
private void startPrefixDiscovery() {
try {
mDnsResolver.startPrefix64Discovery(getNetId());
mState = State.DISCOVERING;
} catch (RemoteException | ServiceSpecificException e) {
Slog.e(TAG, "Error starting prefix discovery on netId " + getNetId() + ": " + e);
}
mState = State.DISCOVERING;
}
private void stopPrefixDiscovery() {
try {
mDnsResolver.stopPrefix64Discovery(getNetId());
mState = State.IDLE;
} catch (RemoteException | ServiceSpecificException e) {
Slog.e(TAG, "Error stopping prefix discovery on netId " + getNetId() + ": " + e);
}
mState = State.IDLE;
}
private void maybeHandleNat64PrefixChange() {
final IpPrefix newPrefix = getNat64Prefix();
if (!Objects.equals(mNat64PrefixInUse, newPrefix)) {
Slog.d(TAG, "NAT64 prefix changed from " + mNat64PrefixInUse + " to "
+ newPrefix);
stop();
// It's safe to call update here, even though this method is called from update, because
// stop() is guaranteed to have moved out of STARTING and RUNNING, which are the only
// states in which this method can be called.
update();
}
}
/**
@@ -325,11 +343,11 @@ public class Nat464Xlat extends BaseNetworkObserver {
// Stop clatd and go back into DISCOVERING or idle.
if (!shouldStartClat(mNetwork)) {
stop();
break;
}
// Only necessary while clat is actually started.
maybeHandleNat64PrefixChange();
break;
// TODO: support the NAT64 prefix changing after it's been discovered. There is
// no need to support this at the moment because it cannot happen without
// changes to the Dns64Configuration code in netd.
}
}
@@ -347,6 +365,8 @@ public class Nat464Xlat extends BaseNetworkObserver {
* has no idea that 464xlat is running on top of it.
*/
public void fixupLinkProperties(@NonNull LinkProperties oldLp, @NonNull LinkProperties lp) {
// This must be done even if clatd is not running, because otherwise shouldStartClat would
// never return true.
lp.setNat64Prefix(getNat64Prefix());
if (!isRunning()) {

View File

@@ -0,0 +1,158 @@
/*
* Copyright (C) 2020 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
import android.app.Instrumentation
import android.content.Context
import android.net.NetworkCapabilities.TRANSPORT_TEST
import android.os.Build
import android.os.HandlerThread
import android.os.Looper
import android.net.NetworkProviderTest.TestNetworkCallback.CallbackEntry.OnUnavailable
import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequested
import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequestWithdrawn
import androidx.test.InstrumentationRegistry
import com.android.testutils.ArrayTrackRecord
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner
import java.util.UUID
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
private const val DEFAULT_TIMEOUT_MS = 5000L
private val instrumentation: Instrumentation
get() = InstrumentationRegistry.getInstrumentation()
private val context: Context get() = InstrumentationRegistry.getContext()
private val PROVIDER_NAME = "NetworkProviderTest"
@RunWith(DevSdkIgnoreRunner::class)
@IgnoreUpTo(Build.VERSION_CODES.Q)
class NetworkProviderTest {
private val mCm = context.getSystemService(ConnectivityManager::class.java)
private val mHandlerThread = HandlerThread("${javaClass.simpleName} handler thread")
@Before
fun setUp() {
instrumentation.getUiAutomation().adoptShellPermissionIdentity()
mHandlerThread.start()
}
@After
fun tearDown() {
mHandlerThread.quitSafely()
instrumentation.getUiAutomation().dropShellPermissionIdentity()
}
private class TestNetworkProvider(context: Context, looper: Looper) :
NetworkProvider(context, looper, PROVIDER_NAME) {
private val seenEvents = ArrayTrackRecord<CallbackEntry>().newReadHead()
sealed class CallbackEntry {
data class OnNetworkRequested(
val request: NetworkRequest,
val score: Int,
val id: Int
) : CallbackEntry()
data class OnNetworkRequestWithdrawn(val request: NetworkRequest) : CallbackEntry()
}
override fun onNetworkRequested(request: NetworkRequest, score: Int, id: Int) {
seenEvents.add(OnNetworkRequested(request, score, id))
}
override fun onNetworkRequestWithdrawn(request: NetworkRequest) {
seenEvents.add(OnNetworkRequestWithdrawn(request))
}
inline fun <reified T : CallbackEntry> expectCallback(
crossinline predicate: (T) -> Boolean
) = seenEvents.poll(DEFAULT_TIMEOUT_MS) { it is T && predicate(it) }
}
private fun createNetworkProvider(): TestNetworkProvider {
return TestNetworkProvider(context, mHandlerThread.looper)
}
@Test
fun testOnNetworkRequested() {
val provider = createNetworkProvider()
assertEquals(provider.getProviderId(), NetworkProvider.ID_NONE)
mCm.registerNetworkProvider(provider)
assertNotEquals(provider.getProviderId(), NetworkProvider.ID_NONE)
val specifier = StringNetworkSpecifier(UUID.randomUUID().toString())
val nr: NetworkRequest = NetworkRequest.Builder()
.addTransportType(TRANSPORT_TEST)
.setNetworkSpecifier(specifier)
.build()
val cb = ConnectivityManager.NetworkCallback()
mCm.requestNetwork(nr, cb)
provider.expectCallback<OnNetworkRequested>() {
callback -> callback.request.getNetworkSpecifier() == specifier &&
callback.request.hasTransport(TRANSPORT_TEST)
}
mCm.unregisterNetworkCallback(cb)
provider.expectCallback<OnNetworkRequestWithdrawn>() {
callback -> callback.request.getNetworkSpecifier() == specifier &&
callback.request.hasTransport(TRANSPORT_TEST)
}
mCm.unregisterNetworkProvider(provider)
// Provider id should be ID_NONE after unregister network provider
assertEquals(provider.getProviderId(), NetworkProvider.ID_NONE)
// unregisterNetworkProvider should not crash even if it's called on an
// already unregistered provider.
mCm.unregisterNetworkProvider(provider)
}
private class TestNetworkCallback : ConnectivityManager.NetworkCallback() {
private val seenEvents = ArrayTrackRecord<CallbackEntry>().newReadHead()
sealed class CallbackEntry {
object OnUnavailable : CallbackEntry()
}
override fun onUnavailable() {
seenEvents.add(OnUnavailable)
}
inline fun <reified T : CallbackEntry> expectCallback(
crossinline predicate: (T) -> Boolean
) = seenEvents.poll(DEFAULT_TIMEOUT_MS) { it is T && predicate(it) }
}
@Test
fun testDeclareNetworkRequestUnfulfillable() {
val provider = createNetworkProvider()
mCm.registerNetworkProvider(provider)
val specifier = StringNetworkSpecifier(UUID.randomUUID().toString())
val nr: NetworkRequest = NetworkRequest.Builder()
.addTransportType(TRANSPORT_TEST)
.setNetworkSpecifier(specifier)
.build()
val cb = TestNetworkCallback()
mCm.requestNetwork(nr, cb)
provider.declareNetworkRequestUnfulfillable(nr)
cb.expectCallback<OnUnavailable>() { nr.getNetworkSpecifier() == specifier }
mCm.unregisterNetworkProvider(provider)
}
}

View File

@@ -5969,6 +5969,9 @@ public class ConnectivityServiceTest {
final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
final String kNat64PrefixString = "2001:db8:64:64:64:64::";
final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
final String kOtherNat64PrefixString = "64:ff9b::";
final IpPrefix kOtherNat64Prefix = new IpPrefix(
InetAddress.getByName(kOtherNat64PrefixString), 96);
final RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, myIpv6.getAddress(),
MOBILE_IFNAME);
final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME);
@@ -6082,6 +6085,24 @@ public class ConnectivityServiceTest {
}
reset(mMockNetd);
// Change the NAT64 prefix without first removing it.
// Expect clatd to be stopped and started with the new prefix.
mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
kOtherNat64PrefixString, 96);
networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
(lp) -> lp.getStackedLinks().size() == 0);
verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
assertRoutesRemoved(cellNetId, stackedDefault);
verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kOtherNat64Prefix.toString());
networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
(lp) -> lp.getNat64Prefix().equals(kOtherNat64Prefix));
clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
(lp) -> lp.getStackedLinks().size() == 1);
assertRoutesAdded(cellNetId, stackedDefault);
reset(mMockNetd);
// Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
// linkproperties are cleaned up.
cellLp.addLinkAddress(myIpv4);
@@ -6096,7 +6117,7 @@ public class ConnectivityServiceTest {
networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
LinkProperties expected = new LinkProperties(cellLp);
expected.setNat64Prefix(kNat64Prefix);
expected.setNat64Prefix(kOtherNat64Prefix);
assertEquals(expected, actualLpAfterIpv4);
assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
assertRoutesRemoved(cellNetId, stackedDefault);
@@ -6115,7 +6136,7 @@ public class ConnectivityServiceTest {
// Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
kNat64PrefixString, 96);
kOtherNat64PrefixString, 96);
networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
(lp) -> lp.getNat64Prefix() == null);

View File

@@ -18,6 +18,8 @@ package com.android.server.connectivity;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import static android.net.NetworkCapabilities.MAX_TRANSPORT;
import static android.net.NetworkCapabilities.MIN_TRANSPORT;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE;
@@ -30,6 +32,7 @@ import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.reset;
@@ -44,16 +47,19 @@ import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.ResolverOptionsParcel;
import android.net.ResolverParamsParcel;
import android.net.RouteInfo;
import android.net.shared.PrivateDnsConfig;
import android.provider.Settings;
import android.test.mock.MockContentResolver;
import android.util.SparseArray;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.MessageUtils;
import com.android.internal.util.test.FakeSettingsProvider;
import org.junit.Before;
@@ -354,4 +360,23 @@ public class DnsManagerTest {
expectedParams.resolverOptions = new ResolverOptionsParcel();
assertResolverParamsEquals(actualParams, expectedParams);
}
@Test
public void testTransportTypesEqual() throws Exception {
SparseArray<String> ncTransTypes = MessageUtils.findMessageNames(
new Class[] { NetworkCapabilities.class }, new String[]{ "TRANSPORT_" });
SparseArray<String> dnsTransTypes = MessageUtils.findMessageNames(
new Class[] { IDnsResolver.class }, new String[]{ "TRANSPORT_" });
assertEquals(0, MIN_TRANSPORT);
assertEquals(MAX_TRANSPORT + 1, ncTransTypes.size());
// TRANSPORT_UNKNOWN in IDnsResolver is defined to -1 and only for resolver.
assertEquals("TRANSPORT_UNKNOWN", dnsTransTypes.get(-1));
assertEquals(ncTransTypes.size(), dnsTransTypes.size() - 1);
for (int i = MIN_TRANSPORT; i < MAX_TRANSPORT; i++) {
String name = ncTransTypes.get(i, null);
assertNotNull("Could not find NetworkCapabilies.TRANSPORT_* constant equal to "
+ i, name);
assertEquals(name, dnsTransTypes.get(i));
}
}
}