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 android.telephony.cts; 18 19 import android.bluetooth.BluetoothAdapter; 20 import android.content.Context; 21 import android.content.pm.PackageManager; 22 import android.cts.util.TestThread; 23 import android.net.ConnectivityManager; 24 import android.net.wifi.WifiInfo; 25 import android.net.wifi.WifiManager; 26 import android.os.Build; 27 import android.os.Looper; 28 import android.telecom.PhoneAccount; 29 import android.telecom.PhoneAccountHandle; 30 import android.telecom.TelecomManager; 31 import android.telephony.CellLocation; 32 import android.telephony.PhoneStateListener; 33 import android.telephony.TelephonyManager; 34 import android.test.AndroidTestCase; 35 import android.util.Log; 36 37 import com.android.internal.telephony.PhoneConstants; 38 39 import java.util.regex.Pattern; 40 41 public class TelephonyManagerTest extends AndroidTestCase { 42 private TelephonyManager mTelephonyManager; 43 private boolean mOnCellLocationChangedCalled = false; 44 private final Object mLock = new Object(); 45 private static final int TOLERANCE = 1000; 46 private PhoneStateListener mListener; 47 private static ConnectivityManager mCm; 48 private static final String TAG = "android.telephony.cts.TelephonyManagerTest"; 49 50 @Override setUp()51 protected void setUp() throws Exception { 52 super.setUp(); 53 mTelephonyManager = 54 (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE); 55 mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE); 56 } 57 58 @Override tearDown()59 protected void tearDown() throws Exception { 60 if (mListener != null) { 61 // unregister the listener 62 mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE); 63 } 64 super.tearDown(); 65 } 66 testListen()67 public void testListen() throws Throwable { 68 if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) { 69 Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE"); 70 return; 71 } 72 73 if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) { 74 // TODO: temp workaround, need to adjust test to for CDMA 75 return; 76 } 77 78 // Test register 79 TestThread t = new TestThread(new Runnable() { 80 public void run() { 81 Looper.prepare(); 82 83 mListener = new PhoneStateListener() { 84 @Override 85 public void onCellLocationChanged(CellLocation location) { 86 if(!mOnCellLocationChangedCalled) { 87 synchronized (mLock) { 88 mOnCellLocationChangedCalled = true; 89 mLock.notify(); 90 } 91 } 92 } 93 }; 94 mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_CELL_LOCATION); 95 CellLocation.requestLocationUpdate(); 96 Looper.loop(); 97 } 98 }); 99 t.start(); 100 synchronized (mLock) { 101 mLock.wait(TOLERANCE); 102 } 103 assertTrue(mOnCellLocationChangedCalled); 104 105 // Test unregister 106 t = new TestThread(new Runnable() { 107 public void run() { 108 Looper.prepare(); 109 // unregister the listener 110 mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE); 111 mOnCellLocationChangedCalled = false; 112 // unregister again, to make sure doing so does not call the listener 113 mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE); 114 CellLocation.requestLocationUpdate(); 115 Looper.loop(); 116 } 117 }); 118 119 t.start(); 120 synchronized (mLock) { 121 mLock.wait(TOLERANCE); 122 } 123 assertFalse(mOnCellLocationChangedCalled); 124 } 125 126 /** 127 * The getter methods here are all related to the information about the telephony. 128 * These getters are related to concrete location, phone, service provider company, so 129 * it's no need to get details of these information, just make sure they are in right 130 * condition(>0 or not null). 131 */ testTelephonyManager()132 public void testTelephonyManager() { 133 assertTrue(mTelephonyManager.getNetworkType() >= TelephonyManager.NETWORK_TYPE_UNKNOWN); 134 assertTrue(mTelephonyManager.getPhoneType() >= TelephonyManager.PHONE_TYPE_NONE); 135 assertTrue(mTelephonyManager.getSimState() >= TelephonyManager.SIM_STATE_UNKNOWN); 136 assertTrue(mTelephonyManager.getDataActivity() >= TelephonyManager.DATA_ACTIVITY_NONE); 137 assertTrue(mTelephonyManager.getDataState() >= TelephonyManager.DATA_DISCONNECTED); 138 assertTrue(mTelephonyManager.getCallState() >= TelephonyManager.CALL_STATE_IDLE); 139 140 // Make sure devices without MMS service won't fail on this 141 if (mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE) { 142 assertFalse(mTelephonyManager.getMmsUserAgent().isEmpty()); 143 assertFalse(mTelephonyManager.getMmsUAProfUrl().isEmpty()); 144 } 145 146 // The following methods may return null. Simply call them to make sure they do not 147 // throw any exceptions. 148 mTelephonyManager.getVoiceMailNumber(); 149 mTelephonyManager.getSimOperatorName(); 150 mTelephonyManager.getNetworkCountryIso(); 151 mTelephonyManager.getCellLocation(); 152 mTelephonyManager.getSimSerialNumber(); 153 mTelephonyManager.getSimOperator(); 154 mTelephonyManager.getNetworkOperatorName(); 155 mTelephonyManager.getSubscriberId(); 156 mTelephonyManager.getLine1Number(); 157 mTelephonyManager.getNetworkOperator(); 158 mTelephonyManager.getSimCountryIso(); 159 mTelephonyManager.getVoiceMailAlphaTag(); 160 mTelephonyManager.getNeighboringCellInfo(); 161 mTelephonyManager.isNetworkRoaming(); 162 mTelephonyManager.getDeviceId(); 163 mTelephonyManager.getDeviceId(mTelephonyManager.getDefaultSim()); 164 mTelephonyManager.getDeviceSoftwareVersion(); 165 mTelephonyManager.getPhoneCount(); 166 167 TelecomManager telecomManager = (TelecomManager) getContext() 168 .getSystemService(Context.TELECOM_SERVICE); 169 PhoneAccountHandle defaultAccount = telecomManager 170 .getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL); 171 mTelephonyManager.getVoicemailRingtoneUri(defaultAccount); 172 mTelephonyManager.isVoicemailVibrationEnabled(defaultAccount); 173 } 174 175 /** 176 * Tests that the phone count returned is valid. 177 */ testGetPhoneCount()178 public void testGetPhoneCount() { 179 int phoneCount = mTelephonyManager.getPhoneCount(); 180 int phoneType = mTelephonyManager.getPhoneType(); 181 switch (phoneType) { 182 case TelephonyManager.PHONE_TYPE_GSM: 183 case TelephonyManager.PHONE_TYPE_CDMA: 184 assertTrue("Phone count should be > 0", phoneCount > 0); 185 break; 186 case TelephonyManager.PHONE_TYPE_NONE: 187 assertTrue("Phone count should be 0", phoneCount == 0 || phoneCount == 1); 188 break; 189 default: 190 throw new IllegalArgumentException("Did you add a new phone type? " + phoneType); 191 } 192 } 193 194 /** 195 * Tests that the device properly reports either a valid IMEI if 196 * GSM, a valid MEID or ESN if CDMA, or a valid MAC address if 197 * only a WiFi device. 198 */ testGetDeviceId()199 public void testGetDeviceId() { 200 String deviceId = mTelephonyManager.getDeviceId(); 201 verifyDeviceId(deviceId); 202 } 203 204 /** 205 * Tests that the device properly reports either a valid IMEI if 206 * GSM, a valid MEID or ESN if CDMA, or a valid MAC address if 207 * only a WiFi device. 208 */ testGetDeviceIdForSlotId()209 public void testGetDeviceIdForSlotId() { 210 String deviceId = mTelephonyManager.getDeviceId(mTelephonyManager.getDefaultSim()); 211 verifyDeviceId(deviceId); 212 // Also verify that no exception is thrown for any slot id (including invalid ones) 213 for (int i = -1; i <= mTelephonyManager.getPhoneCount(); i++) { 214 mTelephonyManager.getDeviceId(i); 215 } 216 } 217 verifyDeviceId(String deviceId)218 private void verifyDeviceId(String deviceId) { 219 int phoneType = mTelephonyManager.getPhoneType(); 220 switch (phoneType) { 221 case TelephonyManager.PHONE_TYPE_GSM: 222 assertGsmDeviceId(deviceId); 223 break; 224 225 case TelephonyManager.PHONE_TYPE_CDMA: 226 // LTE device is using IMEI as device id 227 if (mTelephonyManager.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE) { 228 assertGsmDeviceId(deviceId); 229 } else { 230 assertCdmaDeviceId(deviceId); 231 } 232 break; 233 234 case TelephonyManager.PHONE_TYPE_NONE: 235 boolean nwSupported = mCm.isNetworkSupported(mCm.TYPE_WIFI); 236 PackageManager packageManager = getContext().getPackageManager(); 237 // only check serial number & MAC address if device report wifi feature 238 if (packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) { 239 assertSerialNumber(); 240 assertMacAddress(getWifiMacAddress()); 241 } else if (mCm.getNetworkInfo(ConnectivityManager.TYPE_BLUETOOTH) != null) { 242 assertSerialNumber(); 243 assertMacAddress(getBluetoothMacAddress()); 244 } else { 245 assertTrue(mCm.getNetworkInfo(ConnectivityManager.TYPE_ETHERNET) != null); 246 } 247 break; 248 249 default: 250 throw new IllegalArgumentException("Did you add a new phone type? " + phoneType); 251 } 252 } 253 assertGsmDeviceId(String deviceId)254 private static void assertGsmDeviceId(String deviceId) { 255 // IMEI may include the check digit 256 String imeiPattern = "[0-9]{14,15}"; 257 assertTrue("IMEI device id " + deviceId + " does not match pattern " + imeiPattern, 258 Pattern.matches(imeiPattern, deviceId)); 259 if (deviceId.length() == 15) { 260 // if the ID is 15 digits, the 15th must be a check digit. 261 assertImeiCheckDigit(deviceId); 262 } 263 } 264 assertImeiCheckDigit(String deviceId)265 private static void assertImeiCheckDigit(String deviceId) { 266 int expectedCheckDigit = getLuhnCheckDigit(deviceId.substring(0, 14)); 267 int actualCheckDigit = Character.digit(deviceId.charAt(14), 10); 268 assertEquals("Incorrect check digit for " + deviceId, expectedCheckDigit, actualCheckDigit); 269 } 270 271 /** 272 * Use decimal value (0-9) to index into array to get sum of its digits 273 * needed by Lunh check. 274 * 275 * Example: DOUBLE_DIGIT_SUM[6] = 3 because 6 * 2 = 12 => 1 + 2 = 3 276 */ 277 private static final int[] DOUBLE_DIGIT_SUM = {0, 2, 4, 6, 8, 1, 3, 5, 7, 9}; 278 279 /** 280 * Calculate the check digit by starting from the right, doubling every 281 * each digit, summing all the digits including the doubled ones, and 282 * finding a number to make the sum divisible by 10. 283 * 284 * @param deviceId not including the check digit 285 * @return the check digit 286 */ getLuhnCheckDigit(String deviceId)287 private static int getLuhnCheckDigit(String deviceId) { 288 int sum = 0; 289 int dontDoubleModulus = deviceId.length() % 2; 290 for (int i = deviceId.length() - 1; i >= 0; --i) { 291 int digit = Character.digit(deviceId.charAt(i), 10); 292 if (i % 2 == dontDoubleModulus) { 293 sum += digit; 294 } else { 295 sum += DOUBLE_DIGIT_SUM[digit]; 296 } 297 } 298 sum %= 10; 299 return sum == 0 ? 0 : 10 - sum; 300 } 301 assertCdmaDeviceId(String deviceId)302 private static void assertCdmaDeviceId(String deviceId) { 303 // CDMA device IDs may either be a 14-hex-digit MEID or an 304 // 8-hex-digit ESN. If it's an ESN, it may not be a 305 // pseudo-ESN. 306 if (deviceId.length() == 14) { 307 assertMeidFormat(deviceId); 308 } else if (deviceId.length() == 8) { 309 assertHexadecimalEsnFormat(deviceId); 310 } else { 311 fail("device id on CDMA must be 14-digit hex MEID or 8-digit hex ESN."); 312 } 313 } 314 assertHexadecimalEsnFormat(String deviceId)315 private static void assertHexadecimalEsnFormat(String deviceId) { 316 String esnPattern = "[0-9a-fA-F]{8}"; 317 assertTrue("ESN hex device id " + deviceId + " does not match pattern " + esnPattern, 318 Pattern.matches(esnPattern, deviceId)); 319 assertFalse("ESN hex device id " + deviceId + " must not be a pseudo-ESN", 320 "80".equals(deviceId.substring(0, 2))); 321 } 322 assertMeidFormat(String deviceId)323 private static void assertMeidFormat(String deviceId) { 324 // MEID must NOT include the check digit. 325 String meidPattern = "[0-9a-fA-F]{14}"; 326 assertTrue("MEID device id " + deviceId + " does not match pattern " + meidPattern, 327 Pattern.matches(meidPattern, deviceId)); 328 } 329 assertSerialNumber()330 private void assertSerialNumber() { 331 assertNotNull("Non-telephony devices must have a Build.SERIAL number.", 332 Build.SERIAL); 333 assertTrue("Hardware id must be no longer than 20 characters.", 334 Build.SERIAL.length() <= 20); 335 assertTrue("Hardware id must be alphanumeric.", 336 Pattern.matches("[0-9A-Za-z]+", Build.SERIAL)); 337 } 338 assertMacAddress(String macAddress)339 private void assertMacAddress(String macAddress) { 340 String macPattern = "([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}"; 341 assertTrue("MAC Address " + macAddress + " does not match pattern " + macPattern, 342 Pattern.matches(macPattern, macAddress)); 343 } 344 345 /** @return mac address which requires the WiFi system to be enabled */ getWifiMacAddress()346 private String getWifiMacAddress() { 347 WifiManager wifiManager = (WifiManager) getContext() 348 .getSystemService(Context.WIFI_SERVICE); 349 350 boolean enabled = wifiManager.isWifiEnabled(); 351 352 try { 353 if (!enabled) { 354 wifiManager.setWifiEnabled(true); 355 } 356 357 WifiInfo wifiInfo = wifiManager.getConnectionInfo(); 358 return wifiInfo.getMacAddress(); 359 360 } finally { 361 if (!enabled) { 362 wifiManager.setWifiEnabled(false); 363 } 364 } 365 } 366 getBluetoothMacAddress()367 private String getBluetoothMacAddress() { 368 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 369 if (adapter == null) { 370 return ""; 371 } 372 373 return adapter.getAddress(); 374 } 375 376 private static final String ISO_COUNTRY_CODE_PATTERN = "[a-z]{2}"; 377 testGetNetworkCountryIso()378 public void testGetNetworkCountryIso() { 379 PackageManager packageManager = getContext().getPackageManager(); 380 String countryCode = mTelephonyManager.getNetworkCountryIso(); 381 if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) { 382 assertTrue("Country code '" + countryCode + "' did not match " 383 + ISO_COUNTRY_CODE_PATTERN, 384 Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode)); 385 } else { 386 // Non-telephony may still have the property defined if it has a SIM. 387 } 388 } 389 testGetSimCountryIso()390 public void testGetSimCountryIso() { 391 PackageManager packageManager = getContext().getPackageManager(); 392 String countryCode = mTelephonyManager.getSimCountryIso(); 393 if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) { 394 assertTrue("Country code '" + countryCode + "' did not match " 395 + ISO_COUNTRY_CODE_PATTERN, 396 Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode)); 397 } else { 398 // Non-telephony may still have the property defined if it has a SIM. 399 } 400 } 401 } 402