• 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.server.telecom.tests;
18 
19 import android.content.Context;
20 import android.graphics.Bitmap;
21 import android.graphics.drawable.BitmapDrawable;
22 import android.graphics.drawable.Drawable;
23 import android.net.Uri;
24 import android.support.test.InstrumentationRegistry;
25 import android.test.suitebuilder.annotation.SmallTest;
26 import android.telecom.Logging.Session;
27 
28 import com.android.internal.telephony.CallerInfo;
29 import com.android.internal.telephony.CallerInfoAsyncQuery;
30 import com.android.server.telecom.CallerInfoAsyncQueryFactory;
31 import com.android.server.telecom.CallerInfoLookupHelper;
32 import com.android.server.telecom.ContactsAsyncHelper;
33 import com.android.server.telecom.TelecomSystem;
34 
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.junit.runners.JUnit4;
39 import org.mockito.ArgumentCaptor;
40 import org.mockito.Mock;
41 
42 import java.io.FileNotFoundException;
43 import java.io.InputStream;
44 import java.util.concurrent.CountDownLatch;
45 
46 import static org.junit.Assert.assertEquals;
47 import static org.mockito.Matchers.any;
48 import static org.mockito.Matchers.anyInt;
49 import static org.mockito.Matchers.anyString;
50 import static org.mockito.Matchers.eq;
51 import static org.mockito.Matchers.isNull;
52 import static org.mockito.Mockito.mock;
53 import static org.mockito.Mockito.times;
54 import static org.mockito.Mockito.verify;
55 import static org.mockito.Mockito.when;
56 
57 @RunWith(JUnit4.class)
58 public class CallerInfoLookupHelperTest extends TelecomTestCase {
59     @Mock Context mContext;
60     @Mock CallerInfoAsyncQueryFactory mFactory;
61     @Mock ContactsAsyncHelper mContactsAsyncHelper;
62     @Mock Drawable mDrawable2;
63 
64     CallerInfo mCallerInfo1;
65     CallerInfo mCallerInfo2;
66 
67     @Mock Drawable mDrawable1;
68     CallerInfoLookupHelper mCallerInfoLookupHelper;
69     static final Uri URI1 = Uri.parse("tel:555-555-7010");
70     static final Uri URI2 = Uri.parse("tel:555-555-7016");
71 
72     static final Uri CONTACTS_PHOTO_URI = Uri.parse(
73             "android.resource://com.android.server.telecom.tests/"
74                     + R.drawable.contacts_sample_photo_small);
75 
76     Bitmap mBitmap;
77 
78     @Override
79     @Before
setUp()80     public void setUp() throws Exception {
81         super.setUp();
82         mCallerInfoLookupHelper = new CallerInfoLookupHelper(mContext,
83                 mFactory, mContactsAsyncHelper, new TelecomSystem.SyncRoot() { });
84         when(mFactory.startQuery(anyInt(), eq(mContext), anyString(),
85                 any(CallerInfoAsyncQuery.OnQueryCompleteListener.class), any()))
86                 .thenReturn(mock(CallerInfoAsyncQuery.class));
87         mCallerInfo1 = new CallerInfo();
88         mCallerInfo2 = new CallerInfo();
89 
90         if (mBitmap == null) {
91             InputStream is;
92             try {
93                 is = InstrumentationRegistry.getContext()
94                         .getContentResolver().openInputStream(CONTACTS_PHOTO_URI);
95             } catch (FileNotFoundException e) {
96                 return;
97             }
98 
99             Drawable d = Drawable.createFromStream(is, CONTACTS_PHOTO_URI.toString());
100             mBitmap = ((BitmapDrawable) d).getBitmap();
101         }
102     }
103 
104     @SmallTest
105     @Test
testLookupWithEmptyHandle()106     public void testLookupWithEmptyHandle() {
107         CallerInfoLookupHelper.OnQueryCompleteListener listener = mock(
108                 CallerInfoLookupHelper.OnQueryCompleteListener.class);
109         mCallerInfoLookupHelper.startLookup(Uri.EMPTY, listener);
110 
111         verify(listener).onCallerInfoQueryComplete(eq(Uri.EMPTY), isNull(CallerInfo.class));
112         verifyProperCleanup();
113     }
114 
115     @SmallTest
116     @Test
testSimpleLookup()117     public void testSimpleLookup() {
118         CallerInfoLookupHelper.OnQueryCompleteListener listener = mock(
119                 CallerInfoLookupHelper.OnQueryCompleteListener.class);
120         mCallerInfo1.contactDisplayPhotoUri = CONTACTS_PHOTO_URI;
121 
122         mCallerInfoLookupHelper.startLookup(URI1, listener);
123         waitForActionCompletion();
124 
125         // CallerInfo section
126         ArgumentCaptor<CallerInfoAsyncQuery.OnQueryCompleteListener> queryListenerCaptor =
127                 ArgumentCaptor.forClass(CallerInfoAsyncQuery.OnQueryCompleteListener.class);
128         ArgumentCaptor<Session> logSessionCaptor = ArgumentCaptor.forClass(Session.class);
129         verify(mFactory).startQuery(anyInt(), eq(mContext), eq(URI1.getSchemeSpecificPart()),
130                 queryListenerCaptor.capture(), logSessionCaptor.capture());
131 
132         queryListenerCaptor.getValue().onQueryComplete(
133                 0, logSessionCaptor.getValue(), mCallerInfo1);
134         verify(listener).onCallerInfoQueryComplete(URI1, mCallerInfo1);
135         waitForActionCompletion();
136 
137         // Contacts photo section
138         ArgumentCaptor<ContactsAsyncHelper.OnImageLoadCompleteListener> imageListenerCaptor =
139                 ArgumentCaptor.forClass(ContactsAsyncHelper.OnImageLoadCompleteListener.class);
140         verify(mContactsAsyncHelper).startObtainPhotoAsync(anyInt(), eq(mContext),
141                 eq(CONTACTS_PHOTO_URI), imageListenerCaptor.capture(), logSessionCaptor.capture());
142 
143         imageListenerCaptor.getValue().onImageLoadComplete(0, mDrawable1, mBitmap,
144                 logSessionCaptor.getValue());
145         verify(listener).onContactPhotoQueryComplete(URI1, mCallerInfo1);
146         assertEquals(mDrawable1, mCallerInfo1.cachedPhoto);
147         assertEquals(mBitmap, mCallerInfo1.cachedPhotoIcon);
148 
149         verifyProperCleanup();
150     }
151 
152     @SmallTest
153     @Test
testLookupWithTwoListeners()154     public void testLookupWithTwoListeners() {
155         CallerInfoLookupHelper.OnQueryCompleteListener callListener = mock(
156                 CallerInfoLookupHelper.OnQueryCompleteListener.class);
157         CallerInfoLookupHelper.OnQueryCompleteListener otherListener = mock(
158                 CallerInfoLookupHelper.OnQueryCompleteListener.class);
159         mCallerInfo1.contactDisplayPhotoUri = CONTACTS_PHOTO_URI;
160 
161         mCallerInfoLookupHelper.startLookup(URI1, callListener);
162         mCallerInfoLookupHelper.startLookup(URI1, otherListener);
163         waitForActionCompletion();
164 
165         ArgumentCaptor<CallerInfoAsyncQuery.OnQueryCompleteListener> queryListenerCaptor =
166                 ArgumentCaptor.forClass(CallerInfoAsyncQuery.OnQueryCompleteListener.class);
167         ArgumentCaptor<Session> logSessionCaptor = ArgumentCaptor.forClass(Session.class);
168         verify(mFactory, times(1)).startQuery(anyInt(), eq(mContext),
169                 eq(URI1.getSchemeSpecificPart()), queryListenerCaptor.capture(),
170                 logSessionCaptor.capture());
171 
172         queryListenerCaptor.getValue().onQueryComplete(
173                 0, logSessionCaptor.getValue(), mCallerInfo1);
174         verify(callListener, times(1)).onCallerInfoQueryComplete(URI1, mCallerInfo1);
175         verify(otherListener, times(1)).onCallerInfoQueryComplete(URI1, mCallerInfo1);
176         waitForActionCompletion();
177 
178         ArgumentCaptor<ContactsAsyncHelper.OnImageLoadCompleteListener> imageListenerCaptor =
179                 ArgumentCaptor.forClass(ContactsAsyncHelper.OnImageLoadCompleteListener.class);
180         verify(mContactsAsyncHelper).startObtainPhotoAsync(anyInt(), eq(mContext),
181                 eq(CONTACTS_PHOTO_URI), imageListenerCaptor.capture(), logSessionCaptor.capture());
182 
183         imageListenerCaptor.getValue().onImageLoadComplete(0, mDrawable1, mBitmap,
184                 logSessionCaptor.getValue());
185         verify(callListener).onContactPhotoQueryComplete(URI1, mCallerInfo1);
186         verify(otherListener).onContactPhotoQueryComplete(URI1, mCallerInfo1);
187         assertEquals(mDrawable1, mCallerInfo1.cachedPhoto);
188         assertEquals(mBitmap, mCallerInfo1.cachedPhotoIcon);
189 
190         verifyProperCleanup();
191     }
192 
193     @SmallTest
194     @Test
testListenerAddedAfterCallerInfoBeforePhoto()195     public void testListenerAddedAfterCallerInfoBeforePhoto() {
196         CallerInfoLookupHelper.OnQueryCompleteListener callListener = mock(
197                 CallerInfoLookupHelper.OnQueryCompleteListener.class);
198         CallerInfoLookupHelper.OnQueryCompleteListener otherListener = mock(
199                 CallerInfoLookupHelper.OnQueryCompleteListener.class);
200         mCallerInfo1.contactDisplayPhotoUri = CONTACTS_PHOTO_URI;
201 
202         mCallerInfoLookupHelper.startLookup(URI1, callListener);
203         waitForActionCompletion();
204 
205         ArgumentCaptor<CallerInfoAsyncQuery.OnQueryCompleteListener> queryListenerCaptor =
206                 ArgumentCaptor.forClass(CallerInfoAsyncQuery.OnQueryCompleteListener.class);
207         ArgumentCaptor<Session> logSessionCaptor = ArgumentCaptor.forClass(Session.class);
208         verify(mFactory, times(1)).startQuery(anyInt(), eq(mContext),
209                 eq(URI1.getSchemeSpecificPart()), queryListenerCaptor.capture(),
210                 logSessionCaptor.capture());
211 
212         queryListenerCaptor.getValue().onQueryComplete(
213                 0, logSessionCaptor.getValue(), mCallerInfo1);
214         verify(callListener, times(1)).onCallerInfoQueryComplete(URI1, mCallerInfo1);
215         waitForActionCompletion();
216 
217         ArgumentCaptor<ContactsAsyncHelper.OnImageLoadCompleteListener> imageListenerCaptor =
218                 ArgumentCaptor.forClass(ContactsAsyncHelper.OnImageLoadCompleteListener.class);
219         verify(mContactsAsyncHelper).startObtainPhotoAsync(anyInt(), eq(mContext),
220                 eq(CONTACTS_PHOTO_URI), imageListenerCaptor.capture(), logSessionCaptor.capture());
221         mCallerInfoLookupHelper.startLookup(URI1, otherListener);
222         verify(otherListener, times(1)).onCallerInfoQueryComplete(URI1, mCallerInfo1);
223 
224         imageListenerCaptor.getValue().onImageLoadComplete(0, mDrawable1, mBitmap,
225                 logSessionCaptor.getValue());
226         verify(callListener).onContactPhotoQueryComplete(URI1, mCallerInfo1);
227         verify(otherListener).onContactPhotoQueryComplete(URI1, mCallerInfo1);
228         assertEquals(mDrawable1, mCallerInfo1.cachedPhoto);
229         assertEquals(mBitmap, mCallerInfo1.cachedPhotoIcon);
230 
231         verifyProperCleanup();
232     }
233 
verifyProperCleanup()234     private void verifyProperCleanup() {
235         assertEquals(0, mCallerInfoLookupHelper.getCallerInfoEntries().size());
236     }
237 
waitForActionCompletion()238     private void waitForActionCompletion() {
239         final CountDownLatch lock = new CountDownLatch(1);
240         mCallerInfoLookupHelper.getHandler().post(lock::countDown);
241         while (lock.getCount() > 0) {
242             try {
243                 lock.await();
244             } catch (InterruptedException e) {
245                 // do nothing
246             }
247         }
248     }
249 }
250