AnswerPresenter.java revision e553d43bc397e769a8ad416e3a4f9515d6da8eba
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.incallui; 18 19import android.os.RemoteException; 20import android.telecomm.IInCallAdapter; 21 22import com.android.services.telephony.common.Call; 23 24import java.util.ArrayList; 25 26/** 27 * Presenter for the Incoming call widget. 28 */ 29public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi> 30 implements CallList.CallUpdateListener, CallList.Listener { 31 32 private static final String TAG = AnswerPresenter.class.getSimpleName(); 33 34 private int mCallId = Call.INVALID_CALL_ID; 35 private Call mCall = null; 36 37 @Override 38 public void onUiReady(AnswerUi ui) { 39 super.onUiReady(ui); 40 41 final CallList calls = CallList.getInstance(); 42 final Call call = calls.getIncomingCall(); 43 // TODO: change so that answer presenter never starts up if it's not incoming. 44 if (call != null) { 45 processIncomingCall(call); 46 } 47 48 // Listen for incoming calls. 49 calls.addListener(this); 50 } 51 52 @Override 53 public void onUiUnready(AnswerUi ui) { 54 super.onUiUnready(ui); 55 56 CallList.getInstance().removeListener(this); 57 58 // This is necessary because the activity can be destroyed while an incoming call exists. 59 // This happens when back button is pressed while incoming call is still being shown. 60 if (mCallId != Call.INVALID_CALL_ID) { 61 CallList.getInstance().removeCallUpdateListener(mCallId, this); 62 } 63 } 64 65 @Override 66 public void onCallListChange(CallList callList) { 67 // no-op 68 } 69 70 @Override 71 public void onDisconnect(Call call) { 72 // no-op 73 } 74 75 @Override 76 public void onIncomingCall(Call call) { 77 // TODO: Ui is being destroyed when the fragment detaches. Need clean up step to stop 78 // getting updates here. 79 Log.d(this, "onIncomingCall: " + this); 80 if (getUi() != null) { 81 if (call.getCallId() != mCallId) { 82 // A new call is coming in. 83 processIncomingCall(call); 84 } 85 } 86 } 87 88 private void processIncomingCall(Call call) { 89 mCallId = call.getCallId(); 90 mCall = call; 91 92 // Listen for call updates for the current call. 93 CallList.getInstance().addCallUpdateListener(mCallId, this); 94 95 Log.d(TAG, "Showing incoming for call id: " + mCallId + " " + this); 96 final ArrayList<String> textMsgs = CallList.getInstance().getTextResponses( 97 call.getCallId()); 98 getUi().showAnswerUi(true); 99 100 if (call.can(Call.Capabilities.RESPOND_VIA_TEXT) && textMsgs != null) { 101 getUi().showTextButton(true); 102 getUi().configureMessageDialog(textMsgs); 103 } else { 104 getUi().showTextButton(false); 105 } 106 } 107 108 109 @Override 110 public void onCallStateChanged(Call call) { 111 Log.d(this, "onCallStateChange() " + call + " " + this); 112 if (call.getState() != Call.State.INCOMING && call.getState() != Call.State.CALL_WAITING) { 113 // Stop listening for updates. 114 CallList.getInstance().removeCallUpdateListener(mCallId, this); 115 116 getUi().showAnswerUi(false); 117 118 // mCallId will hold the state of the call. We don't clear the mCall variable here as 119 // it may be useful for sending text messages after phone disconnects. 120 mCallId = Call.INVALID_CALL_ID; 121 } 122 } 123 124 public void onAnswer() { 125 if (mCallId == Call.INVALID_CALL_ID) { 126 return; 127 } 128 129 Log.d(this, "onAnswer " + mCallId); 130 131 CallCommandClient.getInstance().answerCall(mCallId); 132 133 // TODO(santoscordon): Need a TelecommAdapter wrapper object so that we dont have to check 134 // for null like this everywhere. 135 IInCallAdapter telecommAdapter = InCallPresenter.getInstance().getTelecommAdapter(); 136 if (telecommAdapter != null) { 137 // TODO(santoscordon): Remove translator by using only String-based IDs in all of the 138 // in-call app. 139 String callId = CallInfoTranslator.getTelecommCallId(mCall); 140 if (callId != null) { 141 // TODO(santoscordon): TelecommAdapter wrapper would also eliminate much of this 142 // try-catch code. 143 try { 144 Log.i(this, "Answering the call: " + callId); 145 telecommAdapter.answerCall(callId); 146 } catch (RemoteException e) { 147 Log.e(this, "Failed to send answer command.", e); 148 } 149 } 150 } 151 } 152 153 /** 154 * TODO(santoscordon): We are using reject and decline interchangeably. We should settle on 155 * reject since it seems to be more prevalent. 156 */ 157 public void onDecline() { 158 Log.d(this, "onDecline " + mCallId); 159 160 CallCommandClient.getInstance().rejectCall(mCall, false, null); 161 162 IInCallAdapter telecommAdapter = InCallPresenter.getInstance().getTelecommAdapter(); 163 if (telecommAdapter != null) { 164 String callId = CallInfoTranslator.getTelecommCallId(mCall); 165 if (callId != null) { 166 try { 167 Log.i(this, "Rejecting the call: " + callId); 168 telecommAdapter.rejectCall(callId); 169 } catch (RemoteException e) { 170 Log.e(this, "Failed to send reject command.", e); 171 } 172 } 173 } 174 } 175 176 public void onText() { 177 if (getUi() != null) { 178 getUi().showMessageDialog(); 179 } 180 } 181 182 public void rejectCallWithMessage(String message) { 183 Log.d(this, "sendTextToDefaultActivity()..."); 184 185 CallCommandClient.getInstance().rejectCall(mCall, true, message); 186 187 onDismissDialog(); 188 } 189 190 public void onDismissDialog() { 191 InCallPresenter.getInstance().onDismissDialog(); 192 } 193 194 interface AnswerUi extends Ui { 195 public void showAnswerUi(boolean show); 196 public void showTextButton(boolean show); 197 public void showMessageDialog(); 198 public void configureMessageDialog(ArrayList<String> textResponses); 199 } 200} 201