Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 073c203d authored by Mark Chien's avatar Mark Chien Committed by Gerrit Code Review
Browse files

Merge "Fix entitlement failed when device is on CBRS"

parents cc8dd8f2 04bdf873
Loading
Loading
Loading
Loading
+30 −33
Original line number Diff line number Diff line
@@ -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.WIFI_AP_STATE_DISABLED;
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;

@@ -89,6 +90,8 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.os.UserManagerInternal.UserRestrictionsListener;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -97,7 +100,6 @@ import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.MessageUtils;
@@ -182,12 +184,13 @@ public class Tethering extends BaseNetworkObserver {
    // into a single coherent structure.
    private final HashSet<IpServer> mForwardedDownstreams;
    private final VersionedBroadcastListener mCarrierConfigChange;
    private final VersionedBroadcastListener mDefaultSubscriptionChange;
    private final TetheringDependencies mDeps;
    private final EntitlementManager mEntitlementMgr;
    private final Handler mHandler;
    private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks =
            new RemoteCallbackList<>();
    private final PhoneStateListener mPhoneStateListener;
    private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID;

    private volatile TetheringConfiguration mConfig;
    private InterfaceSet mCurrentUpstreamIfaceSet;
@@ -238,7 +241,6 @@ public class Tethering extends BaseNetworkObserver {
            stopTethering(downstream);
        });
        mEntitlementMgr.setTetheringConfigurationFetcher(() -> {
            maybeDefaultDataSubChanged();
            return mConfig;
        });

@@ -250,14 +252,16 @@ public class Tethering extends BaseNetworkObserver {
                    mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
                });

        filter = new IntentFilter();
        filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
        mDefaultSubscriptionChange = new VersionedBroadcastListener(
                "DefaultSubscriptionChangeListener", mContext, mHandler, filter,
                (Intent ignored) -> {
                    mLog.log("OBSERVED default data subscription change");
                    maybeDefaultDataSubChanged();
                    // To avoid launch unexpected provisioning checks, ignore re-provisioning when
        mPhoneStateListener = new PhoneStateListener(mLooper) {
            @Override
            public void onActiveDataSubscriptionIdChanged(int subId) {
                mLog.log("OBSERVED active data subscription change, from " + mActiveDataSubId
                        + " to " + subId);
                if (subId == mActiveDataSubId) return;

                mActiveDataSubId = subId;
                updateConfiguration();
                // 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) {
@@ -265,7 +269,9 @@ public class Tethering extends BaseNetworkObserver {
                } else {
                    mLog.log("IGNORED reevaluate provisioning due to no carrier config loaded");
                }
                });
            }
        };

        mStateReceiver = new StateReceiver();

        // Load tethering configuration.
