Merge "[TNU08] Remove the "tethering is on" notification"
This commit is contained in:
@@ -156,51 +156,6 @@
|
|||||||
<!-- ComponentName of the service used to run no ui tether provisioning. -->
|
<!-- ComponentName of the service used to run no ui tether provisioning. -->
|
||||||
<string translatable="false" name="config_wifi_tether_enable">com.android.settings/.wifi.tether.TetherService</string>
|
<string translatable="false" name="config_wifi_tether_enable">com.android.settings/.wifi.tether.TetherService</string>
|
||||||
|
|
||||||
<!-- Enable tethering notification -->
|
|
||||||
<!-- Icons for showing tether enable notification.
|
|
||||||
Each item should have two elements and be separated with ";".
|
|
||||||
|
|
||||||
The first element is downstream types which is one of tethering. This element has to be
|
|
||||||
made by WIFI, USB, BT, and OR'd with the others. Use "|" to combine multiple downstream
|
|
||||||
types and use "," to separate each combinations. Such as
|
|
||||||
|
|
||||||
USB|BT,WIFI|USB|BT
|
|
||||||
|
|
||||||
The second element is icon for the item. This element has to be composed by
|
|
||||||
<package name>:drawable/<resource name>. Such as
|
|
||||||
|
|
||||||
1. com.android.networkstack.tethering:drawable/stat_sys_tether_general
|
|
||||||
2. android:drawable/xxx
|
|
||||||
|
|
||||||
So the entire string of each item would be
|
|
||||||
|
|
||||||
USB|BT,WIFI|USB|BT;com.android.networkstack.tethering:drawable/stat_sys_tether_general
|
|
||||||
|
|
||||||
NOTE: One config can be separated into two or more for readability. Such as
|
|
||||||
|
|
||||||
WIFI|USB,WIFI|BT,USB|BT,WIFI|USB|BT;android:drawable/xxx
|
|
||||||
|
|
||||||
can be separated into
|
|
||||||
|
|
||||||
WIFI|USB;android:drawable/xxx
|
|
||||||
WIFI|BT;android:drawable/xxx
|
|
||||||
USB|BT;android:drawable/xxx
|
|
||||||
WIFI|USB|BT;android:drawable/xxx
|
|
||||||
|
|
||||||
Notification will not show if the downstream type isn't listed in array.
|
|
||||||
Empty array means disable notifications. -->
|
|
||||||
<!-- In AOSP, hotspot is configured to no notification by default. Because status bar has showed
|
|
||||||
an icon on the right side already -->
|
|
||||||
<string-array translatable="false" name="tethering_notification_icons">
|
|
||||||
<item>USB;com.android.networkstack.tethering:drawable/stat_sys_tether_usb</item>
|
|
||||||
<item>BT;com.android.networkstack.tethering:drawable/stat_sys_tether_bluetooth</item>
|
|
||||||
<item>WIFI|USB,WIFI|BT,USB|BT,WIFI|USB|BT;com.android.networkstack.tethering:drawable/stat_sys_tether_general</item>
|
|
||||||
</string-array>
|
|
||||||
<!-- String for tether enable notification title. -->
|
|
||||||
<string name="tethering_notification_title">@string/tethered_notification_title</string>
|
|
||||||
<!-- String for tether enable notification message. -->
|
|
||||||
<string name="tethering_notification_message">@string/tethered_notification_message</string>
|
|
||||||
|
|
||||||
<!-- No upstream notification is shown when there is a downstream but no upstream that is able
|
<!-- No upstream notification is shown when there is a downstream but no upstream that is able
|
||||||
to do the tethering. -->
|
to do the tethering. -->
|
||||||
<!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to
|
<!-- Delay(millisecond) to show no upstream notification after there's no Backhaul. Set delay to
|
||||||
|
|||||||
@@ -32,44 +32,6 @@
|
|||||||
<item type="string" name="config_mobile_hotspot_provision_response"/>
|
<item type="string" name="config_mobile_hotspot_provision_response"/>
|
||||||
<item type="integer" name="config_mobile_hotspot_provision_check_period"/>
|
<item type="integer" name="config_mobile_hotspot_provision_check_period"/>
|
||||||
<item type="string" name="config_wifi_tether_enable"/>
|
<item type="string" name="config_wifi_tether_enable"/>
|
||||||
<!-- Configuration values for TetheringNotificationUpdater -->
|
|
||||||
<!-- Icons for showing tether enable notification.
|
|
||||||
Each item should have two elements and be separated with ";".
|
|
||||||
|
|
||||||
The first element is downstream types which is one of tethering. This element has to be
|
|
||||||
made by WIFI, USB, BT, and OR'd with the others. Use "|" to combine multiple downstream
|
|
||||||
types and use "," to separate each combinations. Such as
|
|
||||||
|
|
||||||
USB|BT,WIFI|USB|BT
|
|
||||||
|
|
||||||
The second element is icon for the item. This element has to be composed by
|
|
||||||
<package name>:drawable/<resource name>. Such as
|
|
||||||
|
|
||||||
1. com.android.networkstack.tethering:drawable/stat_sys_tether_general
|
|
||||||
2. android:drawable/xxx
|
|
||||||
|
|
||||||
So the entire string of each item would be
|
|
||||||
|
|
||||||
USB|BT,WIFI|USB|BT;com.android.networkstack.tethering:drawable/stat_sys_tether_general
|
|
||||||
|
|
||||||
NOTE: One config can be separated into two or more for readability. Such as
|
|
||||||
|
|
||||||
WIFI|USB,WIFI|BT,USB|BT,WIFI|USB|BT;android:drawable/xxx
|
|
||||||
|
|
||||||
can be separated into
|
|
||||||
|
|
||||||
WIFI|USB;android:drawable/xxx
|
|
||||||
WIFI|BT;android:drawable/xxx
|
|
||||||
USB|BT;android:drawable/xxx
|
|
||||||
WIFI|USB|BT;android:drawable/xxx
|
|
||||||
|
|
||||||
Notification will not show if the downstream type isn't listed in array.
|
|
||||||
Empty array means disable notifications. -->
|
|
||||||
<item type="array" name="tethering_notification_icons"/>
|
|
||||||
<!-- String for tether enable notification title. -->
|
|
||||||
<item type="string" name="tethering_notification_title"/>
|
|
||||||
<!-- String for tether enable notification message. -->
|
|
||||||
<item type="string" name="tethering_notification_message"/>
|
|
||||||
<!-- Params from config.xml that can be overlaid -->
|
<!-- Params from config.xml that can be overlaid -->
|
||||||
</policy>
|
</policy>
|
||||||
</overlayable>
|
</overlayable>
|
||||||
|
|||||||
@@ -17,9 +17,6 @@
|
|||||||
package com.android.networkstack.tethering;
|
package com.android.networkstack.tethering;
|
||||||
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
|
||||||
import static android.net.TetheringManager.TETHERING_BLUETOOTH;
|
|
||||||
import static android.net.TetheringManager.TETHERING_USB;
|
|
||||||
import static android.net.TetheringManager.TETHERING_WIFI;
|
|
||||||
import static android.text.TextUtils.isEmpty;
|
import static android.text.TextUtils.isEmpty;
|
||||||
|
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
@@ -39,10 +36,8 @@ import android.os.UserHandle;
|
|||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.telephony.SubscriptionManager;
|
import android.telephony.SubscriptionManager;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import androidx.annotation.ArrayRes;
|
|
||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.IntDef;
|
import androidx.annotation.IntDef;
|
||||||
import androidx.annotation.IntRange;
|
import androidx.annotation.IntRange;
|
||||||
@@ -77,9 +72,6 @@ public class TetheringNotificationUpdater {
|
|||||||
private static final boolean NO_NOTIFY = false;
|
private static final boolean NO_NOTIFY = false;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final int EVENT_SHOW_NO_UPSTREAM = 1;
|
static final int EVENT_SHOW_NO_UPSTREAM = 1;
|
||||||
// Id to update and cancel enable notification. Must be unique within the tethering app.
|
|
||||||
@VisibleForTesting
|
|
||||||
static final int ENABLE_NOTIFICATION_ID = 1000;
|
|
||||||
// Id to update and cancel restricted notification. Must be unique within the tethering app.
|
// Id to update and cancel restricted notification. Must be unique within the tethering app.
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final int RESTRICTED_NOTIFICATION_ID = 1001;
|
static final int RESTRICTED_NOTIFICATION_ID = 1001;
|
||||||
@@ -120,7 +112,6 @@ public class TetheringNotificationUpdater {
|
|||||||
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@IntDef(value = {
|
@IntDef(value = {
|
||||||
ENABLE_NOTIFICATION_ID,
|
|
||||||
RESTRICTED_NOTIFICATION_ID,
|
RESTRICTED_NOTIFICATION_ID,
|
||||||
NO_UPSTREAM_NOTIFICATION_ID,
|
NO_UPSTREAM_NOTIFICATION_ID,
|
||||||
ROAMING_NOTIFICATION_ID
|
ROAMING_NOTIFICATION_ID
|
||||||
@@ -223,7 +214,6 @@ public class TetheringNotificationUpdater {
|
|||||||
final boolean tetheringActiveChanged =
|
final boolean tetheringActiveChanged =
|
||||||
(downstreamTypes == DOWNSTREAM_NONE) != (mDownstreamTypesMask == DOWNSTREAM_NONE);
|
(downstreamTypes == DOWNSTREAM_NONE) != (mDownstreamTypesMask == DOWNSTREAM_NONE);
|
||||||
final boolean subIdChanged = subId != mActiveDataSubId;
|
final boolean subIdChanged = subId != mActiveDataSubId;
|
||||||
final boolean downstreamChanged = downstreamTypes != mDownstreamTypesMask;
|
|
||||||
final boolean upstreamChanged = noUpstream != mNoUpstream;
|
final boolean upstreamChanged = noUpstream != mNoUpstream;
|
||||||
final boolean roamingChanged = isRoaming != mRoaming;
|
final boolean roamingChanged = isRoaming != mRoaming;
|
||||||
final boolean updateAll = tetheringActiveChanged || subIdChanged;
|
final boolean updateAll = tetheringActiveChanged || subIdChanged;
|
||||||
@@ -232,19 +222,10 @@ public class TetheringNotificationUpdater {
|
|||||||
mNoUpstream = noUpstream;
|
mNoUpstream = noUpstream;
|
||||||
mRoaming = isRoaming;
|
mRoaming = isRoaming;
|
||||||
|
|
||||||
if (updateAll || downstreamChanged) updateEnableNotification();
|
|
||||||
if (updateAll || upstreamChanged) updateNoUpstreamNotification();
|
if (updateAll || upstreamChanged) updateNoUpstreamNotification();
|
||||||
if (updateAll || roamingChanged) updateRoamingNotification();
|
if (updateAll || roamingChanged) updateRoamingNotification();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateEnableNotification() {
|
|
||||||
final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE;
|
|
||||||
|
|
||||||
if (tetheringInactive || setupNotification() == NO_NOTIFY) {
|
|
||||||
clearNotification(ENABLE_NOTIFICATION_ID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateNoUpstreamNotification() {
|
private void updateNoUpstreamNotification() {
|
||||||
final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE;
|
final boolean tetheringInactive = mDownstreamTypesMask == DOWNSTREAM_NONE;
|
||||||
|
|
||||||
@@ -310,64 +291,6 @@ public class TetheringNotificationUpdater {
|
|||||||
NO_UPSTREAM_NOTIFICATION_ID, null /* pendingIntent */, action);
|
NO_UPSTREAM_NOTIFICATION_ID, null /* pendingIntent */, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the downstream types mask which convert from given string.
|
|
||||||
*
|
|
||||||
* @param types This string has to be made by "WIFI", "USB", "BT", and OR'd with the others.
|
|
||||||
*
|
|
||||||
* @return downstream types mask value.
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
@IntRange(from = 0, to = 7)
|
|
||||||
int getDownstreamTypesMask(@NonNull final String types) {
|
|
||||||
int downstreamTypesMask = DOWNSTREAM_NONE;
|
|
||||||
final String[] downstreams = types.split("\\|");
|
|
||||||
for (String downstream : downstreams) {
|
|
||||||
if (USB_DOWNSTREAM.equals(downstream.trim())) {
|
|
||||||
downstreamTypesMask |= (1 << TETHERING_USB);
|
|
||||||
} else if (WIFI_DOWNSTREAM.equals(downstream.trim())) {
|
|
||||||
downstreamTypesMask |= (1 << TETHERING_WIFI);
|
|
||||||
} else if (BLUETOOTH_DOWNSTREAM.equals(downstream.trim())) {
|
|
||||||
downstreamTypesMask |= (1 << TETHERING_BLUETOOTH);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return downstreamTypesMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the icons {@link android.util.SparseArray} which get from given string-array resource
|
|
||||||
* id.
|
|
||||||
*
|
|
||||||
* @param id String-array resource id
|
|
||||||
*
|
|
||||||
* @return {@link android.util.SparseArray} with downstream types and icon id info.
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
@VisibleForTesting
|
|
||||||
SparseArray<Integer> getIcons(@ArrayRes int id, @NonNull Resources res) {
|
|
||||||
final String[] array = res.getStringArray(id);
|
|
||||||
final SparseArray<Integer> icons = new SparseArray<>();
|
|
||||||
for (String config : array) {
|
|
||||||
if (isEmpty(config)) continue;
|
|
||||||
|
|
||||||
final String[] elements = config.split(";");
|
|
||||||
if (elements.length != 2) {
|
|
||||||
Log.wtf(TAG,
|
|
||||||
"Unexpected format in Tethering notification configuration : " + config);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String[] types = elements[0].split(",");
|
|
||||||
for (String type : types) {
|
|
||||||
int mask = getDownstreamTypesMask(type);
|
|
||||||
if (mask == DOWNSTREAM_NONE) continue;
|
|
||||||
icons.put(mask, res.getIdentifier(
|
|
||||||
elements[1].trim(), null /* defType */, null /* defPackage */));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return icons;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean setupRoamingNotification() {
|
private boolean setupRoamingNotification() {
|
||||||
final Resources res = getResourcesForSubId(mContext, mActiveDataSubId);
|
final Resources res = getResourcesForSubId(mContext, mActiveDataSubId);
|
||||||
final boolean upstreamRoamingNotification =
|
final boolean upstreamRoamingNotification =
|
||||||
@@ -403,29 +326,6 @@ public class TetheringNotificationUpdater {
|
|||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean setupNotification() {
|
|
||||||
final Resources res = getResourcesForSubId(mContext, mActiveDataSubId);
|
|
||||||
final SparseArray<Integer> downstreamIcons =
|
|
||||||
getIcons(R.array.tethering_notification_icons, res);
|
|
||||||
|
|
||||||
final int iconId = downstreamIcons.get(mDownstreamTypesMask, NO_ICON_ID);
|
|
||||||
if (iconId == NO_ICON_ID) return NO_NOTIFY;
|
|
||||||
|
|
||||||
final String title = res.getString(R.string.tethering_notification_title);
|
|
||||||
final String message = res.getString(R.string.tethering_notification_message);
|
|
||||||
if (isEmpty(title) || isEmpty(message)) return NO_NOTIFY;
|
|
||||||
|
|
||||||
final PendingIntent pi = PendingIntent.getActivity(
|
|
||||||
mContext.createContextAsUser(UserHandle.CURRENT, 0 /* flags */),
|
|
||||||
0 /* requestCode */,
|
|
||||||
new Intent(Settings.ACTION_TETHER_SETTINGS),
|
|
||||||
Intent.FLAG_ACTIVITY_NEW_TASK,
|
|
||||||
null /* options */);
|
|
||||||
|
|
||||||
showNotification(iconId, title, message, ENABLE_NOTIFICATION_ID, pi, new Action[0]);
|
|
||||||
return NOTIFY_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showNotification(@DrawableRes final int iconId, @NonNull final String title,
|
private void showNotification(@DrawableRes final int iconId, @NonNull final String title,
|
||||||
@NonNull final String message, @NotificationId final int id, @Nullable PendingIntent pi,
|
@NonNull final String message, @NotificationId final int id, @Nullable PendingIntent pi,
|
||||||
@NonNull final Action... actions) {
|
@NonNull final Action... actions) {
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ import android.app.Notification
|
|||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.net.ConnectivityManager.TETHERING_BLUETOOTH
|
|
||||||
import android.net.ConnectivityManager.TETHERING_USB
|
|
||||||
import android.net.ConnectivityManager.TETHERING_WIFI
|
import android.net.ConnectivityManager.TETHERING_WIFI
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.HandlerThread
|
import android.os.HandlerThread
|
||||||
@@ -29,14 +27,12 @@ import android.os.Looper
|
|||||||
import android.net.NetworkCapabilities
|
import android.net.NetworkCapabilities
|
||||||
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING
|
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING
|
||||||
import android.os.UserHandle
|
import android.os.UserHandle
|
||||||
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
|
|
||||||
import android.telephony.TelephonyManager
|
import android.telephony.TelephonyManager
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import androidx.test.runner.AndroidJUnit4
|
import androidx.test.runner.AndroidJUnit4
|
||||||
import com.android.internal.util.test.BroadcastInterceptingContext
|
import com.android.internal.util.test.BroadcastInterceptingContext
|
||||||
import com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE
|
import com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE
|
||||||
import com.android.networkstack.tethering.TetheringNotificationUpdater.ENABLE_NOTIFICATION_ID
|
|
||||||
import com.android.networkstack.tethering.TetheringNotificationUpdater.EVENT_SHOW_NO_UPSTREAM
|
import com.android.networkstack.tethering.TetheringNotificationUpdater.EVENT_SHOW_NO_UPSTREAM
|
||||||
import com.android.networkstack.tethering.TetheringNotificationUpdater.NO_UPSTREAM_NOTIFICATION_ID
|
import com.android.networkstack.tethering.TetheringNotificationUpdater.NO_UPSTREAM_NOTIFICATION_ID
|
||||||
import com.android.networkstack.tethering.TetheringNotificationUpdater.RESTRICTED_NOTIFICATION_ID
|
import com.android.networkstack.tethering.TetheringNotificationUpdater.RESTRICTED_NOTIFICATION_ID
|
||||||
@@ -63,17 +59,9 @@ import org.mockito.Mockito.verifyZeroInteractions
|
|||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
const val TEST_SUBID = 1
|
const val TEST_SUBID = 1
|
||||||
const val WIFI_ICON_ID = 1
|
|
||||||
const val USB_ICON_ID = 2
|
|
||||||
const val BT_ICON_ID = 3
|
|
||||||
const val GENERAL_ICON_ID = 4
|
|
||||||
const val WIFI_MASK = 1 shl TETHERING_WIFI
|
const val WIFI_MASK = 1 shl TETHERING_WIFI
|
||||||
const val USB_MASK = 1 shl TETHERING_USB
|
const val TEST_DISALLOW_TITLE = "Tether function is disallowed"
|
||||||
const val BT_MASK = 1 shl TETHERING_BLUETOOTH
|
const val TEST_DISALLOW_MESSAGE = "Please contact your admin"
|
||||||
const val TITLE = "Tethering active"
|
|
||||||
const val MESSAGE = "Tap here to set up."
|
|
||||||
const val TEST_TITLE = "Hotspot active"
|
|
||||||
const val TEST_MESSAGE = "Tap to set up hotspot."
|
|
||||||
const val TEST_NO_UPSTREAM_TITLE = "Hotspot has no internet access"
|
const val TEST_NO_UPSTREAM_TITLE = "Hotspot has no internet access"
|
||||||
const val TEST_NO_UPSTREAM_MESSAGE = "Device cannot connect to internet."
|
const val TEST_NO_UPSTREAM_MESSAGE = "Device cannot connect to internet."
|
||||||
const val TEST_NO_UPSTREAM_BUTTON = "Turn off hotspot"
|
const val TEST_NO_UPSTREAM_BUTTON = "Turn off hotspot"
|
||||||
@@ -88,7 +76,6 @@ class TetheringNotificationUpdaterTest {
|
|||||||
@Mock private lateinit var mockContext: Context
|
@Mock private lateinit var mockContext: Context
|
||||||
@Mock private lateinit var notificationManager: NotificationManager
|
@Mock private lateinit var notificationManager: NotificationManager
|
||||||
@Mock private lateinit var telephonyManager: TelephonyManager
|
@Mock private lateinit var telephonyManager: TelephonyManager
|
||||||
@Mock private lateinit var defaultResources: Resources
|
|
||||||
@Mock private lateinit var testResources: Resources
|
@Mock private lateinit var testResources: Resources
|
||||||
|
|
||||||
// lateinit for these classes under test, as they should be reset to a different instance for
|
// lateinit for these classes under test, as they should be reset to a different instance for
|
||||||
@@ -97,11 +84,6 @@ class TetheringNotificationUpdaterTest {
|
|||||||
private lateinit var notificationUpdater: TetheringNotificationUpdater
|
private lateinit var notificationUpdater: TetheringNotificationUpdater
|
||||||
private lateinit var fakeTetheringThread: HandlerThread
|
private lateinit var fakeTetheringThread: HandlerThread
|
||||||
|
|
||||||
private val ENABLE_ICON_CONFIGS = arrayOf(
|
|
||||||
"USB;android.test:drawable/usb", "BT;android.test:drawable/bluetooth",
|
|
||||||
"WIFI|BT;android.test:drawable/general", "WIFI|USB;android.test:drawable/general",
|
|
||||||
"USB|BT;android.test:drawable/general", "WIFI|USB|BT;android.test:drawable/general")
|
|
||||||
|
|
||||||
private val ROAMING_CAPABILITIES = NetworkCapabilities()
|
private val ROAMING_CAPABILITIES = NetworkCapabilities()
|
||||||
private val HOME_CAPABILITIES = NetworkCapabilities().addCapability(NET_CAPABILITY_NOT_ROAMING)
|
private val HOME_CAPABILITIES = NetworkCapabilities().addCapability(NET_CAPABILITY_NOT_ROAMING)
|
||||||
private val NOTIFICATION_ICON_ID = R.drawable.stat_sys_tether_general
|
private val NOTIFICATION_ICON_ID = R.drawable.stat_sys_tether_general
|
||||||
@@ -117,29 +99,19 @@ class TetheringNotificationUpdaterTest {
|
|||||||
|
|
||||||
private inner class WrappedNotificationUpdater(c: Context, looper: Looper)
|
private inner class WrappedNotificationUpdater(c: Context, looper: Looper)
|
||||||
: TetheringNotificationUpdater(c, looper) {
|
: TetheringNotificationUpdater(c, looper) {
|
||||||
override fun getResourcesForSubId(context: Context, subId: Int) =
|
override fun getResourcesForSubId(c: Context, subId: Int) =
|
||||||
when (subId) {
|
if (subId == TEST_SUBID) testResources else super.getResourcesForSubId(c, subId)
|
||||||
TEST_SUBID -> testResources
|
|
||||||
INVALID_SUBSCRIPTION_ID -> defaultResources
|
|
||||||
else -> super.getResourcesForSubId(context, subId)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupResources() {
|
private fun setupResources() {
|
||||||
doReturn(ENABLE_ICON_CONFIGS).`when`(defaultResources)
|
|
||||||
.getStringArray(R.array.tethering_notification_icons)
|
|
||||||
doReturn(arrayOf("WIFI;android.test:drawable/wifi")).`when`(testResources)
|
|
||||||
.getStringArray(R.array.tethering_notification_icons)
|
|
||||||
doReturn(5).`when`(testResources)
|
doReturn(5).`when`(testResources)
|
||||||
.getInteger(R.integer.delay_to_show_no_upstream_after_no_backhaul)
|
.getInteger(R.integer.delay_to_show_no_upstream_after_no_backhaul)
|
||||||
doReturn(true).`when`(testResources)
|
doReturn(true).`when`(testResources)
|
||||||
.getBoolean(R.bool.config_upstream_roaming_notification)
|
.getBoolean(R.bool.config_upstream_roaming_notification)
|
||||||
doReturn(TITLE).`when`(defaultResources).getString(R.string.tethering_notification_title)
|
doReturn(TEST_DISALLOW_TITLE).`when`(testResources)
|
||||||
doReturn(MESSAGE).`when`(defaultResources)
|
.getString(R.string.disable_tether_notification_title)
|
||||||
.getString(R.string.tethering_notification_message)
|
doReturn(TEST_DISALLOW_MESSAGE).`when`(testResources)
|
||||||
doReturn(TEST_TITLE).`when`(testResources).getString(R.string.tethering_notification_title)
|
.getString(R.string.disable_tether_notification_message)
|
||||||
doReturn(TEST_MESSAGE).`when`(testResources)
|
|
||||||
.getString(R.string.tethering_notification_message)
|
|
||||||
doReturn(TEST_NO_UPSTREAM_TITLE).`when`(testResources)
|
doReturn(TEST_NO_UPSTREAM_TITLE).`when`(testResources)
|
||||||
.getString(R.string.no_upstream_notification_title)
|
.getString(R.string.no_upstream_notification_title)
|
||||||
doReturn(TEST_NO_UPSTREAM_MESSAGE).`when`(testResources)
|
doReturn(TEST_NO_UPSTREAM_MESSAGE).`when`(testResources)
|
||||||
@@ -150,14 +122,6 @@ class TetheringNotificationUpdaterTest {
|
|||||||
.getString(R.string.upstream_roaming_notification_title)
|
.getString(R.string.upstream_roaming_notification_title)
|
||||||
doReturn(TEST_ROAMING_MESSAGE).`when`(testResources)
|
doReturn(TEST_ROAMING_MESSAGE).`when`(testResources)
|
||||||
.getString(R.string.upstream_roaming_notification_message)
|
.getString(R.string.upstream_roaming_notification_message)
|
||||||
doReturn(USB_ICON_ID).`when`(defaultResources)
|
|
||||||
.getIdentifier(eq("android.test:drawable/usb"), any(), any())
|
|
||||||
doReturn(BT_ICON_ID).`when`(defaultResources)
|
|
||||||
.getIdentifier(eq("android.test:drawable/bluetooth"), any(), any())
|
|
||||||
doReturn(GENERAL_ICON_ID).`when`(defaultResources)
|
|
||||||
.getIdentifier(eq("android.test:drawable/general"), any(), any())
|
|
||||||
doReturn(WIFI_ICON_ID).`when`(testResources)
|
|
||||||
.getIdentifier(eq("android.test:drawable/wifi"), any(), any())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -206,119 +170,27 @@ class TetheringNotificationUpdaterTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNotificationWithDownstreamChanged() {
|
fun testRestrictedNotification() {
|
||||||
// Wifi downstream. No notification.
|
// Set test sub id.
|
||||||
notificationUpdater.onDownstreamChanged(WIFI_MASK)
|
|
||||||
verifyNotificationCancelled(listOf(ENABLE_NOTIFICATION_ID))
|
|
||||||
|
|
||||||
// Same downstream changed. Nothing happened.
|
|
||||||
notificationUpdater.onDownstreamChanged(WIFI_MASK)
|
|
||||||
verifyZeroInteractions(notificationManager)
|
|
||||||
|
|
||||||
// Wifi and usb downstreams. Show enable notification
|
|
||||||
notificationUpdater.onDownstreamChanged(WIFI_MASK or USB_MASK)
|
|
||||||
verifyNotification(GENERAL_ICON_ID, TITLE, MESSAGE, ENABLE_NOTIFICATION_ID)
|
|
||||||
|
|
||||||
// Usb downstream. Still show enable notification.
|
|
||||||
notificationUpdater.onDownstreamChanged(USB_MASK)
|
|
||||||
verifyNotification(USB_ICON_ID, TITLE, MESSAGE, ENABLE_NOTIFICATION_ID)
|
|
||||||
|
|
||||||
// No downstream. No notification.
|
|
||||||
notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
|
|
||||||
verifyNotificationCancelled(listOf(ENABLE_NOTIFICATION_ID, NO_UPSTREAM_NOTIFICATION_ID,
|
|
||||||
ROAMING_NOTIFICATION_ID))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testNotificationWithActiveDataSubscriptionIdChanged() {
|
|
||||||
// Usb downstream. Showed enable notification with default resource.
|
|
||||||
notificationUpdater.onDownstreamChanged(USB_MASK)
|
|
||||||
verifyNotification(USB_ICON_ID, TITLE, MESSAGE, ENABLE_NOTIFICATION_ID)
|
|
||||||
|
|
||||||
// Same subId changed. Nothing happened.
|
|
||||||
notificationUpdater.onActiveDataSubscriptionIdChanged(INVALID_SUBSCRIPTION_ID)
|
|
||||||
verifyZeroInteractions(notificationManager)
|
|
||||||
|
|
||||||
// Set test sub id. Clear notification with test resource.
|
|
||||||
notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
|
notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
|
||||||
verifyNotificationCancelled(listOf(ENABLE_NOTIFICATION_ID, NO_UPSTREAM_NOTIFICATION_ID,
|
verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
|
||||||
ROAMING_NOTIFICATION_ID))
|
|
||||||
|
|
||||||
// Wifi downstream. Show enable notification with test resource.
|
|
||||||
notificationUpdater.onDownstreamChanged(WIFI_MASK)
|
|
||||||
verifyNotification(WIFI_ICON_ID, TEST_TITLE, TEST_MESSAGE, ENABLE_NOTIFICATION_ID)
|
|
||||||
|
|
||||||
// No downstream. No notification.
|
|
||||||
notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
|
|
||||||
verifyNotificationCancelled(listOf(ENABLE_NOTIFICATION_ID, NO_UPSTREAM_NOTIFICATION_ID,
|
|
||||||
ROAMING_NOTIFICATION_ID))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun assertIconNumbers(number: Int, configs: Array<String?>) {
|
|
||||||
doReturn(configs).`when`(defaultResources)
|
|
||||||
.getStringArray(R.array.tethering_notification_icons)
|
|
||||||
assertEquals(number, notificationUpdater.getIcons(
|
|
||||||
R.array.tethering_notification_icons, defaultResources).size())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testGetIcons() {
|
|
||||||
assertIconNumbers(0, arrayOfNulls<String>(0))
|
|
||||||
assertIconNumbers(0, arrayOf(null, ""))
|
|
||||||
assertIconNumbers(3, arrayOf(
|
|
||||||
// These configurations are invalid with wrong strings or symbols.
|
|
||||||
";", ",", "|", "|,;", "WIFI", "1;2", " U SB; ", "bt;", "WIFI;USB;BT", "WIFI|USB|BT",
|
|
||||||
"WIFI,BT,USB", " WIFI| | | USB, test:drawable/test",
|
|
||||||
// This configuration is valid with two downstream types (USB, BT).
|
|
||||||
"USB|,,,,,|BT;drawable/test ",
|
|
||||||
// This configuration is valid with one downstream types (WIFI).
|
|
||||||
" WIFI ; android.test:drawable/xxx "))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testGetDownstreamTypesMask() {
|
|
||||||
assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask(""))
|
|
||||||
assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask("1"))
|
|
||||||
assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask("WIFI_P2P"))
|
|
||||||
assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask("usb"))
|
|
||||||
assertEquals(WIFI_MASK, notificationUpdater.getDownstreamTypesMask(" WIFI "))
|
|
||||||
assertEquals(USB_MASK, notificationUpdater.getDownstreamTypesMask("USB | B T"))
|
|
||||||
assertEquals(BT_MASK, notificationUpdater.getDownstreamTypesMask(" WIFI: | BT"))
|
|
||||||
assertEquals(WIFI_MASK or USB_MASK,
|
|
||||||
notificationUpdater.getDownstreamTypesMask("1|2|USB|WIFI|BLUETOOTH||"))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testSetupRestrictedNotification() {
|
|
||||||
val title = context.resources.getString(R.string.disable_tether_notification_title)
|
|
||||||
val message = 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.
|
// User restrictions on. Show restricted notification.
|
||||||
notificationUpdater.notifyTetheringDisabledByRestriction()
|
notificationUpdater.notifyTetheringDisabledByRestriction()
|
||||||
verifyNotification(NOTIFICATION_ICON_ID, title, message, RESTRICTED_NOTIFICATION_ID)
|
verifyNotification(NOTIFICATION_ICON_ID, TEST_DISALLOW_TITLE, TEST_DISALLOW_MESSAGE,
|
||||||
|
RESTRICTED_NOTIFICATION_ID)
|
||||||
|
|
||||||
// User restrictions off. Clear notification.
|
// User restrictions off. Clear notification.
|
||||||
notificationUpdater.tetheringRestrictionLifted()
|
notificationUpdater.tetheringRestrictionLifted()
|
||||||
verifyNotificationCancelled(listOf(RESTRICTED_NOTIFICATION_ID))
|
verifyNotificationCancelled(listOf(RESTRICTED_NOTIFICATION_ID))
|
||||||
|
|
||||||
// Set test sub id. No notification.
|
// No downstream.
|
||||||
notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
|
notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
|
||||||
verifyNotificationCancelled(listOf(ENABLE_NOTIFICATION_ID, NO_UPSTREAM_NOTIFICATION_ID,
|
verifyZeroInteractions(notificationManager)
|
||||||
ROAMING_NOTIFICATION_ID))
|
|
||||||
|
|
||||||
// User restrictions on again. Show restricted notification with test resource.
|
// User restrictions on again. Show restricted notification.
|
||||||
notificationUpdater.notifyTetheringDisabledByRestriction()
|
notificationUpdater.notifyTetheringDisabledByRestriction()
|
||||||
verifyNotification(NOTIFICATION_ICON_ID, disallowTitle, disallowMessage,
|
verifyNotification(NOTIFICATION_ICON_ID, TEST_DISALLOW_TITLE, TEST_DISALLOW_MESSAGE,
|
||||||
RESTRICTED_NOTIFICATION_ID)
|
RESTRICTED_NOTIFICATION_ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,15 +228,14 @@ class TetheringNotificationUpdaterTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNotificationWithUpstreamCapabilitiesChanged_NoUpstream() {
|
fun testNoUpstreamNotification() {
|
||||||
// Set test sub id. No notification.
|
// Set test sub id.
|
||||||
notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
|
notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
|
||||||
verifyNotificationCancelled(listOf(ENABLE_NOTIFICATION_ID, NO_UPSTREAM_NOTIFICATION_ID,
|
verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
|
||||||
ROAMING_NOTIFICATION_ID))
|
|
||||||
|
|
||||||
// Wifi downstream. Show enable notification with test resource.
|
// Wifi downstream.
|
||||||
notificationUpdater.onDownstreamChanged(WIFI_MASK)
|
notificationUpdater.onDownstreamChanged(WIFI_MASK)
|
||||||
verifyNotification(WIFI_ICON_ID, TEST_TITLE, TEST_MESSAGE, ENABLE_NOTIFICATION_ID)
|
verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
|
||||||
|
|
||||||
// There is no upstream. Show no upstream notification.
|
// There is no upstream. Show no upstream notification.
|
||||||
notificationUpdater.onUpstreamCapabilitiesChanged(null)
|
notificationUpdater.onUpstreamCapabilitiesChanged(null)
|
||||||
@@ -386,15 +257,14 @@ class TetheringNotificationUpdaterTest {
|
|||||||
verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
|
verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
|
||||||
NO_UPSTREAM_NOTIFICATION_ID)
|
NO_UPSTREAM_NOTIFICATION_ID)
|
||||||
|
|
||||||
// No downstream. No notification.
|
// No downstream.
|
||||||
notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
|
notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
|
||||||
verifyNotificationCancelled(listOf(ENABLE_NOTIFICATION_ID, NO_UPSTREAM_NOTIFICATION_ID,
|
verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
|
||||||
ROAMING_NOTIFICATION_ID))
|
|
||||||
|
|
||||||
// Put up enable notification with wifi downstream and home capabilities.
|
// Wifi downstream and home capabilities.
|
||||||
notificationUpdater.onDownstreamChanged(WIFI_MASK)
|
notificationUpdater.onDownstreamChanged(WIFI_MASK)
|
||||||
notificationUpdater.onUpstreamCapabilitiesChanged(HOME_CAPABILITIES)
|
notificationUpdater.onUpstreamCapabilitiesChanged(HOME_CAPABILITIES)
|
||||||
verifyNotification(WIFI_ICON_ID, TEST_TITLE, TEST_MESSAGE, ENABLE_NOTIFICATION_ID)
|
verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
|
||||||
|
|
||||||
// Set R.integer.delay_to_show_no_upstream_after_no_backhaul to -1 and change to no upstream
|
// Set R.integer.delay_to_show_no_upstream_after_no_backhaul to -1 and change to no upstream
|
||||||
// again. Don't put up no upstream notification.
|
// again. Don't put up no upstream notification.
|
||||||
@@ -429,15 +299,14 @@ class TetheringNotificationUpdaterTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNotificationWithUpstreamCapabilitiesChanged_Roaming() {
|
fun testRoamingNotification() {
|
||||||
// Set test sub id. Clear notification.
|
// Set test sub id.
|
||||||
notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
|
notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
|
||||||
verifyNotificationCancelled(listOf(ENABLE_NOTIFICATION_ID, NO_UPSTREAM_NOTIFICATION_ID,
|
verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
|
||||||
ROAMING_NOTIFICATION_ID))
|
|
||||||
|
|
||||||
// Wifi downstream. Show enable notification with test resource.
|
// Wifi downstream.
|
||||||
notificationUpdater.onDownstreamChanged(WIFI_MASK)
|
notificationUpdater.onDownstreamChanged(WIFI_MASK)
|
||||||
verifyNotification(WIFI_ICON_ID, TEST_TITLE, TEST_MESSAGE, ENABLE_NOTIFICATION_ID)
|
verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
|
||||||
|
|
||||||
// Upstream capabilities changed to roaming state. Show roaming notification.
|
// Upstream capabilities changed to roaming state. Show roaming notification.
|
||||||
notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES)
|
notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES)
|
||||||
@@ -464,14 +333,16 @@ class TetheringNotificationUpdaterTest {
|
|||||||
verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
|
verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
|
||||||
NO_UPSTREAM_NOTIFICATION_ID)
|
NO_UPSTREAM_NOTIFICATION_ID)
|
||||||
|
|
||||||
// No downstream. No notification.
|
// No downstream.
|
||||||
notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
|
notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
|
||||||
verifyNotificationCancelled(listOf(ENABLE_NOTIFICATION_ID, NO_UPSTREAM_NOTIFICATION_ID,
|
verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
|
||||||
ROAMING_NOTIFICATION_ID))
|
|
||||||
|
|
||||||
// Wifi downstream again. Show enable notification with test resource.
|
// Wifi downstream again.
|
||||||
notificationUpdater.onDownstreamChanged(WIFI_MASK)
|
notificationUpdater.onDownstreamChanged(WIFI_MASK)
|
||||||
verifyNotification(WIFI_ICON_ID, TEST_TITLE, TEST_MESSAGE, ENABLE_NOTIFICATION_ID)
|
notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS)
|
||||||
|
verifyNotificationCancelled(listOf(ROAMING_NOTIFICATION_ID), false)
|
||||||
|
verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
|
||||||
|
NO_UPSTREAM_NOTIFICATION_ID)
|
||||||
|
|
||||||
// Set R.bool.config_upstream_roaming_notification to false and change upstream
|
// Set R.bool.config_upstream_roaming_notification to false and change upstream
|
||||||
// network to roaming state again. No roaming notification.
|
// network to roaming state again. No roaming notification.
|
||||||
|
|||||||
Reference in New Issue
Block a user