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         public void onRttModeChanged(Call call, int mode) {}
     65         public void onRttStatusChanged(Call call, boolean enabled, Call.RttCall rttCall) {}
     66         public void onRttRequest(Call call, int id) {}
     67         public void onRttInitiationFailure(Call call, int reason) {}
     68         public void onHandoverComplete(Call call) {}
     69         public void onHandoverFailed(Call call, int failureReason) {}
     70 
     71         final public MockInCallService getService() {
     72             return mService;
     73         }
     74 
     75         final public void setService(MockInCallService service) {
     76             mService = service;
     77         }
     78     }
     79 
     80     /**
     81      * Note that the super implementations of the callback methods are all no-ops, but we call
     82      * them anyway to make sure that the CTS coverage tool detects that we are testing them.
     83      */
     84     private Call.Callback mCallCallback = new Call.Callback() {
     85         @Override
     86         public void onStateChanged(Call call, int state) {
     87             super.onStateChanged(call, state);
     88             if (getCallbacks() != null) {
     89                 getCallbacks().onCallStateChanged(call, state);
     90             }
     91         }
     92 
     93         @Override
     94         public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {
     95             super.onVideoCallChanged(call, videoCall);
     96             saveVideoCall(call, videoCall);
     97         }
     98 
     99         @Override
    100         public void onParentChanged(Call call, Call parent) {
    101             super.onParentChanged(call, parent);
    102             if (getCallbacks() != null) {
    103                 getCallbacks().onParentChanged(call, parent);
    104             }
    105         }
    106 
    107         @Override
    108         public void onChildrenChanged(Call call, List<Call> children) {
    109             super.onChildrenChanged(call, children);
    110             if (getCallbacks() != null) {
    111                 getCallbacks().onChildrenChanged(call, children);
    112             }
    113         }
    114 
    115         @Override
    116         public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {
    117             super.onConferenceableCallsChanged(call, conferenceableCalls);
    118             if (getCallbacks() != null) {
    119                 getCallbacks().onConferenceableCallsChanged(call, conferenceableCalls);
    120             }
    121         }
    122 
    123         @Override
    124         public void onCallDestroyed(Call call) {
    125             super.onCallDestroyed(call);
    126             if (getCallbacks() != null) {
    127                 getCallbacks().onCallDestroyed(call);
    128             }
    129         }
    130 
    131         @Override
    132         public void onDetailsChanged(Call call, Call.Details details) {
    133             super.onDetailsChanged(call, details);
    134             if (getCallbacks() != null) {
    135                 getCallbacks().onDetailsChanged(call, details);
    136             }
    137         }
    138 
    139         @Override
    140         public void onPostDialWait(Call call, String remainingPostDialSequence) {
    141             super.onPostDialWait(call, remainingPostDialSequence);
    142             if (getCallbacks() != null) {
    143                 getCallbacks().onPostDialWait(call, remainingPostDialSequence);
    144             }
    145         }
    146 
    147         @Override
    148         public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {
    149             super.onCannedTextResponsesLoaded(call, cannedTextResponses);
    150             if (getCallbacks() != null) {
    151                 getCallbacks().onCannedTextResponsesLoaded(call, cannedTextResponses);
    152             }
    153         }
    154 
    155         @Override
    156         public void onConnectionEvent(Call call, String event, Bundle extras) {
    157             super.onConnectionEvent(call, event, extras);
    158             if (getCallbacks() != null) {
    159                 getCallbacks().onConnectionEvent(call, event, extras);
    160             }
    161         }
    162 
    163         @Override
    164         public void onRttModeChanged(Call call, int mode) {
    165             super.onRttModeChanged(call, mode);
    166             if (getCallbacks() != null) {
    167                 getCallbacks().onRttModeChanged(call, mode);
    168             }
    169         }
    170 
    171         @Override
    172         public void onRttStatusChanged(Call call, boolean enabled, Call.RttCall rttCall) {
    173             super.onRttStatusChanged(call, enabled, rttCall);
    174             if (getCallbacks() != null) {
    175                 getCallbacks().onRttStatusChanged(call, enabled, rttCall);
    176             }
    177         }
    178 
    179         @Override
    180         public void onRttRequest(Call call, int id) {
    181             super.onRttRequest(call, id);
    182             if (getCallbacks() != null) {
    183                 getCallbacks().onRttRequest(call, id);
    184             }
    185         }
    186 
    187         @Override
    188         public void onRttInitiationFailure(Call call, int reason) {
    189             super.onRttInitiationFailure(call, reason);
    190             if (getCallbacks() != null) {
    191                 getCallbacks().onRttInitiationFailure(call, reason);
    192             }
    193         }
    194 
    195         @Override
    196         public void onHandoverComplete(Call call) {
    197             super.onHandoverComplete(call);
    198             if (getCallbacks() != null) {
    199                 getCallbacks().onHandoverComplete(call);
    200             }
    201         }
    202 
    203         @Override
    204         public void onHandoverFailed(Call call, int failureReason) {
    205             super.onHandoverFailed(call, failureReason);
    206             if (getCallbacks() != null) {
    207                 getCallbacks().onHandoverFailed(call, failureReason);
    208             }
    209         }
    210     };
    211 
    212     private void saveVideoCall(Call call, VideoCall videoCall) {
    213         if (videoCall != null) {
    214             if (!mVideoCallCallbacks.containsKey(call)) {
    215                 MockVideoCallCallback listener = new MockVideoCallCallback(call);
    216                 videoCall.registerCallback(listener);
    217                 mVideoCallCallbacks.put(call, listener);
    218             }
    219         } else {
    220             mVideoCallCallbacks.remove(call);
    221         }
    222     }
    223 
    224     @Override
    225     public android.os.IBinder onBind(android.content.Intent intent) {
    226         Log.i(LOG_TAG, "Service bounded");
    227         if (getCallbacks() != null) {
    228             getCallbacks().setService(this);
    229         }
    230         mIsServiceBound = true;
    231         return super.onBind(intent);
    232     }
    233 
    234     @Override
    235     public void onCallAdded(Call call) {
    236         super.onCallAdded(call);
    237         if (call.getDetails().hasProperty(Call.Details.PROPERTY_CONFERENCE) == true) {
    238             if (!mConferenceCalls.contains(call)) {
    239                 mConferenceCalls.add(call);
    240                 call.registerCallback(mCallCallback);
    241             }
    242         } else {
    243             if (!mCalls.contains(call)) {
    244                 mCalls.add(call);
    245                 call.registerCallback(mCallCallback);
    246                 VideoCall videoCall = call.getVideoCall();
    247                 if (videoCall != null) {
    248                     saveVideoCall(call, videoCall);
    249                 }
    250             }
    251         }
    252         if (getCallbacks() != null) {
    253             getCallbacks().onCallAdded(call, mCalls.size() + mConferenceCalls.size());
    254         }
    255     }
    256 
    257     @Override
    258     public void onCallRemoved(Call call) {
    259         super.onCallRemoved(call);
    260         if (call.getDetails().hasProperty(Call.Details.PROPERTY_CONFERENCE) == true) {
    261             mConferenceCalls.remove(call);
    262         } else {
    263             mCalls.remove(call);
    264         }
    265         if (getCallbacks() != null) {
    266             getCallbacks().onCallRemoved(call, mCalls.size() + mConferenceCalls.size());
    267             saveVideoCall(call, null /* remove videoCall */);
    268         }
    269     }
    270 
    271     @Override
    272     public void onCanAddCallChanged(boolean canAddCall) {
    273         super.onCanAddCallChanged(canAddCall);
    274         if (getCallbacks() != null) {
    275             getCallbacks().onCanAddCallsChanged(canAddCall);
    276         }
    277     }
    278 
    279     @Override
    280     public void onBringToForeground(boolean showDialpad) {
    281         super.onBringToForeground(showDialpad);
    282         if (getCallbacks() != null) {
    283             getCallbacks().onBringToForeground(showDialpad);
    284         }
    285     }
    286 
    287     @Override
    288     public void onCallAudioStateChanged(CallAudioState audioState) {
    289         super.onCallAudioStateChanged(audioState);
    290         if (getCallbacks() != null) {
    291             getCallbacks().onCallAudioStateChanged(audioState);
    292         }
    293     }
    294 
    295     @Override
    296     public void onSilenceRinger(){
    297         super.onSilenceRinger();
    298         if(getCallbacks() != null) {
    299             getCallbacks().onSilenceRinger();
    300         }
    301     }
    302 
    303     /**
    304      * @return the number of calls currently added to the {@code InCallService}.
    305      */
    306     public int getCallCount() {
    307         return mCalls.size();
    308     }
    309 
    310     /**
    311      * @return the number of conference calls currently added to the {@code InCallService}.
    312      */
    313     public int getConferenceCallCount() {
    314         return mConferenceCalls.size();
    315     }
    316 
    317     /**
    318      * @return the most recently added call that exists inside the {@code InCallService}
    319      */
    320     public Call getLastCall() {
    321         if (!mCalls.isEmpty()) {
    322             return mCalls.get(mCalls.size() - 1);
    323         }
    324         return null;
    325     }
    326 
    327     /**
    328      * @return the most recently added conference call that exists inside the {@code InCallService}
    329      */
    330     public Call getLastConferenceCall() {
    331         if (!mConferenceCalls.isEmpty()) {
    332             return mConferenceCalls.get(mConferenceCalls.size() - 1);
    333         }
    334         return null;
    335     }
    336 
    337     public void disconnectLastCall() {
    338         final Call call = getLastCall();
    339         if (call != null) {
    340             call.disconnect();
    341         }
    342     }
    343 
    344     public void disconnectLastConferenceCall() {
    345         final Call call = getLastConferenceCall();
    346         if (call != null) {
    347             call.disconnect();
    348         }
    349     }
    350 
    351     public void disconnectAllCalls() {
    352         for (final Call call: mCalls) {
    353             call.disconnect();
    354         }
    355     }
    356 
    357     public void disconnectAllConferenceCalls() {
    358         for (final Call call: mConferenceCalls) {
    359             call.disconnect();
    360         }
    361     }
    362 
    363     public static void setCallbacks(InCallServiceCallbacks callbacks) {
    364         synchronized (sLock) {
    365             sCallbacks = callbacks;
    366         }
    367     }
    368 
    369     private InCallServiceCallbacks getCallbacks() {
    370         synchronized (sLock) {
    371             if (sCallbacks != null) {
    372                 sCallbacks.setService(this);
    373             }
    374             return sCallbacks;
    375         }
    376     }
    377 
    378     /**
    379      * Determines if a video callback has been registered for the passed in call.
    380      *
    381      * @param call The call.
    382      * @return {@code true} if a video callback has been registered.
    383      */
    384     public boolean isVideoCallbackRegistered(Call call) {
    385         return mVideoCallCallbacks.containsKey(call);
    386     }
    387 
    388     /**
    389      * Retrieves the video callbacks associated with a call.
    390      * @param call The call.
    391      * @return The {@link MockVideoCallCallback} instance associated with the call.
    392      */
    393     public MockVideoCallCallback getVideoCallCallback(Call call) {
    394         return mVideoCallCallbacks.get(call);
    395     }
    396 
    397     @Override
    398     public boolean onUnbind(Intent intent) {
    399         Log.i(LOG_TAG, "Service has been unbound");
    400         assertTrue(mIsServiceBound);
    401         mIsServiceBound = false;
    402         return super.onUnbind(intent);
    403     }
    404 
    405     public static boolean isServiceBound() {
    406         return mIsServiceBound;
    407     }
    408 }
    409