1 /* 2 * Copyright (C) 2011 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 static android.provider.VoicemailContract.Status.CONFIGURATION_STATE; 20 import static android.provider.VoicemailContract.Status.CONFIGURATION_STATE_CAN_BE_CONFIGURED; 21 import static android.provider.VoicemailContract.Status.CONFIGURATION_STATE_NOT_CONFIGURED; 22 import static android.provider.VoicemailContract.Status.DATA_CHANNEL_STATE; 23 import static android.provider.VoicemailContract.Status.DATA_CHANNEL_STATE_NO_CONNECTION; 24 import static android.provider.VoicemailContract.Status.DATA_CHANNEL_STATE_OK; 25 import static android.provider.VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE; 26 import static android.provider.VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING; 27 import static android.provider.VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_NO_CONNECTION; 28 import static android.provider.VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK; 29 30 import android.content.ContentResolver; 31 import android.content.ContentValues; 32 import android.database.Cursor; 33 import android.net.Uri; 34 import android.provider.VoicemailContract.Status; 35 import android.test.AndroidTestCase; 36 37 import com.android.dialer.R; 38 import com.android.dialer.voicemail.VoicemailStatusHelper.StatusMessage; 39 40 import java.util.List; 41 42 /** 43 * Unit tests for {@link VoicemailStatusHelperImpl}. 44 */ 45 public class VoicemailStatusHelperImplTest extends AndroidTestCase { 46 private static final String[] TEST_PACKAGES = new String[] { 47 "com.test.package1", 48 "com.test.package2" 49 }; 50 51 private static final Uri TEST_SETTINGS_URI = Uri.parse("http://www.visual.voicemail.setup"); 52 private static final Uri TEST_VOICEMAIL_URI = Uri.parse("tel:901"); 53 54 private static final int ACTION_MSG_CALL_VOICEMAIL = 55 R.string.voicemail_status_action_call_server; 56 private static final int ACTION_MSG_CONFIGURE = R.string.voicemail_status_action_configure; 57 58 private static final int STATUS_MSG_NONE = -1; 59 private static final int STATUS_MSG_VOICEMAIL_NOT_AVAILABLE = 60 R.string.voicemail_status_voicemail_not_available; 61 private static final int STATUS_MSG_AUDIO_NOT_AVAIALABLE = 62 R.string.voicemail_status_audio_not_available; 63 private static final int STATUS_MSG_MESSAGE_WAITING = R.string.voicemail_status_messages_waiting; 64 private static final int STATUS_MSG_INVITE_FOR_CONFIGURATION = 65 R.string.voicemail_status_configure_voicemail; 66 67 // Object under test. 68 private VoicemailStatusHelper mStatusHelper; 69 70 @Override 71 protected void setUp() throws Exception { 72 super.setUp(); 73 mStatusHelper = new VoicemailStatusHelperImpl(); 74 } 75 76 @Override 77 protected void tearDown() throws Exception { 78 for (String sourcePackage : TEST_PACKAGES) { 79 deleteEntryForPackage(sourcePackage); 80 } 81 // Set member variables to null so that they are garbage collected across different runs 82 // of the tests. 83 mStatusHelper = null; 84 super.tearDown(); 85 } 86 87 88 public void testNoStatusEntries() { 89 assertEquals(0, getStatusMessages().size()); 90 } 91 92 public void testAllOK() { 93 insertEntryForPackage(TEST_PACKAGES[0], getAllOkStatusValues()); 94 insertEntryForPackage(TEST_PACKAGES[1], getAllOkStatusValues()); 95 assertEquals(0, getStatusMessages().size()); 96 } 97 98 public void testNotAllOKForOnePackage() { 99 insertEntryForPackage(TEST_PACKAGES[0], getAllOkStatusValues()); 100 insertEntryForPackage(TEST_PACKAGES[1], getAllOkStatusValues()); 101 102 ContentValues values = new ContentValues(); 103 // Good data channel + no notification 104 // action: call voicemail 105 // msg: voicemail not available in call log page & none in call details page. 106 values.put(NOTIFICATION_CHANNEL_STATE, NOTIFICATION_CHANNEL_STATE_NO_CONNECTION); 107 values.put(DATA_CHANNEL_STATE, DATA_CHANNEL_STATE_OK); 108 updateEntryForPackage(TEST_PACKAGES[1], values); 109 checkExpectedMessage(TEST_PACKAGES[1], values, STATUS_MSG_VOICEMAIL_NOT_AVAILABLE, 110 STATUS_MSG_NONE, ACTION_MSG_CALL_VOICEMAIL); 111 112 // Message waiting + good data channel - no action. 113 values.put(NOTIFICATION_CHANNEL_STATE, NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING); 114 values.put(DATA_CHANNEL_STATE, DATA_CHANNEL_STATE_OK); 115 updateEntryForPackage(TEST_PACKAGES[1], values); 116 checkNoMessages(TEST_PACKAGES[1], values); 117 118 // No data channel + no notification 119 // action: call voicemail 120 // msg: voicemail not available in call log page & audio not available in call details page. 121 values.put(NOTIFICATION_CHANNEL_STATE, NOTIFICATION_CHANNEL_STATE_OK); 122 values.put(DATA_CHANNEL_STATE, DATA_CHANNEL_STATE_NO_CONNECTION); 123 updateEntryForPackage(TEST_PACKAGES[1], values); 124 checkExpectedMessage(TEST_PACKAGES[1], values, STATUS_MSG_VOICEMAIL_NOT_AVAILABLE, 125 STATUS_MSG_AUDIO_NOT_AVAIALABLE, ACTION_MSG_CALL_VOICEMAIL); 126 127 // No data channel + Notification OK 128 // action: call voicemail 129 // msg: voicemail not available in call log page & audio not available in call details page. 130 values.put(NOTIFICATION_CHANNEL_STATE, NOTIFICATION_CHANNEL_STATE_NO_CONNECTION); 131 values.put(DATA_CHANNEL_STATE, DATA_CHANNEL_STATE_NO_CONNECTION); 132 updateEntryForPackage(TEST_PACKAGES[1], values); 133 checkExpectedMessage(TEST_PACKAGES[1], values, STATUS_MSG_VOICEMAIL_NOT_AVAILABLE, 134 STATUS_MSG_AUDIO_NOT_AVAIALABLE, ACTION_MSG_CALL_VOICEMAIL); 135 136 // No data channel + Notification OK 137 // action: call voicemail 138 // msg: message waiting in call log page & audio not available in call details page. 139 values.put(NOTIFICATION_CHANNEL_STATE, NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING); 140 values.put(DATA_CHANNEL_STATE, DATA_CHANNEL_STATE_NO_CONNECTION); 141 updateEntryForPackage(TEST_PACKAGES[1], values); 142 checkExpectedMessage(TEST_PACKAGES[1], values, STATUS_MSG_MESSAGE_WAITING, 143 STATUS_MSG_AUDIO_NOT_AVAIALABLE, ACTION_MSG_CALL_VOICEMAIL); 144 145 // Not configured. No user action, so no message. 146 values.put(CONFIGURATION_STATE, CONFIGURATION_STATE_NOT_CONFIGURED); 147 updateEntryForPackage(TEST_PACKAGES[1], values); 148 checkNoMessages(TEST_PACKAGES[1], values); 149 150 // Can be configured - invite user for configure voicemail. 151 values.put(CONFIGURATION_STATE, CONFIGURATION_STATE_CAN_BE_CONFIGURED); 152 updateEntryForPackage(TEST_PACKAGES[1], values); 153 checkExpectedMessage(TEST_PACKAGES[1], values, STATUS_MSG_INVITE_FOR_CONFIGURATION, 154 STATUS_MSG_NONE, ACTION_MSG_CONFIGURE, TEST_SETTINGS_URI); 155 } 156 157 // Test that priority of messages are handled well. 158 public void testMessageOrdering() { 159 insertEntryForPackage(TEST_PACKAGES[0], getAllOkStatusValues()); 160 insertEntryForPackage(TEST_PACKAGES[1], getAllOkStatusValues()); 161 162 final ContentValues valuesNoNotificationGoodDataChannel = new ContentValues(); 163 valuesNoNotificationGoodDataChannel.put(NOTIFICATION_CHANNEL_STATE, 164 NOTIFICATION_CHANNEL_STATE_NO_CONNECTION); 165 valuesNoNotificationGoodDataChannel.put(DATA_CHANNEL_STATE, DATA_CHANNEL_STATE_OK); 166 167 final ContentValues valuesNoNotificationNoDataChannel = new ContentValues(); 168 valuesNoNotificationNoDataChannel.put(NOTIFICATION_CHANNEL_STATE, 169 NOTIFICATION_CHANNEL_STATE_NO_CONNECTION); 170 valuesNoNotificationNoDataChannel.put(DATA_CHANNEL_STATE, DATA_CHANNEL_STATE_NO_CONNECTION); 171 172 // Package1 with valuesNoNotificationGoodDataChannel and 173 // package2 with valuesNoNotificationNoDataChannel. Package2 should be above. 174 updateEntryForPackage(TEST_PACKAGES[0], valuesNoNotificationGoodDataChannel); 175 updateEntryForPackage(TEST_PACKAGES[1], valuesNoNotificationNoDataChannel); 176 List<StatusMessage> messages = getStatusMessages(); 177 assertEquals(2, messages.size()); 178 assertEquals(TEST_PACKAGES[0], messages.get(1).sourcePackage); 179 assertEquals(TEST_PACKAGES[1], messages.get(0).sourcePackage); 180 181 // Now reverse the values - ordering should be reversed as well. 182 updateEntryForPackage(TEST_PACKAGES[0], valuesNoNotificationNoDataChannel); 183 updateEntryForPackage(TEST_PACKAGES[1], valuesNoNotificationGoodDataChannel); 184 messages = getStatusMessages(); 185 assertEquals(2, messages.size()); 186 assertEquals(TEST_PACKAGES[0], messages.get(0).sourcePackage); 187 assertEquals(TEST_PACKAGES[1], messages.get(1).sourcePackage); 188 } 189 190 /** Checks that the expected source status message is returned by VoicemailStatusHelper. */ 191 private void checkExpectedMessage(String sourcePackage, ContentValues values, 192 int expectedCallLogMsg, int expectedCallDetailsMsg, int expectedActionMsg, 193 Uri expectedUri) { 194 List<StatusMessage> messages = getStatusMessages(); 195 assertEquals(1, messages.size()); 196 checkMessageMatches(messages.get(0), sourcePackage, expectedCallLogMsg, 197 expectedCallDetailsMsg, expectedActionMsg, expectedUri); 198 } 199 200 private void checkExpectedMessage(String sourcePackage, ContentValues values, 201 int expectedCallLogMsg, int expectedCallDetailsMessage, int expectedActionMsg) { 202 checkExpectedMessage(sourcePackage, values, expectedCallLogMsg, expectedCallDetailsMessage, 203 expectedActionMsg, TEST_VOICEMAIL_URI); 204 } 205 206 private void checkMessageMatches(StatusMessage message, String expectedSourcePackage, 207 int expectedCallLogMsg, int expectedCallDetailsMsg, int expectedActionMsg, 208 Uri expectedUri) { 209 assertEquals(expectedSourcePackage, message.sourcePackage); 210 assertEquals(expectedCallLogMsg, message.callLogMessageId); 211 assertEquals(expectedCallDetailsMsg, message.callDetailsMessageId); 212 assertEquals(expectedActionMsg, message.actionMessageId); 213 if (expectedUri == null) { 214 assertNull(message.actionUri); 215 } else { 216 assertEquals(expectedUri, message.actionUri); 217 } 218 } 219 220 private void checkNoMessages(String sourcePackage, ContentValues values) { 221 assertEquals(1, updateEntryForPackage(sourcePackage, values)); 222 List<StatusMessage> messages = getStatusMessages(); 223 assertEquals(0, messages.size()); 224 } 225 226 private ContentValues getAllOkStatusValues() { 227 ContentValues values = new ContentValues(); 228 values.put(Status.SETTINGS_URI, TEST_SETTINGS_URI.toString()); 229 values.put(Status.VOICEMAIL_ACCESS_URI, TEST_VOICEMAIL_URI.toString()); 230 values.put(Status.CONFIGURATION_STATE, Status.CONFIGURATION_STATE_OK); 231 values.put(Status.DATA_CHANNEL_STATE, Status.DATA_CHANNEL_STATE_OK); 232 values.put(Status.NOTIFICATION_CHANNEL_STATE, Status.NOTIFICATION_CHANNEL_STATE_OK); 233 return values; 234 } 235 236 private void insertEntryForPackage(String sourcePackage, ContentValues values) { 237 // If insertion fails then try update as the record might already exist. 238 if (getContentResolver().insert(Status.buildSourceUri(sourcePackage), values) == null) { 239 updateEntryForPackage(sourcePackage, values); 240 } 241 } 242 243 private void deleteEntryForPackage(String sourcePackage) { 244 getContentResolver().delete(Status.buildSourceUri(sourcePackage), null, null); 245 } 246 247 private int updateEntryForPackage(String sourcePackage, ContentValues values) { 248 return getContentResolver().update( 249 Status.buildSourceUri(sourcePackage), values, null, null); 250 } 251 252 private List<StatusMessage> getStatusMessages() { 253 // Restrict the cursor to only the the test packages to eliminate any side effects if there 254 // are other status messages already stored on the device. 255 Cursor cursor = getContentResolver().query(Status.CONTENT_URI, 256 VoicemailStatusHelperImpl.PROJECTION, getTestPackageSelection(), null, null); 257 return mStatusHelper.getStatusMessages(cursor); 258 } 259 260 private String getTestPackageSelection() { 261 StringBuilder sb = new StringBuilder(); 262 for (String sourcePackage : TEST_PACKAGES) { 263 if (sb.length() > 0) { 264 sb.append(" OR "); 265 } 266 sb.append(String.format("(source_package='%s')", sourcePackage)); 267 } 268 return sb.toString(); 269 } 270 271 private ContentResolver getContentResolver() { 272 return getContext().getContentResolver(); 273 } 274 } 275