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

Commit 071c3abf authored by markchien's avatar markchien Committed by Mark Chien
Browse files

Make members final in TetheringService

1. Move isTetheringSupport logic from TetheringService to Tethering.
2. Small readability improvement in TetheringTest. Also change
config_tether_upstream_automatic from false to true in TetheringTest.
So TetheringTests would default run automatic select upstream flow
instead of selecting by legacy perferred network type list.

Bug: 153609486
Test: atest TetheringTest
Change-Id: I5a82a6347f62d3a7031db5c56e8e0c8530dafd8f
Merged-In: I5a82a6347f62d3a7031db5c56e8e0c8530dafd8f
(cherry picked from commit 458885a6)
parent 7f770f7a
Loading
Loading
Loading
Loading
+27 −9
Original line number Diff line number Diff line
@@ -109,8 +109,10 @@ import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceSpecificException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -228,6 +230,7 @@ public class Tethering {
    private final ConnectedClientsTracker mConnectedClientsTracker;
    private final TetheringThreadExecutor mExecutor;
    private final TetheringNotificationUpdater mNotificationUpdater;
    private final UserManager mUserManager;
    private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID;
    // All the usage of mTetheringEventCallback should run in the same thread.
    private ITetheringEventCallback mTetheringEventCallback = null;
@@ -305,23 +308,24 @@ public class Tethering {

        mStateReceiver = new StateReceiver();

        final UserManager userManager = (UserManager) mContext.getSystemService(
                Context.USER_SERVICE);
        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        mTetheringRestriction = new UserRestrictionActionListener(
                userManager, this, mNotificationUpdater);
                mUserManager, this, mNotificationUpdater);
        mExecutor = new TetheringThreadExecutor(mHandler);
        mActiveDataSubIdListener = new ActiveDataSubIdListener(mExecutor);
        mNetdCallback = new NetdCallback();

        // Load tethering configuration.
        updateConfiguration();

        startStateMachineUpdaters();
    }

    /**
     * Start to register callbacks.
     * Call this function when tethering is ready to handle callback events.
     */
    public void startStateMachineUpdaters() {
    private void startStateMachineUpdaters() {
        try {
            mNetd.registerUnsolicitedEventListener(mNetdCallback);
        } catch (RemoteException e) {
@@ -779,7 +783,7 @@ public class Tethering {

    // TODO: Figure out how to update for local hotspot mode interfaces.
    private void sendTetherStateChangedBroadcast() {
        if (!mDeps.isTetheringSupported()) return;
        if (!isTetheringSupported()) return;

        final ArrayList<String> availableList = new ArrayList<>();
        final ArrayList<String> tetherList = new ArrayList<>();
@@ -1020,14 +1024,14 @@ public class Tethering {

    @VisibleForTesting
    protected static class UserRestrictionActionListener {
        private final UserManager mUserManager;
        private final UserManager mUserMgr;
        private final Tethering mWrapper;
        private final TetheringNotificationUpdater mNotificationUpdater;
        public boolean mDisallowTethering;

        public UserRestrictionActionListener(@NonNull UserManager um, @NonNull Tethering wrapper,
                @NonNull TetheringNotificationUpdater updater) {
            mUserManager = um;
            mUserMgr = um;
            mWrapper = wrapper;
            mNotificationUpdater = updater;
            mDisallowTethering = false;
@@ -1037,7 +1041,7 @@ public class Tethering {
            // getUserRestrictions gets restriction for this process' user, which is the primary
            // user. This is fine because DISALLOW_CONFIG_TETHERING can only be set on the primary
            // user. See UserManager.DISALLOW_CONFIG_TETHERING.
            final Bundle restrictions = mUserManager.getUserRestrictions();
            final Bundle restrictions = mUserMgr.getUserRestrictions();
            final boolean newlyDisallowed =
                    restrictions.getBoolean(UserManager.DISALLOW_CONFIG_TETHERING);
            final boolean prevDisallowed = mDisallowTethering;
@@ -1988,7 +1992,7 @@ public class Tethering {
        mHandler.post(() -> {
            mTetheringEventCallbacks.register(callback, new CallbackCookie(hasListPermission));
            final TetheringCallbackStartedParcel parcel = new TetheringCallbackStartedParcel();
            parcel.tetheringSupported = mDeps.isTetheringSupported();
            parcel.tetheringSupported = isTetheringSupported();
            parcel.upstreamNetwork = mTetherUpstream;
            parcel.config = mConfig.toStableParcelable();
            parcel.states =
@@ -2111,6 +2115,20 @@ public class Tethering {
        }
    }

    // if ro.tether.denied = true we default to no tethering
    // gservices could set the secure setting to 1 though to enable it on a build where it
    // had previously been turned off.
    boolean isTetheringSupported() {
        final int defaultVal =
                SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1;
        final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
        final boolean tetherEnabledInSettings = tetherSupported
                && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);

        return tetherEnabledInSettings && hasTetherableConfiguration();
    }

    void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) {
        // Binder.java closes the resource for us.
        @SuppressWarnings("resource")
+71 −114
Original line number Diff line number Diff line
@@ -40,15 +40,12 @@ import android.net.TetheringRequestParcel;
import android.net.dhcp.DhcpServerCallbacks;
import android.net.dhcp.DhcpServingParamsParcel;
import android.net.ip.IpServer;
import android.net.util.SharedLog;
import android.os.Binder;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SystemProperties;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;

@@ -68,21 +65,14 @@ import java.io.PrintWriter;
public class TetheringService extends Service {
    private static final String TAG = TetheringService.class.getSimpleName();

    private final SharedLog mLog = new SharedLog(TAG);
    private TetheringConnector mConnector;
    private Context mContext;
    private TetheringDependencies mDeps;
    private Tethering mTethering;
    private UserManager mUserManager;

    @Override
    public void onCreate() {
        mLog.mark("onCreate");
        mDeps = getTetheringDependencies();
        mContext = mDeps.getContext();
        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        mTethering = makeTethering(mDeps);
        mTethering.startStateMachineUpdaters();
        final TetheringDependencies deps = makeTetheringDependencies();
        // The Tethering object needs a fully functional context to start, so this can't be done
        // in the constructor.
        mConnector = new TetheringConnector(makeTethering(deps), TetheringService.this);
    }

    /**
@@ -94,21 +84,10 @@ public class TetheringService extends Service {
        return new Tethering(deps);
    }

    /**
     * Create a binder connector for the system server to communicate with the tethering.
     */
    private synchronized IBinder makeConnector() {
        if (mConnector == null) {
            mConnector = new TetheringConnector(mTethering, TetheringService.this);
        }
        return mConnector;
    }

    @NonNull
    @Override
    public IBinder onBind(Intent intent) {
        mLog.mark("onBind");
        return makeConnector();
        return mConnector;
    }

    private static class TetheringConnector extends ITetheringConnector.Stub {
@@ -248,7 +227,7 @@ public class TetheringService extends Service {
                    listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
                    return true;
                }
                if (!mService.isTetheringSupported()) {
                if (!mTethering.isTetheringSupported()) {
                    listener.onResult(TETHER_ERROR_UNSUPPORTED);
                    return true;
                }
@@ -266,7 +245,7 @@ public class TetheringService extends Service {
                receiver.send(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, null);
                return true;
            }
            if (!mService.isTetheringSupported()) {
            if (!mTethering.isTetheringSupported()) {
                receiver.send(TETHER_ERROR_UNSUPPORTED, null);
                return true;
            }
@@ -300,20 +279,6 @@ public class TetheringService extends Service {
        }
    }

    // if ro.tether.denied = true we default to no tethering
    // gservices could set the secure setting to 1 though to enable it on a build where it
    // had previously been turned off.
    private boolean isTetheringSupported() {
        final int defaultVal =
                SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1;
        final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
        final boolean tetherEnabledInSettings = tetherSupported
                && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);

        return tetherEnabledInSettings && mTethering.hasTetherableConfiguration();
    }

    /**
     * Check if the package is a allowed to write settings. This also accounts that such an access
     * happened.
@@ -332,9 +297,8 @@ public class TetheringService extends Service {
     * An injection method for testing.
     */
    @VisibleForTesting
    public TetheringDependencies getTetheringDependencies() {
        if (mDeps == null) {
            mDeps = new TetheringDependencies() {
    public TetheringDependencies makeTetheringDependencies() {
        return new TetheringDependencies() {
            @Override
            public NetworkRequest getDefaultNetworkRequest() {
                // TODO: b/147280869, add a proper system API to replace this.
@@ -355,11 +319,6 @@ public class TetheringService extends Service {
                return tetherThread.getLooper();
            }

                @Override
                public boolean isTetheringSupported() {
                    return TetheringService.this.isTetheringSupported();
                }

            @Override
            public Context getContext() {
                return TetheringService.this;
@@ -413,6 +372,4 @@ public class TetheringService extends Service {
            }
        };
    }
        return mDeps;
    }
}
+9 −10
Original line number Diff line number Diff line
@@ -83,8 +83,7 @@ public final class TetheringServiceTest {
        mTetheringConnector = mockConnector.getTetheringConnector();
        final MockTetheringService service = mockConnector.getService();
        mTethering = service.getTethering();
        verify(mTethering).startStateMachineUpdaters();
        when(mTethering.hasTetherableConfiguration()).thenReturn(true);
        when(mTethering.isTetheringSupported()).thenReturn(true);
    }

    @After
@@ -97,7 +96,7 @@ public final class TetheringServiceTest {
        when(mTethering.tether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR);
        final TestTetheringResult result = new TestTetheringResult();
        mTetheringConnector.tether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
        verify(mTethering).hasTetherableConfiguration();
        verify(mTethering).isTetheringSupported();
        verify(mTethering).tether(TEST_IFACE_NAME);
        verifyNoMoreInteractions(mTethering);
        result.assertResult(TETHER_ERROR_NO_ERROR);
@@ -109,7 +108,7 @@ public final class TetheringServiceTest {
        final TestTetheringResult result = new TestTetheringResult();
        mTetheringConnector.untether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
                result);
        verify(mTethering).hasTetherableConfiguration();
        verify(mTethering).isTetheringSupported();
        verify(mTethering).untether(TEST_IFACE_NAME);
        verifyNoMoreInteractions(mTethering);
        result.assertResult(TETHER_ERROR_NO_ERROR);
@@ -121,7 +120,7 @@ public final class TetheringServiceTest {
        final TestTetheringResult result = new TestTetheringResult();
        mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG,
                TEST_ATTRIBUTION_TAG, result);
        verify(mTethering).hasTetherableConfiguration();
        verify(mTethering).isTetheringSupported();
        verify(mTethering).setUsbTethering(true /* enable */);
        verifyNoMoreInteractions(mTethering);
        result.assertResult(TETHER_ERROR_NO_ERROR);
@@ -133,7 +132,7 @@ public final class TetheringServiceTest {
        final TetheringRequestParcel request = new TetheringRequestParcel();
        request.tetheringType = TETHERING_WIFI;
        mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
        verify(mTethering).hasTetherableConfiguration();
        verify(mTethering).isTetheringSupported();
        verify(mTethering).startTethering(eq(request), eq(result));
        verifyNoMoreInteractions(mTethering);
    }
@@ -143,7 +142,7 @@ public final class TetheringServiceTest {
        final TestTetheringResult result = new TestTetheringResult();
        mTetheringConnector.stopTethering(TETHERING_WIFI, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
                result);
        verify(mTethering).hasTetherableConfiguration();
        verify(mTethering).isTetheringSupported();
        verify(mTethering).stopTethering(TETHERING_WIFI);
        verifyNoMoreInteractions(mTethering);
        result.assertResult(TETHER_ERROR_NO_ERROR);
@@ -154,7 +153,7 @@ public final class TetheringServiceTest {
        final ResultReceiver result = new ResultReceiver(null);
        mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result,
                true /* showEntitlementUi */, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG);
        verify(mTethering).hasTetherableConfiguration();
        verify(mTethering).isTetheringSupported();
        verify(mTethering).requestLatestTetheringEntitlementResult(eq(TETHERING_WIFI),
                eq(result), eq(true) /* showEntitlementUi */);
        verifyNoMoreInteractions(mTethering);
@@ -181,7 +180,7 @@ public final class TetheringServiceTest {
    public void testStopAllTethering() throws Exception {
        final TestTetheringResult result = new TestTetheringResult();
        mTetheringConnector.stopAllTethering(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
        verify(mTethering).hasTetherableConfiguration();
        verify(mTethering).isTetheringSupported();
        verify(mTethering).untetherAll();
        verifyNoMoreInteractions(mTethering);
        result.assertResult(TETHER_ERROR_NO_ERROR);
@@ -191,7 +190,7 @@ public final class TetheringServiceTest {
    public void testIsTetheringSupported() throws Exception {
        final TestTetheringResult result = new TestTetheringResult();
        mTetheringConnector.isTetheringSupported(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
        verify(mTethering).hasTetherableConfiguration();
        verify(mTethering).isTetheringSupported();
        verifyNoMoreInteractions(mTethering);
        result.assertResult(TETHER_ERROR_NO_ERROR);
    }
+32 −24
Original line number Diff line number Diff line
@@ -485,18 +485,6 @@ public class TetheringTest {
        MockitoAnnotations.initMocks(this);
        when(mResources.getStringArray(R.array.config_tether_dhcp_range))
                .thenReturn(new String[0]);
        when(mResources.getStringArray(R.array.config_tether_usb_regexs))
                .thenReturn(new String[] { "test_rndis\\d" });
        when(mResources.getStringArray(R.array.config_tether_wifi_regexs))
                .thenReturn(new String[]{ "test_wlan\\d" });
        when(mResources.getStringArray(R.array.config_tether_wifi_p2p_regexs))
                .thenReturn(new String[]{ "test_p2p-p2p\\d-.*" });
        when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs))
                .thenReturn(new String[0]);
        when(mResources.getStringArray(R.array.config_tether_ncm_regexs))
                .thenReturn(new String[] { "test_ncm\\d" });
        when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[0]);
        when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(false);
        when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
                false);
        when(mNetd.interfaceGetList())
@@ -515,6 +503,7 @@ public class TetheringTest {
        mServiceContext = new TestContext(mContext);
        mContentResolver = new MockContentResolver(mServiceContext);
        mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
        setTetheringSupported(true /* supported */);
        mIntents = new Vector<>();
        mBroadcastReceiver = new BroadcastReceiver() {
            @Override
@@ -525,7 +514,6 @@ public class TetheringTest {
        mServiceContext.registerReceiver(mBroadcastReceiver,
                new IntentFilter(ACTION_TETHER_STATE_CHANGED));
        mTethering = makeTethering();
        mTethering.startStateMachineUpdaters();
        verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any());
        verify(mNetd).registerUnsolicitedEventListener(any());
        final ArgumentCaptor<PhoneStateListener> phoneListenerCaptor =
@@ -536,6 +524,31 @@ public class TetheringTest {
        mPhoneStateListener = phoneListenerCaptor.getValue();
    }

    private void setTetheringSupported(final boolean supported) {
        Settings.Global.putInt(mContentResolver, Settings.Global.TETHER_SUPPORTED,
                supported ? 1 : 0);
        when(mUserManager.hasUserRestriction(
                UserManager.DISALLOW_CONFIG_TETHERING)).thenReturn(!supported);
        // Setup tetherable configuration.
        when(mResources.getStringArray(R.array.config_tether_usb_regexs))
                .thenReturn(new String[] { "test_rndis\\d" });
        when(mResources.getStringArray(R.array.config_tether_wifi_regexs))
                .thenReturn(new String[]{ "test_wlan\\d" });
        when(mResources.getStringArray(R.array.config_tether_wifi_p2p_regexs))
                .thenReturn(new String[]{ "test_p2p-p2p\\d-.*" });
        when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs))
                .thenReturn(new String[0]);
        when(mResources.getStringArray(R.array.config_tether_ncm_regexs))
                .thenReturn(new String[] { "test_ncm\\d" });
        when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[0]);
        when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(true);
    }

    private void initTetheringUpstream(UpstreamNetworkState upstreamState) {
        when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
        when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())).thenReturn(upstreamState);
    }

    private Tethering makeTethering() {
        mTetheringDependencies.reset();
        return new Tethering(mTetheringDependencies);
@@ -672,9 +685,7 @@ public class TetheringTest {
    }

    private void prepareUsbTethering(UpstreamNetworkState upstreamState) {
        when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
        when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
                .thenReturn(upstreamState);
        initTetheringUpstream(upstreamState);

        // Emulate pressing the USB tethering button in Settings UI.
        mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB), null);
@@ -700,7 +711,7 @@ public class TetheringTest {
        verify(mNetd, times(1)).interfaceGetList();

        // UpstreamNetworkMonitor should receive selected upstream
        verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any());
        verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream();
        verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
    }

@@ -872,8 +883,7 @@ public class TetheringTest {

        // Then 464xlat comes up
        upstreamState = buildMobile464xlatUpstreamState();
        when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
                .thenReturn(upstreamState);
        initTetheringUpstream(upstreamState);

        // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES.
        mTetheringDependencies.mUpstreamNetworkMonitorMasterSM.sendMessage(
@@ -1344,9 +1354,7 @@ public class TetheringTest {
        callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
        // 2. Enable wifi tethering.
        UpstreamNetworkState upstreamState = buildMobileDualStackUpstreamState();
        when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
        when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
                .thenReturn(upstreamState);
        initTetheringUpstream(upstreamState);
        when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
        mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
        mLooper.dispatchAll();
@@ -1723,7 +1731,7 @@ public class TetheringTest {
        final Tethering.TetherMasterSM stateMachine = (Tethering.TetherMasterSM)
                mTetheringDependencies.mUpstreamNetworkMonitorMasterSM;
        final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
        when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())).thenReturn(upstreamState);
        initTetheringUpstream(upstreamState);
        stateMachine.chooseUpstreamType(true);

        verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(eq(upstreamState.network));
@@ -1735,7 +1743,7 @@ public class TetheringTest {
        final Tethering.TetherMasterSM stateMachine = (Tethering.TetherMasterSM)
                mTetheringDependencies.mUpstreamNetworkMonitorMasterSM;
        final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
        when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())).thenReturn(upstreamState);
        initTetheringUpstream(upstreamState);
        stateMachine.chooseUpstreamType(true);

        stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState);