Merge "Notify the user and turn off tethering when the service is disallowed."

This commit is contained in:
TreeHugger Robot
2017-08-02 09:13:31 +00:00
committed by Android (Google) Code Review
4 changed files with 156 additions and 4 deletions

View File

@@ -3471,6 +3471,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>

View File

@@ -1954,6 +1954,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" />

View File

@@ -70,6 +70,9 @@ import android.os.Parcel;
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.telephony.TelephonyManager;
@@ -89,6 +92,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;
@@ -236,6 +240,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();
}
@@ -710,6 +721,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) {
@@ -746,9 +762,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 =
@@ -770,7 +793,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) {
@@ -874,6 +898,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);

View File

@@ -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.
}