@@ -276,7 +282,8 @@ public class Tethering extends BaseNetworkObserver {

    private void startStateMachineUpdaters(Handler handler) {
        mCarrierConfigChange.startListening();
        mDefaultSubscriptionChange.startListening();
        TelephonyManager.from(mContext).listen(mPhoneStateListener,
                PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);

        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_STATE);
@@ -304,27 +311,17 @@ public class Tethering extends BaseNetworkObserver {

    // NOTE: This is always invoked on the mLooper thread.
    private void updateConfiguration() {
        final int subId = mDeps.getDefaultDataSubscriptionId();
        updateConfiguration(subId);
    }

    private void updateConfiguration(final int subId) {
        mConfig = new TetheringConfiguration(mContext, mLog, subId);
        mConfig = mDeps.generateTetheringConfiguration(mContext, mLog, mActiveDataSubId);
        mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired);
    }

    private void maybeDunSettingChanged() {
        final boolean isDunRequired = TetheringConfiguration.checkDunRequired(mContext);
        final boolean isDunRequired = TetheringConfiguration.checkDunRequired(
                mContext, mActiveDataSubId);
        if (isDunRequired == mConfig.isDunRequired) return;
        updateConfiguration();
    }

    private void maybeDefaultDataSubChanged() {
        final int subId = mDeps.getDefaultDataSubscriptionId();
        if (subId == mConfig.subId) return;
        updateConfiguration(subId);
    }

    @Override
    public void interfaceStatusChanged(String iface, boolean up) {
        // Never called directly: only called from interfaceLinkStateChanged.
+3 −3
Original line number Diff line number Diff line
@@ -112,7 +112,7 @@ public class TetheringConfiguration {
        tetherableWifiRegexs = getResourceStringArray(res, config_tether_wifi_regexs);
        tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs);

        isDunRequired = checkDunRequired(ctx);
        isDunRequired = checkDunRequired(ctx, subId);

        chooseUpstreamAutomatically = getResourceBoolean(res, config_tether_upstream_automatic);
        preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired);
@@ -228,9 +228,9 @@ public class TetheringConfiguration {
    }

    /** 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);
        return (tm != null) ? tm.getTetherApnRequired() : false;
        return (tm != null) ? tm.getTetherApnRequired(id) : false;
    }

    private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) {
+4 −4
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import android.net.NetworkRequest;
import android.net.ip.IpServer;
import android.net.util.SharedLog;
import android.os.Handler;
import android.telephony.SubscriptionManager;

import com.android.internal.util.StateMachine;
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() {
        return SubscriptionManager.getDefaultDataSubscriptionId();
    public TetheringConfiguration generateTetheringConfiguration(Context ctx, SharedLog log,
            int subId) {
        return new TetheringConfiguration(ctx, log, subId);
    }
}
+37 −2
Original line number Diff line number Diff line
@@ -100,6 +100,8 @@ import android.os.UserManager;
import android.os.test.TestLooper;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.test.mock.MockContentResolver;

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.server.connectivity.tethering.IPv6TetheringCoordinator;
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.UpstreamNetworkMonitor;

@@ -118,6 +121,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@@ -147,6 +151,7 @@ public class TetheringTest {
    @Mock private MockableSystemProperties mSystemProperties;
    @Mock private OffloadHardwareInterface mOffloadHardwareInterface;
    @Mock private Resources mResources;
    @Mock private TelephonyManager mTelephonyManager;
    @Mock private UsbManager mUsbManager;
    @Mock private WifiManager mWifiManager;
    @Mock private CarrierConfigManager mCarrierConfigManager;
@@ -171,6 +176,7 @@ public class TetheringTest {
    private MockContentResolver mContentResolver;
    private BroadcastReceiver mBroadcastReceiver;
    private Tethering mTethering;
    private PhoneStateListener mPhoneStateListener;

    private class MockContext extends BroadcastInterceptingContext {
        MockContext(Context base) {
@@ -193,6 +199,7 @@ public class TetheringTest {
        public Object getSystemService(String name) {
            if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
            if (Context.USB_SERVICE.equals(name)) return mUsbManager;
            if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
            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 {
        StateMachine upstreamNetworkMonitorMasterSM;
        ArrayList<IpServer> ipv6CoordinatorNotifyList;
@@ -276,8 +294,9 @@ public class TetheringTest {
        }

        @Override
        public int getDefaultDataSubscriptionId() {
            return INVALID_SUBSCRIPTION_ID;
        public TetheringConfiguration generateTetheringConfiguration(Context ctx, SharedLog log,
                int subId) {
            return new MockTetheringConfiguration(ctx, log, subId);
        }
    }

@@ -372,6 +391,11 @@ public class TetheringTest {
        mTetheringDependencies.reset();
        mTethering = makeTethering();
        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() {
@@ -982,6 +1006,17 @@ public class TetheringTest {
        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
    // already operating tethering mode interface.
}
+6 −5
Original line number Diff line number Diff line
@@ -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.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.when;

import android.content.ContentResolver;
@@ -141,7 +142,7 @@ public class TetheringConfigurationTest {

    @Test
    public void testDunFromTelephonyManagerMeansDun() {
        when(mTelephonyManager.getTetherApnRequired()).thenReturn(true);
        when(mTelephonyManager.getTetherApnRequired(anyInt())).thenReturn(true);

        final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI);
        final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration(
@@ -165,7 +166,7 @@ public class TetheringConfigurationTest {

    @Test
    public void testDunNotRequiredFromTelephonyManagerMeansNoDun() {
        when(mTelephonyManager.getTetherApnRequired()).thenReturn(false);
        when(mTelephonyManager.getTetherApnRequired(anyInt())).thenReturn(false);

        final TetheringConfiguration cfgWifi = getTetheringConfiguration(TYPE_WIFI);
        final TetheringConfiguration cfgMobileWifiHipri = getTetheringConfiguration(
@@ -208,7 +209,7 @@ public class TetheringConfigurationTest {
    @Test
    public void testNoDefinedUpstreamTypesAddsEthernet() {
        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(
                mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -231,7 +232,7 @@ public class TetheringConfigurationTest {
    public void testDefinedUpstreamTypesSansEthernetAddsEthernet() {
        when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(
                new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI});
        when(mTelephonyManager.getTetherApnRequired()).thenReturn(false);
        when(mTelephonyManager.getTetherApnRequired(anyInt())).thenReturn(false);

        final TetheringConfiguration cfg = new TetheringConfiguration(
                mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
@@ -249,7 +250,7 @@ public class TetheringConfigurationTest {
    public void testDefinedUpstreamTypesWithEthernetDoesNotAddEthernet() {
        when(mResources.getIntArray(config_tether_upstream_types))
                .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(
                mMockContext, mLog, INVALID_SUBSCRIPTION_ID);