diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2018-02-28 10:03:02 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2018-02-28 10:03:02 +0000 |
commit | e8b557bc08facb3d60b605f3e8cb26b31baaa28b (patch) | |
tree | 919f3f567603fb8cf0b98d86f200f546910d66f8 | |
parent | 4c00edd36139789a94cc4a01c51451edc4476df8 (diff) | |
parent | 9f3bad7260d718558d6f2f2048d973f2cd588b0b (diff) |
Merge "Notify the user and turn off tethering when the service is disallowed."
-rw-r--r-- | core/res/res/values/strings.xml | 7 | ||||
-rw-r--r-- | core/res/res/values/symbols.xml | 2 | ||||
-rw-r--r-- | services/core/java/com/android/server/connectivity/Tethering.java | 64 | ||||
-rw-r--r-- | tests/net/java/com/android/server/connectivity/TetheringTest.java | 87 |
4 files changed, 156 insertions, 4 deletions
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 0a36ba747520..dc14b2345e04 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3462,6 +3462,13 @@ <string name="tethered_notification_title">Tethering or hotspot active</string> <string name="tethered_notification_message">Tap to set up.</string> + <!-- Strings for tether disabling notification --> + <!-- This notification is shown when tethering has been disabled on a user's device. + The device is managed by the user's employer. Tethering can't be turned on unless the + IT administrator allows it. The noun "admin" is another reference for "IT administrator." --> + <string name="disable_tether_notification_title">Tethering is disabled</string> + <string name="disable_tether_notification_message">Contact your admin for details</string> + <!-- Strings for possible PreferenceActivity Back/Next buttons --> <string name="back_button_label">Back</string> <string name="next_button_label">Next</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 6396c4cdc935..ad5af95d462e 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1967,6 +1967,8 @@ <java-symbol type="string" name="smv_process" /> <java-symbol type="string" name="tethered_notification_message" /> <java-symbol type="string" name="tethered_notification_title" /> + <java-symbol type="string" name="disable_tether_notification_message" /> + <java-symbol type="string" name="disable_tether_notification_title" /> <java-symbol type="string" name="adb_debugging_notification_channel_tv" /> <java-symbol type="string" name="usb_accessory_notification_title" /> <java-symbol type="string" name="usb_mtp_notification_title" /> diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index 1767a21f576b..cffa8346859c 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -71,6 +71,9 @@ import android.os.PersistableBundle; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.UserHandle; +import android.os.UserManager; +import android.os.UserManagerInternal; +import android.os.UserManagerInternal.UserRestrictionsListener; import android.provider.Settings; import android.telephony.CarrierConfigManager; import android.text.TextUtils; @@ -87,6 +90,7 @@ import com.android.internal.util.MessageUtils; import com.android.internal.util.Protocol; import com.android.internal.util.State; import com.android.internal.util.StateMachine; +import com.android.server.LocalServices; import com.android.server.connectivity.tethering.IControlsTethering; import com.android.server.connectivity.tethering.IPv6TetheringCoordinator; import com.android.server.connectivity.tethering.OffloadController; @@ -246,6 +250,13 @@ public class Tethering extends BaseNetworkObserver { filter.addDataScheme("file"); mContext.registerReceiver(mStateReceiver, filter, null, smHandler); + UserManagerInternal userManager = LocalServices.getService(UserManagerInternal.class); + + // this check is useful only for some unit tests; example: ConnectivityServiceTest + if (userManager != null) { + userManager.addUserRestrictionsListener(new TetheringUserRestrictionListener(this)); + } + // load device config info updateConfiguration(); } @@ -733,6 +744,11 @@ public class Tethering extends BaseNetworkObserver { } private void showTetheredNotification(int id) { + showTetheredNotification(id, true); + } + + @VisibleForTesting + protected void showTetheredNotification(int id, boolean tetheringOn) { NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); if (notificationManager == null) { @@ -769,9 +785,16 @@ public class Tethering extends BaseNetworkObserver { null, UserHandle.CURRENT); Resources r = Resources.getSystem(); - CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title); - CharSequence message = r.getText(com.android.internal.R.string. - tethered_notification_message); + final CharSequence title; + final CharSequence message; + + if (tetheringOn) { + title = r.getText(com.android.internal.R.string.tethered_notification_title); + message = r.getText(com.android.internal.R.string.tethered_notification_message); + } else { + title = r.getText(com.android.internal.R.string.disable_tether_notification_title); + message = r.getText(com.android.internal.R.string.disable_tether_notification_message); + } if (mTetheredNotificationBuilder == null) { mTetheredNotificationBuilder = @@ -793,7 +816,8 @@ public class Tethering extends BaseNetworkObserver { mTetheredNotificationBuilder.buildInto(new Notification()), UserHandle.ALL); } - private void clearTetheredNotification() { + @VisibleForTesting + protected void clearTetheredNotification() { NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); if (notificationManager != null && mLastNotificationId != 0) { @@ -896,6 +920,38 @@ public class Tethering extends BaseNetworkObserver { } } + @VisibleForTesting + protected static class TetheringUserRestrictionListener implements UserRestrictionsListener { + private final Tethering mWrapper; + + public TetheringUserRestrictionListener(Tethering wrapper) { + mWrapper = wrapper; + } + + public void onUserRestrictionsChanged(int userId, + Bundle newRestrictions, + Bundle prevRestrictions) { + final boolean newlyDisallowed = + newRestrictions.getBoolean(UserManager.DISALLOW_CONFIG_TETHERING); + final boolean previouslyDisallowed = + prevRestrictions.getBoolean(UserManager.DISALLOW_CONFIG_TETHERING); + final boolean tetheringDisallowedChanged = (newlyDisallowed != previouslyDisallowed); + + if (!tetheringDisallowedChanged) { + return; + } + + mWrapper.clearTetheredNotification(); + final boolean isTetheringActiveOnDevice = (mWrapper.getTetheredIfaces().length != 0); + + if (newlyDisallowed && isTetheringActiveOnDevice) { + mWrapper.showTetheredNotification( + com.android.internal.R.drawable.stat_sys_tether_general, false); + mWrapper.untetherAll(); + } + } + } + private void disableWifiIpServingLocked(String ifname, int apState) { mLog.log("Canceling WiFi tethering request - AP_STATE=" + apState); diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java index a115146486a4..099cfd457160 100644 --- a/tests/net/java/com/android/server/connectivity/TetheringTest.java +++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java @@ -40,6 +40,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.mock; import android.content.BroadcastReceiver; import android.content.ContentResolver; @@ -59,12 +60,14 @@ import android.net.NetworkRequest; import android.net.util.SharedLog; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; +import android.os.Bundle; import android.os.Handler; import android.os.INetworkManagementService; import android.os.PersistableBundle; import android.os.RemoteException; import android.os.test.TestLooper; import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -558,6 +561,90 @@ public class TetheringTest { verifyNoMoreInteractions(mNMService); } + private void userRestrictionsListenerBehaviour( + boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList, + int expectedInteractionsWithShowNotification) throws Exception { + final int userId = 0; + final Bundle currRestrictions = new Bundle(); + final Bundle newRestrictions = new Bundle(); + Tethering tethering = mock(Tethering.class); + Tethering.TetheringUserRestrictionListener turl = + new Tethering.TetheringUserRestrictionListener(tethering); + + currRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, currentDisallow); + newRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, nextDisallow); + when(tethering.getTetheredIfaces()).thenReturn(activeTetheringIfacesList); + + turl.onUserRestrictionsChanged(userId, newRestrictions, currRestrictions); + + verify(tethering, times(expectedInteractionsWithShowNotification)) + .showTetheredNotification(anyInt(), eq(false)); + + verify(tethering, times(expectedInteractionsWithShowNotification)).untetherAll(); + } + + @Test + public void testDisallowTetheringWhenNoTetheringInterfaceIsActive() throws Exception { + final String[] emptyActiveIfacesList = new String[]{}; + final boolean currDisallow = false; + final boolean nextDisallow = true; + final int expectedInteractionsWithShowNotification = 0; + + userRestrictionsListenerBehaviour(currDisallow, nextDisallow, emptyActiveIfacesList, + expectedInteractionsWithShowNotification); + } + + @Test + public void testDisallowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception { + final String[] nonEmptyActiveIfacesList = new String[]{mTestIfname}; + final boolean currDisallow = false; + final boolean nextDisallow = true; + final int expectedInteractionsWithShowNotification = 1; + + userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList, + expectedInteractionsWithShowNotification); + } + + @Test + public void testAllowTetheringWhenNoTetheringInterfaceIsActive() throws Exception { + final String[] nonEmptyActiveIfacesList = new String[]{}; + final boolean currDisallow = true; + final boolean nextDisallow = false; + final int expectedInteractionsWithShowNotification = 0; + + userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList, + expectedInteractionsWithShowNotification); + } + + @Test + public void testAllowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception { + final String[] nonEmptyActiveIfacesList = new String[]{mTestIfname}; + final boolean currDisallow = true; + final boolean nextDisallow = false; + final int expectedInteractionsWithShowNotification = 0; + + userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList, + expectedInteractionsWithShowNotification); + } + + @Test + public void testDisallowTetheringUnchanged() throws Exception { + final String[] nonEmptyActiveIfacesList = new String[]{mTestIfname}; + final int expectedInteractionsWithShowNotification = 0; + boolean currDisallow = true; + boolean nextDisallow = true; + + userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList, + expectedInteractionsWithShowNotification); + + currDisallow = false; + nextDisallow = false; + + userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList, + expectedInteractionsWithShowNotification); + } + + // TODO: Test that a request for hotspot mode doesn't interfere with an // already operating tethering mode interface. } |