Allow firing the LOST_INTERNET intent immediately in config

When config_notifyNoInternetAsDialogWhenHighPriority is on, the
LOST_INTERNET notification intent should be fired immediately
rather than as a pending intent.

Bug: 281970908
Test: Improve test for this in NetworkNotificationManagerTest
(cherry picked from https://android-review.googlesource.com/q/commit:e13b833b21342d80ef940783acba4b3eecfce968)
Merged-In: I88565839a12a1ab4b096f763250944ebaf6c5349
Change-Id: I88565839a12a1ab4b096f763250944ebaf6c5349
This commit is contained in:
Chalard Jean
2023-06-05 18:47:42 +09:00
parent a0e8ab4933
commit 3bf3a59f35
3 changed files with 108 additions and 22 deletions

View File

@@ -135,10 +135,17 @@
<!-- Whether to cancel network notifications automatically when tapped --> <!-- Whether to cancel network notifications automatically when tapped -->
<bool name="config_autoCancelNetworkNotifications">true</bool> <bool name="config_autoCancelNetworkNotifications">true</bool>
<!-- When no internet or partial connectivity is detected on a network, and a high priority <!-- Configuration to let OEMs customize what to do when :
(heads up) notification would be shown due to the network being explicitly selected, • Partial connectivity is detected on the network
directly show the dialog that would normally be shown when tapping the notification • No internet is detected on the network, and
instead of showing the notification. --> - the network was explicitly selected
- the system is configured to actively prefer bad wifi (see config_activelyPreferBadWifi)
The default behavior (false) is to post a notification with a PendingIntent so
the user is informed and can act if they wish.
Making this true instead will have the system fire the intent immediately instead
of showing a notification. OEMs who do this should have some intent receiver
listening to the intent and take the action they prefer (e.g. show a dialog,
show a customized notification etc). -->
<bool name="config_notifyNoInternetAsDialogWhenHighPriority">false</bool> <bool name="config_notifyNoInternetAsDialogWhenHighPriority">false</bool>
<!-- When showing notifications indicating partial connectivity, display the same notifications <!-- When showing notifications indicating partial connectivity, display the same notifications

View File

@@ -322,7 +322,11 @@ public class NetworkNotificationManager {
private boolean maybeNotifyViaDialog(Resources res, NotificationType notifyType, private boolean maybeNotifyViaDialog(Resources res, NotificationType notifyType,
PendingIntent intent) { PendingIntent intent) {
if (notifyType != NotificationType.NO_INTERNET final boolean activelyPreferBadWifi = SdkLevel.isAtLeastU()
|| (SdkLevel.isAtLeastT()
&& res.getInteger(R.integer.config_activelyPreferBadWifi) == 1);
if ((notifyType != NotificationType.LOST_INTERNET || !activelyPreferBadWifi)
&& notifyType != NotificationType.NO_INTERNET
&& notifyType != NotificationType.PARTIAL_CONNECTIVITY) { && notifyType != NotificationType.PARTIAL_CONNECTIVITY) {
return false; return false;
} }
@@ -432,7 +436,8 @@ public class NetworkNotificationManager {
* A notification with a higher number will take priority over a notification with a lower * A notification with a higher number will take priority over a notification with a lower
* number. * number.
*/ */
private static int priority(NotificationType t) { @VisibleForTesting
public static int priority(NotificationType t) {
if (t == null) { if (t == null) {
return 0; return 0;
} }

View File

@@ -62,6 +62,7 @@ import android.testing.PollingCheck;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -73,6 +74,7 @@ import androidx.test.uiautomator.UiSelector;
import androidx.test.uiautomator.Until; import androidx.test.uiautomator.Until;
import com.android.connectivity.resources.R; import com.android.connectivity.resources.R;
import com.android.modules.utils.build.SdkLevel;
import com.android.server.connectivity.NetworkNotificationManager.NotificationType; import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
import com.android.testutils.DevSdkIgnoreRule; import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner; import com.android.testutils.DevSdkIgnoreRunner;
@@ -385,15 +387,75 @@ public class NetworkNotificationManagerTest {
verify(mNotificationManager, never()).cancel(eq(tag), eq(PARTIAL_CONNECTIVITY.eventId)); verify(mNotificationManager, never()).cancel(eq(tag), eq(PARTIAL_CONNECTIVITY.eventId));
} }
private static final int EXPECT_DIALOG = 0;
private static final int EXPECT_NOTIFICATION = 1;
@Test @Test
public void testNotifyNoInternetAsDialogWhenHighPriority() throws Exception { public void testNotifyNoInternet_asNotification_ActivelyPrefer() throws Exception {
doReturn(true).when(mResources).getBoolean( doTestNotifyNotificationAsDialogWhenHighPriority(false /* notifyAsDialog */,
true /* activelyPreferBadWifi */, NO_INTERNET, EXPECT_NOTIFICATION);
}
@Test
public void testNotifyNoInternet_asNotification_NotActivelyPrefer() throws Exception {
doTestNotifyNotificationAsDialogWhenHighPriority(false /* notifyAsDialog */,
false /* activelyPreferBadWifi */, NO_INTERNET, EXPECT_NOTIFICATION);
}
@Test
public void testNotifyNoInternet_asDialog_ActivelyPrefer() throws Exception {
doTestNotifyNotificationAsDialogWhenHighPriority(true /* notifyAsDialog */,
true /* activelyPreferBadWifi */, NO_INTERNET, EXPECT_DIALOG);
}
@Test
public void testNotifyNoInternet_asDialog_NotActivelyPrefer() throws Exception {
doTestNotifyNotificationAsDialogWhenHighPriority(true /* notifyAsDialog */,
false /* activelyPreferBadWifi */, NO_INTERNET, EXPECT_DIALOG);
}
@Test
public void testNotifyLostInternet_asNotification_ActivelyPrefer() throws Exception {
doTestNotifyNotificationAsDialogWhenHighPriority(false /* notifyAsDialog */,
true /* activelyPreferBadWifi */, LOST_INTERNET, EXPECT_NOTIFICATION);
}
@Test
public void testNotifyLostInternet_asNotification_NotActivelyPrefer() throws Exception {
doTestNotifyNotificationAsDialogWhenHighPriority(false /* notifyAsDialog */,
false /* activelyPreferBadWifi */, LOST_INTERNET, EXPECT_NOTIFICATION);
}
@Test
public void testNotifyLostInternet_asDialog_ActivelyPrefer() throws Exception {
doTestNotifyNotificationAsDialogWhenHighPriority(true /* notifyAsDialog */,
true /* activelyPreferBadWifi */, LOST_INTERNET,
SdkLevel.isAtLeastT() ? EXPECT_DIALOG : EXPECT_NOTIFICATION);
}
@Test
public void testNotifyLostInternet_asDialog_NotActivelyPrefer() throws Exception {
doTestNotifyNotificationAsDialogWhenHighPriority(true /* notifyAsDialog */,
false /* activelyPreferBadWifi */, LOST_INTERNET,
SdkLevel.isAtLeastU() ? EXPECT_DIALOG : EXPECT_NOTIFICATION);
}
// Pass EXPECT_DIALOG or EXPECT_NOTIFICATION to |expectBehavior|
public void doTestNotifyNotificationAsDialogWhenHighPriority(
final boolean notifyAsDialog, final boolean activelyPreferBadWifi,
@NonNull final NotificationType notifType, final int expectBehavior) throws Exception {
doReturn(notifyAsDialog).when(mResources).getBoolean(
R.bool.config_notifyNoInternetAsDialogWhenHighPriority); R.bool.config_notifyNoInternetAsDialogWhenHighPriority);
doReturn(activelyPreferBadWifi ? 1 : 0).when(mResources).getInteger(
R.integer.config_activelyPreferBadWifi);
final Instrumentation instr = InstrumentationRegistry.getInstrumentation(); final Instrumentation instr = InstrumentationRegistry.getInstrumentation();
final UiDevice uiDevice = UiDevice.getInstance(instr); final UiDevice uiDevice = UiDevice.getInstance(instr);
final Context ctx = instr.getContext(); final Context ctx = instr.getContext();
final PowerManager pm = ctx.getSystemService(PowerManager.class); final PowerManager pm = ctx.getSystemService(PowerManager.class);
// If the prio of this notif is < that of NETWORK_SWITCH, it's the lowest prio and
// therefore it can't be tested whether it cancels other lower-prio notifs.
final boolean isLowestPrioNotif = NetworkNotificationManager.priority(notifType)
< NetworkNotificationManager.priority(NETWORK_SWITCH);
// Wake up the device (it has no effect if the device is already awake). // Wake up the device (it has no effect if the device is already awake).
uiDevice.executeShellCommand("input keyevent KEYCODE_WAKEUP"); uiDevice.executeShellCommand("input keyevent KEYCODE_WAKEUP");
@@ -409,9 +471,13 @@ public class NetworkNotificationManagerTest {
uiDevice.wait(Until.hasObject(By.pkg(launcherPackageName)), uiDevice.wait(Until.hasObject(By.pkg(launcherPackageName)),
UI_AUTOMATOR_WAIT_TIME_MILLIS)); UI_AUTOMATOR_WAIT_TIME_MILLIS));
mManager.showNotification(TEST_NOTIF_ID, NETWORK_SWITCH, mWifiNai, mCellNai, null, false); if (!isLowestPrioNotif) {
mManager.showNotification(TEST_NOTIF_ID, NETWORK_SWITCH, mWifiNai, mCellNai,
null, false);
// Non-"no internet" notifications are not affected // Non-"no internet" notifications are not affected
verify(mNotificationManager).notify(eq(TEST_NOTIF_TAG), eq(NETWORK_SWITCH.eventId), any()); verify(mNotificationManager).notify(eq(TEST_NOTIF_TAG), eq(NETWORK_SWITCH.eventId),
any());
}
final String testAction = "com.android.connectivity.coverage.TEST_DIALOG"; final String testAction = "com.android.connectivity.coverage.TEST_DIALOG";
final Intent intent = new Intent(testAction) final Intent intent = new Intent(testAction)
@@ -420,12 +486,15 @@ public class NetworkNotificationManagerTest {
final PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0 /* requestCode */, final PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0 /* requestCode */,
intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
mManager.showNotification(TEST_NOTIF_ID, NO_INTERNET, mWifiNai, null /* switchToNai */, mManager.showNotification(TEST_NOTIF_ID, notifType, mWifiNai, null /* switchToNai */,
pendingIntent, true /* highPriority */); pendingIntent, true /* highPriority */);
if (!isLowestPrioNotif) {
// Previous notifications are still dismissed // Previous notifications are still dismissed
verify(mNotificationManager).cancel(TEST_NOTIF_TAG, NETWORK_SWITCH.eventId); verify(mNotificationManager).cancel(TEST_NOTIF_TAG, NETWORK_SWITCH.eventId);
}
if (expectBehavior == EXPECT_DIALOG) {
// Verify that the activity is shown (the activity shows the action on screen) // Verify that the activity is shown (the activity shows the action on screen)
final UiObject actionText = uiDevice.findObject(new UiSelector().text(testAction)); final UiObject actionText = uiDevice.findObject(new UiSelector().text(testAction));
assertTrue("Activity not shown", actionText.waitForExists(TEST_TIMEOUT_MS)); assertTrue("Activity not shown", actionText.waitForExists(TEST_TIMEOUT_MS));
@@ -434,8 +503,13 @@ public class NetworkNotificationManagerTest {
actionText.click(); actionText.click();
assertTrue("Activity not dismissed", actionText.waitUntilGone(TEST_TIMEOUT_MS)); assertTrue("Activity not dismissed", actionText.waitUntilGone(TEST_TIMEOUT_MS));
// Verify no NO_INTERNET notification was posted // Verify that the notification was not posted
verify(mNotificationManager, never()).notify(any(), eq(NO_INTERNET.eventId), any()); verify(mNotificationManager, never()).notify(any(), eq(notifType.eventId), any());
} else {
// Notification should have been posted, and will have overridden the previous
// one because it has the same id (hence no cancel).
verify(mNotificationManager).notify(eq(TEST_NOTIF_TAG), eq(notifType.eventId), any());
}
} }
private void doNotificationTextTest(NotificationType type, @StringRes int expectedTitleRes, private void doNotificationTextTest(NotificationType type, @StringRes int expectedTitleRes,