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