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 package android.telephony.cts;
17 
18 import static androidx.test.InstrumentationRegistry.getContext;
19 
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.assertTrue;
24 
25 import android.content.ContentResolver;
26 import android.content.ContentValues;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.net.Uri;
30 import android.os.RemoteException;
31 import android.provider.Contacts;
32 import android.provider.Contacts.People;
33 import android.telephony.PhoneNumberUtils;
34 import android.telephony.SubscriptionManager;
35 import android.telephony.TelephonyManager;
36 import android.text.Editable;
37 import android.text.Spannable;
38 import android.text.SpannableString;
39 import android.text.SpannableStringBuilder;
40 import android.text.style.TtsSpan;
41 
42 import org.junit.After;
43 import org.junit.Before;
44 import org.junit.Test;
45 
46 import java.util.Locale;
47 
48 public class PhoneNumberUtilsTest {
49     private static final int MIN_MATCH = 7;
50 
51     // mPhoneNumber ~ "+17005550020", length == 7.
52     private byte[] mPhoneNumber = { (byte) 0x91, (byte) 0x71, (byte) 0x00, (byte) 0x55,
53             (byte) 0x05, (byte) 0x20, (byte) 0xF0 };
54 
55     private int mOldMinMatch;
56 
57     @Before
setUp()58     public void setUp() throws Exception {
59         mOldMinMatch = PhoneNumberUtils.getMinMatchForTest();
60         PhoneNumberUtils.setMinMatchForTest(MIN_MATCH);
61     }
62 
63     @After
tearDown()64     public void tearDown() throws Exception {
65         PhoneNumberUtils.setMinMatchForTest(mOldMinMatch);
66     }
67 
68     @Test
testExtractMethods()69     public void testExtractMethods() {
70 
71         // Test extractNetworkPortion
72         assertNull(PhoneNumberUtils.extractNetworkPortion(null));
73         assertEquals("+17005554141", PhoneNumberUtils.extractNetworkPortion("+17005554141"));
74         assertEquals("+17005554141*#N",
75                 PhoneNumberUtils.extractNetworkPortion("+1 (700).555-4141*#N"));
76         assertEquals("170055541", PhoneNumberUtils.extractNetworkPortion(
77                 String.format("1 (700).555-41%c1234", PhoneNumberUtils.PAUSE)));
78         assertEquals("**21**17005554141#",
79                 PhoneNumberUtils.extractNetworkPortion("**21**+17005554141#"));
80 
81         // Test extractPostDialPortion
82         assertNull(PhoneNumberUtils.extractPostDialPortion(null));
83         assertEquals("", PhoneNumberUtils.extractPostDialPortion("+17005554141"));
84         assertEquals(String.format("%c1234", PhoneNumberUtils.PAUSE),
85                 PhoneNumberUtils.extractPostDialPortion(
86                 String.format("+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE)));
87         assertEquals(String.format("%c1234", PhoneNumberUtils.WAIT),
88                 PhoneNumberUtils.extractPostDialPortion(
89                 String.format("+1 (700).555-41NN%c1234", PhoneNumberUtils.WAIT)));
90         assertEquals(String.format("%c1234%c%cN", PhoneNumberUtils.WAIT, PhoneNumberUtils.PAUSE,
91                 PhoneNumberUtils.WAIT), PhoneNumberUtils
92                 .extractPostDialPortion(
93                         String.format("+1 (700).555-41NN%c1-2.34 %c%cN", PhoneNumberUtils.WAIT,
94                                 PhoneNumberUtils.PAUSE,
95                                 PhoneNumberUtils.WAIT)));
96         assertEquals("example", PhoneNumberUtils.getUsernameFromUriNumber("example@example.com"));
97     }
98 
99     @Test
testCallMethods()100     public void testCallMethods() {
101         // Test calledPartyBCDToString
102         assertEquals("+17005550020", PhoneNumberUtils.calledPartyBCDToString(mPhoneNumber, 0, 7));
103 
104         // Test toCallerIDMinMatch
105         assertNull(PhoneNumberUtils.toCallerIDMinMatch(null));
106 //        assertEquals("1414555", PhoneNumberUtils.toCallerIDMinMatch("17005554141"));
107 //        assertEquals("1414555", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-4141"));
108 //        assertEquals("1414555", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-4141,1234"));
109 //        assertEquals("1414555", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-4141;1234"));
110 //        assertEquals("NN14555", PhoneNumberUtils.toCallerIDMinMatch("1-700-555-41NN"));
111         assertEquals("", PhoneNumberUtils.toCallerIDMinMatch(""));
112         assertEquals("0032", PhoneNumberUtils.toCallerIDMinMatch("2300"));
113         assertEquals("0032+", PhoneNumberUtils.toCallerIDMinMatch("+2300"));
114         assertEquals("#130#*", PhoneNumberUtils.toCallerIDMinMatch("*#031#"));
115 
116         // Test networkPortionToCalledPartyBCD, calledPartyBCDToString
117         byte[] bRet = PhoneNumberUtils.networkPortionToCalledPartyBCD("+17005550020");
118         assertEquals(mPhoneNumber.length, bRet.length);
119         for (int i = 0; i < mPhoneNumber.length; i++) {
120             assertEquals(mPhoneNumber[i], bRet[i]);
121         }
122         bRet = PhoneNumberUtils.networkPortionToCalledPartyBCD("7005550020");
123         assertEquals("7005550020", PhoneNumberUtils.calledPartyBCDToString(bRet, 0, bRet.length));
124 
125         // Test calledPartyBCDFragmentToString
126         assertEquals("1917005550020", PhoneNumberUtils.calledPartyBCDFragmentToString(mPhoneNumber,
127                 0, 7));
128 
129         // Test networkPortionToCalledPartyBCDWithLength
130         bRet = PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength("+17005550020");
131         assertEquals(mPhoneNumber.length + 1, bRet.length);
132         for (int i = 0; i < mPhoneNumber.length; i++) {
133             assertEquals(mPhoneNumber[i], bRet[i + 1]);
134         }
135 
136         // Test numberToCalledPartyBCD
137         bRet = PhoneNumberUtils.numberToCalledPartyBCD("+17005550020");
138         assertEquals(mPhoneNumber.length, bRet.length);
139         for (int i = 0; i < mPhoneNumber.length; i++) {
140             assertEquals(mPhoneNumber[i], bRet[i]);
141         }
142     }
143 
144     @Test
testGetMethods()145     public void testGetMethods() throws RemoteException {
146         // Test getStrippedReversed
147         assertNull(PhoneNumberUtils.getStrippedReversed(null));
148         assertEquals("14145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-4141"));
149         assertEquals("14145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-4141,1234"));
150         assertEquals("14145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-4141;1234"));
151         assertEquals("NN145550071", PhoneNumberUtils.getStrippedReversed("1-700-555-41NN"));
152         assertEquals("", PhoneNumberUtils.getStrippedReversed(""));
153         assertEquals("#130#*+", PhoneNumberUtils.getStrippedReversed("+*#031#"));
154 
155         // Test getFormatTypeForLocale
156         int formatType = PhoneNumberUtils.getFormatTypeForLocale(Locale.CHINA);
157         assertEquals(PhoneNumberUtils.FORMAT_UNKNOWN, formatType);
158         formatType = PhoneNumberUtils.getFormatTypeForLocale(Locale.US);
159         assertEquals(PhoneNumberUtils.FORMAT_NANP, formatType);
160         formatType = PhoneNumberUtils.getFormatTypeForLocale(Locale.JAPAN);
161         assertEquals(PhoneNumberUtils.FORMAT_JAPAN, formatType);
162 
163         // Test getNumberFromIntent, query nothing, return null.
164         Intent intent = new Intent();
165         intent.setData(Contacts.People.CONTENT_URI);
166         Context context = getContext();
167         assertNull(PhoneNumberUtils.getNumberFromIntent(intent, context));
168 
169         intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:+18005555555"));
170         assertEquals("+18005555555", PhoneNumberUtils.getNumberFromIntent(intent, getContext()));
171 
172         ContentResolver cr = getContext().getContentResolver();
173         Uri personRecord = null;
174         Uri phoneRecord = null;
175         try {
176             // insert a contact with phone number
177             ContentValues values = new ContentValues();
178             values.put(People.NAME, "CTS test contact");
179             personRecord = cr.insert(People.CONTENT_URI, values);
180             Uri phoneUri = Uri.withAppendedPath(personRecord, People.Phones.CONTENT_DIRECTORY);
181             values.clear();
182             values.put(People.Phones.TYPE, People.Phones.TYPE_HOME);
183             values.put(People.Phones.NUMBER, "+18005552871");
184             phoneRecord = cr.insert(phoneUri, values);
185 
186             intent = new Intent(Intent.ACTION_DIAL, phoneRecord);
187             assertEquals("+18005552871",
188                     PhoneNumberUtils.getNumberFromIntent(intent, getContext()));
189         } finally {
190             if (personRecord != null) {
191                 cr.delete(personRecord, null, null);
192             }
193             if (phoneRecord != null) {
194                 cr.delete(phoneRecord, null, null);
195             }
196         }
197     }
198 
199     @Test
testFormatMethods()200     public void testFormatMethods() {
201         // Test formatNanpNumber
202         SpannableStringBuilder builderNumber = new SpannableStringBuilder();
203         builderNumber.append("8005551212");
204         PhoneNumberUtils.formatNanpNumber(builderNumber);
205         assertEquals("800-555-1212", builderNumber.toString());
206         builderNumber.clear();
207         builderNumber.append("800555121");
208         PhoneNumberUtils.formatNanpNumber(builderNumber);
209         assertEquals("800-555-121", builderNumber.toString());
210         builderNumber.clear();
211         builderNumber.append("555-1212");
212         PhoneNumberUtils.formatNanpNumber(builderNumber);
213         assertEquals("555-1212", builderNumber.toString());
214         builderNumber.clear();
215         builderNumber.append("180055512");
216         PhoneNumberUtils.formatNanpNumber(builderNumber);
217         assertEquals("1-800-555-12", builderNumber.toString());
218         builderNumber.clear();
219         builderNumber.append("+180055512");
220         PhoneNumberUtils.formatNanpNumber(builderNumber);
221         assertEquals("+1-800-555-12", builderNumber.toString());
222 
223         // Test convertKeypadLettersToDigits
224         assertEquals("1-800-4664-411", PhoneNumberUtils
225                 .convertKeypadLettersToDigits("1-800-GOOG-411"));
226         assertEquals("1-800-466-4411", PhoneNumberUtils
227                 .convertKeypadLettersToDigits("1-800-466-4411"));
228         assertEquals("222-333-444-555-666-7777-888-9999", PhoneNumberUtils
229                 .convertKeypadLettersToDigits("ABC-DEF-GHI-JKL-MNO-PQRS-TUV-WXYZ"));
230         assertEquals("222-333-444-555-666-7777-888-9999", PhoneNumberUtils
231                 .convertKeypadLettersToDigits("abc-def-ghi-jkl-mno-pqrs-tuv-wxyz"));
232         assertEquals("(800) 222-3334", PhoneNumberUtils
233                 .convertKeypadLettersToDigits("(800) ABC-DEFG"));
234 
235         // Test stringFromStringAndTOA
236         assertNull(PhoneNumberUtils.stringFromStringAndTOA(null, 1));
237         assertEquals("+888888888", PhoneNumberUtils.stringFromStringAndTOA("888888888",
238                 PhoneNumberUtils.TOA_International));
239 
240         // Test formatJapaneseNumber
241         Editable jpEditNumber = Editable.Factory.getInstance().newEditable("0377777777");
242         PhoneNumberUtils.formatJapaneseNumber(jpEditNumber);
243         assertEquals("03-7777-7777", jpEditNumber.toString());
244         jpEditNumber = Editable.Factory.getInstance().newEditable("09077777777");
245         PhoneNumberUtils.formatJapaneseNumber(jpEditNumber);
246         assertEquals("090-7777-7777", jpEditNumber.toString());
247         jpEditNumber = Editable.Factory.getInstance().newEditable("0120777777");
248         PhoneNumberUtils.formatJapaneseNumber(jpEditNumber);
249         assertEquals("0120-777-777", jpEditNumber.toString());
250         jpEditNumber = Editable.Factory.getInstance().newEditable("+81377777777");
251         PhoneNumberUtils.formatJapaneseNumber(jpEditNumber);
252         assertEquals("+81-3-7777-7777", jpEditNumber.toString());
253         jpEditNumber = Editable.Factory.getInstance().newEditable("+819077777777");
254         PhoneNumberUtils.formatJapaneseNumber(jpEditNumber);
255         assertEquals("+81-90-7777-7777", jpEditNumber.toString());
256 
257         // Test formatNumber(String). Only numbers begin with +1 or +81 can be formatted.
258         assertEquals("+1-888-888-888", PhoneNumberUtils.formatNumber("+1888888888"));
259         // Test formatNumber(Editable, int)
260         Editable editNumber = Editable.Factory.getInstance().newEditable("0377777777");
261         PhoneNumberUtils.formatNumber(editNumber, PhoneNumberUtils.FORMAT_UNKNOWN);
262         assertEquals("0377777777", editNumber.toString());
263         editNumber = Editable.Factory.getInstance().newEditable("+177777777");
264         PhoneNumberUtils.formatNumber(editNumber, PhoneNumberUtils.FORMAT_UNKNOWN);
265         assertEquals("+1-777-777-77", editNumber.toString());
266         editNumber = Editable.Factory.getInstance().newEditable("+8177777777");
267         PhoneNumberUtils.formatNumber(editNumber, PhoneNumberUtils.FORMAT_UNKNOWN);
268         assertEquals("+81-77-777-777", editNumber.toString());
269 
270         // Test stripSeparators
271         assertEquals("+188888888", PhoneNumberUtils.stripSeparators("+188-888-888"));
272 
273         // Test toaFromString
274         assertEquals(PhoneNumberUtils.TOA_International, PhoneNumberUtils
275                 .toaFromString("+88888888"));
276         assertEquals(PhoneNumberUtils.TOA_Unknown, PhoneNumberUtils.toaFromString("88888888"));
277     }
278 
279     @Test
testJudgeMethods()280     public void testJudgeMethods() {
281         // Test is12Key, isDialable, isISODigit, isReallyDialable, isStartsPostDial
282         for (char c = '0'; c <= '9'; c++) {
283             assertTrue(PhoneNumberUtils.is12Key(c));
284             assertTrue(PhoneNumberUtils.isDialable(c));
285             assertTrue(PhoneNumberUtils.isISODigit(c));
286             assertTrue(PhoneNumberUtils.isNonSeparator(c));
287             assertTrue(PhoneNumberUtils.isReallyDialable(c));
288         }
289         char c = '*';
290         assertTrue(PhoneNumberUtils.is12Key(c));
291         assertTrue(PhoneNumberUtils.isDialable(c));
292         assertTrue(PhoneNumberUtils.isNonSeparator(c));
293         assertTrue(PhoneNumberUtils.isReallyDialable(c));
294         c = '#';
295         assertTrue(PhoneNumberUtils.is12Key(c));
296         assertTrue(PhoneNumberUtils.isDialable(c));
297         assertTrue(PhoneNumberUtils.isNonSeparator(c));
298         assertTrue(PhoneNumberUtils.isReallyDialable(c));
299         c = '$';
300         assertFalse(PhoneNumberUtils.is12Key(c));
301         assertFalse(PhoneNumberUtils.isDialable(c));
302         assertFalse(PhoneNumberUtils.isDialable(c));
303         c = '+';
304         assertTrue(PhoneNumberUtils.isDialable(c));
305         assertFalse(PhoneNumberUtils.isISODigit(c));
306         assertTrue(PhoneNumberUtils.isNonSeparator(c));
307         assertTrue(PhoneNumberUtils.isReallyDialable(c));
308         c = PhoneNumberUtils.WILD;
309         assertTrue(PhoneNumberUtils.isDialable(c));
310         assertTrue(PhoneNumberUtils.isNonSeparator(c));
311         assertFalse(PhoneNumberUtils.isReallyDialable(c));
312         c = PhoneNumberUtils.WAIT;
313         assertTrue(PhoneNumberUtils.isNonSeparator(c));
314         assertTrue(PhoneNumberUtils.isStartsPostDial(c));
315         c = PhoneNumberUtils.PAUSE;
316         assertTrue(PhoneNumberUtils.isNonSeparator(c));
317         assertTrue(PhoneNumberUtils.isStartsPostDial(c));
318         c = '8';
319         assertFalse(PhoneNumberUtils.isStartsPostDial(c));
320 
321         // Test isEmergencyNumber, now only know US emergency number
322         TelephonyManager tm = (TelephonyManager)getContext().getSystemService(
323                  Context.TELEPHONY_SERVICE);
324         // Test isEmergencyNumber, now only know US emergency number
325         if ("US".equals(tm.getSimCountryIso())) {
326             assertTrue(PhoneNumberUtils.isEmergencyNumber("911"));
327             assertFalse(PhoneNumberUtils.isEmergencyNumber("119"));
328         }
329 
330         // Test isGlobalPhoneNumber
331         assertTrue(PhoneNumberUtils.isGlobalPhoneNumber("+17005554141"));
332         assertFalse(PhoneNumberUtils.isGlobalPhoneNumber("android"));
333 
334         // Test isWellFormedSmsAddress
335         assertTrue(PhoneNumberUtils.isWellFormedSmsAddress("+17005554141"));
336         assertFalse(PhoneNumberUtils.isWellFormedSmsAddress("android"));
337 
338         // Test isUriNumber
339         assertTrue(PhoneNumberUtils.isUriNumber("example@example.com"));
340         assertFalse(PhoneNumberUtils.isUriNumber("+18005555555"));
341 
342         // Test isVoicemailNumber -- this is closely tied to the SIM so we'll just test some basic
343         // cases
344         assertFalse(PhoneNumberUtils.isVoiceMailNumber(getContext(),
345                 SubscriptionManager.getDefaultSubscriptionId(), null));
346         assertFalse(PhoneNumberUtils.isVoiceMailNumber(getContext(),
347                 SubscriptionManager.getDefaultSubscriptionId(), ""));
348 
349     }
350 
351     @Test
testGetPhoneTtsSpan()352     public void testGetPhoneTtsSpan() {
353         // Setup: phone number without a country code. Lets keep coverage minimal to avoid
354         // exercising the underlying PhoneNumberUtil or constraining localization changes.
355         String phoneNumber = "6512223333";
356         // Execute
357         TtsSpan ttsSpan = PhoneNumberUtils.createTtsSpan(phoneNumber);
358         // Verify: the created TtsSpan contains the phone number.
359         assertEquals("6512223333", ttsSpan.getArgs().get(TtsSpan.ARG_NUMBER_PARTS));
360     }
361 
362     @Test
testAddPhoneTtsSpan()363     public void testAddPhoneTtsSpan() {
364         // Setup: phone number without a country code. Lets keep coverage minimal to avoid
365         // exercising the underlying PhoneNumberUtil or constraining localization changes.
366         Spannable spannable = new SpannableString("Hello 6502223333");
367         // Execute
368         PhoneNumberUtils.addTtsSpan(spannable, 5, spannable.length());
369         // Verify: the Spannable is annotated with a TtsSpan in the correct location.
370         TtsSpan[] ttsSpans = spannable.getSpans(5, spannable.length() - 1, TtsSpan.class);
371         assertEquals(1, ttsSpans.length);
372         assertEquals("6502223333", ttsSpans[0].getArgs().get(TtsSpan.ARG_NUMBER_PARTS));
373     }
374 
375     @Test
testGetPhoneTtsSpannable()376     public void testGetPhoneTtsSpannable() {
377         // Setup: phone number without a country code. Lets keep coverage minimal to avoid
378         // exercising the underlying PhoneNumberUtil or constraining localization changes.
379         CharSequence phoneNumber = "6512223333";
380         // Execute
381         Spannable spannable = (Spannable) PhoneNumberUtils.createTtsSpannable(phoneNumber);
382         // Verify: returned char sequence contains a TtsSpan with the phone number in it
383         TtsSpan[] ttsSpans = spannable.getSpans(0, spannable.length() - 1, TtsSpan.class);
384         assertEquals(1, ttsSpans.length);
385         assertEquals("6512223333", ttsSpans[0].getArgs().get(TtsSpan.ARG_NUMBER_PARTS));
386     }
387 
388     @Test
testFormatNumberToE164()389     public void testFormatNumberToE164() {
390         assertNull(PhoneNumberUtils.formatNumber("invalid#", "US"));
391         assertNull(PhoneNumberUtils.formatNumberToE164("1234567", "US"));
392 
393         assertEquals("+18004664114", PhoneNumberUtils.formatNumberToE164("800-GOOG-114", "US"));
394         assertEquals("+16502910000", PhoneNumberUtils.formatNumberToE164("650 2910000", "US"));
395         assertEquals("+12023458246", PhoneNumberUtils.formatNumberToE164("(202)345-8246", "US"));
396         assertEquals("+812023458246", PhoneNumberUtils.formatNumberToE164("202-345-8246", "JP"));
397     }
398 }
399