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