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