From f0d60e99024c32bbfc5ea4eab0a5462f7609640b Mon Sep 17 00:00:00 2001 From: tom hsu Date: Tue, 22 Mar 2022 00:41:20 +0800 Subject: [PATCH] [Tetheirng] Refactor carrier config to EntitlementManager - To reduce CarrierConfigManager access times, move CarrierManager to TetheringConfiguration. Bug: 225900149 Test: atest EntitlementManagerTest pass Test: atest TetheringConfigurationTest pass Change-Id: I5b206e2bc012cbbca26fb1e5c72558383981f183 --- .../tethering/EntitlementManager.java | 64 ++----------------- .../networkstack/tethering/Tethering.java | 2 +- .../tethering/TetheringConfiguration.java | 51 +++++++++++++++ .../tethering/EntitlementManagerTest.java | 32 +--------- .../tethering/TetheringConfigurationTest.java | 58 +++++++++++++++++ 5 files changed, 118 insertions(+), 89 deletions(-) diff --git a/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java b/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java index 844efdec5a..adc95abea4 100644 --- a/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java +++ b/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java @@ -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; } diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java index 0b607bd038..380013332a 100644 --- a/Tethering/src/com/android/networkstack/tethering/Tethering.java +++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java @@ -476,7 +476,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"); diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java index eaf85899a1..2c848ee4ab 100644 --- a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java +++ b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java @@ -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; @@ -206,6 +212,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); @@ -301,6 +312,10 @@ public class TetheringConfiguration { pw.print("provisioningAppNoUi: "); pw.println(provisioningAppNoUi); + pw.println("isCarrierSupportTethering: " + isCarrierSupportTethering); + pw.println("isCarrierConfigAffirmsEntitlementCheckRequired: " + + isCarrierConfigAffirmsEntitlementCheckRequired); + pw.print("enableBpfOffload: "); pw.println(mEnableBpfOffload); @@ -330,6 +345,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()); @@ -565,6 +583,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. */ diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java index 690ff71912..01d7b4b568 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/EntitlementManagerTest.java @@ -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."); diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java index e8bb31554a..9c9f40d892 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java @@ -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 void mockService(String serviceName, Class 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(