Merge "Fix entitlement failed when device is on CBRS" am: 073c203dae

am: 4e7c3ad945

Change-Id: I45354a577b49ec09b3f3fd879f059d676eb42d54
This commit is contained in:
Mark Chien
2019-07-08 14:19:17 -07:00
committed by android-build-merger
5 changed files with 80 additions and 47 deletions

View File

@@ -44,6 +44,7 @@ import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
import static android.net.wifi.WifiManager.IFACE_IP_MODE_UNSPECIFIED; import static android.net.wifi.WifiManager.IFACE_IP_MODE_UNSPECIFIED;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED; import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.android.server.ConnectivityService.SHORT_ARG; import static com.android.server.ConnectivityService.SHORT_ARG;
@@ -89,6 +90,8 @@ import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.os.UserManagerInternal; import android.os.UserManagerInternal;
import android.os.UserManagerInternal.UserRestrictionsListener; import android.os.UserManagerInternal.UserRestrictionsListener;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.Log; import android.util.Log;
@@ -97,7 +100,6 @@ import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.DumpUtils; import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.MessageUtils; import com.android.internal.util.MessageUtils;
@@ -182,12 +184,13 @@ public class Tethering extends BaseNetworkObserver {
// into a single coherent structure. // into a single coherent structure.
private final HashSet<IpServer> mForwardedDownstreams; private final HashSet<IpServer> mForwardedDownstreams;
private final VersionedBroadcastListener mCarrierConfigChange; private final VersionedBroadcastListener mCarrierConfigChange;
private final VersionedBroadcastListener mDefaultSubscriptionChange;
private final TetheringDependencies mDeps; private final TetheringDependencies mDeps;
private final EntitlementManager mEntitlementMgr; private final EntitlementManager mEntitlementMgr;
private final Handler mHandler; private final Handler mHandler;
private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks = private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks =
new RemoteCallbackList<>(); new RemoteCallbackList<>();
private final PhoneStateListener mPhoneStateListener;
private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID;
private volatile TetheringConfiguration mConfig; private volatile TetheringConfiguration mConfig;
private InterfaceSet mCurrentUpstreamIfaceSet; private InterfaceSet mCurrentUpstreamIfaceSet;
@@ -238,7 +241,6 @@ public class Tethering extends BaseNetworkObserver {
stopTethering(downstream); stopTethering(downstream);
}); });
mEntitlementMgr.setTetheringConfigurationFetcher(() -> { mEntitlementMgr.setTetheringConfigurationFetcher(() -> {
maybeDefaultDataSubChanged();
return mConfig; return mConfig;
}); });
@@ -250,22 +252,26 @@ public class Tethering extends BaseNetworkObserver {
mEntitlementMgr.reevaluateSimCardProvisioning(mConfig); mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
}); });
filter = new IntentFilter(); mPhoneStateListener = new PhoneStateListener(mLooper) {
filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); @Override
mDefaultSubscriptionChange = new VersionedBroadcastListener( public void onActiveDataSubscriptionIdChanged(int subId) {
"DefaultSubscriptionChangeListener", mContext, mHandler, filter, mLog.log("OBSERVED active data subscription change, from " + mActiveDataSubId
(Intent ignored) -> { + " to " + subId);
mLog.log("OBSERVED default data subscription change"); if (subId == mActiveDataSubId) return;
maybeDefaultDataSubChanged();
// To avoid launch unexpected provisioning checks, ignore re-provisioning when mActiveDataSubId = subId;
// no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning() will be updateConfiguration();
// triggered again when CarrierConfig is loaded. // To avoid launching unexpected provisioning checks, ignore re-provisioning when
if (mEntitlementMgr.getCarrierConfig(mConfig) != null) { // no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning() will be
mEntitlementMgr.reevaluateSimCardProvisioning(mConfig); // triggered again when CarrierConfig is loaded.
} else { if (mEntitlementMgr.getCarrierConfig(mConfig) != null) {
mLog.log("IGNORED reevaluate provisioning due to no carrier config loaded"); mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
} } else {
}); mLog.log("IGNORED reevaluate provisioning due to no carrier config loaded");
}
}
};
mStateReceiver = new StateReceiver(); mStateReceiver = new StateReceiver();
// Load tethering configuration. // Load tethering configuration.
@@ -276,7 +282,8 @@ public class Tethering extends BaseNetworkObserver {
private void startStateMachineUpdaters(Handler handler) { private void startStateMachineUpdaters(Handler handler) {
mCarrierConfigChange.startListening(); mCarrierConfigChange.startListening();
mDefaultSubscriptionChange.startListening(); TelephonyManager.from(mContext).listen(mPhoneStateListener,
PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_STATE); filter.addAction(UsbManager.ACTION_USB_STATE);
@@ -304,27 +311,17 @@ 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(); mConfig = mDeps.generateTetheringConfiguration(mContext, mLog, mActiveDataSubId);
updateConfiguration(subId);
}
private void updateConfiguration(final int subId) {
mConfig = new TetheringConfiguration(mContext, mLog, subId);
mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired); mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired);
} }
private void maybeDunSettingChanged() { private void maybeDunSettingChanged() {
final boolean isDunRequired = TetheringConfiguration.checkDunRequired(mContext); final boolean isDunRequired = TetheringConfiguration.checkDunRequired(
mContext, mActiveDataSubId);
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.

View File

@@ -112,7 +112,7 @@ public class TetheringConfiguration {
tetherableWifiRegexs = getResourceStringArray(res, config_tether_wifi_regexs); tetherableWifiRegexs = getResourceStringArray(res, config_tether_wifi_regexs);
tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs); tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs);
isDunRequired = checkDunRequired(ctx); isDunRequired = checkDunRequired(ctx, subId);
chooseUpstreamAutomatically = getResourceBoolean(res, config_tether_upstream_automatic); chooseUpstreamAutomatically = getResourceBoolean(res, config_tether_upstream_automatic);
preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired); preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired);
@@ -228,9 +228,9 @@ public class TetheringConfiguration {
} }
/** Check whether dun is required. */ /** Check whether dun is required. */
public static boolean checkDunRequired(Context ctx) { public static boolean checkDunRequired(Context ctx, int id) {
final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE); final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE);
return (tm != null) ? tm.getTetherApnRequired() : false; return (tm != null) ? tm.getTetherApnRequired(id) : false;
} }
private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) { private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) {

View File

@@ -21,7 +21,6 @@ import android.net.NetworkRequest;
import android.net.ip.IpServer; import android.net.ip.IpServer;
import android.net.util.SharedLog; import android.net.util.SharedLog;
import android.os.Handler; import android.os.Handler;
import android.telephony.SubscriptionManager;
import com.android.internal.util.StateMachine; import com.android.internal.util.StateMachine;
import com.android.server.connectivity.MockableSystemProperties; import com.android.server.connectivity.MockableSystemProperties;
@@ -88,9 +87,10 @@ public class TetheringDependencies {
} }
/** /**
* Get default data subscription id to build TetheringConfiguration. * Generate a new TetheringConfiguration according to input sub Id.
*/ */
public int getDefaultDataSubscriptionId() { public TetheringConfiguration generateTetheringConfiguration(Context ctx, SharedLog log,
return SubscriptionManager.getDefaultDataSubscriptionId(); int subId) {
return new TetheringConfiguration(ctx, log, subId);
} }
} }

