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