AnswerPresenter.java revision 3034f16f6b74004738ca8e85cefc3f503679f44f
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.telecom.PhoneCapabilities;
20import android.app.KeyguardManager;
21import android.content.Context;
22
23import java.util.List;
24
25/**
26 * Presenter for the Incoming call widget.
27 */
28public 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        final KeyguardManager km =
180                (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
181        final boolean isLockScreenShowing = km.inKeyguardRestrictedInputMode();
182
183        mHasTextMessages = textMsgs != null;
184        boolean withSms = call.can(PhoneCapabilities.RESPOND_VIA_TEXT) && mHasTextMessages;
185        if (call.isVideoCall(context)) {
186            if (withSms && !isLockScreenShowing) {
187                getUi().showTargets(AnswerFragment.TARGET_SET_FOR_VIDEO_WITH_SMS);
188                getUi().configureMessageDialog(textMsgs);
189            } else {
190                getUi().showTargets(AnswerFragment.TARGET_SET_FOR_VIDEO_WITHOUT_SMS);
191            }
192        } else {
193            if (withSms && !isLockScreenShowing) {
194                getUi().showTargets(AnswerFragment.TARGET_SET_FOR_AUDIO_WITH_SMS);
195                getUi().configureMessageDialog(textMsgs);
196            } else {
197                getUi().showTargets(AnswerFragment.TARGET_SET_FOR_AUDIO_WITHOUT_SMS);
198            }
199        }
200    }
201
202    interface AnswerUi extends Ui {
203        public void showAnswerUi(boolean show);
204        public void showTargets(int targetSet);
205        public void showMessageDialog();
206        public void configureMessageDialog(List<String> textResponses);
207        public Context getContext();
208    }
209}
210