diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java index 5191bb74ed..0d1b22ee54 100644 --- a/Tethering/src/com/android/networkstack/tethering/Tethering.java +++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java @@ -97,6 +97,7 @@ import android.net.TetheringConfigurationParcel; import android.net.TetheringInterface; import android.net.TetheringManager.TetheringRequest; import android.net.TetheringRequestParcel; +import android.net.Uri; import android.net.ip.IpServer; import android.net.wifi.WifiClient; import android.net.wifi.WifiManager; @@ -343,9 +344,8 @@ public class Tethering { mEntitlementMgr.reevaluateSimCardProvisioning(mConfig); }); - mSettingsObserver = new SettingsObserver(mHandler); - mContext.getContentResolver().registerContentObserver( - Settings.Global.getUriFor(TETHER_FORCE_USB_FUNCTIONS), false, mSettingsObserver); + mSettingsObserver = new SettingsObserver(mContext, mHandler); + mSettingsObserver.startObserve(); mStateReceiver = new StateReceiver(); @@ -397,18 +397,42 @@ public class Tethering { } private class SettingsObserver extends ContentObserver { - SettingsObserver(Handler handler) { + private final Uri mForceUsbFunctions; + private final Uri mTetherSupported; + private final Context mContext; + + SettingsObserver(Context ctx, Handler handler) { super(handler); + mContext = ctx; + mForceUsbFunctions = Settings.Global.getUriFor(TETHER_FORCE_USB_FUNCTIONS); + mTetherSupported = Settings.Global.getUriFor(Settings.Global.TETHER_SUPPORTED); + } + + public void startObserve() { + mContext.getContentResolver().registerContentObserver(mForceUsbFunctions, false, this); + mContext.getContentResolver().registerContentObserver(mTetherSupported, false, this); } @Override public void onChange(boolean selfChange) { - mLog.i("OBSERVED Settings change"); - final boolean isUsingNcm = mConfig.isUsingNcm(); - updateConfiguration(); - if (isUsingNcm != mConfig.isUsingNcm()) { - stopTetheringInternal(TETHERING_USB); - stopTetheringInternal(TETHERING_NCM); + Log.wtf(TAG, "Should never be reached."); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + if (mForceUsbFunctions.equals(uri)) { + mLog.i("OBSERVED TETHER_FORCE_USB_FUNCTIONS settings change"); + final boolean isUsingNcm = mConfig.isUsingNcm(); + updateConfiguration(); + if (isUsingNcm != mConfig.isUsingNcm()) { + stopTetheringInternal(TETHERING_USB); + stopTetheringInternal(TETHERING_NCM); + } + } else if (mTetherSupported.equals(uri)) { + mLog.i("OBSERVED TETHER_SUPPORTED settings change"); + updateSupportedDownstreams(mConfig); + } else { + mLog.e("Unexpected settings change: " + uri); } } } @@ -1322,7 +1346,9 @@ public class Tethering { } private void handleUserRestrictionAction() { - mTetheringRestriction.onUserRestrictionsChanged(); + if (mTetheringRestriction.onUserRestrictionsChanged()) { + updateSupportedDownstreams(mConfig); + } } private void handleDataSaverChanged() { @@ -1350,6 +1376,8 @@ public class Tethering { return getTetheredIfaces().length > 0; } + // TODO: Refine TetheringTest then remove UserRestrictionActionListener class and handle + // onUserRestrictionsChanged inside Tethering#handleUserRestrictionAction directly. @VisibleForTesting protected static class UserRestrictionActionListener { private final UserManager mUserMgr; @@ -1365,7 +1393,8 @@ public class Tethering { mDisallowTethering = false; } - public void onUserRestrictionsChanged() { + // return whether tethering disallowed is changed. + public boolean onUserRestrictionsChanged() { // 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. @@ -1376,15 +1405,13 @@ public class Tethering { mDisallowTethering = newlyDisallowed; final boolean tetheringDisallowedChanged = (newlyDisallowed != prevDisallowed); - if (!tetheringDisallowedChanged) { - return; - } + if (!tetheringDisallowedChanged) return false; if (!newlyDisallowed) { // Clear the restricted notification when user is allowed to have tethering // function. mNotificationUpdater.tetheringRestrictionLifted(); - return; + return true; } if (mTethering.isTetheringActive()) { @@ -1395,6 +1422,8 @@ public class Tethering { // Untether from all downstreams since tethering is disallowed. mTethering.untetherAll(); } + + return true; // TODO(b/148139325): send tetheringSupported on restriction change } } diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java index 66ad167cfa..a36d67fc19 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java @@ -2899,9 +2899,13 @@ public class TetheringTest { } private void forceUsbTetheringUse(final int function) { - Settings.Global.putInt(mContentResolver, TETHER_FORCE_USB_FUNCTIONS, function); + setSetting(TETHER_FORCE_USB_FUNCTIONS, function); + } + + private void setSetting(final String key, final int value) { + Settings.Global.putInt(mContentResolver, key, value); final ContentObserver observer = mTethering.getSettingsObserverForTest(); - observer.onChange(false /* selfChange */); + observer.onChange(false /* selfChange */, Settings.Global.getUriFor(key)); mLooper.dispatchAll(); } @@ -2957,74 +2961,86 @@ public class TetheringTest { TETHERING_WIFI_P2P, TETHERING_BLUETOOTH, TETHERING_ETHERNET }); } + private void setUserRestricted(boolean restricted) { + final Bundle restrictions = new Bundle(); + restrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, restricted); + when(mUserManager.getUserRestrictions()).thenReturn(restrictions); + when(mUserManager.hasUserRestriction( + UserManager.DISALLOW_CONFIG_TETHERING)).thenReturn(restricted); + + final Intent intent = new Intent(UserManager.ACTION_USER_RESTRICTIONS_CHANGED); + mServiceContext.sendBroadcastAsUser(intent, UserHandle.ALL); + mLooper.dispatchAll(); + } + @Test public void testTetheringSupported() throws Exception { final ArraySet expectedTypes = getAllSupportedTetheringTypes(); // Check tethering is supported after initialization. - setTetheringSupported(true /* supported */); TestTetheringEventCallback callback = new TestTetheringEventCallback(); mTethering.registerTetheringEventCallback(callback); mLooper.dispatchAll(); - updateConfigAndVerifySupported(callback, expectedTypes); + verifySupported(callback, expectedTypes); - // Could disable tethering supported by settings. - Settings.Global.putInt(mContentResolver, Settings.Global.TETHER_SUPPORTED, 0); - updateConfigAndVerifySupported(callback, new ArraySet<>()); + // Could change tethering supported by settings. + setSetting(Settings.Global.TETHER_SUPPORTED, 0); + verifySupported(callback, new ArraySet<>()); + setSetting(Settings.Global.TETHER_SUPPORTED, 1); + verifySupported(callback, expectedTypes); - // Could disable tethering supported by user restriction. - setTetheringSupported(true /* supported */); - updateConfigAndVerifySupported(callback, expectedTypes); - when(mUserManager.hasUserRestriction( - UserManager.DISALLOW_CONFIG_TETHERING)).thenReturn(true); - updateConfigAndVerifySupported(callback, new ArraySet<>()); + // Could change tethering supported by user restriction. + setUserRestricted(true /* restricted */); + verifySupported(callback, new ArraySet<>()); + setUserRestricted(false /* restricted */); + verifySupported(callback, expectedTypes); - // Tethering is supported if it has any supported downstream. - setTetheringSupported(true /* supported */); - updateConfigAndVerifySupported(callback, expectedTypes); // Usb tethering is not supported: expectedTypes.remove(TETHERING_USB); when(mResources.getStringArray(R.array.config_tether_usb_regexs)) .thenReturn(new String[0]); - updateConfigAndVerifySupported(callback, expectedTypes); + sendConfigurationChanged(); + verifySupported(callback, expectedTypes); // Wifi tethering is not supported: expectedTypes.remove(TETHERING_WIFI); when(mResources.getStringArray(R.array.config_tether_wifi_regexs)) .thenReturn(new String[0]); - updateConfigAndVerifySupported(callback, expectedTypes); + sendConfigurationChanged(); + verifySupported(callback, expectedTypes); // Bluetooth tethering is not supported: expectedTypes.remove(TETHERING_BLUETOOTH); when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs)) .thenReturn(new String[0]); if (isAtLeastT()) { - updateConfigAndVerifySupported(callback, expectedTypes); + sendConfigurationChanged(); + verifySupported(callback, expectedTypes); // P2p tethering is not supported: expectedTypes.remove(TETHERING_WIFI_P2P); when(mResources.getStringArray(R.array.config_tether_wifi_p2p_regexs)) .thenReturn(new String[0]); - updateConfigAndVerifySupported(callback, expectedTypes); + sendConfigurationChanged(); + verifySupported(callback, expectedTypes); // Ncm tethering is not supported: expectedTypes.remove(TETHERING_NCM); when(mResources.getStringArray(R.array.config_tether_ncm_regexs)) .thenReturn(new String[0]); - updateConfigAndVerifySupported(callback, expectedTypes); + sendConfigurationChanged(); + verifySupported(callback, expectedTypes); // Ethernet tethering (last supported type) is not supported: expectedTypes.remove(TETHERING_ETHERNET); mForceEthernetServiceUnavailable = true; - updateConfigAndVerifySupported(callback, new ArraySet<>()); - + sendConfigurationChanged(); + verifySupported(callback, new ArraySet<>()); } else { // If wifi, usb and bluetooth are all not supported, all the types are not supported. - expectedTypes.clear(); - updateConfigAndVerifySupported(callback, expectedTypes); + sendConfigurationChanged(); + verifySupported(callback, new ArraySet<>()); } } - private void updateConfigAndVerifySupported(final TestTetheringEventCallback callback, + private void verifySupported(final TestTetheringEventCallback callback, final ArraySet expectedTypes) { - sendConfigurationChanged(); - assertEquals(expectedTypes.size() > 0, mTethering.isTetheringSupported()); callback.expectSupportedTetheringTypes(expectedTypes); }