• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
setUp()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
tearDown()137     public void tearDown() throws Exception {
138         super.tearDown();
139         ContactsPreferencesFactory.setTestInstance(null);
140         mInCallPresenter.tearDown();
141     }
142 
testPostNonPullable()143     public void testPostNonPullable() {
144         TestTelecomCall call = getTestCall(false);
145         mExternalCallNotifier.onExternalCallAdded(call.getCall());
146         Notification notification = verifyNotificationPosted();
147         assertNull(notification.actions);
148     }
149 
testPostPullable()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 
testNotificationDismissed()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 
testNotificationUpdated()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 
verifyNotificationPosted()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 
getTestCall(boolean canPull)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