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