1/* 2 * Copyright (C) 2015 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.dialer.voicemail; 18 19import static com.android.dialer.voicemail.VoicemailPlaybackPresenter.Tasks.CHECK_FOR_CONTENT; 20 21import android.app.Activity; 22import android.content.ContentResolver; 23import android.content.ContentUris; 24import android.content.ContentValues; 25import android.content.Context; 26import android.content.res.AssetManager; 27import android.net.Uri; 28import android.provider.VoicemailContract; 29import android.test.ActivityInstrumentationTestCase2; 30import android.test.suitebuilder.annotation.LargeTest; 31import android.view.View; 32import android.widget.TextView; 33 34import com.android.contacts.common.test.IntegrationTestUtils; 35import com.android.dialer.R; 36import com.android.dialer.calllog.CallLogActivity; 37import com.android.dialer.util.AsyncTaskExecutors; 38import com.android.dialer.util.FakeAsyncTaskExecutor; 39import com.android.dialer.util.LocaleTestUtils; 40import com.android.dialer.voicemail.VoicemailPlaybackLayout; 41import com.android.dialer.voicemail.VoicemailPlaybackPresenter; 42 43import java.io.IOException; 44import java.io.InputStream; 45import java.io.OutputStream; 46import java.util.List; 47import java.util.Locale; 48 49/** 50 * Unit tests for the {@link VoicemailPlaybackPresenter} and {@link VoicemailPlaybackLayout}. 51 */ 52@LargeTest 53public class VoicemailPlaybackTest extends ActivityInstrumentationTestCase2<CallLogActivity> { 54 private static final String TEST_ASSET_NAME = "quick_test_recording.mp3"; 55 private static final String MIME_TYPE = "audio/mp3"; 56 private static final String CONTACT_NUMBER = "+1412555555"; 57 private static final String VOICEMAIL_FILE_LOCATION = "/sdcard/sadlfj893w4j23o9sfu.mp3"; 58 59 private Activity mActivity; 60 private VoicemailPlaybackPresenter mPresenter; 61 private VoicemailPlaybackLayout mLayout; 62 63 private Uri mVoicemailUri; 64 private IntegrationTestUtils mTestUtils; 65 private LocaleTestUtils mLocaleTestUtils; 66 private FakeAsyncTaskExecutor mFakeAsyncTaskExecutor; 67 68 public VoicemailPlaybackTest() { 69 super(CallLogActivity.class); 70 } 71 72 @Override 73 public void setUp() throws Exception { 74 super.setUp(); 75 76 mFakeAsyncTaskExecutor = new FakeAsyncTaskExecutor(getInstrumentation()); 77 AsyncTaskExecutors.setFactoryForTest(mFakeAsyncTaskExecutor.getFactory()); 78 mTestUtils = new IntegrationTestUtils(getInstrumentation()); 79 80 // Some of the tests rely on the text - safest to force a specific locale. 81 mLocaleTestUtils = new LocaleTestUtils(getInstrumentation().getTargetContext()); 82 mLocaleTestUtils.setLocale(Locale.US); 83 84 mActivity = getActivity(); 85 mLayout = new VoicemailPlaybackLayout(mActivity); 86 mLayout.onFinishInflate(); 87 88 mPresenter = VoicemailPlaybackPresenter.getInstance(mActivity, null); 89 } 90 91 @Override 92 protected void tearDown() throws Exception { 93 cleanUpVoicemailUri(); 94 95 mLocaleTestUtils.restoreLocale(); 96 mLocaleTestUtils = null; 97 98 mLayout = null; 99 mPresenter = null; 100 mTestUtils = null; 101 AsyncTaskExecutors.setFactoryForTest(null); 102 103 super.tearDown(); 104 } 105 106 public void testFetchingVoicemail() throws Throwable { 107 setUriForRealFileVoicemailEntry(); 108 setPlaybackViewForPresenter(); 109 assertHasOneTextViewContaining("Loading voicemail"); 110 } 111 112 public void testWhenCheckForContentCompletes() throws Throwable { 113 setUriForRealFileVoicemailEntry(); 114 setPlaybackViewForPresenter(); 115 116 // There is a background check that is testing to see if we have the content available. 117 // Once that task completes, we shouldn't be showing the fetching message. 118 mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT); 119 getInstrumentation().waitForIdleSync(); 120 121 assertHasOneTextViewContaining("Buffering"); 122 assertHasZeroTextViewsContaining("Loading voicemail"); 123 } 124 125 public void testInvalidVoicemailShowsErrorMessage() throws Throwable { 126 setUriForInvalidVoicemailEntry(); 127 setPlaybackViewForPresenter(); 128 129 mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT); 130 getInstrumentation().waitForIdleSync(); 131 132 // The media player will have thrown an IOException since the file doesn't exist. 133 // This should have put a failed to play message on screen, buffering is gone. 134 assertHasOneTextViewContaining("Couldn't play voicemail"); 135 assertHasZeroTextViewsContaining("Buffering"); 136 } 137 138 public void testClickingSpeakerphoneButton() throws Throwable { 139 setUriForRealFileVoicemailEntry(); 140 setPlaybackViewForPresenter(); 141 142 // Wait for check for content to complete. 143 mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT); 144 getInstrumentation().waitForIdleSync(); 145 146 // Force the speakerphone to false to start. 147 mPresenter.setSpeakerphoneOn(false); 148 assertFalse(mPresenter.isSpeakerphoneOn()); 149 150 View speakerphoneButton = mLayout.findViewById(R.id.playback_speakerphone); 151 speakerphoneButton.performClick(); 152 assertTrue(mPresenter.isSpeakerphoneOn()); 153 } 154 155 private void cleanUpVoicemailUri() { 156 if (mVoicemailUri != null) { 157 getContentResolver().delete(VoicemailContract.Voicemails.CONTENT_URI, 158 "_ID = ?", new String[] { String.valueOf(ContentUris.parseId(mVoicemailUri)) }); 159 mVoicemailUri = null; 160 } 161 } 162 163 private void setUriForRealFileVoicemailEntry() throws IOException { 164 assertNull(mVoicemailUri); 165 ContentValues values = new ContentValues(); 166 values.put(VoicemailContract.Voicemails.DATE, String.valueOf(System.currentTimeMillis())); 167 values.put(VoicemailContract.Voicemails.NUMBER, CONTACT_NUMBER); 168 values.put(VoicemailContract.Voicemails.MIME_TYPE, MIME_TYPE); 169 values.put(VoicemailContract.Voicemails.HAS_CONTENT, 1); 170 String packageName = getInstrumentation().getTargetContext().getPackageName(); 171 mVoicemailUri = getContentResolver().insert( 172 VoicemailContract.Voicemails.buildSourceUri(packageName), values); 173 AssetManager assets = getAssets(); 174 try (InputStream inputStream = assets.open(TEST_ASSET_NAME); 175 OutputStream outputStream = getContentResolver().openOutputStream(mVoicemailUri)) { 176 copyBetweenStreams(inputStream, outputStream); 177 } 178 } 179 180 private void setUriForInvalidVoicemailEntry() { 181 assertNull(mVoicemailUri); 182 ContentResolver contentResolver = getContentResolver(); 183 ContentValues values = new ContentValues(); 184 values.put(VoicemailContract.Voicemails.NUMBER, CONTACT_NUMBER); 185 values.put(VoicemailContract.Voicemails.HAS_CONTENT, 1); 186 values.put(VoicemailContract.Voicemails._DATA, VOICEMAIL_FILE_LOCATION); 187 mVoicemailUri = contentResolver.insert(VoicemailContract.Voicemails.CONTENT_URI, values); 188 } 189 190 private void setPlaybackViewForPresenter() { 191 getInstrumentation().runOnMainSync(new Runnable() { 192 @Override 193 public void run() { 194 mPresenter.setPlaybackView(mLayout, mVoicemailUri, false); 195 } 196 }); 197 } 198 199 public void copyBetweenStreams(InputStream in, OutputStream out) throws IOException { 200 byte[] buffer = new byte[1024]; 201 int bytesRead; 202 while ((bytesRead = in.read(buffer)) > 0) { 203 out.write(buffer, 0, bytesRead); 204 } 205 } 206 207 private void assertHasOneTextViewContaining(String text) throws Throwable { 208 assertNotNull(mLayout); 209 List<TextView> views = mTestUtils.getTextViewsWithString(mLayout, text); 210 assertEquals("There should have been one TextView with text '" + text + "' but found " 211 + views, 1, views.size()); 212 } 213 214 private void assertHasZeroTextViewsContaining(String text) throws Throwable { 215 assertNotNull(mLayout); 216 List<TextView> views = mTestUtils.getTextViewsWithString(mLayout, text); 217 assertEquals("There should have been no TextViews with text '" + text + "' but found " 218 + views, 0, views.size()); 219 } 220 221 private ContentResolver getContentResolver() { 222 return getInstrumentation().getTargetContext().getContentResolver(); 223 } 224 225 private AssetManager getAssets() { 226 return getInstrumentation().getContext().getAssets(); 227 } 228} 229