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 17 package com.android.server.telecom; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.content.pm.PackageManager; 22 import android.content.pm.ResolveInfo; 23 import android.os.UserHandle; 24 import android.telecom.Log; 25 import android.widget.Toast; 26 27 import com.android.server.telecom.ui.ConfirmCallDialogActivity; 28 import com.android.server.telecom.ui.DisconnectedCallNotifier; 29 30 import java.util.List; 31 32 public final class TelecomBroadcastIntentProcessor { 33 /** The action used to send SMS response for the missed call notification. */ 34 public static final String ACTION_SEND_SMS_FROM_NOTIFICATION = 35 "com.android.server.telecom.ACTION_SEND_SMS_FROM_NOTIFICATION"; 36 37 /** The action used to call a handle back for the missed call notification. */ 38 public static final String ACTION_CALL_BACK_FROM_NOTIFICATION = 39 "com.android.server.telecom.ACTION_CALL_BACK_FROM_NOTIFICATION"; 40 41 /** The action used to send SMS response for the disconnected call notification. */ 42 public static final String ACTION_DISCONNECTED_SEND_SMS_FROM_NOTIFICATION = 43 "com.android.server.telecom.ACTION_DISCONNECTED_SEND_SMS_FROM_NOTIFICATION"; 44 45 /** The action used to call a handle back for the disconnected call notification. */ 46 public static final String ACTION_DISCONNECTED_CALL_BACK_FROM_NOTIFICATION = 47 "com.android.server.telecom.ACTION_DISCONNECTED_CALL_BACK_FROM_NOTIFICATION"; 48 49 /** The action used to clear missed calls. */ 50 public static final String ACTION_CLEAR_MISSED_CALLS = 51 "com.android.server.telecom.ACTION_CLEAR_MISSED_CALLS"; 52 53 /** 54 * The action used to answer the current incoming call displayed by 55 * {@link com.android.server.telecom.ui.IncomingCallNotifier}. 56 */ 57 public static final String ACTION_ANSWER_FROM_NOTIFICATION = 58 "com.android.server.telecom.ACTION_ANSWER_FROM_NOTIFICATION"; 59 60 /** 61 * The action used to reject the current incoming call displayed by 62 * {@link com.android.server.telecom.ui.IncomingCallNotifier}. 63 */ 64 public static final String ACTION_REJECT_FROM_NOTIFICATION = 65 "com.android.server.telecom.ACTION_REJECT_FROM_NOTIFICATION"; 66 67 /** 68 * The action used to proceed with a call being confirmed via 69 * {@link com.android.server.telecom.ui.ConfirmCallDialogActivity}. 70 */ 71 public static final String ACTION_PROCEED_WITH_CALL = 72 "com.android.server.telecom.PROCEED_WITH_CALL"; 73 74 /** 75 * The action used to cancel a call being confirmed via 76 * {@link com.android.server.telecom.ui.ConfirmCallDialogActivity}. 77 */ 78 public static final String ACTION_CANCEL_CALL = 79 "com.android.server.telecom.CANCEL_CALL"; 80 81 /** 82 * The action used to proceed with a redirected call being confirmed via the call redirection 83 * confirmation dialog. 84 */ 85 public static final String ACTION_PLACE_REDIRECTED_CALL = 86 "com.android.server.telecom.PROCEED_WITH_REDIRECTED_CALL"; 87 88 /** 89 * The action used to confirm to proceed the call without redirection via the call redirection 90 * confirmation dialog. 91 */ 92 public static final String ACTION_PLACE_UNREDIRECTED_CALL = 93 "com.android.server.telecom.PROCEED_WITH_UNREDIRECTED_CALL"; 94 95 /** 96 * The action used to cancel a redirected call being confirmed via the call redirection 97 * confirmation dialog. 98 */ 99 public static final String ACTION_CANCEL_REDIRECTED_CALL = 100 "com.android.server.telecom.CANCEL_REDIRECTED_CALL"; 101 102 public static final String EXTRA_USERHANDLE = "userhandle"; 103 public static final String EXTRA_REDIRECTION_OUTGOING_CALL_ID = 104 "android.telecom.extra.REDIRECTION_OUTGOING_CALL_ID"; 105 public static final String EXTRA_REDIRECTION_APP_NAME = 106 "android.telecom.extra.REDIRECTION_APP_NAME"; 107 108 private final Context mContext; 109 private final CallsManager mCallsManager; 110 TelecomBroadcastIntentProcessor(Context context, CallsManager callsManager)111 public TelecomBroadcastIntentProcessor(Context context, CallsManager callsManager) { 112 mContext = context; 113 mCallsManager = callsManager; 114 } 115 processIntent(Intent intent)116 public void processIntent(Intent intent) { 117 String action = intent.getAction(); 118 119 if (ACTION_SEND_SMS_FROM_NOTIFICATION.equals(action) || 120 ACTION_CALL_BACK_FROM_NOTIFICATION.equals(action) || 121 ACTION_CLEAR_MISSED_CALLS.equals(action)) { 122 Log.v(this, "Action received: %s.", action); 123 UserHandle userHandle = intent.getParcelableExtra(EXTRA_USERHANDLE); 124 if (userHandle == null) { 125 Log.d(this, "user handle can't be null, not processing the broadcast"); 126 return; 127 } 128 129 MissedCallNotifier missedCallNotifier = mCallsManager.getMissedCallNotifier(); 130 131 // Send an SMS from the missed call notification. 132 if (ACTION_SEND_SMS_FROM_NOTIFICATION.equals(action)) { 133 // Close the notification shade and the notification itself. 134 closeSystemDialogs(mContext); 135 missedCallNotifier.clearMissedCalls(userHandle); 136 sendSmsIntent(intent, userHandle); 137 138 // Call back recent caller from the missed call notification. 139 } else if (ACTION_CALL_BACK_FROM_NOTIFICATION.equals(action)) { 140 // Close the notification shade and the notification itself. 141 closeSystemDialogs(mContext); 142 missedCallNotifier.clearMissedCalls(userHandle); 143 sendCallBackIntent(intent, userHandle); 144 145 // Clear the missed call notification and call log entries. 146 } else if (ACTION_CLEAR_MISSED_CALLS.equals(action)) { 147 missedCallNotifier.clearMissedCalls(userHandle); 148 } 149 } else if(ACTION_DISCONNECTED_SEND_SMS_FROM_NOTIFICATION.equals(action) || 150 ACTION_DISCONNECTED_CALL_BACK_FROM_NOTIFICATION.equals(action)) { 151 Log.v(this, "Action received: %s.", action); 152 UserHandle userHandle = intent.getParcelableExtra(EXTRA_USERHANDLE); 153 if (userHandle == null) { 154 Log.d(this, "disconnect user handle can't be null, not processing the broadcast"); 155 return; 156 } 157 158 DisconnectedCallNotifier disconnectedCallNotifier = 159 mCallsManager.getDisconnectedCallNotifier(); 160 161 // Send an SMS from the disconnected call notification. 162 if (ACTION_DISCONNECTED_SEND_SMS_FROM_NOTIFICATION.equals(action)) { 163 // Close the notification shade and the notification itself. 164 closeSystemDialogs(mContext); 165 disconnectedCallNotifier.clearNotification(userHandle); 166 sendSmsIntent(intent, userHandle); 167 168 // Call back recent caller from the disconnected call notification. 169 } else if (ACTION_DISCONNECTED_CALL_BACK_FROM_NOTIFICATION.equals(action)) { 170 // Close the notification shade and the notification itself. 171 closeSystemDialogs(mContext); 172 disconnectedCallNotifier.clearNotification(userHandle); 173 sendCallBackIntent(intent, userHandle); 174 } 175 } else if (ACTION_ANSWER_FROM_NOTIFICATION.equals(action)) { 176 Log.startSession("TBIP.aAFM"); 177 try { 178 // Answer the current ringing call. 179 Call incomingCall = mCallsManager.getIncomingCallNotifier().getIncomingCall(); 180 if (incomingCall != null) { 181 mCallsManager.answerCall(incomingCall, incomingCall.getVideoState()); 182 } 183 } finally { 184 Log.endSession(); 185 } 186 } else if (ACTION_REJECT_FROM_NOTIFICATION.equals(action)) { 187 Log.startSession("TBIP.aRFM"); 188 try { 189 190 // Reject the current ringing call. 191 Call incomingCall = mCallsManager.getIncomingCallNotifier().getIncomingCall(); 192 if (incomingCall != null) { 193 mCallsManager.rejectCall(incomingCall, false /* isRejectWithMessage */, null); 194 } 195 } finally { 196 Log.endSession(); 197 } 198 } else if (ACTION_PROCEED_WITH_CALL.equals(action)) { 199 Log.startSession("TBIP.aPWC"); 200 try { 201 String callId = intent.getStringExtra( 202 ConfirmCallDialogActivity.EXTRA_OUTGOING_CALL_ID); 203 mCallsManager.confirmPendingCall(callId); 204 } finally { 205 Log.endSession(); 206 } 207 } else if (ACTION_CANCEL_CALL.equals(action)) { 208 Log.startSession("TBIP.aCC"); 209 try { 210 String callId = intent.getStringExtra( 211 ConfirmCallDialogActivity.EXTRA_OUTGOING_CALL_ID); 212 mCallsManager.cancelPendingCall(callId); 213 } finally { 214 Log.endSession(); 215 } 216 } else if (ACTION_PLACE_REDIRECTED_CALL.equals(action)) { 217 Log.startSession("TBIP.aPRC"); 218 try { 219 mCallsManager.processRedirectedOutgoingCallAfterUserInteraction( 220 intent.getStringExtra(EXTRA_REDIRECTION_OUTGOING_CALL_ID), 221 ACTION_PLACE_REDIRECTED_CALL); 222 } finally { 223 Log.endSession(); 224 } 225 } else if (ACTION_PLACE_UNREDIRECTED_CALL.equals(action)) { 226 Log.startSession("TBIP.aPUC"); 227 try { 228 mCallsManager.processRedirectedOutgoingCallAfterUserInteraction( 229 intent.getStringExtra(EXTRA_REDIRECTION_OUTGOING_CALL_ID), 230 ACTION_PLACE_UNREDIRECTED_CALL); 231 } finally { 232 Log.endSession(); 233 } 234 } else if (ACTION_CANCEL_REDIRECTED_CALL.equals(action)) { 235 Log.startSession("TBIP.aCRC"); 236 try { 237 mCallsManager.processRedirectedOutgoingCallAfterUserInteraction( 238 intent.getStringExtra(EXTRA_REDIRECTION_OUTGOING_CALL_ID), 239 ACTION_CANCEL_REDIRECTED_CALL); 240 } finally { 241 Log.endSession(); 242 } 243 } 244 } 245 246 /** 247 * Closes open system dialogs and the notification shade. 248 */ closeSystemDialogs(Context context)249 private void closeSystemDialogs(Context context) { 250 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 251 context.sendBroadcastAsUser(intent, UserHandle.ALL); 252 } 253 sendSmsIntent(Intent intent, UserHandle userHandle)254 private void sendSmsIntent(Intent intent, UserHandle userHandle) { 255 Intent callIntent = new Intent(Intent.ACTION_SENDTO, intent.getData()); 256 callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 257 PackageManager packageManager = mContext.getPackageManager(); 258 List<ResolveInfo> activities = packageManager.queryIntentActivitiesAsUser( 259 callIntent, PackageManager.MATCH_DEFAULT_ONLY, userHandle.getIdentifier()); 260 if (activities.size() > 0) { 261 mContext.startActivityAsUser(callIntent, userHandle); 262 } else { 263 Toast.makeText(mContext, com.android.internal.R.string.noApplications, 264 Toast.LENGTH_SHORT).show(); 265 } 266 } 267 sendCallBackIntent(Intent intent, UserHandle userHandle)268 private void sendCallBackIntent(Intent intent, UserHandle userHandle) { 269 Intent callIntent = new Intent(Intent.ACTION_CALL, intent.getData()); 270 callIntent.setFlags( 271 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 272 mContext.startActivityAsUser(callIntent, userHandle); 273 } 274 } 275