View File

@@ -100,6 +100,8 @@ import android.os.UserManager;
import android.os.test.TestLooper; import android.os.test.TestLooper;
import android.provider.Settings; import android.provider.Settings;
import android.telephony.CarrierConfigManager; import android.telephony.CarrierConfigManager;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.test.mock.MockContentResolver; import android.test.mock.MockContentResolver;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -111,6 +113,7 @@ import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.connectivity.tethering.IPv6TetheringCoordinator; import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
import com.android.server.connectivity.tethering.OffloadHardwareInterface; import com.android.server.connectivity.tethering.OffloadHardwareInterface;
import com.android.server.connectivity.tethering.TetheringConfiguration;
import com.android.server.connectivity.tethering.TetheringDependencies; import com.android.server.connectivity.tethering.TetheringDependencies;
import com.android.server.connectivity.tethering.UpstreamNetworkMonitor; import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
@@ -118,6 +121,7 @@ import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
@@ -147,6 +151,7 @@ public class TetheringTest {
@Mock private MockableSystemProperties mSystemProperties; @Mock private MockableSystemProperties mSystemProperties;
@Mock private OffloadHardwareInterface mOffloadHardwareInterface; @Mock private OffloadHardwareInterface mOffloadHardwareInterface;
@Mock private Resources mResources; @Mock private Resources mResources;
@Mock private TelephonyManager mTelephonyManager;
@Mock private UsbManager mUsbManager; @Mock private UsbManager mUsbManager;
@Mock private WifiManager mWifiManager; @Mock private WifiManager mWifiManager;
@Mock private CarrierConfigManager mCarrierConfigManager; @Mock private CarrierConfigManager mCarrierConfigManager;
@@ -171,6 +176,7 @@ public class TetheringTest {
private MockContentResolver mContentResolver; private MockContentResolver mContentResolver;
private BroadcastReceiver mBroadcastReceiver; private BroadcastReceiver mBroadcastReceiver;
private Tethering mTethering; private Tethering mTethering;
private PhoneStateListener mPhoneStateListener;
private class MockContext extends BroadcastInterceptingContext { private class MockContext extends BroadcastInterceptingContext {
MockContext(Context base) { MockContext(Context base) {
@@ -193,6 +199,7 @@ public class TetheringTest {
public Object getSystemService(String name) { public Object getSystemService(String name) {
if (Context.WIFI_SERVICE.equals(name)) return mWifiManager; if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
if (Context.USB_SERVICE.equals(name)) return mUsbManager; if (Context.USB_SERVICE.equals(name)) return mUsbManager;
if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
return super.getSystemService(name); return super.getSystemService(name);
} }
} }
@@ -234,6 +241,17 @@ public class TetheringTest {
} }
} }
private class MockTetheringConfiguration extends TetheringConfiguration {
MockTetheringConfiguration(Context ctx, SharedLog log, int id) {
super(ctx, log, id);
}
@Override
protected Resources getResourcesForSubIdWrapper(Context ctx, int subId) {
return mResources;
}
}
public class MockTetheringDependencies extends TetheringDependencies { public class MockTetheringDependencies extends TetheringDependencies {
StateMachine upstreamNetworkMonitorMasterSM; StateMachine upstreamNetworkMonitorMasterSM;
ArrayList<IpServer> ipv6CoordinatorNotifyList; ArrayList<IpServer> ipv6CoordinatorNotifyList;
@@ -276,8 +294,9 @@ public class TetheringTest {
} }
@Override @Override
public int getDefaultDataSubscriptionId() { public TetheringConfiguration generateTetheringConfiguration(Context ctx, SharedLog log,
return INVALID_SUBSCRIPTION_ID; int subId) {
return new MockTetheringConfiguration(ctx, log, subId);
} }
} }
@@ -372,6 +391,11 @@ public class TetheringTest {
mTetheringDependencies.reset(); mTetheringDependencies.reset();
mTethering = makeTethering(); mTethering = makeTethering();
verify(mNMService).registerTetheringStatsProvider(any(), anyString()); verify(mNMService).registerTetheringStatsProvider(any(), anyString());
final ArgumentCaptor<PhoneStateListener> phoneListenerCaptor =
ArgumentCaptor.forClass(PhoneStateListener.class);
verify(mTelephonyManager).listen(phoneListenerCaptor.capture(),
eq(PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE));
mPhoneStateListener = phoneListenerCaptor.getValue();
} }
private Tethering makeTethering() { private Tethering makeTethering() {
@@ -982,6 +1006,17 @@ public class TetheringTest {
callback2.expectUpstreamChanged(upstreamState.network); callback2.expectUpstreamChanged(upstreamState.network);
} }
@Test
public void testMultiSimAware() throws Exception {
final TetheringConfiguration initailConfig = mTethering.getTetheringConfiguration();
assertEquals(INVALID_SUBSCRIPTION_ID, initailConfig.subId);
final int fakeSubId = 1234;
mPhoneStateListener.onActiveDataSubscriptionIdChanged(fakeSubId);
final TetheringConfiguration newConfig = mTethering.getTetheringConfiguration();
assertEquals(fakeSubId, newConfig.subId);
}
// TODO: Test that a request for hotspot mode doesn't interfere with an // TODO: Test that a request for hotspot mode doesn't interfere with an
// already operating tethering mode interface. // already operating tethering mode interface.
} }

