CTS tests for notif delegate notif canceling
Test: this
Bug: 134585713
Change-Id: If24af43392c873e3807bb38f1e0ac4cfa467eec9
diff --git a/tests/app/NotificationDelegator/AndroidManifest.xml b/tests/app/NotificationDelegator/AndroidManifest.xml
index 54d1f05..fbdf219 100644
--- a/tests/app/NotificationDelegator/AndroidManifest.xml
+++ b/tests/app/NotificationDelegator/AndroidManifest.xml
@@ -30,5 +30,13 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
+
+ <activity android:name="com.android.test.notificationdelegator.NotificationDelegateAndPost">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
</application>
</manifest>
diff --git a/tests/app/NotificationDelegator/src/com/android/test/notificationdelegator/NotificationDelegateAndPost.java b/tests/app/NotificationDelegator/src/com/android/test/notificationdelegator/NotificationDelegateAndPost.java
new file mode 100644
index 0000000..521adc5
--- /dev/null
+++ b/tests/app/NotificationDelegator/src/com/android/test/notificationdelegator/NotificationDelegateAndPost.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 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.test.notificationdelegator;
+
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.os.Bundle;
+import android.util.Log;
+
+public class NotificationDelegateAndPost extends Activity {
+ private static final String TAG = "DelegateAndPost";
+ private static final String DELEGATE = "android.app.stubs";
+ private static final String CHANNEL = "channel";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity);
+
+ NotificationManager nm = getSystemService(NotificationManager.class);
+
+ nm.createNotificationChannel(new NotificationChannel(CHANNEL, CHANNEL, IMPORTANCE_LOW));
+ nm.setNotificationDelegate(DELEGATE);
+ Log.d(TAG, "Set delegate: " + nm.getNotificationDelegate());
+
+ Log.d(TAG, "Posting notification with id 9");
+
+ Notification n = new Notification.Builder(this, CHANNEL)
+ .setSmallIcon(android.R.drawable.sym_def_app_icon)
+ .setContentTitle("posted by delegator")
+ .build();
+
+ nm.notify(9, n);
+
+ finish();
+ }
+}
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index 2f9658a..5c49b68 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -91,9 +91,6 @@
import android.util.Log;
import android.widget.RemoteViews;
-import androidx.test.filters.FlakyTest;
-import androidx.test.InstrumentationRegistry;
-
import com.android.compatibility.common.util.SystemUtil;
import junit.framework.Assert;
@@ -111,6 +108,9 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
+
/* This tests NotificationListenerService together with NotificationManager, as you need to have
* notifications to manipulate in order to test the listener service. */
public class NotificationManagerTest extends AndroidTestCase {
@@ -119,6 +119,7 @@
final String NOTIFICATION_CHANNEL_ID = "NotificationManagerTest";
private static final String DELEGATOR = "com.android.test.notificationdelegator";
+ private static final String DELEGATE_POST_CLASS = DELEGATOR + ".NotificationDelegateAndPost";
private static final String REVOKE_CLASS = DELEGATOR + ".NotificationRevoker";
private static final int WAIT_TIME = 2000;
@@ -257,14 +258,13 @@
return null;
}
-
- private StatusBarNotification findPostedNotification(int id) {
+ private StatusBarNotification findPostedNotification(int id, boolean all) {
// notification is a bit asynchronous so it may take a few ms to appear in
// getActiveNotifications()
// we will check for it for up to 300ms before giving up
StatusBarNotification n = null;
for (int tries = 3; tries-- > 0; ) {
- final StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
+ final StatusBarNotification[] sbns = getActiveNotifications(all);
for (StatusBarNotification sbn : sbns) {
Log.d(TAG, "Found " + sbn.getKey());
if (sbn.getId() == id) {
@@ -282,6 +282,14 @@
return n;
}
+ private StatusBarNotification[] getActiveNotifications(boolean all) {
+ if (all) {
+ return mListener.getActiveNotifications();
+ } else {
+ return mNotificationManager.getActiveNotifications();
+ }
+ }
+
private PendingIntent getPendingIntent() {
return PendingIntent.getActivity(
getContext(), 0, new Intent(getContext(), this.getClass()), 0);
@@ -1287,7 +1295,7 @@
NotificationListenerService.Ranking outRanking =
new NotificationListenerService.Ranking();
- StatusBarNotification sbn = findPostedNotification(notificationId);
+ StatusBarNotification sbn = findPostedNotification(notificationId, false);
// check that the key and channel ids are the same in the ranking as the posted notification
for (String key : rankingMap.getOrderedKeys()) {
@@ -1931,7 +1939,7 @@
.build();
mNotificationManager.notify(id, notification);
- StatusBarNotification n = findPostedNotification(id);
+ StatusBarNotification n = findPostedNotification(id, false);
assertNotNull(n);
assertEquals(notification.fullScreenIntent, n.getNotification().fullScreenIntent);
}
@@ -1985,7 +1993,77 @@
.build();
mNotificationManager.notifyAsPackage(DELEGATOR, "tag", 0, n);
- findPostedNotification(0);
+ assertNotNull(findPostedNotification(0, false));
+
+ final Intent revokeIntent = new Intent();
+ revokeIntent.setClassName(DELEGATOR, REVOKE_CLASS);
+ revokeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(revokeIntent);
+ Thread.sleep(1000);
+ }
+
+ public void testNotificationDelegate_grantAndPostAndCancel() throws Exception {
+ // grant this test permission to post
+ final Intent activityIntent = new Intent();
+ activityIntent.setPackage(DELEGATOR);
+ activityIntent.setAction(Intent.ACTION_MAIN);
+ activityIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+ activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // wait for the activity to launch and finish
+ mContext.startActivity(activityIntent);
+ Thread.sleep(1000);
+
+ // send notification
+ Notification n = new Notification.Builder(mContext, "channel")
+ .setSmallIcon(android.R.id.icon)
+ .build();
+ mNotificationManager.notifyAsPackage(DELEGATOR, "toBeCanceled", 10000, n);
+
+ assertNotNull(findPostedNotification(10000, false));
+
+ mNotificationManager.cancelAsPackage(DELEGATOR, "toBeCanceled", 10000);
+
+ assertNull(findPostedNotification(10000, false));
+
+ final Intent revokeIntent = new Intent();
+ revokeIntent.setClassName(DELEGATOR, REVOKE_CLASS);
+ revokeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(revokeIntent);
+ Thread.sleep(1000);
+ }
+
+ public void testNotificationDelegate_cannotCancelNotificationsPostedByDelegator()
+ throws Exception {
+ if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
+ return;
+ }
+
+ toggleListenerAccess(TestNotificationListener.getId(),
+ InstrumentationRegistry.getInstrumentation(), true);
+ Thread.sleep(500); // wait for listener to be allowed
+
+ mListener = TestNotificationListener.getInstance();
+ assertNotNull(mListener);
+
+ // grant this test permission to post
+ final Intent activityIntent = new Intent();
+ activityIntent.setClassName(DELEGATOR, DELEGATE_POST_CLASS);
+ activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ mContext.startActivity(activityIntent);
+
+ assertNotNull(findPostedNotification(9, true));
+
+ try {
+ mNotificationManager.cancelAsPackage(DELEGATOR, null, 9);
+ fail ("Delegate should not be able to cancel notification they did not post");
+ } catch (SecurityException e) {
+ // yay
+ }
+
+ // double check that the notification does still exist
+ assertNotNull(findPostedNotification(9, true));
final Intent revokeIntent = new Intent();
revokeIntent.setClassName(DELEGATOR, REVOKE_CLASS);
@@ -2104,7 +2182,7 @@
.build();
mNotificationManager.notify(id, notification);
- StatusBarNotification n = findPostedNotification(id);
+ StatusBarNotification n = findPostedNotification(id, false);
assertNotNull(n);
}
@@ -2199,8 +2277,8 @@
sendNotification(notificationId2, R.drawable.black);
Thread.sleep(500); // wait for notification listener to receive notification
- StatusBarNotification sbn1 = findPostedNotification(notificationId1);
- StatusBarNotification sbn2 = findPostedNotification(notificationId2);
+ StatusBarNotification sbn1 = findPostedNotification(notificationId1, false);
+ StatusBarNotification sbn2 = findPostedNotification(notificationId2, false);
mListener.setNotificationsShown(new String[]{ sbn1.getKey() });
toggleListenerAccess(TestNotificationListener.getId(),
@@ -2296,8 +2374,8 @@
sendNotification(notificationId2, R.drawable.black);
Thread.sleep(500); // wait for notification listener to receive notification
- StatusBarNotification sbn1 = findPostedNotification(notificationId1);
- StatusBarNotification sbn2 = findPostedNotification(notificationId2);
+ StatusBarNotification sbn1 = findPostedNotification(notificationId1, false);
+ StatusBarNotification sbn2 = findPostedNotification(notificationId2, false);
StatusBarNotification[] notifs =
mListener.getActiveNotifications(new String[]{ sbn2.getKey(), sbn1.getKey() });
assertEquals(sbn2.getKey(), notifs[0].getKey());
@@ -2345,7 +2423,7 @@
sendNotification(notificationId, R.drawable.black);
Thread.sleep(500); // wait for notification listener to receive notification
- StatusBarNotification sbn = findPostedNotification(notificationId);
+ StatusBarNotification sbn = findPostedNotification(notificationId, false);
mListener.cancelNotification(sbn.getPackageName(), sbn.getTag(), sbn.getId());
if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {