diff --git a/tests/cts/hostside/app/AndroidManifest.xml b/tests/cts/hostside/app/AndroidManifest.xml index c7978f8775..0598a3b02a 100644 --- a/tests/cts/hostside/app/AndroidManifest.xml +++ b/tests/cts/hostside/app/AndroidManifest.xml @@ -31,6 +31,14 @@ + + + + + 0) { + listeners.append(":"); + } + listeners.append(MyNotificationListenerService.getId()); + executeShellCommand("settings put secure enabled_notification_listeners " + listeners); + final String newListeners = getNotificationListenerServices(); + assertEquals("Failed to set 'enabled_notification_listeners'", + listeners.toString(), newListeners); + } + + private String getNotificationListenerServices() throws Exception { + return executeShellCommand("settings get secure enabled_notification_listeners"); + } + + protected void setPendingIntentWhitelistDuration(int durationMs) throws Exception { + final String command = String.format( + "settings put global device_idle_constants %s=%d", + "notification_whitelist_duration", durationMs); + executeSilentShellCommand(command); + } + + protected void resetDeviceIdleSettings() throws Exception { + executeShellCommand("settings delete global device_idle_constants"); + } + protected void startForegroundService() throws Exception { executeShellCommand( "am startservice -f 1 com.android.cts.net.hostside.app2/.MyForegroundService"); @@ -667,6 +704,13 @@ abstract class AbstractRestrictBackgroundNetworkTestCase extends Instrumentation + "--receiver-foreground --receiver-registered-only"); } + protected void sendNotification(int notificationId) { + final Intent intent = new Intent(ACTION_SEND_NOTIFICATION); + intent.putExtra(EXTRA_NOTIFICATION_ID, notificationId); + Log.d(TAG, "Sending broadcast: " + intent); + mContext.sendBroadcast(intent); + } + private String toString(int status) { switch (status) { case RESTRICT_BACKGROUND_STATUS_DISABLED: diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyNotificationListenerService.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyNotificationListenerService.java new file mode 100644 index 0000000000..b9c303107c --- /dev/null +++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyNotificationListenerService.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.cts.net.hostside; + +import android.app.Notification; +import android.app.PendingIntent.CanceledException; +import android.service.notification.NotificationListenerService; +import android.service.notification.StatusBarNotification; +import android.util.Log; + +/** + * NotificationListenerService implementation that executes the notification actions once they're + * created. + */ +public class MyNotificationListenerService extends NotificationListenerService { + private static final String TAG = "MyNotificationListenerService"; + + @Override + public void onListenerConnected() { + Log.d(TAG, "onListenerConnected()"); + } + + @Override + public void onNotificationPosted(StatusBarNotification sbn) { + Log.d(TAG, "onNotificationPosted(): " + sbn); + if (!sbn.getPackageName().startsWith(getPackageName())) { + Log.v(TAG, "ignoring notification from a different package"); + return; + } + final Notification notification = sbn.getNotification(); + if (notification.actions == null) { + Log.w(TAG, "ignoring notification without an action"); + } + for (Notification.Action action : notification.actions) { + Log.i(TAG, "Sending pending intent " + action.actionIntent); + try { + action.actionIntent.send(); + } catch (CanceledException e) { + Log.w(TAG, "Pending Intent canceled"); + } + } + } + + static String getId() { + return String.format("%s/%s", MyNotificationListenerService.class.getPackage().getName(), + MyNotificationListenerService.class.getName()); + } +} diff --git a/tests/cts/hostside/app2/AndroidManifest.xml b/tests/cts/hostside/app2/AndroidManifest.xml index 80b669d4eb..1fa49ba837 100644 --- a/tests/cts/hostside/app2/AndroidManifest.xml +++ b/tests/cts/hostside/app2/AndroidManifest.xml @@ -45,7 +45,8 @@ - + + diff --git a/tests/cts/hostside/app2/res/drawable/ic_notification.png b/tests/cts/hostside/app2/res/drawable/ic_notification.png new file mode 100644 index 0000000000..6ae570b4db Binary files /dev/null and b/tests/cts/hostside/app2/res/drawable/ic_notification.png differ diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java index d827921654..f02f651f06 100644 --- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java +++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java @@ -36,9 +36,13 @@ public final class Common { "com.android.cts.net.hostside.app2.action.RECEIVER_READY"; static final String ACTION_FINISH_ACTIVITY = "com.android.cts.net.hostside.app2.action.FINISH_ACTIVITY"; + static final String ACTION_SEND_NOTIFICATION = + "com.android.cts.net.hostside.app2.action.SEND_NOTIFICATION"; static final String EXTRA_ACTION = "com.android.cts.net.hostside.app2.extra.ACTION"; static final String EXTRA_RECEIVER_NAME = "com.android.cts.net.hostside.app2.extra.RECEIVER_NAME"; + static final String EXTRA_NOTIFICATION_ID = + "com.android.cts.net.hostside.app2.extra.NOTIFICATION_ID"; static int getUid(Context context) { final String packageName = context.getPackageName(); diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java index 114d5c11d9..96e9d2bab4 100644 --- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java +++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java @@ -22,17 +22,17 @@ import static com.android.cts.net.hostside.app2.Common.ACTION_CHECK_NETWORK; import static com.android.cts.net.hostside.app2.Common.ACTION_GET_COUNTERS; import static com.android.cts.net.hostside.app2.Common.ACTION_GET_RESTRICT_BACKGROUND_STATUS; import static com.android.cts.net.hostside.app2.Common.ACTION_RECEIVER_READY; +import static com.android.cts.net.hostside.app2.Common.ACTION_SEND_NOTIFICATION; import static com.android.cts.net.hostside.app2.Common.EXTRA_ACTION; +import static com.android.cts.net.hostside.app2.Common.EXTRA_NOTIFICATION_ID; import static com.android.cts.net.hostside.app2.Common.EXTRA_RECEIVER_NAME; import static com.android.cts.net.hostside.app2.Common.MANIFEST_RECEIVER; import static com.android.cts.net.hostside.app2.Common.TAG; import static com.android.cts.net.hostside.app2.Common.getUid; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -41,6 +41,11 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.util.Log; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + /** * Receiver used to: *
    @@ -85,6 +90,9 @@ public class MyBroadcastReceiver extends BroadcastReceiver { Log.d(TAG, message); setResultData(message); break; + case ACTION_SEND_NOTIFICATION: + sendNotification(context, intent); + break; default: Log.e(TAG, "received unexpected action: " + action); } @@ -213,4 +221,23 @@ public class MyBroadcastReceiver extends BroadcastReceiver { final int counter = getCounter(context, action, receiverName); setResultData(String.valueOf(counter)); } + + /** + * Sends a system notification containing actions with pending intents to launch the app's + * main activitiy or service. + */ + private void sendNotification(Context context, Intent intent) { + final int notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1); + final Intent serviceIntent = new Intent(context, MyService.class); + final PendingIntent pendingIntent = PendingIntent.getService(context, 0, serviceIntent, 0); + + final Notification notification = new Notification.Builder(context) + .setSmallIcon(R.drawable.ic_notification) + .setContentTitle("Light, Cameras...") + .setContentIntent(pendingIntent) + .addAction(R.drawable.ic_notification, "ACTION", pendingIntent) + .build(); + ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE)) + .notify(notificationId, notification); + } } diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java index 8152e55297..c741b12fd0 100644 --- a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java +++ b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java @@ -184,6 +184,11 @@ public class HostsideRestrictBackgroundNetworkTests extends HostsideNetworkTestC "testBackgroundNetworkAccess_enabled"); } + public void testDozeModeMetered_enabledButWhitelistedOnNotificationAction() throws Exception { + runDeviceTests(TEST_PKG, TEST_PKG + ".DozeModeMeteredTest", + "testBackgroundNetworkAccess_enabledButWhitelistedOnNotificationAction"); + } + // TODO: currently power-save mode and idle uses the same whitelist, so this test would be // redundant (as it would be testing the same as testBatterySaverMode_reinstall()) // public void testDozeMode_reinstall() throws Exception { @@ -204,6 +209,12 @@ public class HostsideRestrictBackgroundNetworkTests extends HostsideNetworkTestC "testBackgroundNetworkAccess_enabled"); } + public void testDozeModeNonMetered_enabledButWhitelistedOnNotificationAction() + throws Exception { + runDeviceTests(TEST_PKG, TEST_PKG + ".DozeModeNonMeteredTest", + "testBackgroundNetworkAccess_enabledButWhitelistedOnNotificationAction"); + } + /********************** * Mixed modes tests. * **********************/