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.tests.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.Bitmap; 28 import android.graphics.BitmapFactory; 29 import android.graphics.Color; 30 import android.net.Uri; 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.List; 39 40 /** 41 * Class used to create, update and cancel the notification used to display and update call state 42 * for {@link TestConnectionService}. 43 */ 44 public class CallServiceNotifier { 45 private static final CallServiceNotifier INSTANCE = new CallServiceNotifier(); 46 47 static final String CALL_PROVIDER_ID = "testapps_TestConnectionService_CALL_PROVIDER_ID"; 48 static final String SIM_SUBSCRIPTION_ID = "testapps_TestConnectionService_SIM_SUBSCRIPTION_ID"; 49 static final String CONNECTION_MANAGER_ID = 50 "testapps_TestConnectionService_CONNECTION_MANAGER_ID"; 51 52 /** 53 * Static notification IDs. 54 */ 55 private static final int CALL_NOTIFICATION_ID = 1; 56 private static final int PHONE_ACCOUNT_NOTIFICATION_ID = 2; 57 58 /** 59 * Whether the added call should be started as a video call. Referenced by 60 * {@link TestConnectionService} to know whether to provide a call video provider. 61 */ 62 public static boolean mStartVideoCall; 63 64 /** 65 * Singleton accessor. 66 */ 67 public static CallServiceNotifier getInstance() { 68 return INSTANCE; 69 } 70 71 /** 72 * Creates a CallService & initializes notification manager. 73 */ 74 private CallServiceNotifier() { 75 } 76 77 /** 78 * Updates the notification in the notification pane. 79 */ 80 public void updateNotification(Context context) { 81 log("adding the notification ------------"); 82 getNotificationManager(context).notify(CALL_NOTIFICATION_ID, getMainNotification(context)); 83 getNotificationManager(context).notify( 84 PHONE_ACCOUNT_NOTIFICATION_ID, getPhoneAccountNotification(context)); 85 } 86 87 /** 88 * Cancels the notification. 89 */ 90 public void cancelNotifications(Context context) { 91 log("canceling notification"); 92 getNotificationManager(context).cancel(CALL_NOTIFICATION_ID); 93 getNotificationManager(context).cancel(PHONE_ACCOUNT_NOTIFICATION_ID); 94 } 95 96 /** 97 * Registers a phone account with telecom. 98 */ 99 public void registerPhoneAccount(Context context) { 100 TelecomManager telecomManager = 101 (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); 102 103 telecomManager.clearAccounts(); 104 105 telecomManager.registerPhoneAccount(PhoneAccount.builder( 106 new PhoneAccountHandle( 107 new ComponentName(context, TestConnectionService.class), 108 CALL_PROVIDER_ID), 109 "TelecomTestApp Call Provider") 110 .setAddress(Uri.parse("tel:555-TEST")) 111 .setSubscriptionAddress(Uri.parse("tel:555-TEST")) 112 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 113 .setIcon(context, R.drawable.stat_sys_phone_call, Color.RED) 114 .setHighlightColor(Color.RED) 115 .setShortDescription("a short description for the call provider") 116 .setSupportedUriSchemes(Arrays.asList("tel")) 117 .build()); 118 119 telecomManager.registerPhoneAccount(PhoneAccount.builder( 120 new PhoneAccountHandle( 121 new ComponentName(context, TestConnectionService.class), 122 SIM_SUBSCRIPTION_ID), 123 "TelecomTestApp SIM Subscription") 124 .setAddress(Uri.parse("tel:555-TSIM")) 125 .setSubscriptionAddress(Uri.parse("tel:555-TSIM")) 126 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER | 127 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 128 .setIcon(context, R.drawable.stat_sys_phone_call, Color.GREEN) 129 .setHighlightColor(Color.GREEN) 130 .setShortDescription("a short description for the sim subscription") 131 .build()); 132 133 telecomManager.registerPhoneAccount(PhoneAccount.builder( 134 new PhoneAccountHandle( 135 new ComponentName(context, TestConnectionManager.class), 136 CONNECTION_MANAGER_ID), 137 "TelecomTestApp CONNECTION MANAGER") 138 .setAddress(Uri.parse("tel:555-CMGR")) 139 .setSubscriptionAddress(Uri.parse("tel:555-CMGR")) 140 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER) 141 .setIcon(context, R.drawable.stat_sys_phone_call, Color.BLUE) 142 .setShortDescription("a short description for the connection manager") 143 .build()); 144 } 145 146 /** 147 * Displays all phone accounts registered with telecom. 148 */ 149 public void showAllPhoneAccounts(Context context) { 150 TelecomManager telecomManager = 151 (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); 152 List<PhoneAccountHandle> accounts = telecomManager.getCallCapablePhoneAccounts(); 153 154 Toast.makeText(context, accounts.toString(), Toast.LENGTH_LONG).show(); 155 } 156 157 /** 158 * Returns the system's notification manager needed to add/remove notifications. 159 */ 160 private NotificationManager getNotificationManager(Context context) { 161 return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 162 } 163 164 /** 165 * Creates a notification object for using the telecom APIs. 166 */ 167 private Notification getPhoneAccountNotification(Context context) { 168 final Notification.Builder builder = new Notification.Builder(context); 169 // Both notifications have buttons and only the first one with buttons will show its 170 // buttons. Since the phone accounts notification is always first, setting false ensures 171 // it can be dismissed to use the other notification. 172 builder.setOngoing(false); 173 builder.setPriority(Notification.PRIORITY_HIGH); 174 175 final PendingIntent intent = createShowAllPhoneAccountsIntent(context); 176 builder.setContentIntent(intent); 177 178 builder.setSmallIcon(android.R.drawable.stat_sys_phone_call); 179 // TODO: Consider moving this into a strings.xml 180 builder.setContentText("Test phone accounts via telecom APIs."); 181 builder.setContentTitle("Test Phone Accounts"); 182 183 addRegisterPhoneAccountAction(builder, context); 184 addShowAllPhoneAccountsAction(builder, context); 185 186 return builder.build(); 187 } 188 189 /** 190 * Creates a notification object out of the current calls state. 191 */ 192 private Notification getMainNotification(Context context) { 193 final Notification.Builder builder = new Notification.Builder(context); 194 builder.setOngoing(true); 195 builder.setPriority(Notification.PRIORITY_HIGH); 196 builder.setSmallIcon(android.R.drawable.stat_sys_phone_call); 197 builder.setContentText("Test calls via CallService API"); 198 builder.setContentTitle("Test Connection Service"); 199 200 addAddVideoCallAction(builder, context); 201 addAddCallAction(builder, context); 202 addExitAction(builder, context); 203 204 return builder.build(); 205 } 206 207 /** 208 * Creates the intent to remove the notification. 209 */ 210 private PendingIntent createExitIntent(Context context) { 211 final Intent intent = new Intent(CallNotificationReceiver.ACTION_CALL_SERVICE_EXIT, null, 212 context, CallNotificationReceiver.class); 213 214 return PendingIntent.getBroadcast(context, 0, intent, 0); 215 } 216 217 /** 218 * Creates the intent to register a phone account. 219 */ 220 private PendingIntent createRegisterPhoneAccountIntent(Context context) { 221 final Intent intent = new Intent(CallNotificationReceiver.ACTION_REGISTER_PHONE_ACCOUNT, 222 null, context, CallNotificationReceiver.class); 223 return PendingIntent.getBroadcast(context, 0, intent, 0); 224 } 225 226 /** 227 * Creates the intent to show all phone accounts. 228 */ 229 private PendingIntent createShowAllPhoneAccountsIntent(Context context) { 230 final Intent intent = new Intent(CallNotificationReceiver.ACTION_SHOW_ALL_PHONE_ACCOUNTS, 231 null, context, CallNotificationReceiver.class); 232 return PendingIntent.getBroadcast(context, 0, intent, 0); 233 } 234 235 /** 236 * Creates the intent to start an incoming video call 237 */ 238 private PendingIntent createIncomingVideoCall(Context context) { 239 final Intent intent = new Intent(CallNotificationReceiver.ACTION_VIDEO_CALL, 240 null, context, CallNotificationReceiver.class); 241 return PendingIntent.getBroadcast(context, 0, intent, 0); 242 } 243 244 /** 245 * Creates the intent to start an incoming audio call 246 */ 247 private PendingIntent createIncomingAudioCall(Context context) { 248 final Intent intent = new Intent(CallNotificationReceiver.ACTION_AUDIO_CALL, 249 null, context, CallNotificationReceiver.class); 250 return PendingIntent.getBroadcast(context, 0, intent, 0); 251 } 252 253 /** 254 * Adds an action to the Notification Builder for adding an incoming call through Telecom. 255 * @param builder The Notification Builder. 256 */ 257 private void addAddCallAction(Notification.Builder builder, Context context) { 258 builder.addAction(0, "Add Call", createIncomingAudioCall(context)); 259 } 260 261 /** 262 * Adds an action to the Notification Builder to add an incoming video call through Telecom. 263 */ 264 private void addAddVideoCallAction(Notification.Builder builder, Context context) { 265 builder.addAction(0, "Add Video", createIncomingVideoCall(context)); 266 } 267 268 /** 269 * Adds an action to remove the notification. 270 */ 271 private void addExitAction(Notification.Builder builder, Context context) { 272 builder.addAction(0, "Exit", createExitIntent(context)); 273 } 274 275 /** 276 * Adds an action to show all registered phone accounts on a device. 277 */ 278 private void addShowAllPhoneAccountsAction(Notification.Builder builder, Context context) { 279 builder.addAction(0, "Show Accts", createShowAllPhoneAccountsIntent(context)); 280 } 281 282 /** 283 * Adds an action to register a new phone account. 284 */ 285 private void addRegisterPhoneAccountAction(Notification.Builder builder, Context context) { 286 builder.addAction(0, "Reg.Acct.", createRegisterPhoneAccountIntent(context)); 287 } 288 289 public boolean shouldStartVideoCall() { 290 return mStartVideoCall; 291 } 292 293 private static void log(String msg) { 294 Log.w("testcallservice", "[CallServiceNotifier] " + msg); 295 } 296 } 297