blob: 6c13007eaf7cbb7c7d5f63e1fae1bbb96df36b66 [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.cts;
import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetClass;
import dalvik.annotation.TestTargetNew;
import dalvik.annotation.TestTargets;
import android.content.ContentResolver;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Looper;
import android.os.cts.TestThread;
import android.provider.Settings;
import android.telephony.CellLocation;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.test.AndroidTestCase;
import java.util.regex.Pattern;
@TestTargetClass(TelephonyManager.class)
public class TelephonyManagerTest extends AndroidTestCase {
private TelephonyManager mTelephonyManager;
private boolean mOnCellLocationChangedCalled = false;
private final Object mLock = new Object();
private static final int TOLERANCE = 1000;
private Looper mLooper;
private PhoneStateListener mListener;
@Override
protected void setUp() throws Exception {
super.setUp();
mTelephonyManager =
(TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE);
}
@Override
protected void tearDown() throws Exception {
if (mListener != null) {
// unregister the listener
mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
}
super.tearDown();
}
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "listen",
args = {PhoneStateListener.class, int.class}
)
public void testListen() throws Throwable {
if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
// TODO: temp workaround, need to adjust test to for CDMA
return;
}
// Test register
TestThread t = new TestThread(new Runnable() {
public void run() {
Looper.prepare();
mLooper = Looper.myLooper();
mListener = new PhoneStateListener() {
@Override
public void onCellLocationChanged(CellLocation location) {
synchronized (mLock) {
mOnCellLocationChangedCalled = true;
mLock.notify();
}
}
};
mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_CELL_LOCATION);
Looper.loop();
}
});
t.start();
CellLocation.requestLocationUpdate();
synchronized (mLock) {
while (!mOnCellLocationChangedCalled) {
mLock.wait();
}
}
mLooper.quit();
assertTrue(mOnCellLocationChangedCalled);
// Test unregister
t = new TestThread(new Runnable() {
public void run() {
Looper.prepare();
mLooper = Looper.myLooper();
// unregister the listener
mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
mOnCellLocationChangedCalled = false;
// unregister again, to make sure doing so does not call the listener
mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
Looper.loop();
}
});
t.start();
CellLocation.requestLocationUpdate();
synchronized (mLock) {
mLock.wait(TOLERANCE);
}
mLooper.quit();
assertFalse(mOnCellLocationChangedCalled);
}
/**
* The getter methods here are all related to the information about the telephony.
* These getters are related to concrete location, phone, service provider company, so
* it's no need to get details of these information, just make sure they are in right
* condition(>0 or not null).
*/
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getNetworkType",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getPhoneType",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getVoiceMailNumber",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getSimOperatorName",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getNetworkCountryIso",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getCellLocation",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getDeviceSoftwareVersion",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getSimState",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getSimSerialNumber",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getDeviceId",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getSimOperator",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getNetworkOperatorName",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getSubscriberId",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getLine1Number",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getNetworkOperator",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getSimCountryIso",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getDataActivity",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getDataState",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getCallState",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "isNetworkRoaming",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getVoiceMailAlphaTag",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getNeighboringCellInfo",
args = {}
)
})
public void testTelephonyManager() {
assertTrue(mTelephonyManager.getNetworkType() >= TelephonyManager.NETWORK_TYPE_UNKNOWN);
assertTrue(mTelephonyManager.getPhoneType() >= TelephonyManager.PHONE_TYPE_NONE);
assertTrue(mTelephonyManager.getSimState() >= TelephonyManager.SIM_STATE_UNKNOWN);
assertTrue(mTelephonyManager.getDataActivity() >= TelephonyManager.DATA_ACTIVITY_NONE);
assertTrue(mTelephonyManager.getDataState() >= TelephonyManager.DATA_DISCONNECTED);
assertTrue(mTelephonyManager.getCallState() >= TelephonyManager.CALL_STATE_IDLE);
// The following methods may return null. Simply call them to make sure they do not
// throw any exceptions.
mTelephonyManager.getVoiceMailNumber();
mTelephonyManager.getSimOperatorName();
mTelephonyManager.getNetworkCountryIso();
mTelephonyManager.getCellLocation();
mTelephonyManager.getSimSerialNumber();
mTelephonyManager.getSimOperator();
mTelephonyManager.getNetworkOperatorName();
mTelephonyManager.getSubscriberId();
mTelephonyManager.getLine1Number();
mTelephonyManager.getNetworkOperator();
mTelephonyManager.getSimCountryIso();
mTelephonyManager.getVoiceMailAlphaTag();
mTelephonyManager.getNeighboringCellInfo();
mTelephonyManager.isNetworkRoaming();
mTelephonyManager.getDeviceId();
mTelephonyManager.getDeviceSoftwareVersion();
}
/**
* Tests that the device properly reports either a valid IMEI if
* GSM, a valid MEID or ESN if CDMA, or a valid MAC address if
* only a WiFi device.
*/
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getDeviceId",
args = {}
)
public void testGetDeviceId() {
String deviceId = mTelephonyManager.getDeviceId();
int phoneType = mTelephonyManager.getPhoneType();
switch (phoneType) {
case TelephonyManager.PHONE_TYPE_GSM:
assertImeiDeviceId(deviceId);
break;
case TelephonyManager.PHONE_TYPE_CDMA:
assertCdmaDeviceId(deviceId);
break;
case TelephonyManager.PHONE_TYPE_NONE:
assertNull(deviceId);
assertHardwareId();
assertMacAddressReported();
break;
default:
throw new IllegalArgumentException("Did you add a new phone type? " + phoneType);
}
}
private static void assertImeiDeviceId(String deviceId) {
assertImeiFormat(deviceId);
assertImeiCheckDigit(deviceId);
assertReportingBodyIdentifier(deviceId, true); // Must be decimal identifier
}
private static void assertImeiFormat(String deviceId) {
// IMEI must include the check digit
String imeiPattern = "[0-9]{15}";
assertTrue("IMEI device id " + deviceId + " does not match pattern " + imeiPattern,
Pattern.matches(imeiPattern, deviceId));
}
private static void assertImeiCheckDigit(String deviceId) {
int expectedCheckDigit = getLuhnCheckDigit(deviceId.substring(0, 14));
int actualCheckDigit = Character.digit(deviceId.charAt(14), 10);
assertEquals("Incorrect check digit for " + deviceId, expectedCheckDigit, actualCheckDigit);
}
/**
* Use decimal value (0-9) to index into array to get sum of its digits
* needed by Lunh check.
*
* Example: DOUBLE_DIGIT_SUM[6] = 3 because 6 * 2 = 12 => 1 + 2 = 3
*/
private static final int[] DOUBLE_DIGIT_SUM = {0, 2, 4, 6, 8, 1, 3, 5, 7, 9};
/**
* Calculate the check digit by starting from the right, doubling every
* each digit, summing all the digits including the doubled ones, and
* finding a number to make the sum divisible by 10.
*
* @param deviceId not including the check digit
* @return the check digit
*/
private static int getLuhnCheckDigit(String deviceId) {
int sum = 0;
int dontDoubleModulus = deviceId.length() % 2;
for (int i = deviceId.length() - 1; i >= 0; --i) {
int digit = Character.digit(deviceId.charAt(i), 10);
if (i % 2 == dontDoubleModulus) {
sum += digit;
} else {
sum += DOUBLE_DIGIT_SUM[digit];
}
}
sum %= 10;
return sum == 0 ? 0 : 10 - sum;
}
private static void assertReportingBodyIdentifier(String deviceId, boolean decimalIdentifier) {
// Check the reporting body identifier
int reportingBodyIdentifier = Integer.parseInt(deviceId.substring(0, 2), 16);
int decimalBound = 0xA0;
String message = String.format("%s RR %x not %s than %x",
decimalIdentifier ? "IMEI" : "MEID",
reportingBodyIdentifier,
decimalIdentifier ? "<" : ">=",
decimalBound);
assertEquals(message, decimalIdentifier, reportingBodyIdentifier < decimalBound);
}
private static void assertCdmaDeviceId(String deviceId) {
if (deviceId.length() == 14) {
assertMeidFormat(deviceId);
} else if (deviceId.length() == 8) {
assertHexadecimalEsnFormat(deviceId);
} else {
fail("device id on CDMA must be 14-digit hex MEID or 8-digit hex ESN.");
}
}
private static void assertHexadecimalEsnFormat(String deviceId) {
String esnPattern = "[0-9a-fA-F]{8}";
assertTrue("ESN hex device id " + deviceId + " does not match pattern " + esnPattern,
Pattern.matches(esnPattern, deviceId));
assertFalse("ESN hex device id " + deviceId + " must not be a pseudo-ESN",
"80".equals(deviceId.substring(0, 2)));
}
private static void assertMeidFormat(String deviceId) {
if (deviceId.substring(0, 2).matches("99|98|97")) {
// MEID must NOT include the check digit.
String meidPattern = "(99|98|97)[0-9]{12}";
assertTrue("MEID device id " + deviceId + " does not match pattern " + meidPattern,
Pattern.matches(meidPattern, deviceId));
} else {
// MEID must NOT include the check digit.
String meidPattern = "[0-9a-fA-F]{14}";
assertTrue("MEID device id " + deviceId + " does not match pattern " + meidPattern,
Pattern.matches(meidPattern, deviceId));
assertReportingBodyIdentifier(deviceId, false);
}
}
private void assertHardwareId() {
ContentResolver resolver = mContext.getContentResolver();
String hardwareId = Settings.Secure.getString(resolver, "hardware_id");
assertNotNull("Non-telephony devices must define a Settings.Secure 'hardware_id' property.",
hardwareId);
assertTrue("Hardware id must be no longer than 20 characters.",
hardwareId.length() <= 20);
assertTrue("Hardware id must be alphanumeric.",
Pattern.matches("[0-9A-Za-z]+", hardwareId));
}
private void assertMacAddressReported() {
String macAddress = getMacAddress();
String macPattern = "([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}";
assertTrue("MAC Address " + macAddress + " does not match pattern " + macPattern,
Pattern.matches(macPattern, macAddress));
}
/** @return mac address which requires the WiFi system to be enabled */
private String getMacAddress() {
WifiManager wifiManager = (WifiManager) getContext()
.getSystemService(Context.WIFI_SERVICE);
boolean enabled = wifiManager.isWifiEnabled();
try {
if (!enabled) {
wifiManager.setWifiEnabled(true);
}
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
return wifiInfo.getMacAddress();
} finally {
if (!enabled) {
wifiManager.setWifiEnabled(false);
}
}
}
private static final String ISO_COUNTRY_CODE_PATTERN = "[a-z]{2}";
public void testGetNetworkCountryIso() {
String countryCode = mTelephonyManager.getNetworkCountryIso();
assertTrue("Country code '" + countryCode + "' did not match " + ISO_COUNTRY_CODE_PATTERN,
Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode));
}
public void testGetSimCountryIso() {
String countryCode = mTelephonyManager.getSimCountryIso();
assertTrue("Country code '" + countryCode + "' did not match " + ISO_COUNTRY_CODE_PATTERN,
Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode));
}
}