1 /*
2  * Copyright (C) 2014 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 com.google.common.base.Preconditions;
20 
21 import android.content.ActivityNotFoundException;
22 import android.content.Intent;
23 import android.os.Looper;
24 import android.telecom.InCallService;
25 import android.telecom.PhoneAccountHandle;
26 
27 import java.util.List;
28 
29 final class TelecomAdapter implements InCallServiceListener {
30     private static final String ADD_CALL_MODE_KEY = "add_call_mode";
31 
32     private static TelecomAdapter sInstance;
33     private InCallService mInCallService;
34 
getInstance()35     static TelecomAdapter getInstance() {
36         Preconditions.checkState(Looper.getMainLooper().getThread() == Thread.currentThread());
37         if (sInstance == null) {
38             sInstance = new TelecomAdapter();
39         }
40         return sInstance;
41     }
42 
TelecomAdapter()43     private TelecomAdapter() {
44     }
45 
46     @Override
setInCallService(InCallService inCallService)47     public void setInCallService(InCallService inCallService) {
48         mInCallService = inCallService;
49     }
50 
51     @Override
clearInCallService()52     public void clearInCallService() {
53         mInCallService = null;
54     }
55 
getTelecomCallById(String callId)56     private android.telecom.Call getTelecomCallById(String callId) {
57         Call call = CallList.getInstance().getCallById(callId);
58         return call == null ? null : call.getTelecomCall();
59     }
60 
answerCall(String callId, int videoState)61     void answerCall(String callId, int videoState) {
62         android.telecom.Call call = getTelecomCallById(callId);
63         if (call != null) {
64             call.answer(videoState);
65         } else {
66             Log.e(this, "error answerCall, call not in call list: " + callId);
67         }
68     }
69 
rejectCall(String callId, boolean rejectWithMessage, String message)70     void rejectCall(String callId, boolean rejectWithMessage, String message) {
71         android.telecom.Call call = getTelecomCallById(callId);
72         if (call != null) {
73             call.reject(rejectWithMessage, message);
74         } else {
75             Log.e(this, "error rejectCall, call not in call list: " + callId);
76         }
77     }
78 
disconnectCall(String callId)79     void disconnectCall(String callId) {
80         android.telecom.Call call = getTelecomCallById(callId);
81         if (call != null) {
82             call.disconnect();
83         } else {
84             Log.e(this, "error disconnectCall, call not in call list " + callId);
85         }
86     }
87 
holdCall(String callId)88     void holdCall(String callId) {
89         android.telecom.Call call = getTelecomCallById(callId);
90         if (call != null) {
91             call.hold();
92         } else {
93             Log.e(this, "error holdCall, call not in call list " + callId);
94         }
95     }
96 
unholdCall(String callId)97     void unholdCall(String callId) {
98         android.telecom.Call call = getTelecomCallById(callId);
99         if (call != null) {
100             call.unhold();
101         } else {
102             Log.e(this, "error unholdCall, call not in call list " + callId);
103         }
104     }
105 
mute(boolean shouldMute)106     void mute(boolean shouldMute) {
107         if (mInCallService != null) {
108             mInCallService.setMuted(shouldMute);
109         } else {
110             Log.e(this, "error mute, mInCallService is null");
111         }
112     }
113 
setAudioRoute(int route)114     void setAudioRoute(int route) {
115         if (mInCallService != null) {
116             mInCallService.setAudioRoute(route);
117         } else {
118             Log.e(this, "error setAudioRoute, mInCallService is null");
119         }
120     }
121 
separateCall(String callId)122     void separateCall(String callId) {
123         android.telecom.Call call = getTelecomCallById(callId);
124         if (call != null) {
125             call.splitFromConference();
126         } else {
127             Log.e(this, "error separateCall, call not in call list " + callId);
128         }
129     }
130 
merge(String callId)131     void merge(String callId) {
132         android.telecom.Call call = getTelecomCallById(callId);
133         if (call != null) {
134             List<android.telecom.Call> conferenceable = call.getConferenceableCalls();
135             if (!conferenceable.isEmpty()) {
136                 call.conference(conferenceable.get(0));
137             } else {
138                 if (call.getDetails().can(android.telecom.Call.Details.CAPABILITY_MERGE_CONFERENCE)) {
139                     call.mergeConference();
140                 }
141             }
142         } else {
143             Log.e(this, "error merge, call not in call list " + callId);
144         }
145     }
146 
swap(String callId)147     void swap(String callId) {
148         android.telecom.Call call = getTelecomCallById(callId);
149         if (call != null) {
150             if (call.getDetails().can(android.telecom.Call.Details.CAPABILITY_SWAP_CONFERENCE)) {
151                 call.swapConference();
152             }
153         } else {
154             Log.e(this, "error swap, call not in call list " + callId);
155         }
156     }
157 
addCall()158     void addCall() {
159         if (mInCallService != null) {
160             Intent intent = new Intent(Intent.ACTION_DIAL);
161             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
162 
163             // when we request the dialer come up, we also want to inform
164             // it that we're going through the "add call" option from the
165             // InCallScreen / PhoneUtils.
166             intent.putExtra(ADD_CALL_MODE_KEY, true);
167             try {
168                 Log.d(this, "Sending the add Call intent");
169                 mInCallService.startActivity(intent);
170             } catch (ActivityNotFoundException e) {
171                 // This is rather rare but possible.
172                 // Note: this method is used even when the phone is encrypted. At that moment
173                 // the system may not find any Activity which can accept this Intent.
174                 Log.e(this, "Activity for adding calls isn't found.", e);
175             }
176         }
177     }
178 
playDtmfTone(String callId, char digit)179     void playDtmfTone(String callId, char digit) {
180         android.telecom.Call call = getTelecomCallById(callId);
181         if (call != null) {
182             call.playDtmfTone(digit);
183         } else {
184             Log.e(this, "error playDtmfTone, call not in call list " + callId);
185         }
186     }
187 
stopDtmfTone(String callId)188     void stopDtmfTone(String callId) {
189         android.telecom.Call call = getTelecomCallById(callId);
190         if (call != null) {
191             call.stopDtmfTone();
192         } else {
193             Log.e(this, "error stopDtmfTone, call not in call list " + callId);
194         }
195     }
196 
postDialContinue(String callId, boolean proceed)197     void postDialContinue(String callId, boolean proceed) {
198         android.telecom.Call call = getTelecomCallById(callId);
199         if (call != null) {
200             call.postDialContinue(proceed);
201         } else {
202             Log.e(this, "error postDialContinue, call not in call list " + callId);
203         }
204     }
205 
phoneAccountSelected(String callId, PhoneAccountHandle accountHandle, boolean setDefault)206     void phoneAccountSelected(String callId, PhoneAccountHandle accountHandle, boolean setDefault) {
207         if (accountHandle == null) {
208             Log.e(this, "error phoneAccountSelected, accountHandle is null");
209             // TODO: Do we really want to send null accountHandle?
210         }
211 
212         android.telecom.Call call = getTelecomCallById(callId);
213         if (call != null) {
214             call.phoneAccountSelected(accountHandle, setDefault);
215         } else {
216             Log.e(this, "error phoneAccountSelected, call not in call list " + callId);
217         }
218     }
219 
canAddCall()220     boolean canAddCall() {
221         if (mInCallService != null) {
222             return mInCallService.canAddCall();
223         }
224         return false;
225     }
226 }
227