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