Support checking DnsResolver version in isFeatureSupported.
Test: new unit tests Change-Id: Ia251c068806a3d8c970d984322d4cb7e2364c1ef
This commit is contained in:
parent
7cde306fa3
commit
ca67820a94
3 changed files with 89 additions and 20 deletions
|
|
@ -22,6 +22,7 @@ import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
|
|||
import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
|
||||
|
||||
import static com.android.net.module.util.FeatureVersions.CONNECTIVITY_MODULE_ID;
|
||||
import static com.android.net.module.util.FeatureVersions.DNS_RESOLVER_MODULE_ID;
|
||||
import static com.android.net.module.util.FeatureVersions.MODULE_MASK;
|
||||
import static com.android.net.module.util.FeatureVersions.NETWORK_STACK_MODULE_ID;
|
||||
import static com.android.net.module.util.FeatureVersions.VERSION_MASK;
|
||||
|
|
@ -68,7 +69,8 @@ public final class DeviceConfigUtils {
|
|||
@VisibleForTesting
|
||||
public static void resetPackageVersionCacheForTest() {
|
||||
sPackageVersion = -1;
|
||||
sModuleVersion = -1;
|
||||
sTetheringModuleVersion = -1;
|
||||
sResolvModuleVersion = -1;
|
||||
sNetworkStackModuleVersion = -1;
|
||||
}
|
||||
|
||||
|
|
@ -243,23 +245,23 @@ public final class DeviceConfigUtils {
|
|||
}
|
||||
}
|
||||
|
||||
// Guess the tethering module name based on the package prefix of the connectivity resources
|
||||
// Take the resource package name, cut it before "connectivity" and append "tethering".
|
||||
// Guess an APEX module name based on the package prefix of the connectivity resources
|
||||
// Take the resource package name, cut it before "connectivity" and append the module name.
|
||||
// Then resolve that package version number with packageManager.
|
||||
// If that fails retry by appending "go.tethering" instead
|
||||
private static long resolveTetheringModuleVersion(@NonNull Context context)
|
||||
// If that fails retry by appending "go.<moduleName>" instead.
|
||||
private static long resolveApexModuleVersion(@NonNull Context context, String moduleName)
|
||||
throws PackageManager.NameNotFoundException {
|
||||
final String pkgPrefix = resolvePkgPrefix(context);
|
||||
final PackageManager packageManager = context.getPackageManager();
|
||||
try {
|
||||
return packageManager.getPackageInfo(pkgPrefix + "tethering",
|
||||
return packageManager.getPackageInfo(pkgPrefix + moduleName,
|
||||
PackageManager.MATCH_APEX).getLongVersionCode();
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.d(TAG, "Device is using go modules");
|
||||
// fall through
|
||||
}
|
||||
|
||||
return packageManager.getPackageInfo(pkgPrefix + "go.tethering",
|
||||
return packageManager.getPackageInfo(pkgPrefix + "go." + moduleName,
|
||||
PackageManager.MATCH_APEX).getLongVersionCode();
|
||||
}
|
||||
|
||||
|
|
@ -274,19 +276,35 @@ public final class DeviceConfigUtils {
|
|||
return connResourcesPackage.substring(0, pkgPrefixLen);
|
||||
}
|
||||
|
||||
private static volatile long sModuleVersion = -1;
|
||||
private static volatile long sTetheringModuleVersion = -1;
|
||||
|
||||
private static long getTetheringModuleVersion(@NonNull Context context) {
|
||||
if (sModuleVersion >= 0) return sModuleVersion;
|
||||
if (sTetheringModuleVersion >= 0) return sTetheringModuleVersion;
|
||||
|
||||
try {
|
||||
sModuleVersion = resolveTetheringModuleVersion(context);
|
||||
sTetheringModuleVersion = resolveApexModuleVersion(context, "tethering");
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
// It's expected to fail tethering module version resolution on the devices with
|
||||
// flattened apex
|
||||
Log.e(TAG, "Failed to resolve tethering module version: " + e);
|
||||
return DEFAULT_PACKAGE_VERSION;
|
||||
}
|
||||
return sModuleVersion;
|
||||
return sTetheringModuleVersion;
|
||||
}
|
||||
|
||||
private static volatile long sResolvModuleVersion = -1;
|
||||
private static long getResolvModuleVersion(@NonNull Context context) {
|
||||
if (sResolvModuleVersion >= 0) return sResolvModuleVersion;
|
||||
|
||||
try {
|
||||
sResolvModuleVersion = resolveApexModuleVersion(context, "resolv");
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
// It's expected to fail resolv module version resolution on the devices with
|
||||
// flattened apex
|
||||
Log.e(TAG, "Failed to resolve resolv module version: " + e);
|
||||
return DEFAULT_PACKAGE_VERSION;
|
||||
}
|
||||
return sResolvModuleVersion;
|
||||
}
|
||||
|
||||
private static volatile long sNetworkStackModuleVersion = -1;
|
||||
|
|
@ -342,6 +360,8 @@ public final class DeviceConfigUtils {
|
|||
moduleVersion = getTetheringModuleVersion(context);
|
||||
} else if (moduleId == NETWORK_STACK_MODULE_ID) {
|
||||
moduleVersion = getNetworkStackModuleVersion(context);
|
||||
} else if (moduleId == DNS_RESOLVER_MODULE_ID) {
|
||||
moduleVersion = getResolvModuleVersion(context);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown module " + moduleId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ public class FeatureVersions {
|
|||
public static final long VERSION_MASK = 0x00F_FFFF_FFFFL;
|
||||
public static final long CONNECTIVITY_MODULE_ID = 0x01L << MODULE_SHIFT;
|
||||
public static final long NETWORK_STACK_MODULE_ID = 0x02L << MODULE_SHIFT;
|
||||
public static final long DNS_RESOLVER_MODULE_ID = 0x03L << MODULE_SHIFT;
|
||||
// CLAT_ADDRESS_TRANSLATE is a feature of the network stack, which doesn't throw when system
|
||||
// try to add a NAT-T keepalive packet filter with v6 address, introduced in version
|
||||
// M-2023-Sept on July 3rd, 2023.
|
||||
|
|
@ -48,4 +49,11 @@ public class FeatureVersions {
|
|||
// by BPF for the given uid and conditions, introduced in version M-2024-Feb on Nov 6, 2023.
|
||||
public static final long FEATURE_IS_UID_NETWORKING_BLOCKED =
|
||||
CONNECTIVITY_MODULE_ID + 34_14_00_000L;
|
||||
|
||||
// DDR is a feature implemented across NetworkStack, ConnectivityService and DnsResolver.
|
||||
// The flag that enables this feature is in NetworkStack.
|
||||
public static final long FEATURE_DDR_IN_CONNECTIVITY =
|
||||
CONNECTIVITY_MODULE_ID + 35_11_00_000L;
|
||||
public static final long FEATURE_DDR_IN_DNSRESOLVER =
|
||||
DNS_RESOLVER_MODULE_ID + 35_11_00_000L;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
|
|||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
|
||||
import static com.android.net.module.util.FeatureVersions.CONNECTIVITY_MODULE_ID;
|
||||
import static com.android.net.module.util.FeatureVersions.DNS_RESOLVER_MODULE_ID;
|
||||
import static com.android.net.module.util.FeatureVersions.NETWORK_STACK_MODULE_ID;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
|
@ -77,7 +78,9 @@ public class DeviceConfigUtilsTest {
|
|||
private static final int TEST_DEFAULT_FLAG_VALUE = 0;
|
||||
private static final int TEST_MAX_FLAG_VALUE = 1000;
|
||||
private static final int TEST_MIN_FLAG_VALUE = 100;
|
||||
private static final long TEST_PACKAGE_VERSION = 290000000;
|
||||
private static final long TEST_PACKAGE_VERSION = 290500000;
|
||||
private static final long TEST_GO_PACKAGE_VERSION = 290000000; // Not updated
|
||||
private static final long TEST_RESOLV_PACKAGE_VERSION = 290300000; // Updated, but older.
|
||||
private static final String TEST_PACKAGE_NAME = "test.package.name";
|
||||
// The APEX name is the name of the APEX module, as in android.content.pm.ModuleInfo, and is
|
||||
// used for its mount point in /apex. APEX packages are actually APKs with a different
|
||||
|
|
@ -85,14 +88,18 @@ public class DeviceConfigUtilsTest {
|
|||
// that manifest, and is reflected in android.content.pm.ApplicationInfo. Contrary to the APEX
|
||||
// (module) name, different package names are typically used to identify the organization that
|
||||
// built and signed the APEX modules.
|
||||
private static final String TEST_APEX_PACKAGE_NAME = "com.prefix.android.tethering";
|
||||
private static final String TEST_GO_APEX_PACKAGE_NAME = "com.prefix.android.go.tethering";
|
||||
private static final String TEST_TETHERING_PACKAGE_NAME = "com.prefix.android.tethering";
|
||||
private static final String TEST_GO_TETHERING_PACKAGE_NAME = "com.prefix.android.go.tethering";
|
||||
private static final String TEST_RESOLV_PACKAGE_NAME = "com.prefix.android.resolv";
|
||||
private static final String TEST_GO_RESOLV_PACKAGE_NAME = "com.prefix.android.go.resolv";
|
||||
private static final String TEST_CONNRES_PACKAGE_NAME =
|
||||
"com.prefix.android.connectivity.resources";
|
||||
private static final String TEST_NETWORKSTACK_NAME = "com.prefix.android.networkstack";
|
||||
private static final String TEST_GO_NETWORKSTACK_NAME = "com.prefix.android.go.networkstack";
|
||||
private final PackageInfo mPackageInfo = new PackageInfo();
|
||||
private final PackageInfo mApexPackageInfo = new PackageInfo();
|
||||
private final PackageInfo mGoApexPackageInfo = new PackageInfo();
|
||||
private final PackageInfo mTetheringApexPackageInfo = new PackageInfo();
|
||||
private final PackageInfo mResolvApexPackageInfo = new PackageInfo();
|
||||
private MockitoSession mSession;
|
||||
|
||||
@Mock private Context mContext;
|
||||
|
|
@ -105,13 +112,22 @@ public class DeviceConfigUtilsTest {
|
|||
mSession = mockitoSession().spyStatic(DeviceConfig.class).startMocking();
|
||||
|
||||
mPackageInfo.setLongVersionCode(TEST_PACKAGE_VERSION);
|
||||
mApexPackageInfo.setLongVersionCode(TEST_PACKAGE_VERSION);
|
||||
mTetheringApexPackageInfo.setLongVersionCode(TEST_PACKAGE_VERSION);
|
||||
mGoApexPackageInfo.setLongVersionCode(TEST_GO_PACKAGE_VERSION);
|
||||
mResolvApexPackageInfo.setLongVersionCode(TEST_RESOLV_PACKAGE_VERSION);
|
||||
|
||||
doReturn(mPm).when(mContext).getPackageManager();
|
||||
doReturn(TEST_PACKAGE_NAME).when(mContext).getPackageName();
|
||||
doThrow(NameNotFoundException.class).when(mPm).getPackageInfo(anyString(), anyInt());
|
||||
doReturn(mPackageInfo).when(mPm).getPackageInfo(eq(TEST_PACKAGE_NAME), anyInt());
|
||||
doReturn(mApexPackageInfo).when(mPm).getPackageInfo(eq(TEST_APEX_PACKAGE_NAME), anyInt());
|
||||
doReturn(mTetheringApexPackageInfo).when(mPm).getPackageInfo(
|
||||
eq(TEST_TETHERING_PACKAGE_NAME), anyInt());
|
||||
doReturn(mResolvApexPackageInfo).when(mPm).getPackageInfo(eq(TEST_RESOLV_PACKAGE_NAME),
|
||||
anyInt());
|
||||
doReturn(mGoApexPackageInfo).when(mPm).getPackageInfo(eq(TEST_GO_TETHERING_PACKAGE_NAME),
|
||||
anyInt());
|
||||
doReturn(mGoApexPackageInfo).when(mPm).getPackageInfo(eq(TEST_GO_RESOLV_PACKAGE_NAME),
|
||||
anyInt());
|
||||
|
||||
doReturn(mResources).when(mContext).getResources();
|
||||
|
||||
|
|
@ -342,9 +358,9 @@ public class DeviceConfigUtilsTest {
|
|||
@Test
|
||||
public void testFeatureIsEnabledOnGo() throws Exception {
|
||||
doThrow(NameNotFoundException.class).when(mPm).getPackageInfo(
|
||||
eq(TEST_APEX_PACKAGE_NAME), anyInt());
|
||||
doReturn(mApexPackageInfo).when(mPm).getPackageInfo(
|
||||
eq(TEST_GO_APEX_PACKAGE_NAME), anyInt());
|
||||
eq(TEST_TETHERING_PACKAGE_NAME), anyInt());
|
||||
doReturn(mTetheringApexPackageInfo).when(mPm).getPackageInfo(
|
||||
eq(TEST_GO_TETHERING_PACKAGE_NAME), anyInt());
|
||||
doReturn("0").when(() -> DeviceConfig.getProperty(
|
||||
NAMESPACE_CONNECTIVITY, TEST_EXPERIMENT_FLAG));
|
||||
doReturn("0").when(() -> DeviceConfig.getProperty(
|
||||
|
|
@ -483,6 +499,31 @@ public class DeviceConfigUtilsTest {
|
|||
mContext, 889900000L + CONNECTIVITY_MODULE_ID));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIsFeatureSupported_resolvFeature() throws Exception {
|
||||
assertTrue(DeviceConfigUtils.isFeatureSupported(
|
||||
mContext, TEST_RESOLV_PACKAGE_VERSION + DNS_RESOLVER_MODULE_ID));
|
||||
// Return false because feature requires a future version.
|
||||
assertFalse(DeviceConfigUtils.isFeatureSupported(
|
||||
mContext, 889900000L + DNS_RESOLVER_MODULE_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFeatureSupported_goResolvFeature() throws Exception {
|
||||
doThrow(NameNotFoundException.class).when(mPm).getPackageInfo(eq(TEST_RESOLV_PACKAGE_NAME),
|
||||
anyInt());
|
||||
doReturn(mGoApexPackageInfo).when(mPm).getPackageInfo(eq(TEST_GO_RESOLV_PACKAGE_NAME),
|
||||
anyInt());
|
||||
assertFalse(DeviceConfigUtils.isFeatureSupported(
|
||||
mContext, TEST_RESOLV_PACKAGE_VERSION + DNS_RESOLVER_MODULE_ID));
|
||||
assertTrue(DeviceConfigUtils.isFeatureSupported(
|
||||
mContext, TEST_GO_PACKAGE_VERSION + DNS_RESOLVER_MODULE_ID));
|
||||
// Return false because feature requires a future version.
|
||||
assertFalse(DeviceConfigUtils.isFeatureSupported(
|
||||
mContext, 889900000L + DNS_RESOLVER_MODULE_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsFeatureSupported_illegalModule() throws Exception {
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
|
|
|
|||
Loading…
Reference in a new issue