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