Migrate framework-connectivity internal resources

Use ServiceConnectivityResources instead.
Start by creating resources in the ServiceConnectivityResources package
to match the internal configuration, and common overlays.

Bug: 182125649
Test: device boots, has connectivity
Change-Id: I77a3efca2cd644f9828db1ed5d3cae8070fb8363
Merged-In: I77a3efca2cd644f9828db1ed5d3cae8070fb8363
This commit is contained in:
Remi NGUYEN VAN
2021-03-17 23:14:53 +09:00
committed by Lorenzo Colitti
parent e2139a0be2
commit 0d4c78d80d
14 changed files with 269 additions and 35 deletions

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.server.connectivity;
package android.net;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
@@ -27,13 +27,14 @@ import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.util.Log;
import com.android.server.ConnectivityService;
import com.android.internal.annotations.VisibleForTesting;
import java.util.List;
/**
* Utility to obtain the {@link ConnectivityService} {@link Resources}, in the
* Utility to obtain the {@link com.android.server.ConnectivityService} {@link Resources}, in the
* ServiceConnectivityResources APK.
* @hide
*/
public class ConnectivityResources {
private static final String RESOURCES_APK_INTENT =
@@ -44,18 +45,35 @@ public class ConnectivityResources {
private final Context mContext;
@Nullable
private Resources mResources = null;
private Context mResourcesContext = null;
@Nullable
private static Context sTestResourcesContext = null;
public ConnectivityResources(Context context) {
mContext = context;
}
/**
* Get the {@link Resources} of the ServiceConnectivityResources APK.
* Convenience method to mock all resources for the duration of a test.
*
* Call with a null context to reset after the test.
*/
public synchronized Resources get() {
if (mResources != null) {
return mResources;
@VisibleForTesting
public static void setResourcesContextForTest(@Nullable Context testContext) {
sTestResourcesContext = testContext;
}
/**
* Get the {@link Context} of the resources package.
*/
public synchronized Context getResourcesContext() {
if (sTestResourcesContext != null) {
return sTestResourcesContext;
}
if (mResourcesContext != null) {
return mResourcesContext;
}
final List<ResolveInfo> pkgs = mContext.getPackageManager()
@@ -77,7 +95,14 @@ public class ConnectivityResources {
throw new IllegalStateException("Resolved package not found", e);
}
mResources = pkgContext.getResources();
return mResources;
mResourcesContext = pkgContext;
return pkgContext;
}
/**
* Get the {@link Resources} of the ServiceConnectivityResources APK.
*/
public Resources get() {
return getResourcesContext().getResources();
}
}

View File

@@ -19,12 +19,12 @@ package android.net.apf;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.res.Resources;
import android.net.ConnectivityResources;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.R;
/**
* APF program support capabilities. APF stands for Android Packet Filtering and it is a flexible
* way to drop unwanted network packets to save power.
@@ -36,6 +36,8 @@ import com.android.internal.R;
*/
@SystemApi
public final class ApfCapabilities implements Parcelable {
private static ConnectivityResources sResources;
/**
* Version of APF instruction set supported for packet filtering. 0 indicates no support for
* packet filtering using APF programs.
@@ -65,6 +67,14 @@ public final class ApfCapabilities implements Parcelable {
apfPacketFormat = in.readInt();
}
@NonNull
private static synchronized ConnectivityResources getResources(@NonNull Context ctx) {
if (sResources == null) {
sResources = new ConnectivityResources(ctx);
}
return sResources;
}
@Override
public int describeContents() {
@@ -121,13 +131,43 @@ public final class ApfCapabilities implements Parcelable {
* @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames.
*/
public static boolean getApfDrop8023Frames() {
return Resources.getSystem().getBoolean(R.bool.config_apfDrop802_3Frames);
// TODO(b/183076074): remove reading resources from system resources
final Resources systemRes = Resources.getSystem();
final int id = systemRes.getIdentifier("config_apfDrop802_3Frames", "bool", "android");
return systemRes.getBoolean(id);
}
/**
* @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames.
* @hide
*/
public static boolean getApfDrop8023Frames(@NonNull Context context) {
final ConnectivityResources res = getResources(context);
// TODO(b/183076074): use R.bool.config_apfDrop802_3Frames directly
final int id = res.get().getIdentifier("config_apfDrop802_3Frames", "bool",
res.getResourcesContext().getPackageName());
return res.get().getBoolean(id);
}
/**
* @return An array of denylisted EtherType, packets with EtherTypes within it will be dropped.
*/
public static @NonNull int[] getApfEtherTypeBlackList() {
return Resources.getSystem().getIntArray(R.array.config_apfEthTypeBlackList);
// TODO(b/183076074): remove reading resources from system resources
final Resources systemRes = Resources.getSystem();
final int id = systemRes.getIdentifier("config_apfEthTypeBlackList", "array", "android");
return systemRes.getIntArray(id);
}
/**
* @return An array of denylisted EtherType, packets with EtherTypes within it will be dropped.
* @hide
*/
public static @NonNull int[] getApfEtherTypeDenyList(@NonNull Context context) {
final ConnectivityResources res = getResources(context);
// TODO(b/183076074): use R.array.config_apfEthTypeDenyList directly
final int id = res.get().getIdentifier("config_apfEthTypeDenyList", "array",
res.getResourcesContext().getPackageName());
return res.get().getIntArray(id);
}
}

View File

@@ -19,12 +19,11 @@ package android.net.util;
import android.annotation.NonNull;
import android.content.Context;
import android.content.res.Resources;
import android.net.ConnectivityResources;
import android.net.NetworkCapabilities;
import android.text.TextUtils;
import android.util.AndroidRuntimeException;
import com.android.internal.R;
/**
* Collection of utilities for socket keepalive offload.
*
@@ -52,8 +51,11 @@ public final class KeepaliveUtils {
public static int[] getSupportedKeepalives(@NonNull Context context) {
String[] res = null;
try {
res = context.getResources().getStringArray(
R.array.config_networkSupportedKeepaliveCount);
final ConnectivityResources connRes = new ConnectivityResources(context);
// TODO: use R.id.config_networkSupportedKeepaliveCount directly
final int id = connRes.get().getIdentifier("config_networkSupportedKeepaliveCount",
"array", connRes.getResourcesContext().getPackageName());
res = new ConnectivityResources(context).get().getStringArray(id);
} catch (Resources.NotFoundException unused) {
}
if (res == null) throw new KeepaliveDeviceConfigurationException("invalid resource");

View File

@@ -27,6 +27,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.ConnectivityResources;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;
@@ -35,7 +36,6 @@ import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import java.util.Arrays;
@@ -64,6 +64,7 @@ public class MultinetworkPolicyTracker {
private static String TAG = MultinetworkPolicyTracker.class.getSimpleName();
private final Context mContext;
private final ConnectivityResources mResources;
private final Handler mHandler;
private final Runnable mAvoidBadWifiCallback;
private final List<Uri> mSettingsUris;
@@ -107,6 +108,7 @@ public class MultinetworkPolicyTracker {
public MultinetworkPolicyTracker(Context ctx, Handler handler, Runnable avoidBadWifiCallback) {
mContext = ctx;
mResources = new ConnectivityResources(ctx);
mHandler = handler;
mAvoidBadWifiCallback = avoidBadWifiCallback;
mSettingsUris = Arrays.asList(
@@ -160,12 +162,16 @@ public class MultinetworkPolicyTracker {
* Whether the device or carrier configuration disables avoiding bad wifi by default.
*/
public boolean configRestrictsAvoidBadWifi() {
return (getResourcesForActiveSubId().getInteger(R.integer.config_networkAvoidBadWifi) == 0);
// TODO: use R.integer.config_networkAvoidBadWifi directly
final int id = mResources.get().getIdentifier("config_networkAvoidBadWifi",
"integer", mResources.getResourcesContext().getPackageName());
return (getResourcesForActiveSubId().getInteger(id) == 0);
}
@NonNull
private Resources getResourcesForActiveSubId() {
return SubscriptionManager.getResourcesForSubId(mContext, mActiveSubId);
return SubscriptionManager.getResourcesForSubId(
mResources.getResourcesContext(), mActiveSubId);
}
/**
@@ -205,8 +211,10 @@ public class MultinetworkPolicyTracker {
* The default (device and carrier-dependent) value for metered multipath preference.
*/
public int configMeteredMultipathPreference() {
return mContext.getResources().getInteger(
R.integer.config_networkMeteredMultipathPreference);
// TODO: use R.integer.config_networkMeteredMultipathPreference directly
final int id = mResources.get().getIdentifier("config_networkMeteredMultipathPreference",
"integer", mResources.getResourcesContext().getPackageName());
return mResources.get().getInteger(id);
}
public void updateMeteredMultipathPreference() {

View File

@@ -21,7 +21,7 @@ package {
android_app {
name: "ServiceConnectivityResources",
sdk_version: "system_current",
sdk_version: "module_current",
resource_dirs: [
"res",
],

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 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.
-->
<!-- Configuration values for ConnectivityService
DO NOT EDIT THIS FILE for specific device configuration; instead, use a Runtime Resources
Overlay package following the overlayable.xml configuration in the same directory:
https://source.android.com/devices/architecture/rros -->
<resources>
<!-- Whether the device should automatically switch away from Wi-Fi networks that lose
Internet access. Actual device behaviour is controlled by
Settings.Global.NETWORK_AVOID_BAD_WIFI. This is the default value of that setting. -->
<integer translatable="false" name="config_networkAvoidBadWifi">0</integer>
</resources>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 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.
-->
<!-- Configuration values for ConnectivityService
DO NOT EDIT THIS FILE for specific device configuration; instead, use a Runtime Resources
Overlay package following the overlayable.xml configuration in the same directory:
https://source.android.com/devices/architecture/rros -->
<resources>
<!-- Whether the device should automatically switch away from Wi-Fi networks that lose
Internet access. Actual device behaviour is controlled by
Settings.Global.NETWORK_AVOID_BAD_WIFI. This is the default value of that setting. -->
<integer translatable="false" name="config_networkAvoidBadWifi">0</integer>
</resources>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 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.
-->
<!-- Configuration values for ConnectivityService
DO NOT EDIT THIS FILE for specific device configuration; instead, use a Runtime Resources
Overlay package following the overlayable.xml configuration in the same directory:
https://source.android.com/devices/architecture/rros -->
<resources>
<!-- Whether the device should automatically switch away from Wi-Fi networks that lose
Internet access. Actual device behaviour is controlled by
Settings.Global.NETWORK_AVOID_BAD_WIFI. This is the default value of that setting. -->
<integer translatable="false" name="config_networkAvoidBadWifi">0</integer>
</resources>

View File

@@ -52,4 +52,41 @@
<item>12,60000</item><!-- mobile_cbs -->
</string-array>
<!-- Whether the APF Filter in the device should filter out IEEE 802.3 Frames
Those frames are identified by the field Eth-type having values
less than 0x600 -->
<bool translatable="false" name="config_apfDrop802_3Frames">true</bool>
<!-- An array of Denylisted EtherType, packets with EtherTypes within this array
will be dropped
TODO: need to put proper values, these are for testing purposes only -->
<integer-array translatable="false" name="config_apfEthTypeDenyList">
<item>0x88A2</item>
<item>0x88A4</item>
<item>0x88B8</item>
<item>0x88CD</item>
<item>0x88E3</item>
</integer-array>
<!-- Default supported concurrent socket keepalive slots per transport type, used by
ConnectivityManager.createSocketKeepalive() for calculating the number of keepalive
offload slots that should be reserved for privileged access. This string array should be
overridden by the device to present the capability of creating socket keepalives. -->
<!-- An Array of "[NetworkCapabilities.TRANSPORT_*],[supported keepalives] -->
<string-array translatable="false" name="config_networkSupportedKeepaliveCount">
<item>0,1</item>
<item>1,3</item>
</string-array>
<!-- Default value for ConnectivityManager.getMultipathPreference() on metered networks. Actual
device behaviour is controlled by the metered multipath preference in
ConnectivitySettingsManager. This is the default value of that setting. -->
<integer translatable="false" name="config_networkMeteredMultipathPreference">0</integer>
<!-- Whether the device should automatically switch away from Wi-Fi networks that lose
Internet access. Actual device behaviour is controlled by
Settings.Global.NETWORK_AVOID_BAD_WIFI. This is the default value of that setting. -->
<integer translatable="false" name="config_networkAvoidBadWifi">1</integer>
</resources>

View File

@@ -21,6 +21,11 @@
<item type="string" name="config_networkCaptivePortalServerUrl"/>
<item type="integer" name="config_networkTransitionTimeout"/>
<item type="array" name="config_wakeonlan_supported_interfaces"/>
<item type="bool" name="config_apfDrop802_3Frames"/>
<item type="array" name="config_apfEthTypeDenyList"/>
<item type="integer" name="config_networkMeteredMultipathPreference"/>
<item type="array" name="config_networkSupportedKeepaliveCount"/>
<item type="integer" name="config_networkAvoidBadWifi"/>
</policy>
</overlayable>

View File

@@ -165,6 +165,7 @@ import android.net.UnderlyingNetworkInfo;
import android.net.Uri;
import android.net.VpnManager;
import android.net.VpnTransportInfo;
import android.net.ConnectivityResources;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent;
import android.net.netlink.InetDiagMessage;
@@ -223,7 +224,6 @@ import com.android.net.module.util.LocationPermissionChecker;
import com.android.net.module.util.NetworkCapabilitiesUtils;
import com.android.net.module.util.PermissionUtils;
import com.android.server.connectivity.AutodestructReference;
import com.android.server.connectivity.ConnectivityResources;
import com.android.server.connectivity.DnsManager;
import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
import com.android.server.connectivity.KeepaliveTracker;

View File

@@ -18,6 +18,7 @@ package android.net.util
import android.content.Context
import android.content.res.Resources
import android.net.ConnectivityResources
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.MAX_TRANSPORT
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
@@ -26,13 +27,15 @@ import android.net.NetworkCapabilities.TRANSPORT_VPN
import android.net.NetworkCapabilities.TRANSPORT_WIFI
import androidx.test.filters.SmallTest
import com.android.internal.R
import org.junit.After
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertEquals
import org.junit.Assert.fail
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.ArgumentMatchers
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mockito.any
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock
@@ -47,21 +50,33 @@ import org.mockito.Mockito.mock
class KeepaliveUtilsTest {
// Prepare mocked context with given resource strings.
private fun getMockedContextWithStringArrayRes(id: Int, res: Array<out String?>?): Context {
private fun getMockedContextWithStringArrayRes(
id: Int,
name: String,
res: Array<out String?>?
): Context {
val mockRes = mock(Resources::class.java)
doReturn(res).`when`(mockRes).getStringArray(ArgumentMatchers.eq(id))
doReturn(res).`when`(mockRes).getStringArray(eq(id))
doReturn(id).`when`(mockRes).getIdentifier(eq(name), any(), any())
return mock(Context::class.java).apply {
doReturn(mockRes).`when`(this).getResources()
ConnectivityResources.setResourcesContextForTest(this)
}
}
@After
fun tearDown() {
ConnectivityResources.setResourcesContextForTest(null)
}
@Test
fun testGetSupportedKeepalives() {
fun assertRunWithException(res: Array<out String?>?) {
try {
val mockContext = getMockedContextWithStringArrayRes(
R.array.config_networkSupportedKeepaliveCount, res)
R.array.config_networkSupportedKeepaliveCount,
"config_networkSupportedKeepaliveCount", res)
KeepaliveUtils.getSupportedKeepalives(mockContext)
fail("Expected KeepaliveDeviceConfigurationException")
} catch (expected: KeepaliveUtils.KeepaliveDeviceConfigurationException) {
@@ -89,7 +104,8 @@ class KeepaliveUtilsTest {
val expectedValidRes = intArrayOf(3, 0, 0, 0, 4, 0, 0, 0)
val mockContext = getMockedContextWithStringArrayRes(
R.array.config_networkSupportedKeepaliveCount, validRes)
R.array.config_networkSupportedKeepaliveCount,
"config_networkSupportedKeepaliveCount", validRes)
val actual = KeepaliveUtils.getSupportedKeepalives(mockContext)
assertArrayEquals(expectedValidRes, actual)
}

View File

@@ -21,6 +21,7 @@ import android.content.res.Resources
import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER
import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_PERFORMANCE
import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY
import android.net.ConnectivityResources
import android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI
import android.net.ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE
import android.net.util.MultinetworkPolicyTracker.ActiveDataSubscriptionIdListener
@@ -31,8 +32,9 @@ import android.telephony.TelephonyManager
import android.test.mock.MockContentResolver
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.internal.R
import com.android.connectivity.resources.R
import com.android.internal.util.test.FakeSettingsProvider
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
@@ -41,6 +43,7 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.argThat
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mockito.any
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock
@@ -57,6 +60,8 @@ import org.mockito.Mockito.verify
@SmallTest
class MultinetworkPolicyTrackerTest {
private val resources = mock(Resources::class.java).also {
doReturn(R.integer.config_networkAvoidBadWifi).`when`(it).getIdentifier(
eq("config_networkAvoidBadWifi"), eq("integer"), any())
doReturn(0).`when`(it).getInteger(R.integer.config_networkAvoidBadWifi)
}
private val telephonyManager = mock(TelephonyManager::class.java)
@@ -75,6 +80,7 @@ class MultinetworkPolicyTrackerTest {
doReturn(resources).`when`(it).resources
doReturn(it).`when`(it).createConfigurationContext(any())
Settings.Global.putString(resolver, NETWORK_AVOID_BAD_WIFI, "1")
ConnectivityResources.setResourcesContextForTest(it)
}
private val tracker = MultinetworkPolicyTracker(context, null /* handler */)
@@ -85,6 +91,11 @@ class MultinetworkPolicyTrackerTest {
assertEquals(preference, tracker.meteredMultipathPreference)
}
@After
fun tearDown() {
ConnectivityResources.setResourcesContextForTest(null)
}
@Test
fun testUpdateMeteredMultipathPreference() {
assertMultipathPreference(MULTIPATH_PREFERENCE_HANDOVER)

View File

@@ -179,6 +179,7 @@ import android.net.ConnectivityManager.NetworkCallback;
import android.net.ConnectivityManager.PacketKeepalive;
import android.net.ConnectivityManager.PacketKeepaliveCallback;
import android.net.ConnectivityManager.TooManyRequestsException;
import android.net.ConnectivityResources;
import android.net.ConnectivitySettingsManager;
import android.net.ConnectivityThread;
import android.net.DataStallReportParcelable;
@@ -282,7 +283,6 @@ import com.android.internal.util.test.FakeSettingsProvider;
import com.android.net.module.util.ArrayTrackRecord;
import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
import com.android.server.connectivity.ConnectivityConstants;
import com.android.server.connectivity.ConnectivityResources;
import com.android.server.connectivity.MockableSystemProperties;
import com.android.server.connectivity.Nat464Xlat;
import com.android.server.connectivity.NetworkAgentInfo;
@@ -1570,11 +1570,19 @@ public class ConnectivityServiceTest {
com.android.connectivity.resources.R.string.config_networkCaptivePortalServerUrl);
doReturn(new String[]{ WIFI_WOL_IFNAME }).when(mResources).getStringArray(
com.android.connectivity.resources.R.array.config_wakeonlan_supported_interfaces);
final com.android.server.connectivity.ConnectivityResources connRes = mock(
ConnectivityResources.class);
doReturn(new String[] { "0,1", "1,3" }).when(mResources).getStringArray(
com.android.connectivity.resources.R.array.config_networkSupportedKeepaliveCount);
doReturn(com.android.connectivity.resources.R.array.config_networkSupportedKeepaliveCount)
.when(mResources).getIdentifier(eq("config_networkSupportedKeepaliveCount"),
eq("array"), any());
final ConnectivityResources connRes = mock(ConnectivityResources.class);
doReturn(mResources).when(connRes).get();
doReturn(connRes).when(deps).getResources(any());
final Context mockResContext = mock(Context.class);
doReturn(mResources).when(mockResContext).getResources();
ConnectivityResources.setResourcesContextForTest(mockResContext);
return deps;
}
@@ -1630,6 +1638,7 @@ public class ConnectivityServiceTest {
waitForIdle();
FakeSettingsProvider.clearSettingsProvider();
ConnectivityResources.setResourcesContextForTest(null);
mCsHandlerThread.quitSafely();
mAlarmManagerThread.quitSafely();