View File

@@ -29,6 +29,7 @@ import static com.android.internal.R.array.config_tether_upstream_types;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.content.ContentResolver; import android.content.ContentResolver;
@@ -141,7 +142,7 @@ public class TetheringConfigurationTest {
@Test @Test
public void testDunFromTelephonyManagerMeansDun() { public void testDunFromTelephonyManagerMeansDun() {
when(mTelephonyManager.getTetherApnRequired()).thenReturn(true); when(mTelephonyManager.getTetherApnRequired(anyInt())).thenReturn(true);
final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI); final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI);
final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration( final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration(
@@ -165,7 +166,7 @@ public class TetheringConfigurationTest {
@Test @Test
public void testDunNotRequiredFromTelephonyManagerMeansNoDun() { public void testDunNotRequiredFromTelephonyManagerMeansNoDun() {
when(mTelephonyManager.getTetherApnRequired()).thenReturn(false); when(mTelephonyManager.getTetherApnRequired(anyInt())).thenReturn(false);
final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI); final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI);
final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration( final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration(
@@ -208,7 +209,7 @@ public class TetheringConfigurationTest {
@Test @Test
public void testNoDefinedUpstreamTypesAddsEthernet() { public void testNoDefinedUpstreamTypesAddsEthernet() {
when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(new int[]{}); when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(new int[]{});
when(mTelephonyManager.getTetherApnRequired()).thenReturn(false); when(mTelephonyManager.getTetherApnRequired(anyInt())).thenReturn(false);
final TetheringConfiguration cfg = new TetheringConfiguration( final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID); mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -231,7 +232,7 @@ public class TetheringConfigurationTest {
public void testDefinedUpstreamTypesSansEthernetAddsEthernet() { public void testDefinedUpstreamTypesSansEthernetAddsEthernet() {
when(mResources.getIntArray(config_tether_upstream_types)).thenReturn( when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(
new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI}); new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI});
when(mTelephonyManager.getTetherApnRequired()).thenReturn(false); when(mTelephonyManager.getTetherApnRequired(anyInt())).thenReturn(false);
final TetheringConfiguration cfg = new TetheringConfiguration( final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID); mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -249,7 +250,7 @@ public class TetheringConfigurationTest {
public void testDefinedUpstreamTypesWithEthernetDoesNotAddEthernet() { public void testDefinedUpstreamTypesWithEthernetDoesNotAddEthernet() {
when(mResources.getIntArray(config_tether_upstream_types)) when(mResources.getIntArray(config_tether_upstream_types))
.thenReturn(new int[]{TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_HIPRI}); .thenReturn(new int[]{TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_HIPRI});
when(mTelephonyManager.getTetherApnRequired()).thenReturn(false); when(mTelephonyManager.getTetherApnRequired(anyInt())).thenReturn(false);
final TetheringConfiguration cfg = new TetheringConfiguration( final TetheringConfiguration cfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID); mMockContext, mLog, INVALID_SUBSCRIPTION_ID);