Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5469504e authored by Alexandru-Andrei Rotaru's avatar Alexandru-Andrei Rotaru Committed by Alexandru-andrei Rotaru
Browse files

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

Added UserRestrinctionListener for turning the service off one the
DISALLOW_CONFIG_TETHERING is on into Tethering.  Added notification
about
tethering being turned off. Also added Unit Tests to test the
functionality
of the UserRestrictionListener added.

Bug: 27936525
Test: Turn the tehering service on (either wifi, usb or bluetooth).
Automatically the system should send a notification about the service
being active.Close settings from recents. From TestDPC User Restrictions
switch on DISALLOW_CONFIG_TETHERING. The tethering should be turned off
and a notification should appear informing that the service is inactive.

Merged-In: Ib7ea8885cedc2a842ebd4487c8b366a6666996bc
Change-Id: Ib7ea8885cedc2a842ebd4487c8b366a6666996bc
(cherry picked from commit fa6d5c5c)
parent f9caecd1
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -3476,6 +3476,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>
+2 −0
Original line number Diff line number Diff line
@@ -1957,6 +1957,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" />
+60 −4
Original line number Diff line number Diff line
@@ -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);

+87 −0
Original line number Diff line number Diff line
@@ -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.
}