Merge "Notify the user and turn off tethering when the service is disallowed."
This commit is contained in:
@@ -3462,6 +3462,13 @@
|
|||||||
<string name="tethered_notification_title">Tethering or hotspot active</string>
|
<string name="tethered_notification_title">Tethering or hotspot active</string>
|
||||||
<string name="tethered_notification_message">Tap to set up.</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 -->
|
<!-- Strings for possible PreferenceActivity Back/Next buttons -->
|
||||||
<string name="back_button_label">Back</string>
|
<string name="back_button_label">Back</string>
|
||||||
<string name="next_button_label">Next</string>
|
<string name="next_button_label">Next</string>
|
||||||
|
|||||||
@@ -1967,6 +1967,8 @@
|
|||||||
<java-symbol type="string" name="smv_process" />
|
<java-symbol type="string" name="smv_process" />
|
||||||
<java-symbol type="string" name="tethered_notification_message" />
|
<java-symbol type="string" name="tethered_notification_message" />
|
||||||
<java-symbol type="string" name="tethered_notification_title" />
|
<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="adb_debugging_notification_channel_tv" />
|
||||||
<java-symbol type="string" name="usb_accessory_notification_title" />
|
<java-symbol type="string" name="usb_accessory_notification_title" />
|
||||||
<java-symbol type="string" name="usb_mtp_notification_title" />
|
<java-symbol type="string" name="usb_mtp_notification_title" />
|
||||||
|
|||||||
@@ -71,6 +71,9 @@ import android.os.PersistableBundle;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
import android.os.UserManager;
|
||||||
|
import android.os.UserManagerInternal;
|
||||||
|
import android.os.UserManagerInternal.UserRestrictionsListener;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.telephony.CarrierConfigManager;
|
import android.telephony.CarrierConfigManager;
|
||||||
import android.text.TextUtils;
|
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.Protocol;
|
||||||
import com.android.internal.util.State;
|
import com.android.internal.util.State;
|
||||||
import com.android.internal.util.StateMachine;
|
import com.android.internal.util.StateMachine;
|
||||||
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.connectivity.tethering.IControlsTethering;
|
import com.android.server.connectivity.tethering.IControlsTethering;
|
||||||
import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
|
import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
|
||||||
import com.android.server.connectivity.tethering.OffloadController;
|
import com.android.server.connectivity.tethering.OffloadController;
|
||||||
@@ -246,6 +250,13 @@ public class Tethering extends BaseNetworkObserver {
|
|||||||
filter.addDataScheme("file");
|
filter.addDataScheme("file");
|
||||||
mContext.registerReceiver(mStateReceiver, filter, null, smHandler);
|
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
|
// load device config info
|
||||||
updateConfiguration();
|
updateConfiguration();
|
||||||
}
|
}
|
||||||
@@ -733,6 +744,11 @@ public class Tethering extends BaseNetworkObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showTetheredNotification(int id) {
|
private void showTetheredNotification(int id) {
|
||||||
|
showTetheredNotification(id, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
protected void showTetheredNotification(int id, boolean tetheringOn) {
|
||||||
NotificationManager notificationManager =
|
NotificationManager notificationManager =
|
||||||
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
if (notificationManager == null) {
|
if (notificationManager == null) {
|
||||||
@@ -769,9 +785,16 @@ public class Tethering extends BaseNetworkObserver {
|
|||||||
null, UserHandle.CURRENT);
|
null, UserHandle.CURRENT);
|
||||||
|
|
||||||
Resources r = Resources.getSystem();
|
Resources r = Resources.getSystem();
|
||||||
CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
|
final CharSequence title;
|
||||||
CharSequence message = r.getText(com.android.internal.R.string.
|
final CharSequence message;
|
||||||
tethered_notification_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) {
|
if (mTetheredNotificationBuilder == null) {
|
||||||
mTetheredNotificationBuilder =
|
mTetheredNotificationBuilder =
|
||||||
@@ -793,7 +816,8 @@ public class Tethering extends BaseNetworkObserver {
|
|||||||
mTetheredNotificationBuilder.buildInto(new Notification()), UserHandle.ALL);
|
mTetheredNotificationBuilder.buildInto(new Notification()), UserHandle.ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearTetheredNotification() {
|
@VisibleForTesting
|
||||||
|
protected void clearTetheredNotification() {
|
||||||
NotificationManager notificationManager =
|
NotificationManager notificationManager =
|
||||||
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
if (notificationManager != null && mLastNotificationId != 0) {
|
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) {
|
private void disableWifiIpServingLocked(String ifname, int apState) {
|
||||||
mLog.log("Canceling WiFi tethering request - AP_STATE=" + apState);
|
mLog.log("Canceling WiFi tethering request - AP_STATE=" + apState);
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import static org.mockito.Mockito.times;
|
|||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
@@ -59,12 +60,14 @@ import android.net.NetworkRequest;
|
|||||||
import android.net.util.SharedLog;
|
import android.net.util.SharedLog;
|
||||||
import android.net.wifi.WifiConfiguration;
|
import android.net.wifi.WifiConfiguration;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.INetworkManagementService;
|
import android.os.INetworkManagementService;
|
||||||
import android.os.PersistableBundle;
|
import android.os.PersistableBundle;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.test.TestLooper;
|
import android.os.test.TestLooper;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
import android.os.UserManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.support.test.filters.SmallTest;
|
import android.support.test.filters.SmallTest;
|
||||||
import android.support.test.runner.AndroidJUnit4;
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
@@ -558,6 +561,90 @@ public class TetheringTest {
|
|||||||
verifyNoMoreInteractions(mNMService);
|
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
|
// TODO: Test that a request for hotspot mode doesn't interfere with an
|
||||||
// already operating tethering mode interface.
|
// already operating tethering mode interface.
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user