Home | History | Annotate | Download | only in cts
      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 
     49         public void onCallAdded(Call call, int numCalls) {};
     50         public void onCallRemoved(Call call, int numCalls) {};
     51         public void onCallStateChanged(Call call, int state) {};
     52         public void onParentChanged(Call call, Call parent) {};
     53         public void onChildrenChanged(Call call, List<Call> children) {};
     54         public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {};
     55         public void onCallDestroyed(Call call) {};
     56         public void onDetailsChanged(Call call, Call.Details details) {};
     57         public void onCanAddCallsChanged(boolean canAddCalls) {}
     58         public void onBringToForeground(boolean showDialpad) {}
     59         public void onCallAudioStateChanged(CallAudioState audioState) {}
     60         public void onPostDialWait(Call call, String remainingPostDialSequence) {}
     61         public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
     62         public void onSilenceRinger() {}
     63         public void onConnectionEvent(Call call, String event, Bundle extras) {}
     64 
     65         final public MockInCallService getService() {
     66             return mService;
     67         }
     68 
     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 
    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
    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
    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
    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
    218     public void onCanAddCallChanged(boolean canAddCall) {
    219         super.onCanAddCallChanged(canAddCall);
    220         if (getCallbacks() != null) {
    221             getCallbacks().onCanAddCallsChanged(canAddCall);
    222         }
    223     }
    224 
    225     @Override
    226     public void onBringToForeground(boolean showDialpad) {
    227         super.onBringToForeground(showDialpad);
    228         if (getCallbacks() != null) {
    229             getCallbacks().onBringToForeground(showDialpad);
    230         }
    231     }
    232 
    233     @Override
    234     public void onCallAudioStateChanged(CallAudioState audioState) {
    235         super.onCallAudioStateChanged(audioState);
    236         if (getCallbacks() != null) {
    237             getCallbacks().onCallAudioStateChanged(audioState);
    238         }
    239     }
    240 
    241     @Override
    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      */
    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      */
    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      */
    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      */
    276     public Call getLastConferenceCall() {
    277         if (!mConferenceCalls.isEmpty()) {
    278             return mConferenceCalls.get(mConferenceCalls.size() - 1);
    279         }
    280         return null;
    281     }
    282 
    283     public void disconnectLastCall() {
    284         final Call call = getLastCall();
    285         if (call != null) {
    286             call.disconnect();
    287         }
    288     }
    289 
    290     public void disconnectLastConferenceCall() {
    291         final Call call = getLastConferenceCall();
    292         if (call != null) {
    293             call.disconnect();
    294         }
    295     }
    296 
    297     public void disconnectAllCalls() {
    298         for (final Call call: mCalls) {
    299             call.disconnect();
    300         }
    301     }
    302 
    303     public void disconnectAllConferenceCalls() {
    304         for (final Call call: mConferenceCalls) {
    305             call.disconnect();
    306         }
    307     }
    308 
    309     public static void setCallbacks(InCallServiceCallbacks callbacks) {
    310         synchronized (sLock) {
    311             sCallbacks = callbacks;
    312         }
    313     }
    314 
    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      */
    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      */
    339     public MockVideoCallCallback getVideoCallCallback(Call call) {
    340         return mVideoCallCallbacks.get(call);
    341     }
    342 
    343     @Override
    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 
    351     public static boolean isServiceBound() {
    352         return mIsServiceBound;
    353     }
    354 }
    355