Home | History | Annotate | Download | only in testapps
      1 /*
      2  * Copyright (C) 2013 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 
     17 package com.android.server.telecom.testapps;
     18 
     19 import com.android.server.telecom.testapps.R;
     20 
     21 import android.app.Notification;
     22 import android.app.NotificationManager;
     23 import android.app.PendingIntent;
     24 import android.content.ComponentName;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.graphics.Color;
     28 import android.graphics.drawable.Icon;
     29 import android.net.Uri;
     30 import android.os.Bundle;
     31 import android.telecom.PhoneAccount;
     32 import android.telecom.PhoneAccountHandle;
     33 import android.telecom.TelecomManager;
     34 import android.util.Log;
     35 import android.widget.Toast;
     36 
     37 import java.util.Arrays;
     38 import java.util.HashMap;
     39 import java.util.List;
     40 import java.util.Map;
     41 
     42 /**
     43  * Class used to create, update and cancel the notification used to display and update call state
     44  * for {@link TestConnectionService}.
     45  */
     46 public class CallServiceNotifier {
     47     private static final CallServiceNotifier INSTANCE = new CallServiceNotifier();
     48 
     49     public static final String CALL_PROVIDER_ID = "testapps_TestConnectionService_CALL_PROVIDER_ID";
     50     public static final String SIM_SUBSCRIPTION_ID =
     51             "testapps_TestConnectionService_SIM_SUBSCRIPTION_ID";
     52     public static final String SIM_SUBSCRIPTION_ID2 =
     53             "testapps_TestConnectionService_SIM_SUBSCRIPTION_ID2";
     54     public static final String CONNECTION_MANAGER_ID =
     55             "testapps_TestConnectionService_CONNECTION_MANAGER_ID";
     56 
     57     private Map<String, PhoneAccountHandle> mPhoneAccountMap = new HashMap<>();
     58 
     59     /**
     60      * Static notification IDs.
     61      */
     62     private static final int CALL_NOTIFICATION_ID = 1;
     63     private static final int PHONE_ACCOUNT_NOTIFICATION_ID = 2;
     64 
     65     /**
     66      * Whether the added call should be started as a video call. Referenced by
     67      * {@link TestConnectionService} to know whether to provide a call video provider.
     68      */
     69     public static boolean mStartVideoCall;
     70 
     71     /**
     72      * Singleton accessor.
     73      */
     74     public static CallServiceNotifier getInstance() {
     75         return INSTANCE;
     76     }
     77 
     78     /**
     79      * Creates a CallService & initializes notification manager.
     80      */
     81     private CallServiceNotifier() {
     82     }
     83 
     84     /**
     85      * Updates the notification in the notification pane.
     86      */
     87     public void updateNotification(Context context) {
     88         log("adding the notification ------------");
     89         getNotificationManager(context).notify(CALL_NOTIFICATION_ID, getMainNotification(context));
     90         getNotificationManager(context).notify(
     91                 PHONE_ACCOUNT_NOTIFICATION_ID, getPhoneAccountNotification(context));
     92     }
     93 
     94     /**
     95      * Cancels the notification.
     96      */
     97     public void cancelNotifications(Context context) {
     98         log("canceling notification");
     99         getNotificationManager(context).cancel(CALL_NOTIFICATION_ID);
    100         getNotificationManager(context).cancel(PHONE_ACCOUNT_NOTIFICATION_ID);
    101     }
    102 
    103     /**
    104      * Registers a phone account with telecom.
    105      */
    106     public void registerPhoneAccount(Context context) {
    107         TelecomManager telecomManager =
    108                 (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
    109 
    110         telecomManager.clearAccounts();
    111 
    112         Bundle testBundle = new Bundle();
    113         testBundle.putInt("EXTRA_INT_1", 1);
    114         testBundle.putInt("EXTRA_INT_100", 100);
    115         testBundle.putBoolean("EXTRA_BOOL_TRUE", true);
    116         testBundle.putBoolean("EXTRA_BOOL_FALSE", false);
    117         testBundle.putString("EXTRA_STR1", "Hello");
    118         testBundle.putString("EXTRA_STR2", "There");
    119 
    120         PhoneAccountHandle handle1 = new PhoneAccountHandle(
    121                 new ComponentName(context, TestConnectionService.class), CALL_PROVIDER_ID);
    122         mPhoneAccountMap.put(CALL_PROVIDER_ID, handle1);
    123         telecomManager.registerPhoneAccount(PhoneAccount.builder(
    124                 handle1,
    125                 "TelecomTestApp Call Provider")
    126                 .setAddress(Uri.parse("tel:555-TEST"))
    127                 .setSubscriptionAddress(Uri.parse("tel:555-TEST"))
    128                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
    129                         PhoneAccount.CAPABILITY_VIDEO_CALLING |
    130                         PhoneAccount.CAPABILITY_RTT |
    131                         PhoneAccount.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)
    132                 .setIcon(Icon.createWithResource(
    133                         context.getResources(), R.drawable.stat_sys_phone_call))
    134                 .setHighlightColor(Color.RED)
    135                 // TODO: Add icon tint (Color.RED)
    136                 .setShortDescription("a short description for the call provider")
    137                 .setSupportedUriSchemes(Arrays.asList("tel"))
    138                 .setExtras(testBundle)
    139                 .build());
    140 
    141         PhoneAccountHandle handle2 = new PhoneAccountHandle(
    142                 new ComponentName(context, TestConnectionService.class), SIM_SUBSCRIPTION_ID);
    143         mPhoneAccountMap.put(SIM_SUBSCRIPTION_ID, handle2);
    144         telecomManager.registerPhoneAccount(PhoneAccount.builder(
    145                 handle2,
    146                 "TelecomTestApp SIM Subscription")
    147                 .setAddress(Uri.parse("tel:555-TSIM"))
    148                 .setSubscriptionAddress(Uri.parse("tel:555-TSIM"))
    149                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
    150                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
    151                         PhoneAccount.CAPABILITY_VIDEO_CALLING |
    152                         PhoneAccount.CAPABILITY_RTT |
    153                         PhoneAccount.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)
    154                 .setIcon(Icon.createWithResource(
    155                         context.getResources(), R.drawable.stat_sys_phone_call))
    156                 .setHighlightColor(Color.GREEN)
    157                 // TODO: Add icon tint (Color.GREEN)
    158                 .setShortDescription("a short description for the sim subscription")
    159                 .build());
    160 
    161         PhoneAccountHandle handle3 = new PhoneAccountHandle(
    162                 new ComponentName(context, TestConnectionService.class), SIM_SUBSCRIPTION_ID2);
    163         mPhoneAccountMap.put(SIM_SUBSCRIPTION_ID2, handle3);
    164         telecomManager.registerPhoneAccount(PhoneAccount.builder(
    165                 handle3,
    166                 "TelecomTestApp SIM Subscription 2")
    167                 .setAddress(Uri.parse("tel:555-TSI2"))
    168                 .setSubscriptionAddress(Uri.parse("tel:555-TSI2"))
    169                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
    170                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
    171                         PhoneAccount.CAPABILITY_VIDEO_CALLING |
    172                         PhoneAccount.CAPABILITY_RTT |
    173                         PhoneAccount.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)
    174                 .setIcon(Icon.createWithResource(
    175                         context.getResources(), R.drawable.stat_sys_phone_call))
    176                 .setHighlightColor(Color.CYAN)
    177                 .setShortDescription("a short description for the sim subscription")
    178                 .build());
    179 
    180         PhoneAccountHandle handle4 = new PhoneAccountHandle(
    181                 new ComponentName(context, TestConnectionManager.class), CONNECTION_MANAGER_ID);
    182         mPhoneAccountMap.put(CONNECTION_MANAGER_ID, handle4);
    183         telecomManager.registerPhoneAccount(PhoneAccount.builder(
    184                 handle4,
    185                 "TelecomTestApp CONNECTION MANAGER")
    186                 .setAddress(Uri.parse("tel:555-CMGR"))
    187                 .setSubscriptionAddress(Uri.parse("tel:555-CMGR"))
    188                 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
    189                 .setIcon(Icon.createWithResource(
    190                         context.getResources(), R.drawable.stat_sys_phone_call))
    191                 // TODO: Add icon tint (Color.BLUE)
    192                 .setShortDescription("a short description for the connection manager")
    193                 .build());
    194     }
    195 
    196     public PhoneAccountHandle getPhoneAccountHandle(String id) {
    197         return mPhoneAccountMap.get(id);
    198     }
    199 
    200     /**
    201      * Displays all phone accounts registered with telecom.
    202      */
    203     public void showAllPhoneAccounts(Context context) {
    204         TelecomManager telecomManager =
    205                 (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
    206         List<PhoneAccountHandle> accounts = telecomManager.getCallCapablePhoneAccounts();
    207 
    208         Toast.makeText(context, accounts.toString(), Toast.LENGTH_LONG).show();
    209     }
    210 
    211     /**
    212      * Returns the system's notification manager needed to add/remove notifications.
    213      */
    214     private NotificationManager getNotificationManager(Context context) {
    215         return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    216     }
    217 
    218     /**
    219      * Creates a notification object for using the telecom APIs.
    220      */
    221     private Notification getPhoneAccountNotification(Context context) {
    222         final Notification.Builder builder = new Notification.Builder(context);
    223         // Both notifications have buttons and only the first one with buttons will show its
    224         // buttons.  Since the phone accounts notification is always first, setting false ensures
    225         // it can be dismissed to use the other notification.
    226         builder.setOngoing(false);
    227         builder.setPriority(Notification.PRIORITY_HIGH);
    228 
    229         final PendingIntent intent = createShowAllPhoneAccountsIntent(context);
    230         builder.setContentIntent(intent);
    231 
    232         builder.setSmallIcon(android.R.drawable.stat_sys_phone_call);
    233         // TODO: Consider moving this into a strings.xml
    234         builder.setContentText("Test phone accounts via telecom APIs.");
    235         builder.setContentTitle("Test Phone Accounts");
    236 
    237         addRegisterPhoneAccountAction(builder, context);
    238         addShowAllPhoneAccountsAction(builder, context);
    239 
    240         return builder.build();
    241     }
    242 
    243     /**
    244      * Creates a notification object out of the current calls state.
    245      */
    246     private Notification getMainNotification(Context context) {
    247         final Notification.Builder builder = new Notification.Builder(context);
    248         builder.setOngoing(true);
    249         builder.setPriority(Notification.PRIORITY_HIGH);
    250         builder.setSmallIcon(android.R.drawable.stat_sys_phone_call);
    251         builder.setContentText("Test calls via CallService API");
    252         builder.setContentTitle("Test Connection Service");
    253 
    254         addAddOneWayVideoCallAction(builder, context);
    255         addAddTwoWayVideoCallAction(builder, context);
    256         addAddCallAction(builder, context);
    257         addExitAction(builder, context);
    258 
    259         return builder.build();
    260     }
    261 
    262     /**
    263      * Creates the intent to remove the notification.
    264      */
    265     private PendingIntent createExitIntent(Context context) {
    266         final Intent intent = new Intent(CallNotificationReceiver.ACTION_CALL_SERVICE_EXIT, null,
    267                 context, CallNotificationReceiver.class);
    268 
    269         return PendingIntent.getBroadcast(context, 0, intent, 0);
    270     }
    271 
    272     /**
    273      * Creates the intent to register a phone account.
    274      */
    275     private PendingIntent createRegisterPhoneAccountIntent(Context context) {
    276         final Intent intent = new Intent(CallNotificationReceiver.ACTION_REGISTER_PHONE_ACCOUNT,
    277                 null, context, CallNotificationReceiver.class);
    278         return PendingIntent.getBroadcast(context, 0, intent, 0);
    279     }
    280 
    281     /**
    282      * Creates the intent to show all phone accounts.
    283      */
    284     private PendingIntent createShowAllPhoneAccountsIntent(Context context) {
    285         final Intent intent = new Intent(CallNotificationReceiver.ACTION_SHOW_ALL_PHONE_ACCOUNTS,
    286                 null, context, CallNotificationReceiver.class);
    287         return PendingIntent.getBroadcast(context, 0, intent, 0);
    288     }
    289 
    290     /**
    291      * Creates the intent to start an incoming 1-way video call (receive-only)
    292      */
    293     private PendingIntent createOneWayVideoCallIntent(Context context) {
    294         final Intent intent = new Intent(CallNotificationReceiver.ACTION_ONE_WAY_VIDEO_CALL,
    295                 null, context, CallNotificationReceiver.class);
    296         return PendingIntent.getBroadcast(context, 0, intent, 0);
    297     }
    298 
    299     /**
    300      * Creates the intent to start an incoming 2-way video call
    301      */
    302     private PendingIntent createTwoWayVideoCallIntent(Context context) {
    303         final Intent intent = new Intent(CallNotificationReceiver.ACTION_TWO_WAY_VIDEO_CALL,
    304                 null, context, CallNotificationReceiver.class);
    305         return PendingIntent.getBroadcast(context, 0, intent, 0);
    306     }
    307 
    308     /**
    309      * Creates the intent to start an incoming audio call
    310      */
    311     private PendingIntent createIncomingAudioCall(Context context) {
    312         final Intent intent = new Intent(CallNotificationReceiver.ACTION_AUDIO_CALL,
    313                 null, context, CallNotificationReceiver.class);
    314         return PendingIntent.getBroadcast(context, 0, intent, 0);
    315     }
    316 
    317     /**
    318      * Adds an action to the Notification Builder for adding an incoming call through Telecom.
    319      * @param builder The Notification Builder.
    320      */
    321     private void addAddCallAction(Notification.Builder builder, Context context) {
    322         builder.addAction(0, "Add Call", createIncomingAudioCall(context));
    323     }
    324 
    325     /**
    326      * Adds an action to the Notification Builder to add an incoming one-way video call through
    327      * Telecom.
    328      */
    329     private void addAddOneWayVideoCallAction(Notification.Builder builder, Context context) {
    330         builder.addAction(0, "1-way Video", createOneWayVideoCallIntent(context));
    331     }
    332 
    333     /**
    334      * Adds an action to the Notification Builder to add an incoming 2-way video call through
    335      * Telecom.
    336      */
    337     private void addAddTwoWayVideoCallAction(Notification.Builder builder, Context context) {
    338         builder.addAction(0, "2-way Video", createTwoWayVideoCallIntent(context));
    339     }
    340 
    341     /**
    342      * Adds an action to remove the notification.
    343      */
    344     private void addExitAction(Notification.Builder builder, Context context) {
    345         builder.addAction(0, "Exit", createExitIntent(context));
    346     }
    347 
    348     /**
    349      * Adds an action to show all registered phone accounts on a device.
    350      */
    351     private void addShowAllPhoneAccountsAction(Notification.Builder builder, Context context) {
    352         builder.addAction(0, "Show Accts", createShowAllPhoneAccountsIntent(context));
    353     }
    354 
    355     /**
    356      * Adds an action to register a new phone account.
    357      */
    358     private void addRegisterPhoneAccountAction(Notification.Builder builder, Context context) {
    359         builder.addAction(0, "Reg.Acct.", createRegisterPhoneAccountIntent(context));
    360     }
    361 
    362     public boolean shouldStartVideoCall() {
    363         return mStartVideoCall;
    364     }
    365 
    366     private static void log(String msg) {
    367         Log.w("testcallservice", "[CallServiceNotifier] " + msg);
    368     }
    369 }
    370