summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/net/Ikev2VpnProfile.java45
-rw-r--r--core/java/com/android/internal/net/VpnProfile.java32
-rw-r--r--data/fonts/Android.bp36
-rw-r--r--data/fonts/Android.mk57
-rw-r--r--native/android/Android.bp8
-rw-r--r--native/android/trace/android/trace.h29
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java33
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java5
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java25
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java4
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java31
-rw-r--r--telephony/common/com/android/internal/telephony/CellBroadcastUtils.java65
-rw-r--r--tests/net/java/com/android/internal/net/VpnProfileTest.java47
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java2
14 files changed, 269 insertions, 150 deletions
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index 836624beb3b2..407ff04dc4a3 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -101,6 +101,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
private final boolean mIsBypassable; // Defaults in builder
private final boolean mIsMetered; // Defaults in builder
private final int mMaxMtu; // Defaults in builder
+ private final boolean mIsRestrictedToTestNetworks;
private Ikev2VpnProfile(
int type,
@@ -116,7 +117,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
@NonNull List<String> allowedAlgorithms,
boolean isBypassable,
boolean isMetered,
- int maxMtu) {
+ int maxMtu,
+ boolean restrictToTestNetworks) {
super(type);
checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address");
@@ -140,6 +142,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
mIsBypassable = isBypassable;
mIsMetered = isMetered;
mMaxMtu = maxMtu;
+ mIsRestrictedToTestNetworks = restrictToTestNetworks;
validate();
}
@@ -329,6 +332,15 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
return mMaxMtu;
}
+ /**
+ * Returns whether or not this VPN profile is restricted to test networks.
+ *
+ * @hide
+ */
+ public boolean isRestrictedToTestNetworks() {
+ return mIsRestrictedToTestNetworks;
+ }
+
@Override
public int hashCode() {
return Objects.hash(
@@ -345,7 +357,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
mAllowedAlgorithms,
mIsBypassable,
mIsMetered,
- mMaxMtu);
+ mMaxMtu,
+ mIsRestrictedToTestNetworks);
}
@Override
@@ -368,7 +381,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
&& Objects.equals(mAllowedAlgorithms, other.mAllowedAlgorithms)
&& mIsBypassable == other.mIsBypassable
&& mIsMetered == other.mIsMetered
- && mMaxMtu == other.mMaxMtu;
+ && mMaxMtu == other.mMaxMtu
+ && mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks;
}
/**
@@ -381,7 +395,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
*/
@NonNull
public VpnProfile toVpnProfile() throws IOException, GeneralSecurityException {
- final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */);
+ final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */,
+ mIsRestrictedToTestNetworks);
profile.type = mType;
profile.server = mServerAddr;
profile.ipsecIdentifier = mUserIdentity;
@@ -449,6 +464,9 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
builder.setBypassable(profile.isBypassable);
builder.setMetered(profile.isMetered);
builder.setMaxMtu(profile.maxMtu);
+ if (profile.isRestrictedToTestNetworks) {
+ builder.restrictToTestNetworks();
+ }
switch (profile.type) {
case TYPE_IKEV2_IPSEC_USER_PASS:
@@ -621,6 +639,7 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
private boolean mIsBypassable = false;
private boolean mIsMetered = true;
private int mMaxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT;
+ private boolean mIsRestrictedToTestNetworks = false;
/**
* Creates a new builder with the basic parameters of an IKEv2/IPsec VPN.
@@ -842,6 +861,21 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
}
/**
+ * Restricts this profile to use test networks (only).
+ *
+ * <p>This method is for testing only, and must not be used by apps. Calling
+ * provisionVpnProfile() with a profile where test-network usage is enabled will require the
+ * MANAGE_TEST_NETWORKS permission.
+ *
+ * @hide
+ */
+ @NonNull
+ public Builder restrictToTestNetworks() {
+ mIsRestrictedToTestNetworks = true;
+ return this;
+ }
+
+ /**
* Validates, builds and provisions the VpnProfile.
*
* @throws IllegalArgumentException if any of the required keys or values were invalid
@@ -862,7 +896,8 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
mAllowedAlgorithms,
mIsBypassable,
mIsMetered,
- mMaxMtu);
+ mMaxMtu,
+ mIsRestrictedToTestNetworks);
}
}
}
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index 829bd8a5a2a7..8ea5aa815a1c 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -136,13 +136,19 @@ public final class VpnProfile implements Cloneable, Parcelable {
public boolean isMetered = false; // 21
public int maxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT; // 22
public boolean areAuthParamsInline = false; // 23
+ public final boolean isRestrictedToTestNetworks; // 24
// Helper fields.
@UnsupportedAppUsage
public transient boolean saveLogin = false;
public VpnProfile(String key) {
+ this(key, false);
+ }
+
+ public VpnProfile(String key, boolean isRestrictedToTestNetworks) {
this.key = key;
+ this.isRestrictedToTestNetworks = isRestrictedToTestNetworks;
}
@UnsupportedAppUsage
@@ -171,6 +177,7 @@ public final class VpnProfile implements Cloneable, Parcelable {
isMetered = in.readBoolean();
maxMtu = in.readInt();
areAuthParamsInline = in.readBoolean();
+ isRestrictedToTestNetworks = in.readBoolean();
}
/**
@@ -220,6 +227,7 @@ public final class VpnProfile implements Cloneable, Parcelable {
out.writeBoolean(isMetered);
out.writeInt(maxMtu);
out.writeBoolean(areAuthParamsInline);
+ out.writeBoolean(isRestrictedToTestNetworks);
}
/**
@@ -237,12 +245,21 @@ public final class VpnProfile implements Cloneable, Parcelable {
String[] values = new String(value, StandardCharsets.UTF_8).split(VALUE_DELIMITER, -1);
// Acceptable numbers of values are:
// 14-19: Standard profile, with option for serverCert, proxy
- // 24: Standard profile with serverCert, proxy and platform-VPN parameters.
- if ((values.length < 14 || values.length > 19) && values.length != 24) {
+ // 24: Standard profile with serverCert, proxy and platform-VPN parameters
+ // 25: Standard profile with platform-VPN parameters and isRestrictedToTestNetworks
+ if ((values.length < 14 || values.length > 19)
+ && values.length != 24 && values.length != 25) {
return null;
}
- VpnProfile profile = new VpnProfile(key);
+ final boolean isRestrictedToTestNetworks;
+ if (values.length >= 25) {
+ isRestrictedToTestNetworks = Boolean.parseBoolean(values[24]);
+ } else {
+ isRestrictedToTestNetworks = false;
+ }
+
+ VpnProfile profile = new VpnProfile(key, isRestrictedToTestNetworks);
profile.name = values[0];
profile.type = Integer.parseInt(values[1]);
if (profile.type < 0 || profile.type > TYPE_MAX) {
@@ -283,6 +300,8 @@ public final class VpnProfile implements Cloneable, Parcelable {
profile.areAuthParamsInline = Boolean.parseBoolean(values[23]);
}
+ // isRestrictedToTestNetworks (values[24]) assigned as part of the constructor
+
profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty();
return profile;
} catch (Exception e) {
@@ -330,6 +349,7 @@ public final class VpnProfile implements Cloneable, Parcelable {
builder.append(VALUE_DELIMITER).append(isMetered);
builder.append(VALUE_DELIMITER).append(maxMtu);
builder.append(VALUE_DELIMITER).append(areAuthParamsInline);
+ builder.append(VALUE_DELIMITER).append(isRestrictedToTestNetworks);
return builder.toString().getBytes(StandardCharsets.UTF_8);
}
@@ -421,7 +441,8 @@ public final class VpnProfile implements Cloneable, Parcelable {
return Objects.hash(
key, type, server, username, password, dnsServers, searchDomains, routes, mppe,
l2tpSecret, ipsecIdentifier, ipsecSecret, ipsecUserCert, ipsecCaCert, ipsecServerCert,
- proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline);
+ proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline,
+ isRestrictedToTestNetworks);
}
/** Checks VPN profiles for interior equality. */
@@ -453,7 +474,8 @@ public final class VpnProfile implements Cloneable, Parcelable {
&& isBypassable == other.isBypassable
&& isMetered == other.isMetered
&& maxMtu == other.maxMtu
- && areAuthParamsInline == other.areAuthParamsInline;
+ && areAuthParamsInline == other.areAuthParamsInline
+ && isRestrictedToTestNetworks == other.isRestrictedToTestNetworks;
}
@NonNull
diff --git a/data/fonts/Android.bp b/data/fonts/Android.bp
new file mode 100644
index 000000000000..94e6a8096849
--- /dev/null
+++ b/data/fonts/Android.bp
@@ -0,0 +1,36 @@
+// Copyright (C) 2011 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.
+
+prebuilt_font {
+ name: "DroidSansMono.ttf",
+ src: "DroidSansMono.ttf",
+ required: [
+ "DroidSans.ttf",
+ "DroidSans-Bold.ttf",
+ ],
+}
+
+prebuilt_font {
+ name: "AndroidClock.ttf",
+ src: "AndroidClock.ttf",
+}
+
+/////////////////////////////////
+// Copies the font configuration file into system/etc for the product as fonts.xml.
+// Additional fonts should be installed to /product/fonts/ alongside a corresponding
+// fonts_customiztion.xml in /product/etc/
+prebuilt_etc {
+ name: "fonts.xml",
+ src: "fonts.xml",
+}
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 4226e0882538..e22b72346249 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -12,9 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# We have to use BUILD_PREBUILT instead of PRODUCT_COPY_FIES,
-# because MINIMAL_FONT_FOOTPRINT is only available in Android.mks.
-
LOCAL_PATH := $(call my-dir)
##########################################
@@ -37,61 +34,7 @@ endef
##########################################
$(eval $(call create-font-symlink,DroidSans.ttf,Roboto-Regular.ttf))
$(eval $(call create-font-symlink,DroidSans-Bold.ttf,Roboto-Bold.ttf))
-$(eval $(call create-font-symlink,DroidSerif-Regular.ttf,NotoSerif-Regular.ttf))
-$(eval $(call create-font-symlink,DroidSerif-Bold.ttf,NotoSerif-Bold.ttf))
-$(eval $(call create-font-symlink,DroidSerif-Italic.ttf,NotoSerif-Italic.ttf))
-$(eval $(call create-font-symlink,DroidSerif-BoldItalic.ttf,NotoSerif-BoldItalic.ttf))
-
-extra_font_files := \
- DroidSans.ttf \
- DroidSans-Bold.ttf
-
-################################
-# Use DroidSansMono to hang extra_font_files on
-include $(CLEAR_VARS)
-LOCAL_MODULE := DroidSansMono.ttf
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts
-LOCAL_REQUIRED_MODULES := $(extra_font_files)
-include $(BUILD_PREBUILT)
-extra_font_files :=
-
-################################
-# Build the rest of font files as prebuilt.
-
-# $(1): The source file name in LOCAL_PATH.
-# It also serves as the module name and the dest file name.
-define build-one-font-module
-$(eval include $(CLEAR_VARS))\
-$(eval LOCAL_MODULE := $(1))\
-$(eval LOCAL_SRC_FILES := $(1))\
-$(eval LOCAL_MODULE_CLASS := ETC)\
-$(eval LOCAL_MODULE_TAGS := optional)\
-$(eval LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts)\
-$(eval include $(BUILD_PREBUILT))
-endef
-
-font_src_files := \
- AndroidClock.ttf
-
-$(foreach f, $(font_src_files), $(call build-one-font-module, $(f)))
-
-build-one-font-module :=
-font_src_files :=
-
-################################
-# Copies the font configuration file into system/etc for the product as fonts.xml.
-# Additional fonts should be installed to /product/fonts/ alongside a corresponding
-# fonts_customiztion.xml in /product/etc/
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := fonts.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_PREBUILT_MODULE_FILE := frameworks/base/data/fonts/fonts.xml
-include $(BUILD_PREBUILT)
# Run sanity tests on fonts on checkbuild
checkbuild: fontchain_lint
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 9f52d856ea75..8f36decec400 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -93,14 +93,6 @@ cc_library_shared {
},
}
-// Header-only library used for atrace in platform NDK builds
-cc_library_headers {
- name: "libandroid_trace",
- host_supported: true,
- vendor_available: true,
- export_include_dirs: ["trace"],
-}
-
// Network library.
cc_library_shared {
name: "libandroid_net",
diff --git a/native/android/trace/android/trace.h b/native/android/trace/android/trace.h
deleted file mode 100644
index 4e569e566bc2..000000000000
--- a/native/android/trace/android/trace.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.
- */
-#ifndef ANDROID_ATRACE_HEADERS_H
-#define ANDROID_ATRACE_HEADERS_H
-
-#include <cutils/trace.h>
-
-inline void ATrace_beginSection(const char* sectionName) {
- atrace_begin(ATRACE_TAG_APP, sectionName);
-}
-
-inline void ATrace_endSection() {
- atrace_end(ATRACE_TAG_APP);
-}
-
-#endif // ANDROID_ATRACE_HEADERS_H
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
index 91a6e29a05da..48a600dfe6e1 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
@@ -132,7 +132,7 @@ public class TetheringConfiguration {
isDunRequired = checkDunRequired(ctx);
chooseUpstreamAutomatically = getResourceBoolean(
- res, R.bool.config_tether_upstream_automatic, false /** default value */);
+ res, R.bool.config_tether_upstream_automatic, false /** defaultValue */);
preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired);
legacyDhcpRanges = getLegacyDhcpRanges(res);
@@ -375,30 +375,31 @@ public class TetheringConfiguration {
// Priority 1: Device config
// Priority 2: Resource config
// Priority 3: Default value
- final boolean resourceValue = getResourceBoolean(
+ final boolean defaultValue = getResourceBoolean(
res, R.bool.config_tether_enable_bpf_offload, true /** default value */);
- // Due to the limitation of static mock for testing, using #getProperty directly instead
- // of getDeviceConfigBoolean. getDeviceConfigBoolean is not invoked because it uses
- // #getBoolean to get the boolean device config. The test can't know that the returned
- // boolean value comes from device config or default value (because of null property
- // string). Because the test would like to verify null property boolean string case,
- // use DeviceConfig.getProperty here. See also the test case testBpfOffload{*} in
- // TetheringConfigurationTest.java.
- final String value = DeviceConfig.getProperty(
- NAMESPACE_CONNECTIVITY, OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD);
- return (value != null) ? Boolean.parseBoolean(value) : resourceValue;
+ return getDeviceConfigBoolean(OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD, defaultValue);
}
private boolean getEnableLegacyDhcpServer(final Resources res) {
return getResourceBoolean(
- res, R.bool.config_tether_enable_legacy_dhcp_server, false /** default value */)
- || getDeviceConfigBoolean(TETHER_ENABLE_LEGACY_DHCP_SERVER);
+ res, R.bool.config_tether_enable_legacy_dhcp_server, false /** defaultValue */)
+ || getDeviceConfigBoolean(
+ TETHER_ENABLE_LEGACY_DHCP_SERVER, false /** defaultValue */);
+ }
+
+ private boolean getDeviceConfigBoolean(final String name, final boolean defaultValue) {
+ // Due to the limitation of static mock for testing, using #getDeviceConfigProperty instead
+ // of DeviceConfig#getBoolean. If using #getBoolean here, the test can't know that the
+ // returned boolean value comes from device config or default value (because of null
+ // property string). See the test case testBpfOffload{*} in TetheringConfigurationTest.java.
+ final String value = getDeviceConfigProperty(name);
+ return value != null ? Boolean.parseBoolean(value) : defaultValue;
}
@VisibleForTesting
- protected boolean getDeviceConfigBoolean(final String name) {
- return DeviceConfig.getBoolean(NAMESPACE_CONNECTIVITY, name, false /** defaultValue */);
+ protected String getDeviceConfigProperty(String name) {
+ return DeviceConfig.getProperty(NAMESPACE_CONNECTIVITY, name);
}
private Resources getResources(Context ctx, int subId) {
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java
index cdd0e243e31f..72fa916b9e42 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java
@@ -147,9 +147,8 @@ public final class EntitlementManagerTest {
doReturn(false).when(
() -> SystemProperties.getBoolean(
eq(EntitlementManager.DISABLE_PROVISIONING_SYSPROP_KEY), anyBoolean()));
- doReturn(false).when(
- () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY),
- eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean()));
+ doReturn(null).when(
+ () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY), anyString()));
when(mResources.getStringArray(R.array.config_tether_dhcp_range))
.thenReturn(new String[0]);
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
index fbfa871f76c6..1999ad786ed4 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
@@ -30,7 +30,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSess
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
@@ -109,9 +108,9 @@ public class TetheringConfigurationTest {
.mockStatic(DeviceConfig.class)
.strictness(Strictness.WARN)
.startMocking();
- doReturn(false).when(
- () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY),
- eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean()));
+ doReturn(null).when(
+ () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
+ eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER)));
when(mResources.getStringArray(R.array.config_tether_dhcp_range)).thenReturn(
new String[0]);
@@ -328,9 +327,9 @@ public class TetheringConfigurationTest {
public void testNewDhcpServerDisabled() {
when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
true);
- doReturn(false).when(
- () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY),
- eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean()));
+ doReturn("false").when(
+ () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
+ eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER)));
final TetheringConfiguration enableByRes =
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -338,9 +337,9 @@ public class TetheringConfigurationTest {
when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
false);
- doReturn(true).when(
- () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY),
- eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean()));
+ doReturn("true").when(
+ () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
+ eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER)));
final TetheringConfiguration enableByDevConfig =
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -351,9 +350,9 @@ public class TetheringConfigurationTest {
public void testNewDhcpServerEnabled() {
when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
false);
- doReturn(false).when(
- () -> DeviceConfig.getBoolean(eq(NAMESPACE_CONNECTIVITY),
- eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER), anyBoolean()));
+ doReturn("false").when(
+ () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
+ eq(TetheringConfiguration.TETHER_ENABLE_LEGACY_DHCP_SERVER)));
final TetheringConfiguration cfg =
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index b665acc2718d..7734a3c61eaf 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -312,8 +312,8 @@ public class TetheringTest {
}
@Override
- protected boolean getDeviceConfigBoolean(final String name) {
- return false;
+ protected String getDeviceConfigProperty(final String name) {
+ return null;
}
@Override
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 0114b5bb1331..730da28ba8a2 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -65,6 +65,7 @@ import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkProvider;
+import android.net.NetworkRequest;
import android.net.RouteInfo;
import android.net.UidRange;
import android.net.VpnManager;
@@ -2225,12 +2226,27 @@ public class Vpn {
@Override
public void run() {
- // Explicitly use only the network that ConnectivityService thinks is the "best." In
- // other words, only ever use the currently selected default network. This does mean
- // that in both onLost() and onConnected(), any old sessions MUST be torn down. This
- // does NOT include VPNs.
+ // Unless the profile is restricted to test networks, explicitly use only the network
+ // that ConnectivityService thinks is the "best." In other words, only ever use the
+ // currently selected default network. This does mean that in both onLost() and
+ // onConnected(), any old sessions MUST be torn down. This does NOT include VPNs.
+ //
+ // When restricted to test networks, select any network with TRANSPORT_TEST. Since the
+ // creator of the profile and the test network creator both have MANAGE_TEST_NETWORKS,
+ // this is considered safe.
final ConnectivityManager cm = ConnectivityManager.from(mContext);
- cm.requestNetwork(cm.getDefaultRequest(), mNetworkCallback);
+ final NetworkRequest req;
+
+ if (mProfile.isRestrictedToTestNetworks()) {
+ req = new NetworkRequest.Builder()
+ .clearCapabilities()
+ .addTransportType(NetworkCapabilities.TRANSPORT_TEST)
+ .build();
+ } else {
+ req = cm.getDefaultRequest();
+ }
+
+ cm.requestNetwork(req, mNetworkCallback);
}
private boolean isActiveNetwork(@Nullable Network network) {
@@ -2868,6 +2884,11 @@ public class Vpn {
verifyCallingUidAndPackage(packageName);
enforceNotRestrictedUser();
+ if (profile.isRestrictedToTestNetworks) {
+ mContext.enforceCallingPermission(Manifest.permission.MANAGE_TEST_NETWORKS,
+ "Test-mode profiles require the MANAGE_TEST_NETWORKS permission");
+ }
+
final byte[] encodedProfile = profile.encode();
if (encodedProfile.length > MAX_VPN_PROFILE_SIZE_BYTES) {
throw new IllegalArgumentException("Profile too big");
diff --git a/telephony/common/com/android/internal/telephony/CellBroadcastUtils.java b/telephony/common/com/android/internal/telephony/CellBroadcastUtils.java
new file mode 100644
index 000000000000..6c6375586225
--- /dev/null
+++ b/telephony/common/com/android/internal/telephony/CellBroadcastUtils.java
@@ -0,0 +1,65 @@
+/*
+ * 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 com.android.internal.telephony;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.provider.Telephony;
+import android.text.TextUtils;
+import android.util.Log;
+
+/**
+ * This class provides utility functions related to CellBroadcast.
+ */
+public class CellBroadcastUtils {
+ private static final String TAG = "CellBroadcastUtils";
+ private static final boolean VDBG = false;
+
+ /**
+ * Utility method to query the default CBR's package name.
+ */
+ public static String getDefaultCellBroadcastReceiverPackageName(Context context) {
+ PackageManager packageManager = context.getPackageManager();
+ ResolveInfo resolveInfo = packageManager.resolveActivity(
+ new Intent(Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION),
+ PackageManager.MATCH_SYSTEM_ONLY);
+ String packageName;
+
+ if (resolveInfo == null) {
+ Log.e(TAG, "getDefaultCellBroadcastReceiverPackageName: no package found");
+ return null;
+ }
+
+ packageName = resolveInfo.activityInfo.applicationInfo.packageName;
+
+ if (VDBG) {
+ Log.d(TAG, "getDefaultCellBroadcastReceiverPackageName: found package: " + packageName);
+ }
+
+ if (TextUtils.isEmpty(packageName) || packageManager.checkPermission(
+ android.Manifest.permission.READ_CELL_BROADCASTS, packageName)
+ == PackageManager.PERMISSION_DENIED) {
+ Log.e(TAG, "getDefaultCellBroadcastReceiverPackageName: returning null; "
+ + "permission check failed for : " + packageName);
+ return null;
+ }
+
+ return packageName;
+ }
+}
diff --git a/tests/net/java/com/android/internal/net/VpnProfileTest.java b/tests/net/java/com/android/internal/net/VpnProfileTest.java
index ceca6f028866..e5daa71c30ea 100644
--- a/tests/net/java/com/android/internal/net/VpnProfileTest.java
+++ b/tests/net/java/com/android/internal/net/VpnProfileTest.java
@@ -33,7 +33,9 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
/** Unit tests for {@link VpnProfile}. */
@SmallTest
@@ -41,6 +43,9 @@ import java.util.Arrays;
public class VpnProfileTest {
private static final String DUMMY_PROFILE_KEY = "Test";
+ private static final int ENCODED_INDEX_AUTH_PARAMS_INLINE = 23;
+ private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24;
+
@Test
public void testDefaults() throws Exception {
final VpnProfile p = new VpnProfile(DUMMY_PROFILE_KEY);
@@ -67,10 +72,11 @@ public class VpnProfileTest {
assertFalse(p.isMetered);
assertEquals(1360, p.maxMtu);
assertFalse(p.areAuthParamsInline);
+ assertFalse(p.isRestrictedToTestNetworks);
}
private VpnProfile getSampleIkev2Profile(String key) {
- final VpnProfile p = new VpnProfile(key);
+ final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */);
p.name = "foo";
p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
@@ -116,7 +122,7 @@ public class VpnProfileTest {
@Test
public void testParcelUnparcel() {
- assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 22);
+ assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23);
}
@Test
@@ -159,14 +165,41 @@ public class VpnProfileTest {
assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooManyValues));
}
+ private String getEncodedDecodedIkev2ProfileMissingValues(int... missingIndices) {
+ // Sort to ensure when we remove, we can do it from greatest first.
+ Arrays.sort(missingIndices);
+
+ final String encoded = new String(getSampleIkev2Profile(DUMMY_PROFILE_KEY).encode());
+ final List<String> parts =
+ new ArrayList<>(Arrays.asList(encoded.split(VpnProfile.VALUE_DELIMITER)));
+
+ // Remove from back first to ensure indexing is consistent.
+ for (int i = missingIndices.length - 1; i >= 0; i--) {
+ parts.remove(missingIndices[i]);
+ }
+
+ return String.join(VpnProfile.VALUE_DELIMITER, parts.toArray(new String[0]));
+ }
+
@Test
public void testEncodeDecodeInvalidNumberOfValues() {
- final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
- final String encoded = new String(profile.encode());
- final byte[] tooFewValues =
- encoded.substring(0, encoded.lastIndexOf(VpnProfile.VALUE_DELIMITER)).getBytes();
+ final String tooFewValues =
+ getEncodedDecodedIkev2ProfileMissingValues(
+ ENCODED_INDEX_AUTH_PARAMS_INLINE,
+ ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */);
- assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues));
+ assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()));
+ }
+
+ @Test
+ public void testEncodeDecodeMissingIsRestrictedToTestNetworks() {
+ final String tooFewValues =
+ getEncodedDecodedIkev2ProfileMissingValues(
+ ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */);
+
+ // Verify decoding without isRestrictedToTestNetworks defaults to false
+ final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
+ assertFalse(decoded.isRestrictedToTestNetworks);
}
@Test
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 5e2ef0476ce8..e66e26452602 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -5494,6 +5494,8 @@ public class ConnectivityServiceTest {
assertFalse(nc.hasTransport(TRANSPORT_WIFI));
// For safety reasons a VPN without underlying networks is considered metered.
assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
+ // A VPN without underlying networks is not suspended.
+ assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
// Connect cell and use it as an underlying network.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);