Merge "Tethering: fix using wrong subId problem"

This commit is contained in:
Mark Chien
2019-04-16 12:31:10 +00:00
committed by Gerrit Code Review
3 changed files with 117 additions and 98 deletions

View File

@@ -237,13 +237,17 @@ public class Tethering extends BaseNetworkObserver {
mLog.log("OBSERVED UiEnitlementFailed"); mLog.log("OBSERVED UiEnitlementFailed");
stopTethering(downstream); stopTethering(downstream);
}); });
mEntitlementMgr.setTetheringConfigurationFetcher(() -> {
maybeDefaultDataSubChanged();
return mConfig;
});
mCarrierConfigChange = new VersionedBroadcastListener( mCarrierConfigChange = new VersionedBroadcastListener(
"CarrierConfigChangeListener", mContext, mHandler, filter, "CarrierConfigChangeListener", mContext, mHandler, filter,
(Intent ignored) -> { (Intent ignored) -> {
mLog.log("OBSERVED carrier config change"); mLog.log("OBSERVED carrier config change");
updateConfiguration(); updateConfiguration();
mEntitlementMgr.reevaluateSimCardProvisioning(); mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
}); });
filter = new IntentFilter(); filter = new IntentFilter();
@@ -252,12 +256,12 @@ public class Tethering extends BaseNetworkObserver {
"DefaultSubscriptionChangeListener", mContext, mHandler, filter, "DefaultSubscriptionChangeListener", mContext, mHandler, filter,
(Intent ignored) -> { (Intent ignored) -> {
mLog.log("OBSERVED default data subscription change"); mLog.log("OBSERVED default data subscription change");
updateConfiguration(); maybeDefaultDataSubChanged();
// To avoid launch unexpected provisioning checks, ignore re-provisioning when // To avoid launch unexpected provisioning checks, ignore re-provisioning when
// no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning() will be // no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning() will be
// triggered again when CarrierConfig is loaded. // triggered again when CarrierConfig is loaded.
if (mEntitlementMgr.getCarrierConfig() != null) { if (mEntitlementMgr.getCarrierConfig(mConfig) != null) {
mEntitlementMgr.reevaluateSimCardProvisioning(); mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
} else { } else {
mLog.log("IGNORED reevaluate provisioning due to no carrier config loaded"); mLog.log("IGNORED reevaluate provisioning due to no carrier config loaded");
} }
@@ -301,17 +305,26 @@ public class Tethering extends BaseNetworkObserver {
// NOTE: This is always invoked on the mLooper thread. // NOTE: This is always invoked on the mLooper thread.
private void updateConfiguration() { private void updateConfiguration() {
final int subId = mDeps.getDefaultDataSubscriptionId(); final int subId = mDeps.getDefaultDataSubscriptionId();
mConfig = new TetheringConfiguration(mContext, mLog, subId); updateConfiguration(subId);
mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired);
mEntitlementMgr.updateConfiguration(mConfig);
} }
private void maybeUpdateConfiguration() { private void updateConfiguration(final int subId) {
mConfig = new TetheringConfiguration(mContext, mLog, subId);
mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired);
}
private void maybeDunSettingChanged() {
final boolean isDunRequired = TetheringConfiguration.checkDunRequired(mContext); final boolean isDunRequired = TetheringConfiguration.checkDunRequired(mContext);
if (isDunRequired == mConfig.isDunRequired) return; if (isDunRequired == mConfig.isDunRequired) return;
updateConfiguration(); updateConfiguration();
} }
private void maybeDefaultDataSubChanged() {
final int subId = mDeps.getDefaultDataSubscriptionId();
if (subId == mConfig.subId) return;
updateConfiguration(subId);
}
@Override @Override
public void interfaceStatusChanged(String iface, boolean up) { public void interfaceStatusChanged(String iface, boolean up) {
// Never called directly: only called from interfaceLinkStateChanged. // Never called directly: only called from interfaceLinkStateChanged.
@@ -1183,7 +1196,7 @@ public class Tethering extends BaseNetworkObserver {
protected void chooseUpstreamType(boolean tryCell) { protected void chooseUpstreamType(boolean tryCell) {
// We rebuild configuration on ACTION_CONFIGURATION_CHANGED, but we // We rebuild configuration on ACTION_CONFIGURATION_CHANGED, but we
// do not currently know how to watch for changes in DUN settings. // do not currently know how to watch for changes in DUN settings.
maybeUpdateConfiguration(); maybeDunSettingChanged();
final TetheringConfiguration config = mConfig; final TetheringConfiguration config = mConfig;
final NetworkState ns = (config.chooseUpstreamAutomatically) final NetworkState ns = (config.chooseUpstreamAutomatically)

View File

@@ -29,7 +29,6 @@ import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
import static com.android.internal.R.string.config_wifi_tether_enable; import static com.android.internal.R.string.config_wifi_tether_enable;
import android.annotation.Nullable;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@@ -76,6 +75,7 @@ public class EntitlementManager {
protected static final String DISABLE_PROVISIONING_SYSPROP_KEY = "net.tethering.noprovisioning"; protected static final String DISABLE_PROVISIONING_SYSPROP_KEY = "net.tethering.noprovisioning";
private static final String ACTION_PROVISIONING_ALARM = private static final String ACTION_PROVISIONING_ALARM =
"com.android.server.connectivity.tethering.PROVISIONING_RECHECK_ALARM"; "com.android.server.connectivity.tethering.PROVISIONING_RECHECK_ALARM";
private static final String EXTRA_SUBID = "subId";
// {@link ComponentName} of the Service used to run tether provisioning. // {@link ComponentName} of the Service used to run tether provisioning.
private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString( private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(
@@ -99,7 +99,6 @@ public class EntitlementManager {
private final SharedLog mLog; private final SharedLog mLog;
private final SparseIntArray mEntitlementCacheValue; private final SparseIntArray mEntitlementCacheValue;
private final EntitlementHandler mHandler; private final EntitlementHandler mHandler;
private @Nullable TetheringConfiguration mConfig;
private final StateMachine mTetherMasterSM; private final StateMachine mTetherMasterSM;
// Key: ConnectivityManager.TETHERING_*(downstream). // Key: ConnectivityManager.TETHERING_*(downstream).
// Value: ConnectivityManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result). // Value: ConnectivityManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result).
@@ -109,6 +108,7 @@ public class EntitlementManager {
private boolean mUsingCellularAsUpstream = false; private boolean mUsingCellularAsUpstream = false;
private boolean mNeedReRunProvisioningUi = false; private boolean mNeedReRunProvisioningUi = false;
private OnUiEntitlementFailedListener mListener; private OnUiEntitlementFailedListener mListener;
private TetheringConfigurationFetcher mFetcher;
public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log, public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log,
int permissionChangeMessageCode, MockableSystemProperties systemProperties) { int permissionChangeMessageCode, MockableSystemProperties systemProperties) {
@@ -143,12 +143,18 @@ public class EntitlementManager {
void onUiEntitlementFailed(int downstream); void onUiEntitlementFailed(int downstream);
} }
public void setTetheringConfigurationFetcher(final TetheringConfigurationFetcher fetcher) {
mFetcher = fetcher;
}
/** Interface to fetch TetheringConfiguration. */
public interface TetheringConfigurationFetcher {
/** /**
* Pass a new TetheringConfiguration instance each time when * Fetch current tethering configuration. This will be called to ensure whether entitlement
* Tethering#updateConfiguration() is called. * check is needed.
* @return TetheringConfiguration instance.
*/ */
public void updateConfiguration(TetheringConfiguration conf) { TetheringConfiguration fetchTetheringConfiguration();
mConfig = conf;
} }
/** /**
@@ -176,7 +182,8 @@ public class EntitlementManager {
if (!mCurrentTethers.contains(type)) mCurrentTethers.add(type); if (!mCurrentTethers.contains(type)) mCurrentTethers.add(type);
if (isTetherProvisioningRequired()) { final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
if (isTetherProvisioningRequired(config)) {
// If provisioning is required and the result is not available yet, // If provisioning is required and the result is not available yet,
// cellular upstream should not be allowed. // cellular upstream should not be allowed.
if (mCellularPermitted.size() == 0) { if (mCellularPermitted.size() == 0) {
@@ -186,9 +193,9 @@ public class EntitlementManager {
// till upstream change to cellular. // till upstream change to cellular.
if (mUsingCellularAsUpstream) { if (mUsingCellularAsUpstream) {
if (showProvisioningUi) { if (showProvisioningUi) {
runUiTetherProvisioning(type); runUiTetherProvisioning(type, config.subId);
} else { } else {
runSilentTetherProvisioning(type); runSilentTetherProvisioning(type, config.subId);
} }
mNeedReRunProvisioningUi = false; mNeedReRunProvisioningUi = false;
} else { } else {
@@ -237,7 +244,8 @@ public class EntitlementManager {
mUsingCellularAsUpstream = isCellular; mUsingCellularAsUpstream = isCellular;
if (mUsingCellularAsUpstream) { if (mUsingCellularAsUpstream) {
handleMaybeRunProvisioning(); final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
handleMaybeRunProvisioning(config);
} }
} }
@@ -246,8 +254,8 @@ public class EntitlementManager {
mHandler.sendMessage(mHandler.obtainMessage(EVENT_MAYBE_RUN_PROVISIONING)); mHandler.sendMessage(mHandler.obtainMessage(EVENT_MAYBE_RUN_PROVISIONING));
} }
private void handleMaybeRunProvisioning() { private void handleMaybeRunProvisioning(final TetheringConfiguration config) {
if (mCurrentTethers.size() == 0 || !isTetherProvisioningRequired()) { if (mCurrentTethers.size() == 0 || !isTetherProvisioningRequired(config)) {
return; return;
} }
@@ -259,9 +267,9 @@ public class EntitlementManager {
if (mCellularPermitted.indexOfKey(downstream) < 0) { if (mCellularPermitted.indexOfKey(downstream) < 0) {
if (mNeedReRunProvisioningUi) { if (mNeedReRunProvisioningUi) {
mNeedReRunProvisioningUi = false; mNeedReRunProvisioningUi = false;
runUiTetherProvisioning(downstream); runUiTetherProvisioning(downstream, config.subId);
} else { } else {
runSilentTetherProvisioning(downstream); runSilentTetherProvisioning(downstream, config.subId);
} }
} }
} }
@@ -270,29 +278,31 @@ public class EntitlementManager {
/** /**
* Check if the device requires a provisioning check in order to enable tethering. * Check if the device requires a provisioning check in order to enable tethering.
* *
* @param config an object that encapsulates the various tethering configuration elements.
* @return a boolean - {@code true} indicating tether provisioning is required by the carrier. * @return a boolean - {@code true} indicating tether provisioning is required by the carrier.
*/ */
@VisibleForTesting @VisibleForTesting
public boolean isTetherProvisioningRequired() { protected boolean isTetherProvisioningRequired(final TetheringConfiguration config) {
if (mSystemProperties.getBoolean(DISABLE_PROVISIONING_SYSPROP_KEY, false) if (mSystemProperties.getBoolean(DISABLE_PROVISIONING_SYSPROP_KEY, false)
|| mConfig.provisioningApp.length == 0) { || config.provisioningApp.length == 0) {
return false; return false;
} }
if (carrierConfigAffirmsEntitlementCheckNotRequired()) { if (carrierConfigAffirmsEntitlementCheckNotRequired(config)) {
return false; return false;
} }
return (mConfig.provisioningApp.length == 2); return (config.provisioningApp.length == 2);
} }
/** /**
* Re-check tethering provisioning for all enabled tether types. * Re-check tethering provisioning for all enabled tether types.
* Reference ConnectivityManager.TETHERING_{@code *} for each tether type. * Reference ConnectivityManager.TETHERING_{@code *} for each tether type.
* *
* @param config an object that encapsulates the various tethering configuration elements.
* Note: this method is only called from TetherMaster on the handler thread. * Note: this method is only called from TetherMaster on the handler thread.
* If there are new callers from different threads, the logic should move to * If there are new callers from different threads, the logic should move to
* masterHandler to avoid race conditions. * masterHandler to avoid race conditions.
*/ */
public void reevaluateSimCardProvisioning() { public void reevaluateSimCardProvisioning(final TetheringConfiguration config) {
if (DBG) mLog.i("reevaluateSimCardProvisioning"); if (DBG) mLog.i("reevaluateSimCardProvisioning");
if (!mHandler.getLooper().isCurrentThread()) { if (!mHandler.getLooper().isCurrentThread()) {
@@ -303,24 +313,27 @@ public class EntitlementManager {
mCellularPermitted.clear(); mCellularPermitted.clear();
// TODO: refine provisioning check to isTetherProvisioningRequired() ?? // TODO: refine provisioning check to isTetherProvisioningRequired() ??
if (!mConfig.hasMobileHotspotProvisionApp() if (!config.hasMobileHotspotProvisionApp()
|| carrierConfigAffirmsEntitlementCheckNotRequired()) { || carrierConfigAffirmsEntitlementCheckNotRequired(config)) {
evaluateCellularPermission(); evaluateCellularPermission(config);
return; return;
} }
if (mUsingCellularAsUpstream) { if (mUsingCellularAsUpstream) {
handleMaybeRunProvisioning(); handleMaybeRunProvisioning(config);
} }
} }
/** Get carrier configuration bundle. */ /**
public PersistableBundle getCarrierConfig() { * Get carrier configuration bundle.
* @param config an object that encapsulates the various tethering configuration elements.
* */
public PersistableBundle getCarrierConfig(final TetheringConfiguration config) {
final CarrierConfigManager configManager = (CarrierConfigManager) mContext final CarrierConfigManager configManager = (CarrierConfigManager) mContext
.getSystemService(Context.CARRIER_CONFIG_SERVICE); .getSystemService(Context.CARRIER_CONFIG_SERVICE);
if (configManager == null) return null; if (configManager == null) return null;
final PersistableBundle carrierConfig = configManager.getConfig(); final PersistableBundle carrierConfig = configManager.getConfigForSubId(config.subId);
if (CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) { if (CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) {
return carrierConfig; return carrierConfig;
@@ -334,9 +347,10 @@ public class EntitlementManager {
// //
// TODO: find a better way to express this, or alter the checking process // TODO: find a better way to express this, or alter the checking process
// entirely so that this is more intuitive. // entirely so that this is more intuitive.
private boolean carrierConfigAffirmsEntitlementCheckNotRequired() { private boolean carrierConfigAffirmsEntitlementCheckNotRequired(
final TetheringConfiguration config) {
// Check carrier config for entitlement checks // Check carrier config for entitlement checks
final PersistableBundle carrierConfig = getCarrierConfig(); final PersistableBundle carrierConfig = getCarrierConfig(config);
if (carrierConfig == null) return false; if (carrierConfig == null) return false;
// A CarrierConfigManager was found and it has a config. // A CarrierConfigManager was found and it has a config.
@@ -348,17 +362,19 @@ public class EntitlementManager {
/** /**
* Run no UI tethering provisioning check. * Run no UI tethering provisioning check.
* @param type tethering type from ConnectivityManager.TETHERING_{@code *} * @param type tethering type from ConnectivityManager.TETHERING_{@code *}
* @param subId default data subscription ID.
*/ */
protected void runSilentTetherProvisioning(int type) { @VisibleForTesting
protected void runSilentTetherProvisioning(int type, int subId) {
if (DBG) mLog.i("runSilentTetherProvisioning: " + type); if (DBG) mLog.i("runSilentTetherProvisioning: " + type);
// For silent provisioning, settings would stop tethering when entitlement fail. // For silent provisioning, settings would stop tethering when entitlement fail.
ResultReceiver receiver = buildProxyReceiver(type, ResultReceiver receiver = buildProxyReceiver(type, false/* notifyFail */, null);
false/* notifyFail */, null);
Intent intent = new Intent(); Intent intent = new Intent();
intent.putExtra(EXTRA_ADD_TETHER_TYPE, type); intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
intent.putExtra(EXTRA_RUN_PROVISION, true); intent.putExtra(EXTRA_RUN_PROVISION, true);
intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver); intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver);
intent.putExtra(EXTRA_SUBID, subId);
intent.setComponent(TETHER_SERVICE); intent.setComponent(TETHER_SERVICE);
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
try { try {
@@ -368,24 +384,25 @@ public class EntitlementManager {
} }
} }
private void runUiTetherProvisioning(int type, int subId) {
ResultReceiver receiver = buildProxyReceiver(type, true/* notifyFail */, null);
runUiTetherProvisioning(type, subId, receiver);
}
/** /**
* Run the UI-enabled tethering provisioning check. * Run the UI-enabled tethering provisioning check.
* @param type tethering type from ConnectivityManager.TETHERING_{@code *} * @param type tethering type from ConnectivityManager.TETHERING_{@code *}
* @param subId default data subscription ID.
* @param receiver to receive entitlement check result.
*/ */
@VisibleForTesting @VisibleForTesting
protected void runUiTetherProvisioning(int type) { protected void runUiTetherProvisioning(int type, int subId, ResultReceiver receiver) {
ResultReceiver receiver = buildProxyReceiver(type,
true/* notifyFail */, null);
runUiTetherProvisioning(type, receiver);
}
@VisibleForTesting
protected void runUiTetherProvisioning(int type, ResultReceiver receiver) {
if (DBG) mLog.i("runUiTetherProvisioning: " + type); if (DBG) mLog.i("runUiTetherProvisioning: " + type);
Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING); Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING);
intent.putExtra(EXTRA_ADD_TETHER_TYPE, type); intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver); intent.putExtra(EXTRA_PROVISION_CALLBACK, receiver);
intent.putExtra(EXTRA_SUBID, subId);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
try { try {
@@ -396,9 +413,9 @@ public class EntitlementManager {
} }
// Not needed to check if this don't run on the handler thread because it's private. // Not needed to check if this don't run on the handler thread because it's private.
private void scheduleProvisioningRechecks() { private void scheduleProvisioningRechecks(final TetheringConfiguration config) {
if (mProvisioningRecheckAlarm == null) { if (mProvisioningRecheckAlarm == null) {
final int period = mConfig.provisioningCheckPeriod; final int period = config.provisioningCheckPeriod;
if (period <= 0) return; if (period <= 0) return;
Intent intent = new Intent(ACTION_PROVISIONING_ALARM); Intent intent = new Intent(ACTION_PROVISIONING_ALARM);
@@ -421,9 +438,9 @@ public class EntitlementManager {
} }
} }
private void evaluateCellularPermission() { private void evaluateCellularPermission(final TetheringConfiguration config) {
final boolean oldPermitted = mCellularUpstreamPermitted; final boolean oldPermitted = mCellularUpstreamPermitted;
mCellularUpstreamPermitted = (!isTetherProvisioningRequired() mCellularUpstreamPermitted = (!isTetherProvisioningRequired(config)
|| mCellularPermitted.indexOfValue(TETHER_ERROR_NO_ERROR) > -1); || mCellularPermitted.indexOfValue(TETHER_ERROR_NO_ERROR) > -1);
if (DBG) { if (DBG) {
@@ -438,7 +455,7 @@ public class EntitlementManager {
// Only schedule periodic re-check when tether is provisioned // Only schedule periodic re-check when tether is provisioned
// and the result is ok. // and the result is ok.
if (mCellularUpstreamPermitted && mCellularPermitted.size() > 0) { if (mCellularUpstreamPermitted && mCellularPermitted.size() > 0) {
scheduleProvisioningRechecks(); scheduleProvisioningRechecks(config);
} else { } else {
cancelTetherProvisioningRechecks(); cancelTetherProvisioningRechecks();
} }
@@ -457,7 +474,8 @@ public class EntitlementManager {
if (!mCurrentTethers.contains(type)) return; if (!mCurrentTethers.contains(type)) return;
mCellularPermitted.put(type, resultCode); mCellularPermitted.put(type, resultCode);
evaluateCellularPermission(); final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
evaluateCellularPermission(config);
} }
/** /**
@@ -467,7 +485,8 @@ public class EntitlementManager {
protected void removeDownstreamMapping(int type) { protected void removeDownstreamMapping(int type) {
mLog.i("removeDownstreamMapping: " + type); mLog.i("removeDownstreamMapping: " + type);
mCellularPermitted.delete(type); mCellularPermitted.delete(type);
evaluateCellularPermission(); final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
evaluateCellularPermission(config);
} }
private final BroadcastReceiver mReceiver = new BroadcastReceiver() { private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -475,7 +494,8 @@ public class EntitlementManager {
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (ACTION_PROVISIONING_ALARM.equals(intent.getAction())) { if (ACTION_PROVISIONING_ALARM.equals(intent.getAction())) {
mLog.log("Received provisioning alarm"); mLog.log("Received provisioning alarm");
reevaluateSimCardProvisioning(); final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
reevaluateSimCardProvisioning(config);
} }
} }
}; };
@@ -498,7 +518,8 @@ public class EntitlementManager {
handleNotifyUpstream(toBool(msg.arg1)); handleNotifyUpstream(toBool(msg.arg1));
break; break;
case EVENT_MAYBE_RUN_PROVISIONING: case EVENT_MAYBE_RUN_PROVISIONING:
handleMaybeRunProvisioning(); final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
handleMaybeRunProvisioning(config);
break; break;
case EVENT_GET_ENTITLEMENT_VALUE: case EVENT_GET_ENTITLEMENT_VALUE:
handleGetLatestTetheringEntitlementValue(msg.arg1, (ResultReceiver) msg.obj, handleGetLatestTetheringEntitlementValue(msg.arg1, (ResultReceiver) msg.obj,
@@ -636,7 +657,8 @@ public class EntitlementManager {
private void handleGetLatestTetheringEntitlementValue(int downstream, ResultReceiver receiver, private void handleGetLatestTetheringEntitlementValue(int downstream, ResultReceiver receiver,
boolean showEntitlementUi) { boolean showEntitlementUi) {
if (!isTetherProvisioningRequired()) { final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
if (!isTetherProvisioningRequired(config)) {
receiver.send(TETHER_ERROR_NO_ERROR, null); receiver.send(TETHER_ERROR_NO_ERROR, null);
return; return;
} }
@@ -647,7 +669,7 @@ public class EntitlementManager {
receiver.send(cacheValue, null); receiver.send(cacheValue, null);
} else { } else {
ResultReceiver proxy = buildProxyReceiver(downstream, false/* notifyFail */, receiver); ResultReceiver proxy = buildProxyReceiver(downstream, false/* notifyFail */, receiver);
runUiTetherProvisioning(downstream, proxy); runUiTetherProvisioning(downstream, config.subId, proxy);
} }
} }
} }

View File

@@ -29,6 +29,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
@@ -93,6 +94,7 @@ public final class EntitlementManagerTest {
private TestStateMachine mSM; private TestStateMachine mSM;
private WrappedEntitlementManager mEnMgr; private WrappedEntitlementManager mEnMgr;
private TetheringConfiguration mConfig;
private class MockContext extends BroadcastInterceptingContext { private class MockContext extends BroadcastInterceptingContext {
MockContext(Context base) { MockContext(Context base) {
@@ -127,13 +129,13 @@ public final class EntitlementManagerTest {
} }
@Override @Override
protected void runUiTetherProvisioning(int type, ResultReceiver receiver) { protected void runUiTetherProvisioning(int type, int subId, ResultReceiver receiver) {
uiProvisionCount++; uiProvisionCount++;
receiver.send(fakeEntitlementResult, null); receiver.send(fakeEntitlementResult, null);
} }
@Override @Override
protected void runSilentTetherProvisioning(int type) { protected void runSilentTetherProvisioning(int type, int subId) {
silentProvisionCount++; silentProvisionCount++;
addDownstreamMapping(type, fakeEntitlementResult); addDownstreamMapping(type, fakeEntitlementResult);
} }
@@ -162,8 +164,10 @@ public final class EntitlementManagerTest {
mEnMgr = new WrappedEntitlementManager(mMockContext, mSM, mLog, EVENT_EM_UPDATE, mEnMgr = new WrappedEntitlementManager(mMockContext, mSM, mLog, EVENT_EM_UPDATE,
mSystemProperties); mSystemProperties);
mEnMgr.setOnUiEntitlementFailedListener(mEntitlementFailedListener); mEnMgr.setOnUiEntitlementFailedListener(mEntitlementFailedListener);
mEnMgr.updateConfiguration( mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID)); mEnMgr.setTetheringConfigurationFetcher(() -> {
return mConfig;
});
} }
@After @After
@@ -186,17 +190,16 @@ public final class EntitlementManagerTest {
// Act like the CarrierConfigManager is present and ready unless told otherwise. // Act like the CarrierConfigManager is present and ready unless told otherwise.
when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE)) when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
.thenReturn(mCarrierConfigManager); .thenReturn(mCarrierConfigManager);
when(mCarrierConfigManager.getConfig()).thenReturn(mCarrierConfig); when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mCarrierConfig);
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true); mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true); mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
} }
@Test @Test
public void canRequireProvisioning() { public void canRequireProvisioning() {
setupForRequiredProvisioning(); setupForRequiredProvisioning();
mEnMgr.updateConfiguration( assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
assertTrue(mEnMgr.isTetherProvisioningRequired());
} }
@Test @Test
@@ -204,31 +207,27 @@ public final class EntitlementManagerTest {
setupForRequiredProvisioning(); setupForRequiredProvisioning();
when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE)) when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
.thenReturn(null); .thenReturn(null);
mEnMgr.updateConfiguration( mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
// Couldn't get the CarrierConfigManager, but still had a declared provisioning app. // Couldn't get the CarrierConfigManager, but still had a declared provisioning app.
// Therefore provisioning still be required. // Therefore provisioning still be required.
assertTrue(mEnMgr.isTetherProvisioningRequired()); assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
} }
@Test @Test
public void toleratesCarrierConfigMissing() { public void toleratesCarrierConfigMissing() {
setupForRequiredProvisioning(); setupForRequiredProvisioning();
when(mCarrierConfigManager.getConfig()).thenReturn(null); when(mCarrierConfigManager.getConfig()).thenReturn(null);
mEnMgr.updateConfiguration( mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
// We still have a provisioning app configured, so still require provisioning. // We still have a provisioning app configured, so still require provisioning.
assertTrue(mEnMgr.isTetherProvisioningRequired()); assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
} }
@Test @Test
public void toleratesCarrierConfigNotLoaded() { public void toleratesCarrierConfigNotLoaded() {
setupForRequiredProvisioning(); setupForRequiredProvisioning();
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, false); mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
mEnMgr.updateConfiguration(
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID));
// We still have a provisioning app configured, so still require provisioning. // We still have a provisioning app configured, so still require provisioning.
assertTrue(mEnMgr.isTetherProvisioningRequired()); assertTrue(mEnMgr.isTetherProvisioningRequired(mConfig));
} }
@Test @Test
@@ -236,14 +235,12 @@ public final class EntitlementManagerTest {
setupForRequiredProvisioning(); setupForRequiredProvisioning();
when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app)) when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
.thenReturn(null); .thenReturn(null);
mEnMgr.updateConfiguration( mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID)); assertFalse(mEnMgr.isTetherProvisioningRequired(mConfig));
assertFalse(mEnMgr.isTetherProvisioningRequired());
when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app)) when(mResources.getStringArray(R.array.config_mobile_hotspot_provision_app))
.thenReturn(new String[] {"malformedApp"}); .thenReturn(new String[] {"malformedApp"});
mEnMgr.updateConfiguration( mConfig = new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
new TetheringConfiguration(mMockContext, mLog, INVALID_SUBSCRIPTION_ID)); assertFalse(mEnMgr.isTetherProvisioningRequired(mConfig));
assertFalse(mEnMgr.isTetherProvisioningRequired());
} }
@Test @Test
@@ -265,8 +262,6 @@ public final class EntitlementManagerTest {
mEnMgr.reset(); mEnMgr.reset();
setupForRequiredProvisioning(); setupForRequiredProvisioning();
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
INVALID_SUBSCRIPTION_ID));
// 2. No cache value and don't need to run entitlement check. // 2. No cache value and don't need to run entitlement check.
receiver = new ResultReceiver(null) { receiver = new ResultReceiver(null) {
@Override @Override
@@ -361,8 +356,6 @@ public final class EntitlementManagerTest {
public void verifyPermissionResult() { public void verifyPermissionResult() {
setupForRequiredProvisioning(); setupForRequiredProvisioning();
mEnMgr.notifyUpstream(true); mEnMgr.notifyUpstream(true);
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
INVALID_SUBSCRIPTION_ID));
mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED; mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll(); mLooper.dispatchAll();
@@ -379,8 +372,6 @@ public final class EntitlementManagerTest {
public void verifyPermissionIfAllNotApproved() { public void verifyPermissionIfAllNotApproved() {
setupForRequiredProvisioning(); setupForRequiredProvisioning();
mEnMgr.notifyUpstream(true); mEnMgr.notifyUpstream(true);
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
INVALID_SUBSCRIPTION_ID));
mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED; mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll(); mLooper.dispatchAll();
@@ -399,8 +390,6 @@ public final class EntitlementManagerTest {
public void verifyPermissionIfAnyApproved() { public void verifyPermissionIfAnyApproved() {
setupForRequiredProvisioning(); setupForRequiredProvisioning();
mEnMgr.notifyUpstream(true); mEnMgr.notifyUpstream(true);
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
INVALID_SUBSCRIPTION_ID));
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true); mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll(); mLooper.dispatchAll();
@@ -419,8 +408,6 @@ public final class EntitlementManagerTest {
@Test @Test
public void testRunTetherProvisioning() { public void testRunTetherProvisioning() {
setupForRequiredProvisioning(); setupForRequiredProvisioning();
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
INVALID_SUBSCRIPTION_ID));
// 1. start ui provisioning, upstream is mobile // 1. start ui provisioning, upstream is mobile
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR; mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
mEnMgr.notifyUpstream(true); mEnMgr.notifyUpstream(true);
@@ -458,7 +445,7 @@ public final class EntitlementManagerTest {
// 5. tear down mobile, then switch SIM // 5. tear down mobile, then switch SIM
mEnMgr.notifyUpstream(false); mEnMgr.notifyUpstream(false);
mLooper.dispatchAll(); mLooper.dispatchAll();
mEnMgr.reevaluateSimCardProvisioning(); mEnMgr.reevaluateSimCardProvisioning(mConfig);
assertEquals(0, mEnMgr.uiProvisionCount); assertEquals(0, mEnMgr.uiProvisionCount);
assertEquals(0, mEnMgr.silentProvisionCount); assertEquals(0, mEnMgr.silentProvisionCount);
mEnMgr.reset(); mEnMgr.reset();
@@ -474,8 +461,6 @@ public final class EntitlementManagerTest {
@Test @Test
public void testCallStopTetheringWhenUiProvisioningFail() { public void testCallStopTetheringWhenUiProvisioningFail() {
setupForRequiredProvisioning(); setupForRequiredProvisioning();
mEnMgr.updateConfiguration(new TetheringConfiguration(mMockContext, mLog,
INVALID_SUBSCRIPTION_ID));
verify(mEntitlementFailedListener, times(0)).onUiEntitlementFailed(TETHERING_WIFI); verify(mEntitlementFailedListener, times(0)).onUiEntitlementFailed(TETHERING_WIFI);
mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED; mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
mEnMgr.notifyUpstream(true); mEnMgr.notifyUpstream(true);
@@ -486,7 +471,6 @@ public final class EntitlementManagerTest {
verify(mEntitlementFailedListener, times(1)).onUiEntitlementFailed(TETHERING_WIFI); verify(mEntitlementFailedListener, times(1)).onUiEntitlementFailed(TETHERING_WIFI);
} }
public class TestStateMachine extends StateMachine { public class TestStateMachine extends StateMachine {
public final ArrayList<Message> messages = new ArrayList<>(); public final ArrayList<Message> messages = new ArrayList<>();
private final State private final State