Home | History | Annotate | Download | only in tests
      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 
     25 import com.android.internal.telephony.CallerInfo;
     26 import com.android.internal.telephony.CallerInfoAsyncQuery;
     27 import com.android.server.telecom.Call;
     28 import com.android.server.telecom.CallerInfoAsyncQueryFactory;
     29 import com.android.server.telecom.CallerInfoLookupHelper;
     30 import com.android.server.telecom.ContactsAsyncHelper;
     31 import com.android.server.telecom.Session;
     32 import com.android.server.telecom.TelecomSystem;
     33 
     34 import org.mockito.ArgumentCaptor;
     35 import org.mockito.Mock;
     36 
     37 import java.io.FileNotFoundException;
     38 import java.io.InputStream;
     39 import java.net.URI;
     40 import java.util.concurrent.CountDownLatch;
     41 
     42 import static org.mockito.Matchers.any;
     43 import static org.mockito.Matchers.anyInt;
     44 import static org.mockito.Matchers.anyString;
     45 import static org.mockito.Matchers.eq;
     46 import static org.mockito.Mockito.atMost;
     47 import static org.mockito.Mockito.mock;
     48 import static org.mockito.Mockito.times;
     49 import static org.mockito.Mockito.verify;
     50 import static org.mockito.Mockito.when;
     51 
     52 public 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