Merge "[Tetheirng] Refactor carrier config to EntitlementManager"

This commit is contained in:
Tom Hsu
2022-04-21 13:43:14 +00:00
committed by Gerrit Code Review
5 changed files with 118 additions and 89 deletions

View File

@@ -34,7 +34,6 @@ import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
import static com.android.networkstack.apishim.ConstantsShim.ACTION_TETHER_UNSUPPORTED_CARRIER_UI;
import static com.android.networkstack.apishim.ConstantsShim.KEY_CARRIER_SUPPORTS_TETHERING_BOOL;
import android.app.AlarmManager;
import android.app.PendingIntent;
@@ -48,12 +47,10 @@ import android.net.util.SharedLog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcel;
import android.os.PersistableBundle;
import android.os.ResultReceiver;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.util.SparseIntArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -307,13 +304,13 @@ public class EntitlementManager {
if (SystemProperties.getBoolean(DISABLE_PROVISIONING_SYSPROP_KEY, false)) {
return TETHERING_PROVISIONING_NOT_REQUIRED;
}
// TODO: Find a way to avoid get carrier config twice.
if (carrierConfigAffirmsCarrierNotSupport(config)) {
if (!config.isCarrierSupportTethering) {
// To block tethering, behave as if running provisioning check and failed.
return TETHERING_PROVISIONING_CARRIER_UNSUPPORT;
}
if (carrierConfigAffirmsEntitlementCheckNotRequired(config)) {
if (!config.isCarrierConfigAffirmsEntitlementCheckRequired) {
return TETHERING_PROVISIONING_NOT_REQUIRED;
}
return (config.provisioningApp.length == 2)
@@ -379,57 +376,6 @@ public class EntitlementManager {
}
}
/**
* Get carrier configuration bundle.
* @param config an object that encapsulates the various tethering configuration elements.
* */
public PersistableBundle getCarrierConfig(final TetheringConfiguration config) {
final CarrierConfigManager configManager = mContext
.getSystemService(CarrierConfigManager.class);
if (configManager == null) return null;
final PersistableBundle carrierConfig = configManager.getConfigForSubId(
config.activeDataSubId);
if (CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) {
return carrierConfig;
}
return null;
}
// The logic here is aimed solely at confirming that a CarrierConfig exists
// and affirms that entitlement checks are not required.
//
// TODO: find a better way to express this, or alter the checking process
// entirely so that this is more intuitive.
// TODO: Find a way to avoid using getCarrierConfig everytime.
private boolean carrierConfigAffirmsEntitlementCheckNotRequired(
final TetheringConfiguration config) {
// Check carrier config for entitlement checks
final PersistableBundle carrierConfig = getCarrierConfig(config);
if (carrierConfig == null) return false;
// A CarrierConfigManager was found and it has a config.
final boolean isEntitlementCheckRequired = carrierConfig.getBoolean(
CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL);
return !isEntitlementCheckRequired;
}
private boolean carrierConfigAffirmsCarrierNotSupport(final TetheringConfiguration config) {
if (!SdkLevel.isAtLeastT()) {
return false;
}
// Check carrier config for entitlement checks
final PersistableBundle carrierConfig = getCarrierConfig(config);
if (carrierConfig == null) return false;
// A CarrierConfigManager was found and it has a config.
final boolean mIsCarrierSupport = carrierConfig.getBoolean(
KEY_CARRIER_SUPPORTS_TETHERING_BOOL, true);
return !mIsCarrierSupport;
}
/**
* Run no UI tethering provisioning check.
* @param type tethering type from TetheringManager.TETHERING_{@code *}
@@ -479,7 +425,7 @@ public class EntitlementManager {
private void runTetheringProvisioning(
boolean showProvisioningUi, int downstreamType, final TetheringConfiguration config) {
if (carrierConfigAffirmsCarrierNotSupport(config)) {
if (!config.isCarrierSupportTethering) {
mListener.onTetherProvisioningFailed(downstreamType, "Carrier does not support.");
if (showProvisioningUi) {
showCarrierUnsupportedDialog();
@@ -497,7 +443,7 @@ public class EntitlementManager {
}
private void showCarrierUnsupportedDialog() {
// This is only used when carrierConfigAffirmsCarrierNotSupport() is true.
// This is only used when TetheringConfiguration.isCarrierSupportTethering is false.
if (!SdkLevel.isAtLeastT()) {
return;
}

View File

@@ -482,7 +482,7 @@ public class Tethering {
// To avoid launching unexpected provisioning checks, ignore re-provisioning
// when no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning()
// will be triggered again when CarrierConfig is loaded.
if (mEntitlementMgr.getCarrierConfig(mConfig) != null) {
if (TetheringConfiguration.getCarrierConfig(mContext, subId) != null) {
mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
} else {
mLog.log("IGNORED reevaluate provisioning, no carrier config loaded");

View File

@@ -24,14 +24,17 @@ import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
import static com.android.net.module.util.DeviceConfigUtils.TETHERING_MODULE_NAME;
import static com.android.networkstack.apishim.ConstantsShim.KEY_CARRIER_SUPPORTS_TETHERING_BOOL;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.net.TetheringConfigurationParcel;
import android.net.util.SharedLog;
import android.os.PersistableBundle;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -142,6 +145,9 @@ public class TetheringConfiguration {
public final int provisioningCheckPeriod;
public final String provisioningResponse;
public final boolean isCarrierSupportTethering;
public final boolean isCarrierConfigAffirmsEntitlementCheckRequired;
public final int activeDataSubId;
private final boolean mEnableLegacyDhcpServer;
@@ -207,6 +213,11 @@ public class TetheringConfiguration {
provisioningResponse = getResourceString(res,
R.string.config_mobile_hotspot_provision_response);
PersistableBundle carrierConfigs = getCarrierConfig(ctx, activeDataSubId);
isCarrierSupportTethering = carrierConfigAffirmsCarrierSupport(carrierConfigs);
isCarrierConfigAffirmsEntitlementCheckRequired =
carrierConfigAffirmsEntitlementCheckRequired(carrierConfigs);
mOffloadPollInterval = getResourceInteger(res,
R.integer.config_tether_offload_poll_interval,
DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
@@ -329,6 +340,10 @@ public class TetheringConfiguration {
pw.print("provisioningAppNoUi: ");
pw.println(provisioningAppNoUi);
pw.println("isCarrierSupportTethering: " + isCarrierSupportTethering);
pw.println("isCarrierConfigAffirmsEntitlementCheckRequired: "
+ isCarrierConfigAffirmsEntitlementCheckRequired);
pw.print("enableBpfOffload: ");
pw.println(mEnableBpfOffload);
@@ -361,6 +376,9 @@ public class TetheringConfiguration {
toIntArray(preferredUpstreamIfaceTypes)));
sj.add(String.format("provisioningApp:%s", makeString(provisioningApp)));
sj.add(String.format("provisioningAppNoUi:%s", provisioningAppNoUi));
sj.add(String.format("isCarrierSupportTethering:%s", isCarrierSupportTethering));
sj.add(String.format("isCarrierConfigAffirmsEntitlementCheckRequired:%s",
isCarrierConfigAffirmsEntitlementCheckRequired));
sj.add(String.format("enableBpfOffload:%s", mEnableBpfOffload));
sj.add(String.format("enableLegacyDhcpServer:%s", mEnableLegacyDhcpServer));
return String.format("TetheringConfiguration{%s}", sj.toString());
@@ -596,6 +614,39 @@ public class TetheringConfiguration {
return result;
}
private static boolean carrierConfigAffirmsEntitlementCheckRequired(
PersistableBundle carrierConfig) {
if (carrierConfig == null) {
return true;
}
return carrierConfig.getBoolean(
CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
}
private static boolean carrierConfigAffirmsCarrierSupport(PersistableBundle carrierConfig) {
if (!SdkLevel.isAtLeastT() || carrierConfig == null) {
return true;
}
return carrierConfig.getBoolean(KEY_CARRIER_SUPPORTS_TETHERING_BOOL, true);
}
/**
* Get carrier configuration bundle.
*/
public static PersistableBundle getCarrierConfig(Context context, int activeDataSubId) {
final CarrierConfigManager configManager =
context.getSystemService(CarrierConfigManager.class);
if (configManager == null) {
return null;
}
final PersistableBundle carrierConfig = configManager.getConfigForSubId(activeDataSubId);
if (CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) {
return carrierConfig;
}
return null;
}
/**
* Convert this TetheringConfiguration to a TetheringConfigurationParcel.
*/

View File

@@ -303,33 +303,6 @@ public final class EntitlementManagerTest {
assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
}
@Test
public void toleratesCarrierConfigManagerMissing() {
setupForRequiredProvisioning();
mockService(Context.CARRIER_CONFIG_SERVICE, CarrierConfigManager.class, null);
mConfig = new FakeTetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
// Couldn't get the CarrierConfigManager, but still had a declared provisioning app.
// Therefore provisioning still be required.
assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
}
@Test
public void toleratesCarrierConfigMissing() {
setupForRequiredProvisioning();
when(mCarrierConfigManager.getConfig()).thenReturn(null);
mConfig = new FakeTetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
// We still have a provisioning app configured, so still require provisioning.
assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
}
@Test
public void toleratesCarrierConfigNotLoaded() {
setupForRequiredProvisioning();
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
// We still have a provisioning app configured, so still require provisioning.
assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
}
@Test
public void provisioningNotRequiredWhenAppNotFound() {
setupForRequiredProvisioning();
@@ -706,8 +679,8 @@ public final class EntitlementManagerTest {
@IgnoreUpTo(SC_V2)
public void requestLatestTetheringEntitlementResult_carrierDoesNotSupport_noProvisionCount()
throws Exception {
setupForRequiredProvisioning();
setupCarrierConfig(false);
setupForRequiredProvisioning();
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
ResultReceiver receiver = new ResultReceiver(null) {
@Override
@@ -735,6 +708,7 @@ public final class EntitlementManagerTest {
mEnMgr.notifyUpstream(false);
mLooper.dispatchAll();
setupCarrierConfig(false);
mConfig = new FakeTetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
mEnMgr.reevaluateSimCardProvisioning(mConfig);
// Turn on upstream.
@@ -749,8 +723,8 @@ public final class EntitlementManagerTest {
@IgnoreUpTo(SC_V2)
public void startProvisioningIfNeeded_carrierUnsupport()
throws Exception {
setupForRequiredProvisioning();
setupCarrierConfig(false);
setupForRequiredProvisioning();
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
verify(mTetherProvisioningFailedListener, never())
.onTetherProvisioningFailed(TETHERING_WIFI, "Carrier does not support.");

View File

@@ -22,10 +22,13 @@ import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.networkstack.apishim.ConstantsShim.KEY_CARRIER_SUPPORTS_TETHERING_BOOL;
import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_FORCE_USB_FUNCTIONS;
import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_USB_NCM_FUNCTION;
import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_USB_RNDIS_FUNCTION;
@@ -46,8 +49,10 @@ import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.util.SharedLog;
import android.os.Build;
import android.os.PersistableBundle;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyManager;
import android.test.mock.MockContentResolver;
@@ -56,6 +61,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.DeviceConfigUtils;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
@@ -88,6 +94,7 @@ public class TetheringConfigurationTest {
private static final long TEST_PACKAGE_VERSION = 1234L;
@Mock private ApplicationInfo mApplicationInfo;
@Mock private Context mContext;
@Mock private CarrierConfigManager mCarrierConfigManager;
@Mock private TelephonyManager mTelephonyManager;
@Mock private Resources mResources;
@Mock private Resources mResourcesForSubId;
@@ -97,6 +104,7 @@ public class TetheringConfigurationTest {
private boolean mHasTelephonyManager;
private MockitoSession mMockingSession;
private MockContentResolver mContentResolver;
private final PersistableBundle mCarrierConfig = new PersistableBundle();
private class MockTetheringConfiguration extends TetheringConfiguration {
MockTetheringConfiguration(Context ctx, SharedLog log, int id) {
@@ -474,6 +482,56 @@ public class TetheringConfigurationTest {
PROVISIONING_APP_RESPONSE);
}
private <T> void mockService(String serviceName, Class<T> serviceClass, T service) {
when(mMockContext.getSystemServiceName(serviceClass)).thenReturn(serviceName);
when(mMockContext.getSystemService(serviceName)).thenReturn(service);
}
@Test
public void testGetCarrierConfigBySubId_noCarrierConfigManager_configsAreDefault() {
// Act like the CarrierConfigManager is present and ready unless told otherwise.
mockService(Context.CARRIER_CONFIG_SERVICE,
CarrierConfigManager.class, null);
final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
assertTrue(cfg.isCarrierSupportTethering);
assertTrue(cfg.isCarrierConfigAffirmsEntitlementCheckRequired);
}
@Test
public void testGetCarrierConfigBySubId_carrierConfigMissing_configsAreDefault() {
// Act like the CarrierConfigManager is present and ready unless told otherwise.
mockService(Context.CARRIER_CONFIG_SERVICE,
CarrierConfigManager.class, mCarrierConfigManager);
when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(null);
final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
assertTrue(cfg.isCarrierSupportTethering);
assertTrue(cfg.isCarrierConfigAffirmsEntitlementCheckRequired);
}
@Test
public void testGetCarrierConfigBySubId_hasConfigs_carrierUnsupportAndCheckNotRequired() {
mockService(Context.CARRIER_CONFIG_SERVICE,
CarrierConfigManager.class, mCarrierConfigManager);
mCarrierConfig.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
mCarrierConfig.putBoolean(KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, false);
mCarrierConfig.putBoolean(KEY_CARRIER_SUPPORTS_TETHERING_BOOL, false);
when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mCarrierConfig);
final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
if (SdkLevel.isAtLeastT()) {
assertFalse(cfg.isCarrierSupportTethering);
} else {
assertTrue(cfg.isCarrierSupportTethering);
}
assertFalse(cfg.isCarrierConfigAffirmsEntitlementCheckRequired);
}
@Test
public void testEnableLegacyWifiP2PAddress() throws Exception {
final TetheringConfiguration defaultCfg = new TetheringConfiguration(