Home | History | Annotate | Download | only in incallui
      1 /*
      2  * Copyright (C) 2016 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 static org.mockito.Matchers.anyInt;
     20 import static org.mockito.Mockito.any;
     21 import static org.mockito.Mockito.anyBoolean;
     22 import static org.mockito.Mockito.doAnswer;
     23 import static org.mockito.Mockito.eq;
     24 import static org.mockito.Mockito.timeout;
     25 import static org.mockito.Mockito.verify;
     26 import static org.mockito.Mockito.when;
     27 
     28 import com.android.contacts.common.preference.ContactsPreferences;
     29 
     30 import org.mockito.ArgumentCaptor;
     31 import org.mockito.Mock;
     32 import org.mockito.MockitoAnnotations;
     33 import org.mockito.Spy;
     34 import org.mockito.invocation.InvocationOnMock;
     35 import org.mockito.stubbing.Answer;
     36 
     37 import android.app.Notification;
     38 import android.app.NotificationManager;
     39 import android.content.ComponentName;
     40 import android.content.Context;
     41 import android.content.res.Resources;
     42 import android.net.Uri;
     43 import android.telecom.*;
     44 import android.telecom.Call;
     45 import android.telephony.TelephonyManager;
     46 import android.test.AndroidTestCase;
     47 import android.test.mock.MockContext;
     48 
     49 /**
     50  * Unit tests for {@link ExternalCallNotifier}.
     51  */
     52 public class ExternalCallNotifierTest extends AndroidTestCase {
     53     private static final int TIMEOUT_MILLIS = 5000;
     54     private static final String NAME_PRIMARY = "Full Name";
     55     private static final String NAME_ALTERNATIVE = "Name, Full";
     56     private static final String LOCATION = "US";
     57     private static final String NUMBER = "6505551212";
     58 
     59     @Mock private ContactsPreferences mContactsPreferences;
     60     @Mock private NotificationManager mNotificationManager;
     61     @Mock private MockContext mMockContext;
     62     @Mock private Resources mResources;
     63     @Mock private StatusBarNotifier mStatusBarNotifier;
     64     @Mock private ContactInfoCache mContactInfoCache;
     65     @Mock private TelecomManager mTelecomManager;
     66     @Mock private TelephonyManager mTelephonyManager;
     67     @Mock private ProximitySensor mProximitySensor;
     68     @Mock private CallList mCallList;
     69     private InCallPresenter mInCallPresenter;
     70     private ExternalCallNotifier mExternalCallNotifier;
     71     private ContactInfoCache.ContactCacheEntry mContactInfo;
     72 
     73     @Override
     74     public void setUp() throws Exception {
     75         super.setUp();
     76         MockitoAnnotations.initMocks(this);
     77 
     78         when(mContactsPreferences.getDisplayOrder())
     79                 .thenReturn(ContactsPreferences.DISPLAY_ORDER_PRIMARY);
     80 
     81         // Setup the mock context to return mocks for some of the needed services; the notification
     82         // service is especially important as we want to be able to intercept calls into it and
     83         // validate the notifcations.
     84         when(mMockContext.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
     85                 .thenReturn(mNotificationManager);
     86         when(mMockContext.getSystemService(eq(Context.TELECOM_SERVICE)))
     87                 .thenReturn(mTelecomManager);
     88         when(mMockContext.getSystemService(eq(Context.TELEPHONY_SERVICE)))
     89                 .thenReturn(mTelephonyManager);
     90 
     91         // These aspects of the context are used by the notification builder to build the actual
     92         // notification; we will rely on the actual implementations of these.
     93         when(mMockContext.getPackageManager()).thenReturn(mContext.getPackageManager());
     94         when(mMockContext.getResources()).thenReturn(mContext.getResources());
     95         when(mMockContext.getApplicationInfo()).thenReturn(mContext.getApplicationInfo());
     96         when(mMockContext.getContentResolver()).thenReturn(mContext.getContentResolver());
     97         when(mMockContext.getPackageName()).thenReturn(mContext.getPackageName());
     98 
     99         ContactsPreferencesFactory.setTestInstance(null);
    100         mExternalCallNotifier = new ExternalCallNotifier(mMockContext, mContactInfoCache);
    101 
    102         // We don't directly use the InCallPresenter in the test, or even in ExternalCallNotifier
    103         // itself.  However, ExternalCallNotifier needs to make instances of
    104         // com.android.incallui.Call for the purpose of performing contact cache lookups.  The
    105         // Call class depends on the static InCallPresenter for a number of things, so we need to
    106         // set it up here to prevent crashes.
    107         mInCallPresenter = InCallPresenter.getInstance();
    108         mInCallPresenter.setUp(mMockContext, mCallList, new ExternalCallList(),
    109                 null, mStatusBarNotifier, mExternalCallNotifier, mContactInfoCache,
    110                 mProximitySensor);
    111 
    112         // Unlocked all contact info is available
    113         mContactInfo = new ContactInfoCache.ContactCacheEntry();
    114         mContactInfo.namePrimary = NAME_PRIMARY;
    115         mContactInfo.nameAlternative = NAME_ALTERNATIVE;
    116         mContactInfo.location = LOCATION;
    117         mContactInfo.number = NUMBER;
    118 
    119         // Given the mock ContactInfoCache cache, we need to mock out what happens when the
    120         // ExternalCallNotifier calls into the contact info cache to do a lookup.  We will always
    121         // return mock info stored in mContactInfo.
    122         doAnswer(new Answer() {
    123             @Override
    124             public Object answer(InvocationOnMock invocation) throws Throwable {
    125                 Object[] args = invocation.getArguments();
    126                 com.android.incallui.Call call = (com.android.incallui.Call) args[0];
    127                 ContactInfoCache.ContactInfoCacheCallback callback
    128                         = (ContactInfoCache.ContactInfoCacheCallback) args[2];
    129                 callback.onContactInfoComplete(call.getId(), mContactInfo);
    130                 return null;
    131             }
    132         }).when(mContactInfoCache).findInfo(any(com.android.incallui.Call.class), anyBoolean(),
    133                 any(ContactInfoCache.ContactInfoCacheCallback.class));
    134     }
    135 
    136     @Override
    137     public void tearDown() throws Exception {
    138         super.tearDown();
    139         ContactsPreferencesFactory.setTestInstance(null);
    140         mInCallPresenter.tearDown();
    141     }
    142 
    143     public void testPostNonPullable() {
    144         TestTelecomCall call = getTestCall(false);
    145         mExternalCallNotifier.onExternalCallAdded(call.getCall());
    146         Notification notification = verifyNotificationPosted();
    147         assertNull(notification.actions);
    148     }
    149 
    150     public void testPostPullable() {
    151         TestTelecomCall call = getTestCall(true);
    152         mExternalCallNotifier.onExternalCallAdded(call.getCall());
    153         Notification notification = verifyNotificationPosted();
    154         assertEquals(1, notification.actions.length);
    155     }
    156 
    157     public void testNotificationDismissed() {
    158         TestTelecomCall call = getTestCall(false);
    159         mExternalCallNotifier.onExternalCallAdded(call.getCall());
    160         verifyNotificationPosted();
    161 
    162         mExternalCallNotifier.onExternalCallRemoved(call.getCall());
    163         verify(mNotificationManager, timeout(TIMEOUT_MILLIS)).cancel(eq("EXTERNAL_CALL"), eq(0));
    164     }
    165 
    166     public void testNotificationUpdated() {
    167         TestTelecomCall call = getTestCall(false);
    168         mExternalCallNotifier.onExternalCallAdded(call.getCall());
    169         verifyNotificationPosted();
    170 
    171         call.setCapabilities(android.telecom.Call.Details.CAPABILITY_CAN_PULL_CALL);
    172         mExternalCallNotifier.onExternalCallUpdated(call.getCall());
    173 
    174         ArgumentCaptor<Notification> notificationCaptor =
    175                 ArgumentCaptor.forClass(Notification.class);
    176         verify(mNotificationManager, timeout(TIMEOUT_MILLIS).times(2))
    177                 .notify(eq("EXTERNAL_CALL"), eq(0), notificationCaptor.capture());
    178         Notification notification1 = notificationCaptor.getAllValues().get(0);
    179         assertNull(notification1.actions);
    180         Notification notification2 = notificationCaptor.getAllValues().get(1);
    181         assertEquals(1, notification2.actions.length);
    182     }
    183 
    184     private Notification verifyNotificationPosted() {
    185         ArgumentCaptor<Notification> notificationCaptor =
    186                 ArgumentCaptor.forClass(Notification.class);
    187         verify(mNotificationManager, timeout(TIMEOUT_MILLIS))
    188                 .notify(eq("EXTERNAL_CALL"), eq(0), notificationCaptor.capture());
    189         return notificationCaptor.getValue();
    190     }
    191 
    192     private TestTelecomCall getTestCall(boolean canPull) {
    193         TestTelecomCall testCall = TestTelecomCall.createInstance(
    194                 "1",
    195                 Uri.parse("tel:650-555-1212"), /* handle */
    196                 TelecomManager.PRESENTATION_ALLOWED, /* handlePresentation */
    197                 "Joe", /* callerDisplayName */
    198                 TelecomManager.PRESENTATION_ALLOWED, /* callerDisplayNamePresentation */
    199                 new PhoneAccountHandle(new ComponentName("test", "class"),
    200                         "handle"), /* accountHandle */
    201                 canPull ? android.telecom.Call.Details.CAPABILITY_CAN_PULL_CALL : 0, /* capabilities */
    202                 Call.Details.PROPERTY_IS_EXTERNAL_CALL, /* properties */
    203                 null, /* disconnectCause */
    204                 0, /* connectTimeMillis */
    205                 null, /* GatewayInfo */
    206                 VideoProfile.STATE_AUDIO_ONLY, /* videoState */
    207                 null, /* statusHints */
    208                 null, /* extras */
    209                 null /* intentExtras */);
    210         return testCall;
    211     }
    212 }
    213