1/* 2 * Copyright (C) 2009 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.internal.telephony; 18 19import android.test.AndroidTestCase; 20import android.test.suitebuilder.annotation.SmallTest; 21 22import android.content.ContentResolver; 23import android.content.Context; 24import android.content.res.Resources; 25import com.android.internal.telephony.CallerInfo; 26import com.android.internal.telephony.CallerInfoAsyncQuery; 27import android.util.Log; 28import android.os.Looper; 29import android.test.ActivityInstrumentationTestCase; 30import android.util.StringBuilderPrinter; 31 32/* 33 * Check the CallerInfo utility class works as expected. 34 * 35 */ 36 37public class CallerInfoTest extends AndroidTestCase { 38 private CallerInfo mInfo; 39 private Context mContext; 40 41 private static final String kEmergencyNumber = "Emergency Number"; 42 private static final int kToken = 0xdeadbeef; 43 private static final String TAG = "CallerInfoUnitTest"; 44 45 @Override 46 protected void setUp() throws Exception { 47 super.setUp(); 48 mContext = new MockContext(); 49 mInfo = new CallerInfo(); 50 } 51 52 @Override 53 protected void tearDown() throws Exception { 54 super.tearDown(); 55 } 56 57 /** 58 * Checks the caller info instance is flagged as an emergency if 59 * the number is an emergency one. There is no test for the 60 * contact based constructors because emergency number are not in 61 * the contact DB. 62 */ 63 @SmallTest 64 public void testEmergencyIsProperlySet() throws Exception { 65 assertFalse(mInfo.isEmergencyNumber()); 66 67 mInfo = CallerInfo.getCallerInfo(mContext, "911"); 68 assertIsValidEmergencyCallerInfo(); 69 70 mInfo = CallerInfo.getCallerInfo(mContext, "tel:911"); 71 assertIsValidEmergencyCallerInfo(); 72 73 74 // This one hits the content resolver. 75 mInfo = CallerInfo.getCallerInfo(mContext, "18001234567"); 76 assertFalse(mInfo.isEmergencyNumber()); 77 } 78 79 /** 80 * Same as testEmergencyIsProperlySet but uses the async query api. 81 */ 82 @SmallTest 83 public void testEmergencyIsProperlySetUsingAsyncQuery() throws Exception { 84 QueryRunner query; 85 86 query = new QueryRunner("911"); 87 query.runAndCheckCompletion(); 88 assertIsValidEmergencyCallerInfo(); 89 90 query = new QueryRunner("tel:911"); 91 query.runAndCheckCompletion(); 92 assertIsValidEmergencyCallerInfo(); 93 94 query = new QueryRunner("18001234567"); 95 query.runAndCheckCompletion(); 96 assertFalse(mInfo.isEmergencyNumber()); 97 } 98 99 /** 100 * For emergency caller info, phoneNumber should be set to the 101 * string emergency_call_dialog_number_for_display and the 102 * photoResource should be set to the picture_emergency drawable. 103 */ 104 @SmallTest 105 public void testEmergencyNumberAndPhotoAreSet() throws Exception { 106 mInfo = CallerInfo.getCallerInfo(mContext, "911"); 107 108 assertIsValidEmergencyCallerInfo(); 109 } 110 111 // TODO: Add more tests: 112 /** 113 * Check if the voice mail number cannot be retrieved that the 114 * original phone number is preserved. 115 */ 116 /** 117 * Check the markAs* methods work. 118 */ 119 120 121 // 122 // Helpers 123 // 124 125 // Partial implementation of MockResources. 126 public class MockResources extends android.test.mock.MockResources 127 { 128 @Override 129 public String getString(int resId) throws Resources.NotFoundException { 130 switch (resId) { 131 case com.android.internal.R.string.emergency_call_dialog_number_for_display: 132 return kEmergencyNumber; 133 default: 134 throw new UnsupportedOperationException("Missing handling for resid " + resId); 135 } 136 } 137 } 138 139 // Partial implementation of MockContext. 140 public class MockContext extends android.test.mock.MockContext { 141 private ContentResolver mResolver; 142 private Resources mResources; 143 144 public MockContext() { 145 mResolver = new android.test.mock.MockContentResolver(); 146 mResources = new MockResources(); 147 } 148 149 @Override 150 public ContentResolver getContentResolver() { 151 return mResolver; 152 } 153 154 @Override 155 public Resources getResources() { 156 return mResources; 157 } 158 } 159 160 /** 161 * Class to run a CallerInfoAsyncQuery in a separate thread, with 162 * its own Looper. We cannot use the main Looper because on the 163 * 1st quit the thread is maked dead, ie no further test can use 164 * it. Also there is not way to inject a Looper instance in the 165 * query, so we have to use a thread with its own looper. 166 */ 167 private class QueryRunner extends Thread 168 implements CallerInfoAsyncQuery.OnQueryCompleteListener { 169 private Looper mLooper; 170 private String mNumber; 171 private boolean mAsyncCompleted; 172 173 public QueryRunner(String number) { 174 super(); 175 mNumber = number; 176 } 177 178 // Run the query in the thread, wait for completion. 179 public void runAndCheckCompletion() throws InterruptedException { 180 start(); 181 join(); 182 assertTrue(mAsyncCompleted); 183 } 184 185 @Override 186 public void run() { 187 Looper.prepare(); 188 mLooper = Looper.myLooper(); 189 mAsyncCompleted = false; 190 // The query will pick the thread local looper we've just prepared. 191 CallerInfoAsyncQuery.startQuery(kToken, mContext, mNumber, this, null); 192 mLooper.loop(); 193 } 194 195 // Quit the Looper on the 1st callback 196 // (EVENT_EMERGENCY_NUMBER). There is another message 197 // (EVENT_END_OF_QUEUE) that will never be delivered because 198 // the test has exited. The corresponding stack trace 199 // "Handler{xxxxx} sending message to a Handler on a dead 200 // thread" can be ignored. 201 public void onQueryComplete(int token, Object cookie, CallerInfo info) { 202 mAsyncCompleted = true; 203 mInfo = info; 204 mLooper.quit(); 205 } 206 } 207 208 /** 209 * Fail if mInfo does not contain a valid emergency CallerInfo instance. 210 */ 211 private void assertIsValidEmergencyCallerInfo() throws Exception { 212 assertTrue(mInfo.isEmergencyNumber()); 213 214 // For emergency caller info, phoneNumber should be set to the 215 // string emergency_call_dialog_number_for_display and the 216 // photoResource should be set to the picture_emergency drawable. 217 assertEquals(kEmergencyNumber, mInfo.phoneNumber); 218 assertEquals(com.android.internal.R.drawable.picture_emergency, mInfo.photoResource); 219 220 // The name should be null 221 assertNull(mInfo.name); 222 assertEquals(0, mInfo.namePresentation); 223 assertNull(mInfo.cnapName); 224 assertEquals(0, mInfo.numberPresentation); 225 226 assertFalse(mInfo.contactExists); 227 assertEquals(0, mInfo.person_id); 228 assertFalse(mInfo.needUpdate); 229 assertNull(mInfo.contactRefUri); 230 231 assertNull(mInfo.phoneLabel); 232 assertEquals(0, mInfo.numberType); 233 assertNull(mInfo.numberLabel); 234 235 assertNull(mInfo.contactRingtoneUri); 236 assertFalse(mInfo.shouldSendToVoicemail); 237 238 assertNull(mInfo.cachedPhoto); 239 assertFalse(mInfo.isCachedPhotoCurrent); 240 } 241} 242