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