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

Commit 46732350 authored by Paul Hu's avatar Paul Hu Committed by Automerger Merge Worker
Browse files

Merge "[TNU04] Add tethering restricted notification" into rvc-dev am: 984f629a

Change-Id: Ie258a04699021a2b0891628f172e838faca3d4bc
parents 6924e401 984f629a
Loading
Loading
Loading
Loading
+20 −8
Original line number Diff line number Diff line
@@ -303,7 +303,8 @@ public class Tethering {

        final UserManager userManager = (UserManager) mContext.getSystemService(
                Context.USER_SERVICE);
        mTetheringRestriction = new UserRestrictionActionListener(userManager, this);
        mTetheringRestriction = new UserRestrictionActionListener(
                userManager, this, mNotificationUpdater);
        mExecutor = new TetheringThreadExecutor(mHandler);
        mActiveDataSubIdListener = new ActiveDataSubIdListener(mExecutor);

@@ -997,11 +998,14 @@ public class Tethering {
    protected static class UserRestrictionActionListener {
        private final UserManager mUserManager;
        private final Tethering mWrapper;
        private final TetheringNotificationUpdater mNotificationUpdater;
        public boolean mDisallowTethering;

        public UserRestrictionActionListener(UserManager um, Tethering wrapper) {
        public UserRestrictionActionListener(@NonNull UserManager um, @NonNull Tethering wrapper,
                @NonNull TetheringNotificationUpdater updater) {
            mUserManager = um;
            mWrapper = wrapper;
            mNotificationUpdater = updater;
            mDisallowTethering = false;
        }

@@ -1020,15 +1024,23 @@ public class Tethering {
                return;
            }

            // TODO: Add user restrictions notification.
            final boolean isTetheringActiveOnDevice = (mWrapper.getTetheredIfaces().length != 0);
            if (!newlyDisallowed) {
                // Clear the restricted notification when user is allowed to have tethering
                // function.
                mNotificationUpdater.tetheringRestrictionLifted();
                return;
            }

            // Restricted notification is shown when tethering function is disallowed on
            // user's device.
            mNotificationUpdater.notifyTetheringDisabledByRestriction();

            if (newlyDisallowed && isTetheringActiveOnDevice) {
            // Untether from all downstreams since tethering is disallowed.
            mWrapper.untetherAll();

            // TODO(b/148139325): send tetheringSupported on restriction change
        }
    }
    }

    private void disableWifiIpServingLockedCommon(int tetheringType, String ifname, int apState) {
        mLog.log("Canceling WiFi tethering request -"
+31 −10
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.util.SparseArray;

import androidx.annotation.ArrayRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.IntDef;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;

@@ -61,7 +62,9 @@ public class TetheringNotificationUpdater {
    private static final boolean NOTIFY_DONE = true;
    private static final boolean NO_NOTIFY = false;
    // Id to update and cancel tethering notification. Must be unique within the tethering app.
    private static final int NOTIFY_ID = 20191115;
    private static final int ENABLE_NOTIFICATION_ID = 1000;
    // Id to update and cancel restricted notification. Must be unique within the tethering app.
    private static final int RESTRICTED_NOTIFICATION_ID = 1001;
    @VisibleForTesting
    static final int NO_ICON_ID = 0;
    @VisibleForTesting
@@ -85,6 +88,9 @@ public class TetheringNotificationUpdater {
    // INVALID_SUBSCRIPTION_ID.
    private volatile int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;

    @IntDef({ENABLE_NOTIFICATION_ID, RESTRICTED_NOTIFICATION_ID})
    @interface NotificationId {}

    public TetheringNotificationUpdater(@NonNull final Context context) {
        mContext = context;
        mNotificationManager = (NotificationManager) context.createContextAsUser(UserHandle.ALL, 0)
@@ -100,14 +106,14 @@ public class TetheringNotificationUpdater {
    public void onDownstreamChanged(@IntRange(from = 0, to = 7) final int downstreamTypesMask) {
        if (mDownstreamTypesMask == downstreamTypesMask) return;
        mDownstreamTypesMask = downstreamTypesMask;
        updateNotification();
        updateEnableNotification();
    }

    /** Called when active data subscription id changed */
    public void onActiveDataSubscriptionIdChanged(final int subId) {
        if (mActiveDataSubId == subId) return;
        mActiveDataSubId = subId;
        updateNotification();
        updateEnableNotification();
    }

    @VisibleForTesting
@@ -115,16 +121,31 @@ public class TetheringNotificationUpdater {
        return SubscriptionManager.getResourcesForSubId(c, subId);
    }

    private void updateNotification() {
    private void updateEnableNotification() {
        final boolean tetheringInactive = mDownstreamTypesMask <= DOWNSTREAM_NONE;

        if (tetheringInactive || setupNotification() == NO_NOTIFY) {
            clearNotification();
            clearNotification(ENABLE_NOTIFICATION_ID);
        }
    }

    private void clearNotification() {
        mNotificationManager.cancel(null /* tag */, NOTIFY_ID);
    @VisibleForTesting
    void tetheringRestrictionLifted() {
        clearNotification(RESTRICTED_NOTIFICATION_ID);
    }

    private void clearNotification(@NotificationId final int id) {
        mNotificationManager.cancel(null /* tag */, id);
    }

    @VisibleForTesting
    void notifyTetheringDisabledByRestriction() {
        final Resources res = getResourcesForSubId(mContext, mActiveDataSubId);
        final String title = res.getString(R.string.disable_tether_notification_title);
        final String message = res.getString(R.string.disable_tether_notification_message);

        showNotification(R.drawable.stat_sys_tether_general, title, message,
                RESTRICTED_NOTIFICATION_ID);
    }

    /**
@@ -195,12 +216,12 @@ public class TetheringNotificationUpdater {
        final String title = res.getString(R.string.tethering_notification_title);
        final String message = res.getString(R.string.tethering_notification_message);

        showNotification(iconId, title, message);
        showNotification(iconId, title, message, ENABLE_NOTIFICATION_ID);
        return NOTIFY_DONE;
    }

    private void showNotification(@DrawableRes final int iconId, @NonNull final String title,
            @NonNull final String message) {
            @NonNull final String message, @NotificationId final int id) {
        final Intent intent = new Intent(Settings.ACTION_TETHER_SETTINGS);
        final PendingIntent pi = PendingIntent.getActivity(
                mContext.createContextAsUser(UserHandle.CURRENT, 0),
@@ -218,6 +239,6 @@ public class TetheringNotificationUpdater {
                        .setContentIntent(pi)
                        .build();

        mNotificationManager.notify(null /* tag */, NOTIFY_ID, notification);
        mNotificationManager.notify(null /* tag */, id, notification);
    }
}
+38 −3
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ import android.net.ConnectivityManager.TETHERING_USB
import android.net.ConnectivityManager.TETHERING_WIFI
import android.os.UserHandle
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
import androidx.test.InstrumentationRegistry
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.internal.util.test.BroadcastInterceptingContext
@@ -114,7 +114,7 @@ class TetheringNotificationUpdaterTest {
    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        val context = TestContext(InstrumentationRegistry.getContext())
        val context = TestContext(InstrumentationRegistry.getInstrumentation().context)
        doReturn(notificationManager).`when`(mockContext)
                .getSystemService(Context.NOTIFICATION_SERVICE)
        notificationUpdater = WrappedNotificationUpdater(context)
@@ -128,7 +128,8 @@ class TetheringNotificationUpdaterTest {
        verify(notificationManager, never()).cancel(any(), anyInt())

        val notificationCaptor = ArgumentCaptor.forClass(Notification::class.java)
        verify(notificationManager, times(1)).notify(any(), anyInt(), notificationCaptor.capture())
        verify(notificationManager, times(1))
                .notify(any(), anyInt(), notificationCaptor.capture())

        val notification = notificationCaptor.getValue()
        assertEquals(iconId, notification.smallIcon.resId)
@@ -224,4 +225,38 @@ class TetheringNotificationUpdaterTest {
        assertEquals(WIFI_MASK or USB_MASK,
                notificationUpdater.getDownstreamTypesMask("1|2|USB|WIFI|BLUETOOTH||"))
    }

    @Test
    fun testSetupRestrictedNotification() {
        val title = InstrumentationRegistry.getInstrumentation().context.resources
                .getString(R.string.disable_tether_notification_title)
        val message = InstrumentationRegistry.getInstrumentation().context.resources
                .getString(R.string.disable_tether_notification_message)
        val disallowTitle = "Tether function is disallowed"
        val disallowMessage = "Please contact your admin"
        doReturn(title).`when`(defaultResources)
                .getString(R.string.disable_tether_notification_title)
        doReturn(message).`when`(defaultResources)
                .getString(R.string.disable_tether_notification_message)
        doReturn(disallowTitle).`when`(testResources)
                .getString(R.string.disable_tether_notification_title)
        doReturn(disallowMessage).`when`(testResources)
                .getString(R.string.disable_tether_notification_message)

        // User restrictions on. Show restricted notification.
        notificationUpdater.notifyTetheringDisabledByRestriction()
        verifyNotification(R.drawable.stat_sys_tether_general, title, message)

        // User restrictions off. Clear notification.
        notificationUpdater.tetheringRestrictionLifted()
        verifyNoNotification()

        // Set test sub id. No notification.
        notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
        verifyNoNotification()

        // User restrictions on again. Show restricted notification with test resource.
        notificationUpdater.notifyTetheringDisabledByRestriction()
        verifyNotification(R.drawable.stat_sys_tether_general, disallowTitle, disallowMessage)
    }
}
 No newline at end of file
+6 −4
Original line number Diff line number Diff line
@@ -1072,13 +1072,15 @@ public class TetheringTest {
        when(mUserManager.getUserRestrictions()).thenReturn(newRestrictions);

        final Tethering.UserRestrictionActionListener ural =
                new Tethering.UserRestrictionActionListener(mUserManager, mockTethering);
                new Tethering.UserRestrictionActionListener(
                        mUserManager, mockTethering, mNotificationUpdater);
        ural.mDisallowTethering = currentDisallow;

        ural.onUserRestrictionsChanged();

        verify(mockTethering, times(expectedInteractionsWithShowNotification))
                .untetherAll();
        verify(mNotificationUpdater, times(expectedInteractionsWithShowNotification))
                .notifyTetheringDisabledByRestriction();
        verify(mockTethering, times(expectedInteractionsWithShowNotification)).untetherAll();
    }

    @Test
@@ -1086,7 +1088,7 @@ public class TetheringTest {
        final String[] emptyActiveIfacesList = new String[]{};
        final boolean currDisallow = false;
        final boolean nextDisallow = true;
        final int expectedInteractionsWithShowNotification = 0;
        final int expectedInteractionsWithShowNotification = 1;

        runUserRestrictionsChange(currDisallow, nextDisallow, emptyActiveIfacesList,
                expectedInteractionsWithShowNotification);