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