• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 android.telecom.cts;
18 
19 import static org.junit.Assert.assertTrue;
20 
21 import android.content.Intent;
22 import android.os.Bundle;
23 import android.telecom.Call;
24 import android.telecom.CallAudioState;
25 import android.telecom.InCallService;
26 import android.util.ArrayMap;
27 import android.util.Log;
28 
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.concurrent.Semaphore;
33 
34 public class MockInCallService extends InCallService {
35     private static String LOG_TAG = "MockInCallService";
36     private ArrayList<Call> mCalls = new ArrayList<>();
37     private ArrayList<Call> mConferenceCalls = new ArrayList<>();
38     private static InCallServiceCallbacks sCallbacks;
39     private Map<Call, MockVideoCallCallback> mVideoCallCallbacks =
40             new ArrayMap<Call, MockVideoCallCallback>();
41 
42     private static final Object sLock = new Object();
43     private static boolean mIsServiceBound = false;
44 
45     public static abstract class InCallServiceCallbacks {
46         private MockInCallService mService;
47         public Semaphore lock = new Semaphore(0);
48 
onCallAdded(Call call, int numCalls)49         public void onCallAdded(Call call, int numCalls) {};
onCallRemoved(Call call, int numCalls)50         public void onCallRemoved(Call call, int numCalls) {};
onCallStateChanged(Call call, int state)51         public void onCallStateChanged(Call call, int state) {};
onParentChanged(Call call, Call parent)52         public void onParentChanged(Call call, Call parent) {};
onChildrenChanged(Call call, List<Call> children)53         public void onChildrenChanged(Call call, List<Call> children) {};
onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls)54         public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {};
onCallDestroyed(Call call)55         public void onCallDestroyed(Call call) {};
onDetailsChanged(Call call, Call.Details details)56         public void onDetailsChanged(Call call, Call.Details details) {};
onCanAddCallsChanged(boolean canAddCalls)57         public void onCanAddCallsChanged(boolean canAddCalls) {}
onBringToForeground(boolean showDialpad)58         public void onBringToForeground(boolean showDialpad) {}
onCallAudioStateChanged(CallAudioState audioState)59         public void onCallAudioStateChanged(CallAudioState audioState) {}
onPostDialWait(Call call, String remainingPostDialSequence)60         public void onPostDialWait(Call call, String remainingPostDialSequence) {}
onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses)61         public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
onSilenceRinger()62         public void onSilenceRinger() {}
onConnectionEvent(Call call, String event, Bundle extras)63         public void onConnectionEvent(Call call, String event, Bundle extras) {}
64 
getService()65         final public MockInCallService getService() {
66             return mService;
67         }
68 
setService(MockInCallService service)69         final public void setService(MockInCallService service) {
70             mService = service;
71         }
72     }
73 
74     /**
75      * Note that the super implementations of the callback methods are all no-ops, but we call
76      * them anyway to make sure that the CTS coverage tool detects that we are testing them.
77      */
78     private Call.Callback mCallCallback = new Call.Callback() {
79         @Override
80         public void onStateChanged(Call call, int state) {
81             super.onStateChanged(call, state);
82             if (getCallbacks() != null) {
83                 getCallbacks().onCallStateChanged(call, state);
84             }
85         }
86 
87         @Override
88         public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {
89             super.onVideoCallChanged(call, videoCall);
90             saveVideoCall(call, videoCall);
91         }
92 
93         @Override
94         public void onParentChanged(Call call, Call parent) {
95             super.onParentChanged(call, parent);
96             if (getCallbacks() != null) {
97                 getCallbacks().onParentChanged(call, parent);
98             }
99         }
100 
101         @Override
102         public void onChildrenChanged(Call call, List<Call> children) {
103             super.onChildrenChanged(call, children);
104             if (getCallbacks() != null) {
105                 getCallbacks().onChildrenChanged(call, children);
106             }
107         }
108 
109         @Override
110         public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {
111             super.onConferenceableCallsChanged(call, conferenceableCalls);
112             if (getCallbacks() != null) {
113                 getCallbacks().onConferenceableCallsChanged(call, conferenceableCalls);
114             }
115         }
116 
117         @Override
118         public void onCallDestroyed(Call call) {
119             super.onCallDestroyed(call);
120             if (getCallbacks() != null) {
121                 getCallbacks().onCallDestroyed(call);
122             }
123         }
124 
125         @Override
126         public void onDetailsChanged(Call call, Call.Details details) {
127             super.onDetailsChanged(call, details);
128             if (getCallbacks() != null) {
129                 getCallbacks().onDetailsChanged(call, details);
130             }
131         }
132 
133         @Override
134         public void onPostDialWait(Call call, String remainingPostDialSequence) {
135             super.onPostDialWait(call, remainingPostDialSequence);
136             if (getCallbacks() != null) {
137                 getCallbacks().onPostDialWait(call, remainingPostDialSequence);
138             }
139         }
140 
141         @Override
142         public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {
143             super.onCannedTextResponsesLoaded(call, cannedTextResponses);
144             if (getCallbacks() != null) {
145                 getCallbacks().onCannedTextResponsesLoaded(call, cannedTextResponses);
146             }
147         }
148 
149         @Override
150         public void onConnectionEvent(Call call, String event, Bundle extras) {
151             super.onConnectionEvent(call, event, extras);
152             if (getCallbacks() != null) {
153                 getCallbacks().onConnectionEvent(call, event, extras);
154             }
155         }
156     };
157 
saveVideoCall(Call call, VideoCall videoCall)158     private void saveVideoCall(Call call, VideoCall videoCall) {
159         if (videoCall != null) {
160             if (!mVideoCallCallbacks.containsKey(call)) {
161                 MockVideoCallCallback listener = new MockVideoCallCallback(call);
162                 videoCall.registerCallback(listener);
163                 mVideoCallCallbacks.put(call, listener);
164             }
165         } else {
166             mVideoCallCallbacks.remove(call);
167         }
168     }
169 
170     @Override
onBind(android.content.Intent intent)171     public android.os.IBinder onBind(android.content.Intent intent) {
172         Log.i(LOG_TAG, "Service bounded");
173         if (getCallbacks() != null) {
174             getCallbacks().setService(this);
175         }
176         mIsServiceBound = true;
177         return super.onBind(intent);
178     }
179 
180     @Override
onCallAdded(Call call)181     public void onCallAdded(Call call) {
182         super.onCallAdded(call);
183         if (call.getDetails().hasProperty(Call.Details.PROPERTY_CONFERENCE) == true) {
184             if (!mConferenceCalls.contains(call)) {
185                 mConferenceCalls.add(call);
186                 call.registerCallback(mCallCallback);
187             }
188         } else {
189             if (!mCalls.contains(call)) {
190                 mCalls.add(call);
191                 call.registerCallback(mCallCallback);
192                 VideoCall videoCall = call.getVideoCall();
193                 if (videoCall != null) {
194                     saveVideoCall(call, videoCall);
195                 }
196             }
197         }
198         if (getCallbacks() != null) {
199             getCallbacks().onCallAdded(call, mCalls.size() + mConferenceCalls.size());
200         }
201     }
202 
203     @Override
onCallRemoved(Call call)204     public void onCallRemoved(Call call) {
205         super.onCallRemoved(call);
206         if (call.getDetails().hasProperty(Call.Details.PROPERTY_CONFERENCE) == true) {
207             mConferenceCalls.remove(call);
208         } else {
209             mCalls.remove(call);
210         }
211         if (getCallbacks() != null) {
212             getCallbacks().onCallRemoved(call, mCalls.size() + mConferenceCalls.size());
213             saveVideoCall(call, null /* remove videoCall */);
214         }
215     }
216 
217     @Override
onCanAddCallChanged(boolean canAddCall)218     public void onCanAddCallChanged(boolean canAddCall) {
219         super.onCanAddCallChanged(canAddCall);
220         if (getCallbacks() != null) {
221             getCallbacks().onCanAddCallsChanged(canAddCall);
222         }
223     }
224 
225     @Override
onBringToForeground(boolean showDialpad)226     public void onBringToForeground(boolean showDialpad) {
227         super.onBringToForeground(showDialpad);
228         if (getCallbacks() != null) {
229             getCallbacks().onBringToForeground(showDialpad);
230         }
231     }
232 
233     @Override
onCallAudioStateChanged(CallAudioState audioState)234     public void onCallAudioStateChanged(CallAudioState audioState) {
235         super.onCallAudioStateChanged(audioState);
236         if (getCallbacks() != null) {
237             getCallbacks().onCallAudioStateChanged(audioState);
238         }
239     }
240 
241     @Override
onSilenceRinger()242     public void onSilenceRinger(){
243         super.onSilenceRinger();
244         if(getCallbacks() != null) {
245             getCallbacks().onSilenceRinger();
246         }
247     }
248 
249     /**
250      * @return the number of calls currently added to the {@code InCallService}.
251      */
getCallCount()252     public int getCallCount() {
253         return mCalls.size();
254     }
255 
256     /**
257      * @return the number of conference calls currently added to the {@code InCallService}.
258      */
getConferenceCallCount()259     public int getConferenceCallCount() {
260         return mConferenceCalls.size();
261     }
262 
263     /**
264      * @return the most recently added call that exists inside the {@code InCallService}
265      */
getLastCall()266     public Call getLastCall() {
267         if (!mCalls.isEmpty()) {
268             return mCalls.get(mCalls.size() - 1);
269         }
270         return null;
271     }
272 
273     /**
274      * @return the most recently added conference call that exists inside the {@code InCallService}
275      */
getLastConferenceCall()276     public Call getLastConferenceCall() {
277         if (!mConferenceCalls.isEmpty()) {
278             return mConferenceCalls.get(mConferenceCalls.size() - 1);
279         }
280         return null;
281     }
282 
disconnectLastCall()283     public void disconnectLastCall() {
284         final Call call = getLastCall();
285         if (call != null) {
286             call.disconnect();
287         }
288     }
289 
disconnectLastConferenceCall()290     public void disconnectLastConferenceCall() {
291         final Call call = getLastConferenceCall();
292         if (call != null) {
293             call.disconnect();
294         }
295     }
296 
disconnectAllCalls()297     public void disconnectAllCalls() {
298         for (final Call call: mCalls) {
299             call.disconnect();
300         }
301     }
302 
disconnectAllConferenceCalls()303     public void disconnectAllConferenceCalls() {
304         for (final Call call: mConferenceCalls) {
305             call.disconnect();
306         }
307     }
308 
setCallbacks(InCallServiceCallbacks callbacks)309     public static void setCallbacks(InCallServiceCallbacks callbacks) {
310         synchronized (sLock) {
311             sCallbacks = callbacks;
312         }
313     }
314 
getCallbacks()315     private InCallServiceCallbacks getCallbacks() {
316         synchronized (sLock) {
317             if (sCallbacks != null) {
318                 sCallbacks.setService(this);
319             }
320             return sCallbacks;
321         }
322     }
323 
324     /**
325      * Determines if a video callback has been registered for the passed in call.
326      *
327      * @param call The call.
328      * @return {@code true} if a video callback has been registered.
329      */
isVideoCallbackRegistered(Call call)330     public boolean isVideoCallbackRegistered(Call call) {
331         return mVideoCallCallbacks.containsKey(call);
332     }
333 
334     /**
335      * Retrieves the video callbacks associated with a call.
336      * @param call The call.
337      * @return The {@link MockVideoCallCallback} instance associated with the call.
338      */
getVideoCallCallback(Call call)339     public MockVideoCallCallback getVideoCallCallback(Call call) {
340         return mVideoCallCallbacks.get(call);
341     }
342 
343     @Override
onUnbind(Intent intent)344     public boolean onUnbind(Intent intent) {
345         Log.i(LOG_TAG, "Service has been unbound");
346         assertTrue(mIsServiceBound);
347         mIsServiceBound = false;
348         return super.onUnbind(intent);
349     }
350 
isServiceBound()351     public static boolean isServiceBound() {
352         return mIsServiceBound;
353     }
354 }
355