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.dialer.voicemail; 18 19 import android.content.ContentUris; 20 import android.content.ContentValues; 21 import android.content.res.AssetFileDescriptor; 22 import android.net.Uri; 23 import android.os.Bundle; 24 import android.os.ParcelFileDescriptor; 25 import android.provider.CallLog; 26 import android.provider.VoicemailContract; 27 import android.test.InstrumentationTestCase; 28 import android.test.mock.MockContentResolver; 29 30 import com.android.contacts.common.test.mocks.MockContentProvider; 31 import com.android.contacts.common.test.mocks.MockContentProvider.Query; 32 import com.android.dialer.calllog.CallLogQuery; 33 import com.android.dialer.database.VoicemailArchiveContract; 34 import com.android.dialer.util.AsyncTaskExecutors; 35 import com.android.dialer.util.FakeAsyncTaskExecutor; 36 import com.android.dialer.voicemail.VoicemailAsyncTaskUtil.OnGetArchivedVoicemailFilePathListener; 37 import com.android.dialer.voicemail.VoicemailAsyncTaskUtil.OnArchiveVoicemailListener; 38 import com.android.dialer.voicemail.VoicemailAsyncTaskUtil.OnSetVoicemailArchiveStatusListener; 39 40 import org.junit.Rule; 41 import org.junit.rules.TemporaryFolder; 42 import static org.mockito.Mockito.*; 43 44 import java.io.FileNotFoundException; 45 import java.io.IOException; 46 47 public class VoicemailAsyncTaskUtilTest extends InstrumentationTestCase { 48 private static final String TEST_MIME_TYPE = "audio/mp3"; 49 private static final String TEST_NUMBER = "+1412555555"; 50 private static final String TEST_FILE_PATH = "TEST_PATH"; 51 private static final String TEST_TRANSCRIPTION = "TEST_TRANSCRIPTION"; 52 private static final long TEST_DATE = 0; 53 private static final long TEST_DURATION = 0; 54 private static final int TEST_SERVER_ID = 1; 55 private static final int TEST_ID = 2; 56 private static final Uri ARCHIVED_VOICEMAIL_URI = 57 VoicemailArchiveContract.VoicemailArchive.buildWithId(TEST_ID); 58 private static final Uri VOICEMAIL_URI = VoicemailContract.Voicemails.CONTENT_URI 59 .buildUpon().appendPath(Integer.toString(TEST_SERVER_ID)).build(); 60 private static final String[] CALLLOG_QUERY_PROJECTION = new String[] { 61 CallLog.Calls._ID, 62 CallLog.Calls.NUMBER, 63 CallLog.Calls.DATE, 64 CallLog.Calls.DURATION, 65 CallLog.Calls.TYPE, 66 CallLog.Calls.COUNTRY_ISO, 67 CallLog.Calls.VOICEMAIL_URI, 68 CallLog.Calls.GEOCODED_LOCATION, 69 CallLog.Calls.CACHED_NAME, 70 CallLog.Calls.CACHED_NUMBER_TYPE, 71 CallLog.Calls.CACHED_NUMBER_LABEL, 72 CallLog.Calls.CACHED_LOOKUP_URI, 73 CallLog.Calls.CACHED_MATCHED_NUMBER, 74 CallLog.Calls.CACHED_NORMALIZED_NUMBER, 75 CallLog.Calls.CACHED_PHOTO_ID, 76 CallLog.Calls.CACHED_FORMATTED_NUMBER, 77 CallLog.Calls.IS_READ, 78 CallLog.Calls.NUMBER_PRESENTATION, 79 CallLog.Calls.PHONE_ACCOUNT_COMPONENT_NAME, 80 CallLog.Calls.PHONE_ACCOUNT_ID, 81 CallLog.Calls.FEATURES, 82 CallLog.Calls.DATA_USAGE, 83 CallLog.Calls.TRANSCRIPTION, 84 CallLog.Calls.CACHED_PHOTO_URI 85 }; 86 private static final String[] VOICEMAIL_PROJECTION = new String[] { 87 VoicemailContract.Voicemails._ID, 88 VoicemailContract.Voicemails.NUMBER, 89 VoicemailContract.Voicemails.DATE, 90 VoicemailContract.Voicemails.DURATION, 91 VoicemailContract.Voicemails.MIME_TYPE, 92 VoicemailContract.Voicemails.TRANSCRIPTION, 93 }; 94 95 private final MockContentResolver mContentResolver = new MockContentResolver(); 96 private final MockContentProvider mArchiveContentProvider = new TestVoicemailContentProvider(); 97 private final MockContentProvider mVoicemailContentProvider = 98 new TestVoicemailContentProvider(); 99 private final MockContentProvider mCallLogContentProvider = new MockContentProvider(); 100 @Rule 101 private final TemporaryFolder mTemporaryFolder = new TemporaryFolder(); 102 103 private VoicemailAsyncTaskUtil mVoicemailAsyncTaskUtil; 104 private FakeAsyncTaskExecutor mFakeAsyncTaskExecutor; 105 106 @Override 107 protected void setUp() throws Exception { 108 super.setUp(); 109 mFakeAsyncTaskExecutor = new FakeAsyncTaskExecutor(getInstrumentation()); 110 AsyncTaskExecutors.setFactoryForTest(mFakeAsyncTaskExecutor.getFactory()); 111 mContentResolver.addProvider(VoicemailArchiveContract.AUTHORITY, mArchiveContentProvider); 112 mContentResolver.addProvider(VoicemailContract.AUTHORITY, mVoicemailContentProvider); 113 mContentResolver.addProvider(CallLog.AUTHORITY, mCallLogContentProvider); 114 mVoicemailAsyncTaskUtil = new VoicemailAsyncTaskUtil(mContentResolver); 115 } 116 117 @Override 118 protected void tearDown() throws Exception { 119 AsyncTaskExecutors.setFactoryForTest(null); 120 super.tearDown(); 121 } 122 123 public void testGetVoicemailFilePath_VoicemailExists() throws Throwable { 124 newVoicemailArchiveQuery().withAnyProjection() 125 .returnRow(getCombinedContentValuesWithData()); 126 final OnGetArchivedVoicemailFilePathListener listener = 127 mock(OnGetArchivedVoicemailFilePathListener.class); 128 runTestOnUiThread(new Runnable() { 129 @Override 130 public void run() { 131 mVoicemailAsyncTaskUtil.getVoicemailFilePath(listener, ARCHIVED_VOICEMAIL_URI); 132 } 133 }); 134 mFakeAsyncTaskExecutor.runTask(VoicemailAsyncTaskUtil.Tasks.GET_VOICEMAIL_FILE_PATH); 135 verify(listener).onGetArchivedVoicemailFilePath(TEST_FILE_PATH); 136 verifyQueries(); 137 } 138 139 public void testGetVoicemailFilePath_VoicemailNotExists() throws Throwable { 140 newVoicemailArchiveFakeQuery().withAnyProjection().returnEmptyCursor(); 141 final OnGetArchivedVoicemailFilePathListener listener = 142 mock(OnGetArchivedVoicemailFilePathListener.class); 143 runTestOnUiThread(new Runnable() { 144 @Override 145 public void run() { 146 mVoicemailAsyncTaskUtil.getVoicemailFilePath(listener, getFakeVoicemailUri()); 147 } 148 }); 149 mFakeAsyncTaskExecutor.runTask(VoicemailAsyncTaskUtil.Tasks.GET_VOICEMAIL_FILE_PATH); 150 verify(listener).onGetArchivedVoicemailFilePath(null); 151 verifyQueries(); 152 } 153 154 public void testSetVoicemailArchiveStatus_VoicemailNotExists() throws Throwable { 155 newVoicemailArchiveNotExistsUpdateQuery(true); 156 final OnSetVoicemailArchiveStatusListener listener = 157 mock(OnSetVoicemailArchiveStatusListener.class); 158 runTestOnUiThread(new Runnable() { 159 @Override 160 public void run() { 161 mVoicemailAsyncTaskUtil.setVoicemailArchiveStatus(listener, 162 getFakeVoicemailUri(), true); 163 } 164 }); 165 mFakeAsyncTaskExecutor.runTask(VoicemailAsyncTaskUtil.Tasks.SET_VOICEMAIL_ARCHIVE_STATUS); 166 verify(listener).onSetVoicemailArchiveStatus(false); 167 verifyQueries(); 168 } 169 170 public void testSetVoicemailArchiveStatus_VoicemailExists() throws Throwable { 171 newVoicemailArchiveExistsUpdateQuery(true); 172 final OnSetVoicemailArchiveStatusListener listener = 173 mock(OnSetVoicemailArchiveStatusListener.class); 174 runTestOnUiThread(new Runnable() { 175 @Override 176 public void run() { 177 mVoicemailAsyncTaskUtil.setVoicemailArchiveStatus(listener, 178 ARCHIVED_VOICEMAIL_URI, true); 179 } 180 }); 181 mFakeAsyncTaskExecutor.runTask(VoicemailAsyncTaskUtil.Tasks.SET_VOICEMAIL_ARCHIVE_STATUS); 182 verify(listener).onSetVoicemailArchiveStatus(true); 183 verifyQueries(); 184 } 185 186 public void testArchiveVoicemailContent_ArchiveNotExists() throws Throwable { 187 newVoicemailArchiveExistsQuery().returnEmptyCursor(); 188 newQueryCallLogInfo().returnRow(getCallLogContentValues()); 189 newVoicemailQuery().returnRow(getVoicemailContentValues()); 190 newVoicemailArchiveInsert(); 191 final OnArchiveVoicemailListener listener = mock(OnArchiveVoicemailListener.class); 192 runTestOnUiThread(new Runnable() { 193 @Override 194 public void run() { 195 mVoicemailAsyncTaskUtil.archiveVoicemailContent(listener, VOICEMAIL_URI); 196 } 197 }); 198 mFakeAsyncTaskExecutor.runTask(VoicemailAsyncTaskUtil.Tasks.ARCHIVE_VOICEMAIL_CONTENT); 199 verify(listener).onArchiveVoicemail(ARCHIVED_VOICEMAIL_URI); 200 verifyQueries(); 201 } 202 203 public void testArchiveVoicemailContent_ArchiveExists() throws Throwable { 204 newVoicemailArchiveExistsQuery().returnRow(getCombinedValuesWithId()); 205 final OnArchiveVoicemailListener listener = mock(OnArchiveVoicemailListener.class); 206 runTestOnUiThread(new Runnable() { 207 @Override 208 public void run() { 209 mVoicemailAsyncTaskUtil.archiveVoicemailContent(listener, VOICEMAIL_URI); 210 } 211 }); 212 mFakeAsyncTaskExecutor.runTask(VoicemailAsyncTaskUtil.Tasks.ARCHIVE_VOICEMAIL_CONTENT); 213 verify(listener).onArchiveVoicemail(ARCHIVED_VOICEMAIL_URI); 214 verifyQueries(); 215 } 216 217 public void testArchiveVoicemailContent_CallLogInfoNotExists() throws Throwable { 218 newVoicemailArchiveExistsQuery().returnEmptyCursor(); 219 newQueryCallLogInfo().returnEmptyCursor(); 220 newVoicemailQuery().returnEmptyCursor(); 221 final OnArchiveVoicemailListener listener = mock(OnArchiveVoicemailListener.class); 222 runTestOnUiThread(new Runnable() { 223 @Override 224 public void run() { 225 mVoicemailAsyncTaskUtil.archiveVoicemailContent(listener, VOICEMAIL_URI); 226 } 227 }); 228 mFakeAsyncTaskExecutor.runTask(VoicemailAsyncTaskUtil.Tasks.ARCHIVE_VOICEMAIL_CONTENT); 229 verify(listener).onArchiveVoicemail(null); 230 verifyQueries(); 231 } 232 233 private Query newVoicemailArchiveQuery() { 234 return mArchiveContentProvider.expectQuery(ARCHIVED_VOICEMAIL_URI); 235 } 236 237 private Query newVoicemailArchiveFakeQuery() { 238 return mArchiveContentProvider.expectQuery(getFakeVoicemailUri()); 239 } 240 241 private Query newQueryCallLogInfo() { 242 return mCallLogContentProvider.expectQuery(ContentUris.withAppendedId( 243 CallLog.Calls.CONTENT_URI_WITH_VOICEMAIL, ContentUris.parseId(VOICEMAIL_URI))) 244 .withProjection(CALLLOG_QUERY_PROJECTION); 245 } 246 247 private Query newVoicemailQuery() { 248 return mVoicemailContentProvider.expectQuery(VOICEMAIL_URI).withAnySelection() 249 .withProjection(VOICEMAIL_PROJECTION); 250 } 251 252 private Query newVoicemailArchiveExistsQuery() { 253 return mArchiveContentProvider.expectQuery( 254 VoicemailArchiveContract.VoicemailArchive.CONTENT_URI) 255 .withSelection(VoicemailArchiveContract.VoicemailArchive.SERVER_ID + "=" 256 + ContentUris.parseId(VOICEMAIL_URI), (String[]) null) 257 .withProjection(VoicemailArchiveContract.VoicemailArchive._ID); 258 } 259 260 private void newVoicemailArchiveInsert() { 261 mArchiveContentProvider.expectInsert( 262 VoicemailArchiveContract.VoicemailArchive.CONTENT_URI, getCombinedContentValues(), 263 ARCHIVED_VOICEMAIL_URI); 264 } 265 266 private void newVoicemailArchiveNotExistsUpdateQuery(boolean status) { 267 mArchiveContentProvider.expectUpdate(getFakeVoicemailUri(), 268 getArchiveStatusUpdateValues(status), null, null).returnRowsAffected(0); 269 } 270 271 private void newVoicemailArchiveExistsUpdateQuery(boolean status) { 272 mArchiveContentProvider.expectUpdate(ARCHIVED_VOICEMAIL_URI, 273 getArchiveStatusUpdateValues(status), null, null).returnRowsAffected(1); 274 } 275 276 private static ContentValues getCallLogContentValues() { 277 ContentValues values = new ContentValues(); 278 values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.GEOCODED_LOCATION], ""); 279 values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.CACHED_NAME], ""); 280 values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.COUNTRY_ISO], ""); 281 values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.CACHED_NUMBER_TYPE], 0); 282 values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.CACHED_NUMBER_LABEL], ""); 283 values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.CACHED_LOOKUP_URI], ""); 284 values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.CACHED_MATCHED_NUMBER], ""); 285 values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.CACHED_NORMALIZED_NUMBER], ""); 286 values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.CACHED_FORMATTED_NUMBER], ""); 287 values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.NUMBER_PRESENTATION], 0); 288 values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.ACCOUNT_COMPONENT_NAME], ""); 289 values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.ACCOUNT_ID], ""); 290 values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.FEATURES], 0); 291 values.put(CALLLOG_QUERY_PROJECTION[23], ""); 292 return values; 293 } 294 295 private static ContentValues getVoicemailContentValues() { 296 ContentValues values = new ContentValues(); 297 values.put(VoicemailContract.Voicemails.NUMBER, TEST_NUMBER); 298 values.put(VoicemailContract.Voicemails.DATE, TEST_DATE); 299 values.put(VoicemailContract.Voicemails.DURATION, TEST_DURATION); 300 values.put(VoicemailContract.Voicemails.MIME_TYPE, TEST_MIME_TYPE); 301 values.put(VoicemailContract.Voicemails._ID, TEST_SERVER_ID); 302 values.put(VoicemailContract.Voicemails.TRANSCRIPTION, TEST_TRANSCRIPTION); 303 values.put("_data", TEST_FILE_PATH); // VoicemailContract.Voicemails._DATA 304 return values; 305 } 306 307 private static ContentValues getCombinedContentValues() { 308 ContentValues values = new ContentValues(); 309 // Call log info 310 values.put(VoicemailArchiveContract.VoicemailArchive.GEOCODED_LOCATION, ""); 311 values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NAME, ""); 312 values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NUMBER_TYPE, 0); 313 values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NUMBER_LABEL, ""); 314 values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_LOOKUP_URI, ""); 315 values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_MATCHED_NUMBER, ""); 316 values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NORMALIZED_NUMBER, ""); 317 values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_FORMATTED_NUMBER, ""); 318 values.put(VoicemailArchiveContract.VoicemailArchive.NUMBER_PRESENTATION, 0); 319 values.put(VoicemailArchiveContract.VoicemailArchive.ACCOUNT_COMPONENT_NAME, ""); 320 values.put(VoicemailArchiveContract.VoicemailArchive.ACCOUNT_ID, ""); 321 values.put(VoicemailArchiveContract.VoicemailArchive.FEATURES, 0); 322 values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_PHOTO_URI, ""); 323 values.put(VoicemailArchiveContract.VoicemailArchive.COUNTRY_ISO, ""); 324 325 // Voicemail content info 326 values.put(VoicemailArchiveContract.VoicemailArchive.NUMBER, TEST_NUMBER); 327 values.put(VoicemailArchiveContract.VoicemailArchive.DATE, TEST_DATE); 328 values.put(VoicemailArchiveContract.VoicemailArchive.DURATION, TEST_DURATION); 329 values.put(VoicemailArchiveContract.VoicemailArchive.MIME_TYPE, TEST_MIME_TYPE); 330 values.put(VoicemailArchiveContract.VoicemailArchive.SERVER_ID, TEST_SERVER_ID); 331 values.put(VoicemailArchiveContract.VoicemailArchive.TRANSCRIPTION, TEST_TRANSCRIPTION); 332 333 // Custom fields 334 values.put(VoicemailArchiveContract.VoicemailArchive.ARCHIVED, false); 335 return values; 336 } 337 338 private static ContentValues getCombinedContentValuesWithData() { 339 ContentValues values = getCombinedContentValues(); 340 values.put(VoicemailArchiveContract.VoicemailArchive._DATA, TEST_FILE_PATH); 341 return values; 342 } 343 344 private static ContentValues getCombinedValuesWithId() { 345 ContentValues values = getCombinedContentValuesWithData(); 346 values.put(VoicemailArchiveContract.VoicemailArchive._ID, TEST_ID); 347 return values; 348 } 349 350 private static ContentValues getArchiveStatusUpdateValues(boolean status) { 351 ContentValues values = new ContentValues(); 352 values.put(VoicemailArchiveContract.VoicemailArchive.ARCHIVED, status); 353 return values; 354 } 355 356 private static Uri getFakeVoicemailUri() { 357 return VoicemailArchiveContract.VoicemailArchive.buildWithId(0); 358 } 359 360 private void verifyQueries() { 361 mArchiveContentProvider.verify(); 362 mCallLogContentProvider.verify(); 363 mVoicemailContentProvider.verify(); 364 } 365 366 private class TestVoicemailContentProvider extends MockContentProvider { 367 @Override 368 public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { 369 int modeBits = ParcelFileDescriptor.parseMode(mode); 370 try { 371 return ParcelFileDescriptor.open(mTemporaryFolder.newFile(), modeBits); 372 } catch (IOException e) { 373 return null; 374 } 375 } 376 377 @Override 378 public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts) { 379 try { 380 return new AssetFileDescriptor(openFile(uri, "r"), 0, 381 AssetFileDescriptor.UNKNOWN_LENGTH); 382 } catch (FileNotFoundException e) { 383 return null; 384 } 385 } 386 } 387 } 388 389