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.incallui; 18 19 import android.content.Context; 20 import android.telecom.TelecomManager; 21 22 import java.util.List; 23 24 /** 25 * Presenter for the Incoming call widget. 26 */ 27 public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi> 28 implements CallList.CallUpdateListener, CallList.Listener { 29 30 private static final String TAG = AnswerPresenter.class.getSimpleName(); 31 32 private String mCallId; 33 private Call mCall = null; 34 private boolean mHasTextMessages = false; 35 36 @Override 37 public void onUiReady(AnswerUi ui) { 38 super.onUiReady(ui); 39 40 final CallList calls = CallList.getInstance(); 41 Call call; 42 call = calls.getIncomingCall(); 43 if (call != null) { 44 processIncomingCall(call); 45 } 46 call = calls.getVideoUpgradeRequestCall(); 47 if (call != null) { 48 processVideoUpgradeRequestCall(call); 49 } 50 51 // Listen for incoming calls. 52 calls.addListener(this); 53 } 54 55 @Override 56 public void onUiUnready(AnswerUi ui) { 57 super.onUiUnready(ui); 58 59 CallList.getInstance().removeListener(this); 60 61 // This is necessary because the activity can be destroyed while an incoming call exists. 62 // This happens when back button is pressed while incoming call is still being shown. 63 if (mCallId != null) { 64 CallList.getInstance().removeCallUpdateListener(mCallId, this); 65 } 66 } 67 68 @Override 69 public void onCallListChange(CallList callList) { 70 // no-op 71 } 72 73 @Override 74 public void onDisconnect(Call call) { 75 // no-op 76 } 77 78 @Override 79 public void onIncomingCall(Call call) { 80 // TODO: Ui is being destroyed when the fragment detaches. Need clean up step to stop 81 // getting updates here. 82 Log.d(this, "onIncomingCall: " + this); 83 if (getUi() != null) { 84 if (!call.getId().equals(mCallId)) { 85 // A new call is coming in. 86 processIncomingCall(call); 87 } 88 } 89 } 90 91 private void processIncomingCall(Call call) { 92 mCallId = call.getId(); 93 mCall = call; 94 95 // Listen for call updates for the current call. 96 CallList.getInstance().addCallUpdateListener(mCallId, this); 97 98 Log.d(TAG, "Showing incoming for call id: " + mCallId + " " + this); 99 final List<String> textMsgs = CallList.getInstance().getTextResponses(call.getId()); 100 getUi().showAnswerUi(true); 101 configureAnswerTargetsForSms(call, textMsgs); 102 } 103 104 private void processVideoUpgradeRequestCall(Call call) { 105 mCallId = call.getId(); 106 mCall = call; 107 108 // Listen for call updates for the current call. 109 CallList.getInstance().addCallUpdateListener(mCallId, this); 110 getUi().showAnswerUi(true); 111 112 getUi().showTargets(AnswerFragment.TARGET_SET_FOR_VIDEO_UPGRADE_REQUEST); 113 } 114 115 @Override 116 public void onCallChanged(Call call) { 117 Log.d(this, "onCallStateChange() " + call + " " + this); 118 if (call.getState() != Call.State.INCOMING) { 119 // Stop listening for updates. 120 CallList.getInstance().removeCallUpdateListener(mCallId, this); 121 122 getUi().showAnswerUi(false); 123 124 // mCallId will hold the state of the call. We don't clear the mCall variable here as 125 // it may be useful for sending text messages after phone disconnects. 126 mCallId = null; 127 mHasTextMessages = false; 128 } else if (!mHasTextMessages) { 129 final List<String> textMsgs = CallList.getInstance().getTextResponses(call.getId()); 130 if (textMsgs != null) { 131 configureAnswerTargetsForSms(call, textMsgs); 132 } 133 } 134 } 135 136 public void onAnswer(int videoState, Context context) { 137 if (mCallId == null) { 138 return; 139 } 140 141 Log.d(this, "onAnswer " + mCallId); 142 if (mCall.getSessionModificationState() 143 == Call.SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST) { 144 InCallPresenter.getInstance().acceptUpgradeRequest(context); 145 } else { 146 TelecomAdapter.getInstance().answerCall(mCall.getId(), videoState); 147 } 148 } 149 150 /** 151 * TODO: We are using reject and decline interchangeably. We should settle on 152 * reject since it seems to be more prevalent. 153 */ 154 public void onDecline() { 155 Log.d(this, "onDecline " + mCallId); 156 TelecomAdapter.getInstance().rejectCall(mCall.getId(), false, null); 157 } 158 159 public void onText() { 160 if (getUi() != null) { 161 InCallPresenter.getInstance().getTelecomManager().silenceRinger(); 162 getUi().showMessageDialog(); 163 } 164 } 165 166 public void rejectCallWithMessage(String message) { 167 Log.d(this, "sendTextToDefaultActivity()..."); 168 TelecomAdapter.getInstance().rejectCall(mCall.getId(), true, message); 169 170 onDismissDialog(); 171 } 172 173 public void onDismissDialog() { 174 InCallPresenter.getInstance().onDismissDialog(); 175 } 176 177 private void configureAnswerTargetsForSms(Call call, List<String> textMsgs) { 178 final Context context = getUi().getContext(); 179 180 mHasTextMessages = textMsgs != null; 181 boolean withSms = 182 call.can(android.telecom.Call.Details.CAPABILITY_RESPOND_VIA_TEXT) 183 && mHasTextMessages; 184 if (call.isVideoCall(context)) { 185 if (withSms) { 186 getUi().showTargets(AnswerFragment.TARGET_SET_FOR_VIDEO_WITH_SMS); 187 getUi().configureMessageDialog(textMsgs); 188 } else { 189 getUi().showTargets(AnswerFragment.TARGET_SET_FOR_VIDEO_WITHOUT_SMS); 190 } 191 } else { 192 if (withSms) { 193 getUi().showTargets(AnswerFragment.TARGET_SET_FOR_AUDIO_WITH_SMS); 194 getUi().configureMessageDialog(textMsgs); 195 } else { 196 getUi().showTargets(AnswerFragment.TARGET_SET_FOR_AUDIO_WITHOUT_SMS); 197 } 198 } 199 } 200 201 interface AnswerUi extends Ui { 202 public void showAnswerUi(boolean show); 203 public void showTargets(int targetSet); 204 public void showMessageDialog(); 205 public void configureMessageDialog(List<String> textResponses); 206 public Context getContext(); 207 } 208 } 209