| /* |
| * Copyright (C) 2013 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.server.telecom.testapps; |
| |
| import com.android.server.telecom.testapps.R; |
| |
| import android.app.Notification; |
| import android.app.NotificationManager; |
| import android.app.PendingIntent; |
| import android.content.ComponentName; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.graphics.Color; |
| import android.graphics.drawable.Icon; |
| import android.net.Uri; |
| import android.os.Bundle; |
| import android.telecom.PhoneAccount; |
| import android.telecom.PhoneAccountHandle; |
| import android.telecom.TelecomManager; |
| import android.util.Log; |
| import android.widget.Toast; |
| |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * Class used to create, update and cancel the notification used to display and update call state |
| * for {@link TestConnectionService}. |
| */ |
| public class CallServiceNotifier { |
| private static final CallServiceNotifier INSTANCE = new CallServiceNotifier(); |
| |
| public static final String CALL_PROVIDER_ID = "testapps_TestConnectionService_CALL_PROVIDER_ID"; |
| public static final String SIM_SUBSCRIPTION_ID = |
| "testapps_TestConnectionService_SIM_SUBSCRIPTION_ID"; |
| public static final String SIM_SUBSCRIPTION_ID2 = |
| "testapps_TestConnectionService_SIM_SUBSCRIPTION_ID2"; |
| public static final String CONNECTION_MANAGER_ID = |
| "testapps_TestConnectionService_CONNECTION_MANAGER_ID"; |
| |
| private Map<String, PhoneAccountHandle> mPhoneAccountMap = new HashMap<>(); |
| |
| /** |
| * Static notification IDs. |
| */ |
| private static final int CALL_NOTIFICATION_ID = 1; |
| private static final int PHONE_ACCOUNT_NOTIFICATION_ID = 2; |
| |
| /** |
| * Whether the added call should be started as a video call. Referenced by |
| * {@link TestConnectionService} to know whether to provide a call video provider. |
| */ |
| public static boolean mStartVideoCall; |
| |
| /** |
| * Singleton accessor. |
| */ |
| public static CallServiceNotifier getInstance() { |
| return INSTANCE; |
| } |
| |
| /** |
| * Creates a CallService & initializes notification manager. |
| */ |
| private CallServiceNotifier() { |
| } |
| |
| /** |
| * Updates the notification in the notification pane. |
| */ |
| public void updateNotification(Context context) { |
| log("adding the notification ------------"); |
| getNotificationManager(context).notify(CALL_NOTIFICATION_ID, getMainNotification(context)); |
| getNotificationManager(context).notify( |
| PHONE_ACCOUNT_NOTIFICATION_ID, getPhoneAccountNotification(context)); |
| } |
| |
| /** |
| * Cancels the notification. |
| */ |
| public void cancelNotifications(Context context) { |
| log("canceling notification"); |
| getNotificationManager(context).cancel(CALL_NOTIFICATION_ID); |
| getNotificationManager(context).cancel(PHONE_ACCOUNT_NOTIFICATION_ID); |
| } |
| |
| /** |
| * Registers a phone account with telecom. |
| */ |
| public void registerPhoneAccount(Context context) { |
| TelecomManager telecomManager = |
| (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); |
| |
| telecomManager.clearAccounts(); |
| |
| Bundle testBundle = new Bundle(); |
| testBundle.putInt("EXTRA_INT_1", 1); |
| testBundle.putInt("EXTRA_INT_100", 100); |
| testBundle.putBoolean("EXTRA_BOOL_TRUE", true); |
| testBundle.putBoolean("EXTRA_BOOL_FALSE", false); |
| testBundle.putString("EXTRA_STR1", "Hello"); |
| testBundle.putString("EXTRA_STR2", "There"); |
| |
| PhoneAccountHandle handle1 = new PhoneAccountHandle( |
| new ComponentName(context, TestConnectionService.class), CALL_PROVIDER_ID); |
| mPhoneAccountMap.put(CALL_PROVIDER_ID, handle1); |
| telecomManager.registerPhoneAccount(PhoneAccount.builder( |
| handle1, |
| "TelecomTestApp Call Provider") |
| .setAddress(Uri.parse("tel:555-TEST")) |
| .setSubscriptionAddress(Uri.parse("tel:555-TEST")) |
| .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER | |
| PhoneAccount.CAPABILITY_VIDEO_CALLING | |
| PhoneAccount.CAPABILITY_RTT | |
| PhoneAccount.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE) |
| .setIcon(Icon.createWithResource( |
| context.getResources(), R.drawable.stat_sys_phone_call)) |
| .setHighlightColor(Color.RED) |
| // TODO: Add icon tint (Color.RED) |
| .setShortDescription("a short description for the call provider") |
| .setSupportedUriSchemes(Arrays.asList("tel")) |
| .setExtras(testBundle) |
| .build()); |
| |
| PhoneAccountHandle handle2 = new PhoneAccountHandle( |
| new ComponentName(context, TestConnectionService.class), SIM_SUBSCRIPTION_ID); |
| mPhoneAccountMap.put(SIM_SUBSCRIPTION_ID, handle2); |
| telecomManager.registerPhoneAccount(PhoneAccount.builder( |
| handle2, |
| "TelecomTestApp SIM Subscription") |
| .setAddress(Uri.parse("tel:555-TSIM")) |
| .setSubscriptionAddress(Uri.parse("tel:555-TSIM")) |
| .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER | |
| PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION | |
| PhoneAccount.CAPABILITY_VIDEO_CALLING | |
| PhoneAccount.CAPABILITY_RTT | |
| PhoneAccount.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE) |
| .setIcon(Icon.createWithResource( |
| context.getResources(), R.drawable.stat_sys_phone_call)) |
| .setHighlightColor(Color.GREEN) |
| // TODO: Add icon tint (Color.GREEN) |
| .setShortDescription("a short description for the sim subscription") |
| .build()); |
| |
| PhoneAccountHandle handle3 = new PhoneAccountHandle( |
| new ComponentName(context, TestConnectionService.class), SIM_SUBSCRIPTION_ID2); |
| mPhoneAccountMap.put(SIM_SUBSCRIPTION_ID2, handle3); |
| telecomManager.registerPhoneAccount(PhoneAccount.builder( |
| handle3, |
| "TelecomTestApp SIM Subscription 2") |
| .setAddress(Uri.parse("tel:555-TSI2")) |
| .setSubscriptionAddress(Uri.parse("tel:555-TSI2")) |
| .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER | |
| PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION | |
| PhoneAccount.CAPABILITY_VIDEO_CALLING | |
| PhoneAccount.CAPABILITY_RTT | |
| PhoneAccount.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE) |
| .setIcon(Icon.createWithResource( |
| context.getResources(), R.drawable.stat_sys_phone_call)) |
| .setHighlightColor(Color.CYAN) |
| .setShortDescription("a short description for the sim subscription") |
| .build()); |
| |
| PhoneAccountHandle handle4 = new PhoneAccountHandle( |
| new ComponentName(context, TestConnectionManager.class), CONNECTION_MANAGER_ID); |
| mPhoneAccountMap.put(CONNECTION_MANAGER_ID, handle4); |
| telecomManager.registerPhoneAccount(PhoneAccount.builder( |
| handle4, |
| "TelecomTestApp CONNECTION MANAGER") |
| .setAddress(Uri.parse("tel:555-CMGR")) |
| .setSubscriptionAddress(Uri.parse("tel:555-CMGR")) |
| .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER) |
| .setIcon(Icon.createWithResource( |
| context.getResources(), R.drawable.stat_sys_phone_call)) |
| // TODO: Add icon tint (Color.BLUE) |
| .setShortDescription("a short description for the connection manager") |
| .build()); |
| } |
| |
| public PhoneAccountHandle getPhoneAccountHandle(String id) { |
| return mPhoneAccountMap.get(id); |
| } |
| |
| /** |
| * Displays all phone accounts registered with telecom. |
| */ |
| public void showAllPhoneAccounts(Context context) { |
| TelecomManager telecomManager = |
| (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); |
| List<PhoneAccountHandle> accounts = telecomManager.getCallCapablePhoneAccounts(); |
| |
| Toast.makeText(context, accounts.toString(), Toast.LENGTH_LONG).show(); |
| } |
| |
| /** |
| * Returns the system's notification manager needed to add/remove notifications. |
| */ |
| private NotificationManager getNotificationManager(Context context) { |
| return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); |
| } |
| |
| /** |
| * Creates a notification object for using the telecom APIs. |
| */ |
| private Notification getPhoneAccountNotification(Context context) { |
| final Notification.Builder builder = new Notification.Builder(context); |
| // Both notifications have buttons and only the first one with buttons will show its |
| // buttons. Since the phone accounts notification is always first, setting false ensures |
| // it can be dismissed to use the other notification. |
| builder.setOngoing(false); |
| builder.setPriority(Notification.PRIORITY_HIGH); |
| |
| final PendingIntent intent = createShowAllPhoneAccountsIntent(context); |
| builder.setContentIntent(intent); |
| |
| builder.setSmallIcon(android.R.drawable.stat_sys_phone_call); |
| // TODO: Consider moving this into a strings.xml |
| builder.setContentText("Test phone accounts via telecom APIs."); |
| builder.setContentTitle("Test Phone Accounts"); |
| |
| addRegisterPhoneAccountAction(builder, context); |
| addShowAllPhoneAccountsAction(builder, context); |
| |
| return builder.build(); |
| } |
| |
| /** |
| * Creates a notification object out of the current calls state. |
| */ |
| private Notification getMainNotification(Context context) { |
| final Notification.Builder builder = new Notification.Builder(context); |
| builder.setOngoing(true); |
| builder.setPriority(Notification.PRIORITY_HIGH); |
| builder.setSmallIcon(android.R.drawable.stat_sys_phone_call); |
| builder.setContentText("Test calls via CallService API"); |
| builder.setContentTitle("Test Connection Service"); |
| |
| addAddOneWayVideoCallAction(builder, context); |
| addAddTwoWayVideoCallAction(builder, context); |
| addAddCallAction(builder, context); |
| addExitAction(builder, context); |
| |
| return builder.build(); |
| } |
| |
| /** |
| * Creates the intent to remove the notification. |
| */ |
| private PendingIntent createExitIntent(Context context) { |
| final Intent intent = new Intent(CallNotificationReceiver.ACTION_CALL_SERVICE_EXIT, null, |
| context, CallNotificationReceiver.class); |
| |
| return PendingIntent.getBroadcast(context, 0, intent, 0); |
| } |
| |
| /** |
| * Creates the intent to register a phone account. |
| */ |
| private PendingIntent createRegisterPhoneAccountIntent(Context context) { |
| final Intent intent = new Intent(CallNotificationReceiver.ACTION_REGISTER_PHONE_ACCOUNT, |
| null, context, CallNotificationReceiver.class); |
| return PendingIntent.getBroadcast(context, 0, intent, 0); |
| } |
| |
| /** |
| * Creates the intent to show all phone accounts. |
| */ |
| private PendingIntent createShowAllPhoneAccountsIntent(Context context) { |
| final Intent intent = new Intent(CallNotificationReceiver.ACTION_SHOW_ALL_PHONE_ACCOUNTS, |
| null, context, CallNotificationReceiver.class); |
| return PendingIntent.getBroadcast(context, 0, intent, 0); |
| } |
| |
| /** |
| * Creates the intent to start an incoming 1-way video call (receive-only) |
| */ |
| private PendingIntent createOneWayVideoCallIntent(Context context) { |
| final Intent intent = new Intent(CallNotificationReceiver.ACTION_ONE_WAY_VIDEO_CALL, |
| null, context, CallNotificationReceiver.class); |
| return PendingIntent.getBroadcast(context, 0, intent, 0); |
| } |
| |
| /** |
| * Creates the intent to start an incoming 2-way video call |
| */ |
| private PendingIntent createTwoWayVideoCallIntent(Context context) { |
| final Intent intent = new Intent(CallNotificationReceiver.ACTION_TWO_WAY_VIDEO_CALL, |
| null, context, CallNotificationReceiver.class); |
| return PendingIntent.getBroadcast(context, 0, intent, 0); |
| } |
| |
| /** |
| * Creates the intent to start an incoming audio call |
| */ |
| private PendingIntent createIncomingAudioCall(Context context) { |
| final Intent intent = new Intent(CallNotificationReceiver.ACTION_AUDIO_CALL, |
| null, context, CallNotificationReceiver.class); |
| return PendingIntent.getBroadcast(context, 0, intent, 0); |
| } |
| |
| /** |
| * Adds an action to the Notification Builder for adding an incoming call through Telecom. |
| * @param builder The Notification Builder. |
| */ |
| private void addAddCallAction(Notification.Builder builder, Context context) { |
| builder.addAction(0, "Add Call", createIncomingAudioCall(context)); |
| } |
| |
| /** |
| * Adds an action to the Notification Builder to add an incoming one-way video call through |
| * Telecom. |
| */ |
| private void addAddOneWayVideoCallAction(Notification.Builder builder, Context context) { |
| builder.addAction(0, "1-way Video", createOneWayVideoCallIntent(context)); |
| } |
| |
| /** |
| * Adds an action to the Notification Builder to add an incoming 2-way video call through |
| * Telecom. |
| */ |
| private void addAddTwoWayVideoCallAction(Notification.Builder builder, Context context) { |
| builder.addAction(0, "2-way Video", createTwoWayVideoCallIntent(context)); |
| } |
| |
| /** |
| * Adds an action to remove the notification. |
| */ |
| private void addExitAction(Notification.Builder builder, Context context) { |
| builder.addAction(0, "Exit", createExitIntent(context)); |
| } |
| |
| /** |
| * Adds an action to show all registered phone accounts on a device. |
| */ |
| private void addShowAllPhoneAccountsAction(Notification.Builder builder, Context context) { |
| builder.addAction(0, "Show Accts", createShowAllPhoneAccountsIntent(context)); |
| } |
| |
| /** |
| * Adds an action to register a new phone account. |
| */ |
| private void addRegisterPhoneAccountAction(Notification.Builder builder, Context context) { |
| builder.addAction(0, "Reg.Acct.", createRegisterPhoneAccountIntent(context)); |
| } |
| |
| public boolean shouldStartVideoCall() { |
| return mStartVideoCall; |
| } |
| |
| private static void log(String msg) { |
| Log.w("testcallservice", "[CallServiceNotifier] " + msg); |
| } |
| } |