Home | History | Annotate | Download | only in robot
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.cts.robot;
     17 
     18 import android.app.Notification;
     19 import android.app.Notification.Action;
     20 import android.app.NotificationChannel;
     21 import android.app.NotificationManager;
     22 import android.app.PendingIntent;
     23 import android.app.RemoteInput;
     24 import android.content.BroadcastReceiver;
     25 import android.content.ComponentName;
     26 import android.content.Context;
     27 import android.content.Intent;
     28 import android.content.pm.ShortcutInfo;
     29 import android.content.pm.ShortcutManager;
     30 import android.os.SystemClock;
     31 import android.util.Log;
     32 
     33 import java.util.ArrayList;
     34 import java.util.List;
     35 
     36 
     37 public class NotificationBot extends BroadcastReceiver {
     38     private static final String TAG = "NotificationBot";
     39     private static final String NOTIFICATION_CHANNEL_ID = TAG;
     40     private static final String EXTRA_ID = "ID";
     41     private static final String EXTRA_NOTIFICATION = "NOTIFICATION";
     42     private static final String ACTION_POST = "com.android.cts.robot.ACTION_POST";
     43     private static final String ACTION_CANCEL = "com.android.cts.robot.ACTION_CANCEL";
     44     private static final String ACTION_RESET_SETUP_NOTIFICATION =
     45             "com.android.cts.robot.ACTION_RESET_SETUP_NOTIFICATION";
     46 
     47     private static final String ACTION_INLINE_REPLY =
     48             "com.android.cts.robot.ACTION_INLINE_REPLY";
     49 
     50     private static final String EXTRA_RESET_REPLY_PACKAGE = "EXTRA_RESET_REPLY_PACKAGE";
     51     private static final String EXTRA_RESET_REPLY_ACTION = "EXTRA_RESET_REPLY_ACTION";
     52     private static final String EXTRA_NOTIFICATION_TITLE = "EXTRA_NOTIFICATION_TITLE";
     53 
     54     private static final String EXTRA_RESET_REPLY_ERROR = "EXTRA_RESET_REPLY_ERROR";
     55 
     56     private static final String EXTRA_RESET_REQUEST_INTENT = "EXTRA_RESET_REQUEST_INTENT";
     57 
     58     private static final String SUCCESS = "**SUCCESS**";
     59 
     60     @Override
     61     public void onReceive(Context context, Intent intent) {
     62         Log.i(TAG, "received intent: " + intent);
     63         if (ACTION_POST.equals(intent.getAction())) {
     64             Log.i(TAG, ACTION_POST);
     65             if (!intent.hasExtra(EXTRA_NOTIFICATION) || !intent.hasExtra(EXTRA_ID)) {
     66                 Log.e(TAG, "received post action with missing content");
     67                 return;
     68             }
     69             int id = intent.getIntExtra(EXTRA_ID, -1);
     70             Log.i(TAG, "id: " + id);
     71             Notification n = (Notification) intent.getParcelableExtra(EXTRA_NOTIFICATION);
     72             Log.i(TAG, "n: " + n);
     73             NotificationManager noMa =
     74                     (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
     75             noMa.notify(id, n);
     76 
     77         } else if (ACTION_CANCEL.equals(intent.getAction())) {
     78             Log.i(TAG, ACTION_CANCEL);
     79             int id = intent.getIntExtra(EXTRA_ID, -1);
     80             Log.i(TAG, "id: " + id);
     81             if (id < 0) {
     82                 Log.e(TAG, "received cancel action with no ID");
     83                 return;
     84             }
     85             NotificationManager noMa =
     86                     (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
     87             noMa.cancel(id);
     88 
     89         } else if (ACTION_RESET_SETUP_NOTIFICATION.equals(intent.getAction())) {
     90             testShortcutResetSetupNotification(context, intent);
     91 
     92         } else if (ACTION_INLINE_REPLY.equals(intent.getAction())) {
     93             testShortcutResetInlineReplyReceived(context, intent);
     94 
     95         } else {
     96             Log.i(TAG, "received unexpected action: " + intent.getAction());
     97         }
     98     }
     99 
    100     /**
    101      * Test start request from CTS verifier.  Show a notification with inline reply, which will
    102      * trigger {@link #testShortcutResetInlineReplyReceived}.
    103      */
    104     private static void testShortcutResetSetupNotification(Context context, Intent intent) {
    105         final NotificationManager nm = context.getSystemService(NotificationManager.class);
    106         nm.cancelAll();
    107 
    108         final ShortcutManager sm = context.getSystemService(ShortcutManager.class);
    109 
    110         final List<ShortcutInfo> EMPTY_LIST = new ArrayList<>();
    111 
    112         long timeout = SystemClock.elapsedRealtime() + 10 * 1000;
    113 
    114         // First, make sure this package is throttled.
    115         while (!sm.isRateLimitingActive()) {
    116             sm.setDynamicShortcuts(EMPTY_LIST);
    117             try {
    118                 Thread.sleep(0);
    119             } catch (InterruptedException e) {
    120             }
    121             if (SystemClock.elapsedRealtime() >= timeout) {
    122                 sendShortcutResetReply(context, intent,
    123                         "ShortcutMager rate-limiting not activated.");
    124                 return;
    125             }
    126         }
    127 
    128         // Show a notification with inline reply.
    129         final PendingIntent receiverIntent =
    130                 PendingIntent.getBroadcast(context, 0,
    131                         new Intent(ACTION_INLINE_REPLY)
    132                                 .setComponent(new ComponentName(context, NotificationBot.class))
    133                                 .putExtra(EXTRA_RESET_REQUEST_INTENT, intent),
    134                         PendingIntent.FLAG_UPDATE_CURRENT);
    135         final RemoteInput ri = new RemoteInput.Builder("result")
    136                 .setLabel("Type something here and press send button").build();
    137 
    138         NotificationManager notificationManager =
    139                 context.getSystemService(NotificationManager.class);
    140         notificationManager.createNotificationChannel(new NotificationChannel(
    141                 NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID,
    142                 NotificationManager.IMPORTANCE_DEFAULT));
    143         final Notification.Builder nb = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
    144                 .setContentTitle(intent.getStringExtra(EXTRA_NOTIFICATION_TITLE))
    145                 .setSmallIcon(android.R.drawable.ic_popup_sync)
    146                 .addAction(new Action.Builder(0,
    147                         "Type something here and press send button", receiverIntent)
    148                         .addRemoteInput(ri)
    149                         .build());
    150         notificationManager.notify(0, nb.build());
    151     }
    152 
    153     /**
    154      * Invoked when the inline reply from {@link #testShortcutResetSetupNotification} is performed.
    155      *
    156      * Check the shortcut manager rate-limiting state, and post the reply to CTS verifier.
    157      */
    158     private static void testShortcutResetInlineReplyReceived(Context context, Intent intent) {
    159         Log.i(TAG, "Inline reply received");
    160 
    161         final NotificationManager nm = context.getSystemService(NotificationManager.class);
    162         nm.cancelAll();
    163 
    164         // Close notification shade.
    165         context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
    166 
    167         // Check if rate-limiting has been reset.
    168         final ShortcutManager sm = context.getSystemService(ShortcutManager.class);
    169 
    170         String error;
    171         final boolean success = !sm.isRateLimitingActive();
    172         if (success) {
    173             error = SUCCESS;
    174         } else {
    175             error = "Inline reply received, but ShortcutManager rate-limiting is still active.";
    176         }
    177 
    178         // Send back the result.
    179         sendShortcutResetReply(context,
    180                 intent.getParcelableExtra(EXTRA_RESET_REQUEST_INTENT), error);
    181     }
    182 
    183     /**
    184      * Reply an error message, or {@link #SUCCESS} for success, to CTS verifier for shortcut manager
    185      * reset rate-limiting test.
    186 
    187      * @param requestIntent original intent sent from the verifier to
    188      *     {@link #testShortcutResetSetupNotification}.
    189      * @param error error message, or {@link #SUCCESS} if success.
    190      */
    191     private static void sendShortcutResetReply(Context context, Intent requestIntent, String error) {
    192         final Intent replyIntent = new Intent();
    193         replyIntent.setAction(requestIntent.getStringExtra(EXTRA_RESET_REPLY_ACTION));
    194         replyIntent.putExtra(EXTRA_RESET_REPLY_ERROR, error);
    195 
    196         if (error != null) {
    197             Log.e(TAG, error);
    198         }
    199 
    200         context.sendBroadcast(replyIntent);
    201     }
    202 }
    203