Loading packages/Tethering/src/com/android/networkstack/tethering/Tethering.java +27 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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<>(); Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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 = Loading Loading @@ -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") Loading packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java +71 −114 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); } /** Loading @@ -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 { Loading Loading @@ -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; } Loading @@ -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; } Loading Loading @@ -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. Loading @@ -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. Loading @@ -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; Loading Loading @@ -413,6 +372,4 @@ public class TetheringService extends Service { } }; } return mDeps; } } packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java +9 −10 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); Loading @@ -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); Loading @@ -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); Loading @@ -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); } Loading @@ -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); Loading @@ -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); Loading @@ -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); Loading @@ -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); } Loading packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java +32 −24 Original line number Diff line number Diff line Loading @@ -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()) Loading @@ -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 Loading @@ -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 = Loading @@ -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); Loading Loading @@ -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); Loading @@ -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); } Loading Loading @@ -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( Loading Loading @@ -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.startSoftAp(any(WifiConfiguration.class))).thenReturn(true); mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true); mLooper.dispatchAll(); Loading Loading @@ -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)); Loading @@ -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); Loading Loading
packages/Tethering/src/com/android/networkstack/tethering/Tethering.java +27 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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<>(); Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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 = Loading Loading @@ -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") Loading
packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java +71 −114 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); } /** Loading @@ -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 { Loading Loading @@ -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; } Loading @@ -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; } Loading Loading @@ -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. Loading @@ -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. Loading @@ -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; Loading Loading @@ -413,6 +372,4 @@ public class TetheringService extends Service { } }; } return mDeps; } }
packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java +9 −10 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); Loading @@ -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); Loading @@ -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); Loading @@ -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); } Loading @@ -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); Loading @@ -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); Loading @@ -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); Loading @@ -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); } Loading
packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java +32 −24 Original line number Diff line number Diff line Loading @@ -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()) Loading @@ -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 Loading @@ -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 = Loading @@ -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); Loading Loading @@ -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); Loading @@ -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); } Loading Loading @@ -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( Loading Loading @@ -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.startSoftAp(any(WifiConfiguration.class))).thenReturn(true); mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true); mLooper.dispatchAll(); Loading Loading @@ -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)); Loading @@ -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); Loading