• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.bluetooth.telephony;
18 
19 import android.bluetooth.BluetoothLeCallControl;
20 import android.net.Uri;
21 import android.os.Bundle;
22 import android.os.Handler;
23 import android.telecom.Call;
24 import android.telecom.DisconnectCause;
25 import android.telecom.GatewayInfo;
26 import android.telecom.InCallService;
27 import android.telecom.PhoneAccountHandle;
28 
29 import com.android.internal.annotations.VisibleForTesting;
30 
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.UUID;
34 
35 /**
36  * A proxy class of android.telecom.Call that
37  * 1) facilitates testing of the BluetoothInCallService class; We can't mock the final class
38  * Call directly;
39  * 2) Some helper functions, to let Call have same methods as com.android.server.telecom.Call
40  *
41  * This is necessary due to the "final" attribute of the Call class. In order to
42  * test the correct functioning of the BluetoothInCallService class, the final class must be put
43  * into a container that can be mocked correctly.
44  */
45 @VisibleForTesting
46 public class BluetoothCall {
47 
48     private Call mCall;
49     private UUID mCallId;
50 
getCall()51     public Call getCall() {
52         return mCall;
53     }
54 
isCallNull()55     public boolean isCallNull() {
56         return mCall == null;
57     }
58 
setCall(Call call)59     public void setCall(Call call) {
60         mCall = call;
61     }
62 
BluetoothCall(Call call)63     public BluetoothCall(Call call) {
64         mCall = call;
65         mCallId = UUID.randomUUID();
66     }
67 
BluetoothCall(Call call, UUID callId)68     public BluetoothCall(Call call, UUID callId) {
69         mCall = call;
70         mCallId = callId;
71     }
72 
getTbsCallId()73     public UUID getTbsCallId() {
74         return mCallId;
75     }
76 
setTbsCallId(UUID callId)77     public void setTbsCallId(UUID callId) {
78         mCallId = callId;
79     }
80 
getRemainingPostDialSequence()81     public String getRemainingPostDialSequence() {
82         return mCall.getRemainingPostDialSequence();
83     }
84 
answer(int videoState)85     public void answer(int videoState) {
86         mCall.answer(videoState);
87     }
88 
deflect(Uri address)89     public void deflect(Uri address) {
90         mCall.deflect(address);
91     }
92 
reject(boolean rejectWithMessage, String textMessage)93     public void reject(boolean rejectWithMessage, String textMessage) {
94         mCall.reject(rejectWithMessage, textMessage);
95     }
96 
disconnect()97     public void disconnect() {
98         mCall.disconnect();
99     }
100 
hold()101     public void hold() {
102         mCall.hold();
103     }
104 
unhold()105     public void unhold() {
106         mCall.unhold();
107     }
108 
enterBackgroundAudioProcessing()109     public void enterBackgroundAudioProcessing() {
110         mCall.enterBackgroundAudioProcessing();
111     }
112 
exitBackgroundAudioProcessing(boolean shouldRing)113     public void exitBackgroundAudioProcessing(boolean shouldRing) {
114         mCall.exitBackgroundAudioProcessing(shouldRing);
115     }
116 
playDtmfTone(char digit)117     public void playDtmfTone(char digit) {
118         mCall.playDtmfTone(digit);
119     }
120 
stopDtmfTone()121     public void stopDtmfTone() {
122         mCall.stopDtmfTone();
123     }
124 
postDialContinue(boolean proceed)125     public void postDialContinue(boolean proceed) {
126         mCall.postDialContinue(proceed);
127     }
128 
phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault)129     public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
130         mCall.phoneAccountSelected(accountHandle, setDefault);
131     }
132 
conference(BluetoothCall callToConferenceWith)133     public void conference(BluetoothCall callToConferenceWith) {
134         if (callToConferenceWith != null) {
135             mCall.conference(callToConferenceWith.getCall());
136         }
137     }
138 
splitFromConference()139     public void splitFromConference() {
140         mCall.splitFromConference();
141     }
142 
mergeConference()143     public void mergeConference() {
144         mCall.mergeConference();
145     }
146 
swapConference()147     public void swapConference() {
148         mCall.swapConference();
149     }
150 
pullExternalCall()151     public void pullExternalCall() {
152         mCall.pullExternalCall();
153     }
154 
sendCallEvent(String event, Bundle extras)155     public void sendCallEvent(String event, Bundle extras) {
156         mCall.sendCallEvent(event, extras);
157     }
158 
sendRttRequest()159     public void sendRttRequest() {
160         mCall.sendRttRequest();
161     }
162 
respondToRttRequest(int id, boolean accept)163     public void respondToRttRequest(int id, boolean accept) {
164         mCall.respondToRttRequest(id, accept);
165     }
166 
handoverTo(PhoneAccountHandle toHandle, int videoState, Bundle extras)167     public void handoverTo(PhoneAccountHandle toHandle, int videoState, Bundle extras) {
168         mCall.handoverTo(toHandle, videoState, extras);
169     }
170 
stopRtt()171     public void stopRtt() {
172         mCall.stopRtt();
173     }
174 
removeExtras(List<String> keys)175     public void removeExtras(List<String> keys) {
176         mCall.removeExtras(keys);
177     }
178 
removeExtras(String... keys)179     public void removeExtras(String... keys) {
180         mCall.removeExtras(keys);
181     }
182 
183     /**
184      * Returns the parent Call id.
185      */
getParentId()186     public Integer getParentId() {
187         Call parent = mCall.getParent();
188         if (parent != null) {
189             return System.identityHashCode(parent);
190         }
191         return null;
192     }
193 
getChildrenIds()194     public List<Integer> getChildrenIds() {
195         return getIds(mCall.getChildren());
196     }
197 
getConferenceableCalls()198     public List<Integer> getConferenceableCalls() {
199         return getIds(mCall.getConferenceableCalls());
200     }
201 
getState()202     public int getState() {
203         return mCall.getState();
204     }
205 
getCannedTextResponses()206     public List<String> getCannedTextResponses() {
207         return mCall.getCannedTextResponses();
208     }
209 
getVideoCall()210     public InCallService.VideoCall getVideoCall() {
211         return mCall.getVideoCall();
212     }
213 
getDetails()214     public Call.Details getDetails() {
215         return mCall.getDetails();
216     }
217 
getRttCall()218     public Call.RttCall getRttCall() {
219         return mCall.getRttCall();
220     }
221 
isRttActive()222     public boolean isRttActive() {
223         return mCall.isRttActive();
224     }
225 
registerCallback(Call.Callback callback)226     public void registerCallback(Call.Callback callback) {
227         mCall.registerCallback(callback);
228     }
229 
registerCallback(Call.Callback callback, Handler handler)230     public void registerCallback(Call.Callback callback, Handler handler) {
231         mCall.registerCallback(callback, handler);
232     }
233 
unregisterCallback(Call.Callback callback)234     public void unregisterCallback(Call.Callback callback) {
235         mCall.unregisterCallback(callback);
236     }
237 
toString()238     public String toString() {
239         String string = mCall.toString();
240         return string == null ? "" : string;
241     }
242 
addListener(Call.Listener listener)243     public void addListener(Call.Listener listener) {
244         mCall.addListener(listener);
245     }
246 
removeListener(Call.Listener listener)247     public void removeListener(Call.Listener listener) {
248         mCall.removeListener(listener);
249     }
250 
getGenericConferenceActiveChildCallId()251     public Integer getGenericConferenceActiveChildCallId() {
252         return System.identityHashCode(mCall.getGenericConferenceActiveChildCall());
253     }
254 
getContactDisplayName()255     public String getContactDisplayName() {
256         return mCall.getDetails().getContactDisplayName();
257     }
258 
getAccountHandle()259     public PhoneAccountHandle getAccountHandle() {
260         return mCall.getDetails().getAccountHandle();
261     }
262 
getVideoState()263     public int getVideoState() {
264         return mCall.getDetails().getVideoState();
265     }
266 
getCallerDisplayName()267     public String getCallerDisplayName() {
268         return mCall.getDetails().getCallerDisplayName();
269     }
270 
271     @Override
equals(Object o)272     public boolean equals(Object o) {
273         if (o == null) {
274             return getCall() == null;
275         }
276         return o instanceof BluetoothCall && getCall() == ((BluetoothCall) o).getCall();
277     }
278 
279     // helper functions
isSilentRingingRequested()280     public boolean isSilentRingingRequested() {
281         return getDetails().getExtras() != null
282                 && getDetails().getExtras().getBoolean(Call.EXTRA_SILENT_RINGING_REQUESTED);
283     }
284 
isConference()285     public boolean isConference() {
286         return getDetails().hasProperty(Call.Details.PROPERTY_CONFERENCE);
287     }
288 
can(int capability)289     public boolean can(int capability) {
290         return getDetails().can(capability);
291     }
292 
getHandle()293     public Uri getHandle() {
294         return getDetails().getHandle();
295     }
296 
getGatewayInfo()297     public GatewayInfo getGatewayInfo() {
298         return getDetails().getGatewayInfo();
299     }
300 
isIncoming()301     public boolean isIncoming() {
302         return getDetails().getCallDirection() == Call.Details.DIRECTION_INCOMING;
303     }
304 
isExternalCall()305     public boolean isExternalCall() {
306         return getDetails().hasProperty(Call.Details.PROPERTY_IS_EXTERNAL_CALL);
307     }
308 
getId()309     public Integer getId() {
310         return System.identityHashCode(mCall);
311     }
312 
wasConferencePreviouslyMerged()313     public boolean wasConferencePreviouslyMerged() {
314         return can(Call.Details.CAPABILITY_SWAP_CONFERENCE) &&
315                 !can(Call.Details.CAPABILITY_MERGE_CONFERENCE);
316     }
317 
getDisconnectCause()318     public DisconnectCause getDisconnectCause() {
319         return getDetails().getDisconnectCause();
320     }
321 
322     /**
323      * Returns the list of ids of corresponding Call List.
324      */
getIds(List<Call> calls)325     public static List<Integer> getIds(List<Call> calls) {
326         List<Integer> result = new ArrayList<>();
327         for (Call call : calls) {
328             if (call != null) {
329                 result.add(System.identityHashCode(call));
330             }
331         }
332         return result;
333     }
334 
hasProperty(int property)335     public boolean hasProperty(int property) {
336         return getDetails().hasProperty(property);
337     }
338 }
339