• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.telecom.cts;
17 
18 import android.app.Instrumentation;
19 import android.bluetooth.BluetoothDevice;
20 import android.content.ComponentName;
21 import android.content.ContentProviderOperation;
22 import android.content.ContentResolver;
23 import android.content.Context;
24 import android.content.pm.PackageManager;
25 import android.graphics.Color;
26 import android.net.Uri;
27 import android.os.Build;
28 import android.os.Bundle;
29 import android.os.Handler;
30 import android.os.Looper;
31 import android.os.Parcel;
32 import android.os.ParcelFileDescriptor;
33 import android.os.Process;
34 import android.os.SystemClock;
35 import android.os.UserManager;
36 import android.provider.ContactsContract;
37 import android.telecom.PhoneAccount;
38 import android.telecom.PhoneAccountHandle;
39 import android.telecom.TelecomManager;
40 import android.telecom.VideoProfile;
41 
42 import androidx.test.InstrumentationRegistry;
43 
44 import junit.framework.TestCase;
45 
46 import java.io.BufferedReader;
47 import java.io.FileInputStream;
48 import java.io.InputStream;
49 import java.io.InputStreamReader;
50 import java.nio.charset.StandardCharsets;
51 import java.util.ArrayList;
52 import java.util.Optional;
53 import java.util.Random;
54 import java.util.UUID;
55 import java.util.concurrent.CountDownLatch;
56 import java.util.concurrent.TimeUnit;
57 import java.util.function.Predicate;
58 
59 public class TestUtils {
60     static final String TAG = "TelecomCTSTests";
61     static final boolean HAS_TELECOM = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
62     static final long WAIT_FOR_STATE_CHANGE_TIMEOUT_MS = 10000;
63     static final long WAIT_FOR_CALL_ADDED_TIMEOUT_S = 15;
64     static final long WAIT_FOR_STATE_CHANGE_TIMEOUT_CALLBACK = 50;
65     static final long WAIT_FOR_PHONE_STATE_LISTENER_REGISTERED_TIMEOUT_S = 15;
66     static final long WAIT_FOR_PHONE_STATE_LISTENER_CALLBACK_TIMEOUT_S = 15;
67     static final boolean HAS_BLUETOOTH = hasBluetoothFeature();
68     static final BluetoothDevice BLUETOOTH_DEVICE1 = makeBluetoothDevice("00:00:00:00:00:01");
69     static final BluetoothDevice BLUETOOTH_DEVICE2 = makeBluetoothDevice("00:00:00:00:00:02");
70 
71     // Non-final to allow modification by tests not in this package (e.g. permission-related
72     // tests in the Telecom2 test package.
73     public static String PACKAGE = "android.telecom.cts";
74     public static String SELF_MANAGED_PACKAGE = "android.telecom.cts.selfmanagedcstestappone";
75     public static final String TEST_URI_SCHEME = "foobuzz";
76     public static final String COMPONENT = "android.telecom.cts.CtsConnectionService";
77     public static final String INCALL_COMPONENT = "android.telecom.cts/.MockInCallService";
78     public static final String SELF_MANAGED_COMPONENT =
79             "android.telecom.cts.CtsSelfManagedConnectionService";
80     public static final String SELF_MANAGED_COMPONENT_1 =
81             "android.telecom.cts.selfmanagedcstestappone.CtsSelfManagedConnectionServiceOne";
82     public static final String REMOTE_COMPONENT = "android.telecom.cts.CtsRemoteConnectionService";
83     public static final String ACCOUNT_ID_1 = "xtstest_CALL_PROVIDER_ID_1";
84     public static final String ACCOUNT_ID_2 = "xtstest_CALL_PROVIDER_ID_2";
85     public static final String ACCOUNT_ID_SIM = "sim_acct";
86     public static final String ACCOUNT_ID_EMERGENCY = "xtstest_CALL_PROVIDER_EMERGENCY";
87     public static final String EXTRA_PHONE_NUMBER = "android.telecom.cts.extra.PHONE_NUMBER";
88     public static final ComponentName TELECOM_CTS_COMPONENT_NAME = new ComponentName(
89             TestUtils.PACKAGE, TestUtils.COMPONENT);
90     public static final PhoneAccountHandle TEST_PHONE_ACCOUNT_HANDLE =
91             new PhoneAccountHandle(new ComponentName(PACKAGE, COMPONENT), ACCOUNT_ID_1);
92     public static final PhoneAccountHandle TEST_SIM_PHONE_ACCOUNT_HANDLE =
93             new PhoneAccountHandle(new ComponentName(PACKAGE, COMPONENT), ACCOUNT_ID_SIM);
94     public static final PhoneAccountHandle TEST_PHONE_ACCOUNT_HANDLE_2 =
95             new PhoneAccountHandle(new ComponentName(PACKAGE, COMPONENT), ACCOUNT_ID_2);
96     public static final PhoneAccountHandle TEST_EMERGENCY_PHONE_ACCOUNT_HANDLE =
97             new PhoneAccountHandle(new ComponentName(PACKAGE, COMPONENT), ACCOUNT_ID_EMERGENCY);
98     public static final String DEFAULT_TEST_ACCOUNT_1_ID = "ctstest_DEFAULT_TEST_ID_1";
99     public static final String DEFAULT_TEST_ACCOUNT_2_ID = "ctstest_DEFAULT_TEST_ID_2";
100     public static final PhoneAccountHandle TEST_DEFAULT_PHONE_ACCOUNT_HANDLE_1 =
101             new PhoneAccountHandle(new ComponentName(PACKAGE, COMPONENT),
102                     DEFAULT_TEST_ACCOUNT_1_ID);
103     public static final PhoneAccountHandle TEST_DEFAULT_PHONE_ACCOUNT_HANDLE_2 =
104             new PhoneAccountHandle(new ComponentName(PACKAGE, COMPONENT),
105                     DEFAULT_TEST_ACCOUNT_2_ID);
106     public static final PhoneAccountHandle TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE =
107             new PhoneAccountHandle(new ComponentName(PACKAGE, COMPONENT), "handoverFrom");
108     public static final PhoneAccountHandle TEST_HANDOVER_DEST_PHONE_ACCOUNT_HANDLE =
109             new PhoneAccountHandle(new ComponentName(PACKAGE, SELF_MANAGED_COMPONENT),
110                     "handoverTo");
111     public static final String REMOTE_ACCOUNT_ID = "xtstest_REMOTE_CALL_PROVIDER_ID";
112     public static final String SELF_MANAGED_ACCOUNT_ID_1 = "ctstest_SELF_MANAGED_ID_1";
113     public static final PhoneAccountHandle TEST_SELF_MANAGED_HANDLE_1 =
114             new PhoneAccountHandle(new ComponentName(PACKAGE, SELF_MANAGED_COMPONENT),
115                     SELF_MANAGED_ACCOUNT_ID_1);
116     public static final String SELF_MANAGED_ACCOUNT_ID_2 = "ctstest_SELF_MANAGED_ID_2";
117     public static final PhoneAccountHandle TEST_SELF_MANAGED_HANDLE_2 =
118             new PhoneAccountHandle(new ComponentName(PACKAGE, SELF_MANAGED_COMPONENT),
119                     SELF_MANAGED_ACCOUNT_ID_2);
120     public static final String SELF_MANAGED_ACCOUNT_ID_3 = "ctstest_SELF_MANAGED_ID_3";
121     public static final PhoneAccountHandle TEST_SELF_MANAGED_HANDLE_3 =
122             new PhoneAccountHandle(new ComponentName(PACKAGE, SELF_MANAGED_COMPONENT),
123                     SELF_MANAGED_ACCOUNT_ID_3);
124     public static final String SELF_MANAGED_ACCOUNT_ID_4 = "ctstest_SELF_MANAGED_ID_4";
125     public static final PhoneAccountHandle TEST_SELF_MANAGED_HANDLE_4 =
126             new PhoneAccountHandle(new ComponentName(PACKAGE, SELF_MANAGED_COMPONENT),
127                     SELF_MANAGED_ACCOUNT_ID_4);
128     public static final String SELF_MANAGED_CS_1_ACCOUNT_ID_1 = "ctstest_SELF_MANAGED_CS_1_ID_1";
129     public static final String SELF_MANAGED_CS_1_ACCOUNT_ID_3 = "ctstest_SELF_MANAGED_CS_1_ID_3";
130     public static final PhoneAccountHandle TEST_SELF_MANAGED_CS_1_HANDLE_1 =
131             new PhoneAccountHandle(
132                     new ComponentName(SELF_MANAGED_PACKAGE, SELF_MANAGED_COMPONENT_1),
133                     SELF_MANAGED_CS_1_ACCOUNT_ID_1);
134     public static final PhoneAccountHandle TEST_SELF_MANAGED_CS_1_HANDLE_3 =
135             new PhoneAccountHandle(
136                     new ComponentName(SELF_MANAGED_PACKAGE, SELF_MANAGED_COMPONENT_1),
137                     SELF_MANAGED_CS_1_ACCOUNT_ID_3);
138 
139     public static final String ACCOUNT_LABEL = "CTSConnectionService";
140     public static final String SIM_ACCOUNT_LABEL = "CTSConnectionServiceSim";
141     public static final PhoneAccount TEST_PHONE_ACCOUNT = PhoneAccount.builder(
142             TEST_PHONE_ACCOUNT_HANDLE, ACCOUNT_LABEL)
143             .setAddress(Uri.parse("tel:555-TEST"))
144             .setSubscriptionAddress(Uri.parse("tel:555-TEST"))
145             .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
146                     PhoneAccount.CAPABILITY_VIDEO_CALLING |
147                     PhoneAccount.CAPABILITY_RTT |
148                     PhoneAccount.CAPABILITY_CONNECTION_MANAGER |
149                     PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS |
150                     PhoneAccount.CAPABILITY_ADHOC_CONFERENCE_CALLING)
151             .setHighlightColor(Color.RED)
152             .setShortDescription(ACCOUNT_LABEL)
153             .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
154             .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
155             .build();
156 
157     public static final PhoneAccount TEST_PHONE_ACCOUNT_THAT_HANDLES_CONTENT_SCHEME =
158             PhoneAccount.builder(
159                             TEST_PHONE_ACCOUNT_HANDLE, ACCOUNT_LABEL)
160                     .setAddress(Uri.parse("tel:555-TEST"))
161                     .setSubscriptionAddress(Uri.parse("tel:555-TEST"))
162                     .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
163                             PhoneAccount.CAPABILITY_VIDEO_CALLING |
164                             PhoneAccount.CAPABILITY_RTT |
165                             PhoneAccount.CAPABILITY_CONNECTION_MANAGER |
166                             PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS |
167                             PhoneAccount.CAPABILITY_ADHOC_CONFERENCE_CALLING)
168                     .setHighlightColor(Color.RED)
169                     .setShortDescription(ACCOUNT_LABEL)
170                     .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
171                     .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
172                     .addSupportedUriScheme("content")
173                     .build();
174 
175     public static final PhoneAccount TEST_SIM_PHONE_ACCOUNT = PhoneAccount.builder(
176             TEST_SIM_PHONE_ACCOUNT_HANDLE, SIM_ACCOUNT_LABEL)
177             .setAddress(Uri.parse("tel:555-TEST"))
178             .setSubscriptionAddress(Uri.parse("tel:555-TEST"))
179             .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
180                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
181             .setHighlightColor(Color.RED)
182             .setShortDescription(SIM_ACCOUNT_LABEL)
183             .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
184             .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
185             .build();
186 
187     public static final PhoneAccount TEST_PHONE_ACCOUNT_2 = PhoneAccount.builder(
188             TEST_PHONE_ACCOUNT_HANDLE_2, ACCOUNT_LABEL + "2")
189             .setAddress(Uri.parse("tel:555-TEST2"))
190             .setSubscriptionAddress(Uri.parse("tel:555-TEST2"))
191             .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
192                     PhoneAccount.CAPABILITY_VIDEO_CALLING |
193                     PhoneAccount.CAPABILITY_RTT |
194                     PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
195             .setHighlightColor(Color.BLUE)
196             .setShortDescription(ACCOUNT_LABEL)
197             .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
198             .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
199             .build();
200 
201     public static final PhoneAccount TEST_DEFAULT_PHONE_ACCOUNT_1 = PhoneAccount.builder(
202             TEST_DEFAULT_PHONE_ACCOUNT_HANDLE_1, "Default Test 1")
203             .setAddress(Uri.parse("foobuzz:testuri1"))
204             .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
205             .setHighlightColor(Color.RED)
206             .setShortDescription("Default Test 1")
207             .addSupportedUriScheme(TEST_URI_SCHEME)
208             .build();
209     public static final PhoneAccount TEST_DEFAULT_PHONE_ACCOUNT_2 = PhoneAccount.builder(
210             TEST_DEFAULT_PHONE_ACCOUNT_HANDLE_2, "Default Test 2")
211             .setAddress(Uri.parse("foobuzz:testuri2"))
212             .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
213             .setHighlightColor(Color.RED)
214             .setShortDescription("Default Test 2")
215             .addSupportedUriScheme(TEST_URI_SCHEME)
216             .build();
217     private static final Bundle SUPPORTS_HANDOVER_FROM_EXTRAS = new Bundle();
218     private static final Bundle SUPPORTS_HANDOVER_TO_EXTRAS = new Bundle();
219     static {
SUPPORTS_HANDOVER_FROM_EXTRAS.putBoolean(PhoneAccount.EXTRA_SUPPORTS_HANDOVER_FROM, true)220         SUPPORTS_HANDOVER_FROM_EXTRAS.putBoolean(PhoneAccount.EXTRA_SUPPORTS_HANDOVER_FROM, true);
SUPPORTS_HANDOVER_TO_EXTRAS.putBoolean(PhoneAccount.EXTRA_SUPPORTS_HANDOVER_TO, true)221         SUPPORTS_HANDOVER_TO_EXTRAS.putBoolean(PhoneAccount.EXTRA_SUPPORTS_HANDOVER_TO, true);
222     }
223     public static final PhoneAccount TEST_PHONE_ACCOUNT_HANDOVER_SRC = PhoneAccount.builder(
224             TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE, ACCOUNT_LABEL)
225             .setAddress(Uri.parse("tel:555-TEST"))
226             .setExtras(SUPPORTS_HANDOVER_FROM_EXTRAS)
227             .setSubscriptionAddress(Uri.parse("tel:555-TEST"))
228             .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
229             .setHighlightColor(Color.BLUE)
230             .setShortDescription(ACCOUNT_LABEL)
231             .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
232             .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
233             .build();
234     public static final PhoneAccount TEST_PHONE_ACCOUNT_HANDOVER_DEST = PhoneAccount.builder(
235             TEST_HANDOVER_DEST_PHONE_ACCOUNT_HANDLE, ACCOUNT_LABEL)
236             .setAddress(Uri.parse("tel:555-TEST"))
237             .setExtras(SUPPORTS_HANDOVER_TO_EXTRAS)
238             .setSubscriptionAddress(Uri.parse("tel:555-TEST"))
239             .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
240             .setHighlightColor(Color.MAGENTA)
241             .setShortDescription(ACCOUNT_LABEL)
242             .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
243             .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
244             .build();
245     public static final String REMOTE_ACCOUNT_LABEL = "CTSRemoteConnectionService";
246     public static final String SELF_MANAGED_ACCOUNT_LABEL = "android.telecom.cts";
247     public static final PhoneAccount TEST_SELF_MANAGED_PHONE_ACCOUNT_3 = PhoneAccount.builder(
248             TEST_SELF_MANAGED_HANDLE_3, SELF_MANAGED_ACCOUNT_LABEL)
249             .setAddress(Uri.fromParts(TEST_URI_SCHEME, "test@test.com", null))
250             .setSubscriptionAddress(Uri.fromParts(TEST_URI_SCHEME, "test@test.com", null))
251             .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED |
252                     PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING |
253                     PhoneAccount.CAPABILITY_VIDEO_CALLING)
254             .setHighlightColor(Color.BLUE)
255             .setShortDescription(SELF_MANAGED_ACCOUNT_LABEL)
256             .addSupportedUriScheme(TEST_URI_SCHEME)
257             .build();
258     public static final Bundle SELF_MANAGED_ACCOUNT_1_EXTRAS;
259     static {
260         SELF_MANAGED_ACCOUNT_1_EXTRAS = new Bundle();
SELF_MANAGED_ACCOUNT_1_EXTRAS.putBoolean( PhoneAccount.EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE, false)261         SELF_MANAGED_ACCOUNT_1_EXTRAS.putBoolean(
262                 PhoneAccount.EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE, false);
263     }
264     public static final Bundle SELF_MANAGED_ACCOUNT_2_EXTRAS;
265     static {
266         SELF_MANAGED_ACCOUNT_2_EXTRAS = new Bundle();
SELF_MANAGED_ACCOUNT_2_EXTRAS.putBoolean(PhoneAccount.EXTRA_LOG_SELF_MANAGED_CALLS, true)267         SELF_MANAGED_ACCOUNT_2_EXTRAS.putBoolean(PhoneAccount.EXTRA_LOG_SELF_MANAGED_CALLS, true);
268     }
269     public static final Bundle SELF_MANAGED_ACCOUNT_4_EXTRAS;
270     static {
271         SELF_MANAGED_ACCOUNT_4_EXTRAS = new Bundle();
SELF_MANAGED_ACCOUNT_4_EXTRAS.putBoolean( PhoneAccount.EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE, true)272         SELF_MANAGED_ACCOUNT_4_EXTRAS.putBoolean(
273                 PhoneAccount.EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE, true);
274     }
275     public static final Bundle SELF_MANAGED_CS_1_ACCOUNT_1_EXTRAS;
276     static {
277         SELF_MANAGED_CS_1_ACCOUNT_1_EXTRAS = new Bundle();
SELF_MANAGED_CS_1_ACCOUNT_1_EXTRAS.putBoolean( PhoneAccount.EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE, true)278         SELF_MANAGED_CS_1_ACCOUNT_1_EXTRAS.putBoolean(
279                 PhoneAccount.EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE, true);
280     }
281     public static final Bundle SELF_MANAGED_CS_1_ACCOUNT_3_EXTRAS;
282     static {
283         SELF_MANAGED_CS_1_ACCOUNT_3_EXTRAS = new Bundle();
SELF_MANAGED_CS_1_ACCOUNT_3_EXTRAS.putBoolean( PhoneAccount.EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE, false)284         SELF_MANAGED_CS_1_ACCOUNT_3_EXTRAS.putBoolean(
285                 PhoneAccount.EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE, false);
286     }
287 
288     public static final PhoneAccount TEST_SELF_MANAGED_PHONE_ACCOUNT_2 = PhoneAccount.builder(
289             TEST_SELF_MANAGED_HANDLE_2, SELF_MANAGED_ACCOUNT_LABEL)
290             .setAddress(Uri.parse("sip:test@test.com"))
291             .setSubscriptionAddress(Uri.parse("sip:test@test.com"))
292             .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED |
293                     PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING |
294                     PhoneAccount.CAPABILITY_VIDEO_CALLING)
295             .setHighlightColor(Color.BLUE)
296             .setShortDescription(SELF_MANAGED_ACCOUNT_LABEL)
297             .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
298             .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
299             .setExtras(SELF_MANAGED_ACCOUNT_2_EXTRAS)
300             .build();
301     public static final PhoneAccount TEST_SELF_MANAGED_PHONE_ACCOUNT_1 = PhoneAccount.builder(
302             TEST_SELF_MANAGED_HANDLE_1, SELF_MANAGED_ACCOUNT_LABEL)
303             .setAddress(Uri.parse("sip:test@test.com"))
304             .setSubscriptionAddress(Uri.parse("sip:test@test.com"))
305             .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED |
306                     PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING |
307                     PhoneAccount.CAPABILITY_VIDEO_CALLING)
308             .setHighlightColor(Color.BLUE)
309             .setShortDescription(SELF_MANAGED_ACCOUNT_LABEL)
310             .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
311             .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
312             .setExtras(SELF_MANAGED_ACCOUNT_1_EXTRAS)
313             .build();
314     public static final PhoneAccount TEST_SELF_MANAGED_PHONE_ACCOUNT_4 = PhoneAccount.builder(
315             TEST_SELF_MANAGED_HANDLE_4, SELF_MANAGED_ACCOUNT_LABEL)
316             .setAddress(Uri.parse("sip:test@test.com"))
317             .setSubscriptionAddress(Uri.parse("sip:test@test.com"))
318             .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED |
319                     PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING |
320                     PhoneAccount.CAPABILITY_VIDEO_CALLING)
321             .setHighlightColor(Color.BLUE)
322             .setShortDescription(SELF_MANAGED_ACCOUNT_LABEL)
323             .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
324             .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
325             .setExtras(SELF_MANAGED_ACCOUNT_4_EXTRAS)
326             .build();
327     public static final PhoneAccount TEST_SELF_MANAGED_CS_1_PHONE_ACCOUNT_1 = PhoneAccount.builder(
328             TEST_SELF_MANAGED_CS_1_HANDLE_1, SELF_MANAGED_ACCOUNT_LABEL)
329             .setAddress(Uri.parse("sip:test@test.com"))
330             .setSubscriptionAddress(Uri.parse("sip:test@test.com"))
331             .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED
332                     | PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING
333                     | PhoneAccount.CAPABILITY_VIDEO_CALLING)
334             .setHighlightColor(Color.BLUE)
335             .setShortDescription(SELF_MANAGED_ACCOUNT_LABEL)
336             .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
337             .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
338             .setExtras(SELF_MANAGED_CS_1_ACCOUNT_1_EXTRAS)
339             .build();
340     public static final PhoneAccount TEST_SELF_MANAGED_CS_1_PHONE_ACCOUNT_2 = PhoneAccount.builder(
341             TEST_SELF_MANAGED_CS_1_HANDLE_1, SELF_MANAGED_ACCOUNT_LABEL)
342             .setAddress(Uri.parse("sip:test@test.com"))
343             .setSubscriptionAddress(Uri.parse("sip:test@test.com"))
344             .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
345             .setHighlightColor(Color.BLUE)
346             .setShortDescription(SELF_MANAGED_ACCOUNT_LABEL)
347             .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
348             .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
349             .setExtras(SELF_MANAGED_CS_1_ACCOUNT_1_EXTRAS)
350             .build();
351     public static final PhoneAccount TEST_SELF_MANAGED_CS_1_PHONE_ACCOUNT_3 = PhoneAccount.builder(
352             TEST_SELF_MANAGED_CS_1_HANDLE_3, SELF_MANAGED_ACCOUNT_LABEL)
353             .setAddress(Uri.parse("sip:test@test.com"))
354             .setSubscriptionAddress(Uri.parse("sip:test@test.com"))
355             .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
356             .setHighlightColor(Color.BLUE)
357             .setShortDescription(SELF_MANAGED_ACCOUNT_LABEL)
358             .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
359             .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
360             .setExtras(SELF_MANAGED_CS_1_ACCOUNT_3_EXTRAS)
361             .build();
362 
363     /**
364      * See {@link TelecomManager#ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION}
365      */
366     public static final String ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION_STRING =
367             "ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION ";
368 
369     /**
370      * See {@link TelecomManager#ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION}
371      */
372     public static final String ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION_STRING =
373             "ENABLE_GET_PHONE_ACCOUNT_PERMISSION_PROTECTION ";
374 
375     private static final String COMMAND_SET_CALL_DIAGNOSTIC_SERVICE =
376             "telecom set-call-diagnostic-service ";
377 
378     private static final String COMMAND_SET_DEFAULT_DIALER = "telecom set-default-dialer ";
379 
380     private static final String COMMAND_GET_DEFAULT_DIALER = "telecom get-default-dialer";
381 
382     private static final String COMMAND_SET_SYSTEM_DIALER = "telecom set-system-dialer ";
383 
384     private static final String COMMAND_GET_SYSTEM_DIALER = "telecom get-system-dialer";
385 
386     private static final String COMMAND_ENABLE = "telecom set-phone-account-enabled ";
387 
388     private static final String COMMAND_DISABLE = "telecom set-phone-account-disabled ";
389 
390     private static final String COMMAND_SET_ACCT_SUGGESTION =
391             "telecom set-phone-acct-suggestion-component ";
392 
393     private static final String COMMAND_REGISTER_SIM = "telecom register-sim-phone-account ";
394 
395     private static final String COMMAND_SET_DEFAULT_PHONE_ACCOUNT =
396             "telecom set-user-selected-outgoing-phone-account ";
397 
398     private static final String COMMAND_WAIT_ON_HANDLERS = "telecom wait-on-handlers";
399 
400     private static final String COMMAND_ADD_TEST_EMERGENCY_NUMBER =
401             "cmd phone emergency-number-test-mode -a ";
402 
403     private static final String COMMAND_REMOVE_TEST_EMERGENCY_NUMBER =
404             "cmd phone emergency-number-test-mode -r ";
405 
406     private static final String COMMAND_CLEAR_TEST_EMERGENCY_NUMBERS =
407             "cmd phone emergency-number-test-mode -c";
408 
409     private static final String COMMAND_SET_TEST_EMERGENCY_PHONE_ACCOUNT_PACKAGE_NAME_FILTER =
410             "telecom set-test-emergency-phone-account-package-filter ";
411 
412     private static final String COMMAND_AM_COMPAT = "am compat ";
413 
414     public static final String MERGE_CALLER_NAME = "calls-merged";
415     public static final String SWAP_CALLER_NAME = "calls-swapped";
416 
shouldTestTelecom(Context context)417     public static boolean shouldTestTelecom(Context context) {
418         if (!HAS_TELECOM) {
419             return false;
420         }
421         final PackageManager pm = context.getPackageManager();
422         return pm.hasSystemFeature(PackageManager.FEATURE_TELECOM);
423     }
424 
hasTelephonyFeature(Context context)425     public static boolean hasTelephonyFeature(Context context) {
426         final PackageManager pm = context.getPackageManager();
427         return (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) && pm.hasSystemFeature(
428                 PackageManager.FEATURE_TELEPHONY_CALLING));
429     }
430 
setCallDiagnosticService(Instrumentation instrumentation, String packageName)431     public static String setCallDiagnosticService(Instrumentation instrumentation,
432             String packageName)
433             throws Exception {
434         return executeShellCommand(instrumentation, COMMAND_SET_CALL_DIAGNOSTIC_SERVICE
435                 + packageName);
436     }
437 
setDefaultDialer(Instrumentation instrumentation, String packageName)438     public static String setDefaultDialer(Instrumentation instrumentation, String packageName)
439             throws Exception {
440         return executeShellCommand(instrumentation, COMMAND_SET_DEFAULT_DIALER + packageName);
441     }
442 
setSystemDialerOverride(Instrumentation instrumentation)443     public static String setSystemDialerOverride(Instrumentation instrumentation) throws Exception {
444         return executeShellCommand(instrumentation, COMMAND_SET_SYSTEM_DIALER + INCALL_COMPONENT);
445     }
446 
clearSystemDialerOverride( Instrumentation instrumentation)447     public static String clearSystemDialerOverride(
448             Instrumentation instrumentation) throws Exception {
449         return executeShellCommand(instrumentation, COMMAND_SET_SYSTEM_DIALER + "default");
450     }
451 
setCtsPhoneAccountSuggestionService(Instrumentation instrumentation, ComponentName componentName)452     public static String setCtsPhoneAccountSuggestionService(Instrumentation instrumentation,
453             ComponentName componentName) throws Exception {
454         return executeShellCommand(instrumentation,
455                 COMMAND_SET_ACCT_SUGGESTION
456                         + (componentName == null ? "" : componentName.flattenToString()));
457     }
458 
getDefaultDialer(Instrumentation instrumentation)459     public static String getDefaultDialer(Instrumentation instrumentation) throws Exception {
460         return executeShellCommand(instrumentation, COMMAND_GET_DEFAULT_DIALER);
461     }
462 
getSystemDialer(Instrumentation instrumentation)463     public static String getSystemDialer(Instrumentation instrumentation) throws Exception {
464         return executeShellCommand(instrumentation, COMMAND_GET_SYSTEM_DIALER);
465     }
466 
enablePhoneAccount(Instrumentation instrumentation, PhoneAccountHandle handle)467     public static void enablePhoneAccount(Instrumentation instrumentation,
468             PhoneAccountHandle handle) throws Exception {
469         final ComponentName component = handle.getComponentName();
470         final long currentUserSerial = getCurrentUserSerialNumber(instrumentation);
471         executeShellCommand(instrumentation, COMMAND_ENABLE
472                 + component.getPackageName() + "/" + component.getClassName() + " "
473                 + handle.getId() + " " + currentUserSerial);
474     }
475 
disablePhoneAccount(Instrumentation instrumentation, PhoneAccountHandle handle)476     public static void disablePhoneAccount(Instrumentation instrumentation,
477             PhoneAccountHandle handle) throws Exception {
478         final ComponentName component = handle.getComponentName();
479         final long currentUserSerial = getCurrentUserSerialNumber(instrumentation);
480         executeShellCommand(instrumentation, COMMAND_DISABLE
481                 + component.getPackageName() + "/" + component.getClassName() + " "
482                 + handle.getId() + " " + currentUserSerial);
483     }
484 
registerSimPhoneAccount(Instrumentation instrumentation, PhoneAccountHandle handle, String label, String address)485     public static void registerSimPhoneAccount(Instrumentation instrumentation,
486             PhoneAccountHandle handle, String label, String address) throws Exception {
487         final ComponentName component = handle.getComponentName();
488         final long currentUserSerial = getCurrentUserSerialNumber(instrumentation);
489         executeShellCommand(instrumentation, COMMAND_REGISTER_SIM
490                 + component.getPackageName() + "/" + component.getClassName() + " "
491                 + handle.getId() + " " + currentUserSerial + " " + label + " " + address);
492     }
493 
registerEmergencyPhoneAccount(Instrumentation instrumentation, PhoneAccountHandle handle, String label, String address)494     public static void registerEmergencyPhoneAccount(Instrumentation instrumentation,
495             PhoneAccountHandle handle, String label, String address) throws Exception {
496         final ComponentName component = handle.getComponentName();
497         final long currentUserSerial = getCurrentUserSerialNumber(instrumentation);
498         executeShellCommand(instrumentation, COMMAND_REGISTER_SIM  + "-e "
499                 + component.getPackageName() + "/" + component.getClassName() + " "
500                 + handle.getId() + " " + currentUserSerial + " " + label + " " + address);
501     }
502 
setDefaultOutgoingPhoneAccount(Instrumentation instrumentation, PhoneAccountHandle handle)503     public static void setDefaultOutgoingPhoneAccount(Instrumentation instrumentation,
504             PhoneAccountHandle handle) throws Exception {
505         if (handle != null) {
506             final ComponentName component = handle.getComponentName();
507             final long currentUserSerial = getCurrentUserSerialNumber(instrumentation);
508             executeShellCommand(instrumentation, COMMAND_SET_DEFAULT_PHONE_ACCOUNT
509                     + component.getPackageName() + "/" + component.getClassName() + " "
510                     + handle.getId() + " " + currentUserSerial);
511         } else {
512             executeShellCommand(instrumentation, COMMAND_SET_DEFAULT_PHONE_ACCOUNT);
513         }
514     }
515 
waitOnAllHandlers(Instrumentation instrumentation)516     public static void waitOnAllHandlers(Instrumentation instrumentation) {
517         try {
518             executeShellCommand(instrumentation, COMMAND_WAIT_ON_HANDLERS);
519         } catch (Throwable t) {
520             throw new RuntimeException(t);
521         }
522     }
523 
waitOnLocalMainLooper(long timeoutMs)524     public static void waitOnLocalMainLooper(long timeoutMs) {
525         Handler mainHandler = new Handler(Looper.getMainLooper());
526         final CountDownLatch lock = new CountDownLatch(1);
527         mainHandler.post(lock::countDown);
528         while (lock.getCount() > 0) {
529             try {
530                 lock.await(timeoutMs, TimeUnit.MILLISECONDS);
531             } catch (InterruptedException e) {
532                 // do nothing
533             }
534         }
535     }
536 
addTestEmergencyNumber(Instrumentation instr, String testNumber)537     public static void addTestEmergencyNumber(Instrumentation instr,
538             String testNumber) throws Exception {
539         executeShellCommand(instr, COMMAND_ADD_TEST_EMERGENCY_NUMBER + testNumber);
540     }
541 
removeTestEmergencyNumber(Instrumentation instr, String number)542     public static void removeTestEmergencyNumber(Instrumentation instr,
543             String number) throws Exception {
544         executeShellCommand(instr, COMMAND_REMOVE_TEST_EMERGENCY_NUMBER + number);
545     }
546 
clearTestEmergencyNumbers(Instrumentation instr)547     public static void clearTestEmergencyNumbers(Instrumentation instr) throws Exception {
548         executeShellCommand(instr, COMMAND_CLEAR_TEST_EMERGENCY_NUMBERS);
549     }
550 
setTestEmergencyPhoneAccountPackageFilter(Instrumentation instr, Context context)551     public static void setTestEmergencyPhoneAccountPackageFilter(Instrumentation instr,
552             Context context) throws Exception {
553         executeShellCommand(instr, COMMAND_SET_TEST_EMERGENCY_PHONE_ACCOUNT_PACKAGE_NAME_FILTER
554                 + context.getPackageName());
555     }
556 
clearTestEmergencyPhoneAccountPackageFilter( Instrumentation instr)557     public static void clearTestEmergencyPhoneAccountPackageFilter(
558             Instrumentation instr) throws Exception {
559         executeShellCommand(instr, COMMAND_SET_TEST_EMERGENCY_PHONE_ACCOUNT_PACKAGE_NAME_FILTER);
560     }
561 
enableCompatCommand(Instrumentation instr, String commandName)562     public static void enableCompatCommand(Instrumentation instr,
563             String commandName) throws Exception {
564         String cmd = COMMAND_AM_COMPAT + "enable  --no-kill " + commandName + PACKAGE;
565         executeShellCommand(instr, cmd);
566     }
567 
disableCompatCommand(Instrumentation instr, String commandName)568     public static void disableCompatCommand(Instrumentation instr,
569             String commandName) throws Exception {
570         String cmd = COMMAND_AM_COMPAT + "disable  --no-kill " + commandName + PACKAGE;
571         executeShellCommand(instr, cmd);
572     }
573 
resetCompatCommand(Instrumentation instr, String commandName)574     public static void resetCompatCommand(Instrumentation instr,
575             String commandName) throws Exception {
576         String cmd = COMMAND_AM_COMPAT + "reset  --no-kill " + commandName + PACKAGE;
577         executeShellCommand(instr, cmd);
578     }
579 
580     /**
581      * Executes the given shell command and returns the output in a string. Note that even
582      * if we don't care about the output, we have to read the stream completely to make the
583      * command execute.
584      */
executeShellCommand(Instrumentation instrumentation, String command)585     public static String executeShellCommand(Instrumentation instrumentation,
586             String command) throws Exception {
587         final ParcelFileDescriptor pfd =
588                 instrumentation.getUiAutomation().executeShellCommand(command);
589         BufferedReader br = null;
590         try (InputStream in = new FileInputStream(pfd.getFileDescriptor())) {
591             br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
592             String str = null;
593             StringBuilder out = new StringBuilder();
594             while ((str = br.readLine()) != null) {
595                 out.append(str);
596             }
597             return out.toString();
598         } finally {
599             if (br != null) {
600                 closeQuietly(br);
601             }
602             closeQuietly(pfd);
603         }
604     }
605 
closeQuietly(AutoCloseable closeable)606     private static void closeQuietly(AutoCloseable closeable) {
607         if (closeable != null) {
608             try {
609                 closeable.close();
610             } catch (RuntimeException rethrown) {
611                 throw rethrown;
612             } catch (Exception ignored) {
613             }
614         }
615     }
616 
617     /**
618      * Waits for the {@link CountDownLatch} to count down to 0 and then returns without reseting
619      * the latch.
620      * @param lock the latch that the system will wait on.
621      * @return true if the latch was released successfully, false if the latch timed out before
622      * resetting.
623      */
waitForLatchCountDown(CountDownLatch lock)624     public static boolean waitForLatchCountDown(CountDownLatch lock) {
625         if (lock == null) {
626             return false;
627         }
628 
629         boolean success;
630         try {
631             success = lock.await(5000, TimeUnit.MILLISECONDS);
632         } catch (InterruptedException ie) {
633             return false;
634         }
635 
636         return success;
637     }
638 
639     /**
640      * Waits for the {@link CountDownLatch} to count down to 0 and then returns a new reset latch.
641      * @param lock The lock that will await a countDown to 0.
642      * @return a new reset {@link CountDownLatch} if the lock successfully counted down to 0 or
643      * null if the operation timed out.
644      */
waitForLock(CountDownLatch lock)645     public static CountDownLatch waitForLock(CountDownLatch lock) {
646         boolean success = waitForLatchCountDown(lock);
647         if (success) {
648             return new CountDownLatch(1);
649         } else {
650             return null;
651         }
652     }
653 
654     /**
655      * Adds a new incoming call.
656      *
657      * @param instrumentation the Instrumentation, used for shell command execution.
658      * @param telecomManager the TelecomManager.
659      * @param handle the PhoneAccountHandle associated with the call.
660      * @param address the incoming address.
661      * @return the new self-managed incoming call.
662      */
addIncomingCall(Instrumentation instrumentation, TelecomManager telecomManager, PhoneAccountHandle handle, Uri address)663     public static void addIncomingCall(Instrumentation instrumentation,
664                                        TelecomManager telecomManager, PhoneAccountHandle handle,
665                                        Uri address) {
666 
667         // Inform telecom of new incoming self-managed connection.
668         Bundle extras = new Bundle();
669         extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, address);
670         telecomManager.addNewIncomingCall(handle, extras);
671 
672         // Wait for Telecom to finish creating the new connection.
673         try {
674             waitOnAllHandlers(instrumentation);
675         } catch (Exception e) {
676             TestCase.fail("Failed to wait on handlers");
677         }
678     }
hasBluetoothFeature()679     public static boolean hasBluetoothFeature() {
680         try {
681             return InstrumentationRegistry.getContext().getPackageManager()
682                     .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
683         } catch (Exception e) {
684             return false;
685         }
686     }
hasAutomotiveFeature()687     public static boolean hasAutomotiveFeature() {
688         try {
689             return InstrumentationRegistry.getContext().getPackageManager()
690                     .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
691         } catch (Exception e) {
692             return false;
693         }
694     }
makeBluetoothDevice(String address)695     public static BluetoothDevice makeBluetoothDevice(String address) {
696         if (!HAS_BLUETOOTH) return null;
697         Parcel p1 = Parcel.obtain();
698         p1.writeString(address);
699         p1.setDataPosition(0);
700         BluetoothDevice device = BluetoothDevice.CREATOR.createFromParcel(p1);
701         p1.recycle();
702         return device;
703     }
704 
705     /**
706      * Places a new outgoing call.
707      *
708      * @param telecomManager the TelecomManager.
709      * @param handle the PhoneAccountHandle associated with the call.
710      * @param address outgoing call address.
711      * @return the new self-managed outgoing call.
712      */
placeOutgoingCall(Instrumentation instrumentation, TelecomManager telecomManager, PhoneAccountHandle handle, Uri address)713     public static void placeOutgoingCall(Instrumentation instrumentation,
714                                           TelecomManager telecomManager, PhoneAccountHandle handle,
715                                           Uri address) {
716         placeOutgoingCall(instrumentation, telecomManager, handle, address,
717                 VideoProfile.STATE_AUDIO_ONLY);
718     }
719 
720     /**
721      * Places a new outgoing call.
722      *
723      * @param telecomManager the TelecomManager.
724      * @param handle the PhoneAccountHandle associated with the call.
725      * @param address outgoing call address.
726      * @return the new self-managed outgoing call.
727      */
placeOutgoingCall(Instrumentation instrumentation, TelecomManager telecomManager, PhoneAccountHandle handle, Uri address, int videoState)728     public static void placeOutgoingCall(Instrumentation instrumentation,
729                                           TelecomManager telecomManager, PhoneAccountHandle handle,
730                                           Uri address, int videoState) {
731         // Inform telecom of new incoming self-managed connection.
732         Bundle extras = new Bundle();
733         extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, handle);
734 
735         if (!VideoProfile.isAudioOnly(videoState)) {
736             extras.putInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState);
737         }
738 
739         telecomManager.placeCall(address, extras);
740 
741         // Wait for Telecom to finish creating the new connection.
742         try {
743             waitOnAllHandlers(instrumentation);
744         } catch (Exception e) {
745             TestCase.fail("Failed to wait on handlers");
746         }
747     }
748 
749     /**
750      * Waits for a new SelfManagedConnection with the given address to be added.
751      * @param address The expected address.
752      * @return The SelfManagedConnection found.
753      */
waitForAndGetConnection(Uri address)754     public static SelfManagedConnection waitForAndGetConnection(Uri address) {
755         // Wait for creation of the new connection.
756         if (!CtsSelfManagedConnectionService.waitForBinding()) {
757             TestCase.fail("Could not bind to Self-Managed ConnectionService");
758         }
759         CtsSelfManagedConnectionService connectionService =
760                 CtsSelfManagedConnectionService.getConnectionService();
761         TestCase.assertTrue(connectionService.waitForUpdate(
762                 CtsSelfManagedConnectionService.CONNECTION_CREATED_LOCK));
763 
764         Optional<SelfManagedConnection> connectionOptional = connectionService.getConnections()
765                 .stream()
766                 .filter(connection -> address.equals(connection.getAddress()))
767                 .findFirst();
768         assert(connectionOptional.isPresent());
769         return connectionOptional.get();
770     }
771 
772     /**
773      * Utility class used to track the number of times a callback was invoked, and the arguments it
774      * was invoked with. This class is prefixed Invoke rather than the more typical Call for
775      * disambiguation purposes.
776      */
777     public static final class InvokeCounter {
778         private final String mName;
779         private final Object mLock = new Object();
780         private final ArrayList<Object[]> mInvokeArgs = new ArrayList<>();
781 
782         private int mInvokeCount;
783 
InvokeCounter(String callbackName)784         public InvokeCounter(String callbackName) {
785             mName = callbackName;
786         }
787 
invoke(Object... args)788         public void invoke(Object... args) {
789             synchronized (mLock) {
790                 mInvokeCount++;
791                 mInvokeArgs.add(args);
792                 mLock.notifyAll();
793             }
794         }
795 
getArgs(int index)796         public Object[] getArgs(int index) {
797             synchronized (mLock) {
798                 return mInvokeArgs.get(index);
799             }
800         }
801 
getInvokeCount()802         public int getInvokeCount() {
803             synchronized (mLock) {
804                 return mInvokeCount;
805             }
806         }
807 
waitForCount(int count)808         public void waitForCount(int count) {
809             waitForCount(count, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
810         }
811 
waitForCount(int count, long timeoutMillis)812         public void waitForCount(int count, long timeoutMillis) {
813             waitForCount(count, timeoutMillis, null);
814         }
815 
waitForCount(long timeoutMillis)816         public void waitForCount(long timeoutMillis) {
817              synchronized (mLock) {
818              try {
819                   mLock.wait(timeoutMillis);
820              }catch (InterruptedException ex) {
821                   ex.printStackTrace();
822              }
823            }
824         }
825 
waitForCount(int count, long timeoutMillis, String message)826         public void waitForCount(int count, long timeoutMillis, String message) {
827             synchronized (mLock) {
828                 final long startTimeMillis = SystemClock.uptimeMillis();
829                 while (mInvokeCount < count) {
830                     try {
831                         final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
832                         final long remainingTimeMillis = timeoutMillis - elapsedTimeMillis;
833                         if (remainingTimeMillis <= 0) {
834                             if (message != null) {
835                                 TestCase.fail(message);
836                             } else {
837                                 TestCase.fail(String.format("Expected %s to be called %d times.",
838                                         mName, count));
839                             }
840                         }
841                         mLock.wait(timeoutMillis);
842                     } catch (InterruptedException ie) {
843                         /* ignore */
844                     }
845                 }
846             }
847         }
848 
849         /**
850          * Waits for a predicate to return {@code true} within the specified timeout.  Uses the
851          * {@link #mLock} for this {@link InvokeCounter} to eliminate the need to perform busy-wait.
852          * @param predicate The predicate.
853          * @param timeoutMillis The timeout.
854          */
waitForPredicate(Predicate predicate, long timeoutMillis)855         public void waitForPredicate(Predicate predicate, long timeoutMillis) {
856             synchronized (mLock) {
857                 long startTimeMillis = SystemClock.uptimeMillis();
858                 long elapsedTimeMillis = 0;
859                 long remainingTimeMillis = timeoutMillis;
860                 Object foundValue = null;
861                 boolean wasFound = false;
862                 do {
863                     try {
864                         mLock.wait(timeoutMillis);
865                         foundValue = (mInvokeArgs.get(mInvokeArgs.size()-1))[0];
866                         wasFound = predicate.test(foundValue);
867                         elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
868                         remainingTimeMillis = timeoutMillis - elapsedTimeMillis;
869                     } catch (InterruptedException ie) {
870                         /* ignore */
871                     }
872                 } while (!wasFound && remainingTimeMillis > 0);
873                 if (wasFound) {
874                     return;
875                 } else if (remainingTimeMillis <= 0) {
876                     TestCase.fail("Expected value not found within time limit");
877                 }
878             }
879         }
880 
clearArgs()881         public void clearArgs() {
882             synchronized (mLock) {
883                 mInvokeArgs.clear();
884             }
885         }
886 
reset()887         public void reset() {
888             synchronized (mLock) {
889                 clearArgs();
890                 mInvokeCount = 0;
891             }
892         }
893     }
894 
getCurrentUserSerialNumber(Instrumentation instrumentation)895     private static long getCurrentUserSerialNumber(Instrumentation instrumentation) {
896         UserManager userManager =
897                 instrumentation.getContext().getSystemService(UserManager.class);
898         return userManager.getSerialNumberForUser(Process.myUserHandle());
899     }
900 
901 
902 
insertContact(ContentResolver contentResolver, String phoneNumber)903     public static Uri insertContact(ContentResolver contentResolver, String phoneNumber)
904             throws Exception {
905         ArrayList<ContentProviderOperation> ops = new ArrayList<>();
906         ops.add(ContentProviderOperation
907                 .newInsert(ContactsContract.RawContacts.CONTENT_URI)
908                 .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, "test_type")
909                 .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, "test_name")
910                 .build());
911         ops.add(ContentProviderOperation
912                 .newInsert(ContactsContract.Data.CONTENT_URI)
913                 .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
914                 .withValue(ContactsContract.Data.MIMETYPE,
915                         ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
916                 .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, "test")
917                 .build());
918         ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
919                 .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
920                 .withValue(ContactsContract.Data.MIMETYPE,
921                         ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
922                 .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phoneNumber)
923                 .withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
924                         ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
925                 .withYieldAllowed(true)
926                 .build());
927         return contentResolver.applyBatch(ContactsContract.AUTHORITY, ops)[0].uri;
928     }
929 
deleteContact(ContentResolver contentResolver, Uri deleteUri)930     public static int deleteContact(ContentResolver contentResolver, Uri deleteUri) {
931         return contentResolver.delete(deleteUri, null, null);
932     }
933 
934     /**
935      * Generates random phone accounts.
936      * @param seed random seed to use for random UUIDs; passed in for determinism.
937      * @param count How many phone accounts to use.
938      * @return Random phone accounts.
939      */
generateRandomPhoneAccounts(long seed, int count, String packageName, String component)940     public static ArrayList<PhoneAccount> generateRandomPhoneAccounts(long seed, int count,
941             String packageName, String component) {
942         Random random = new Random(seed);
943         ArrayList<PhoneAccount> accounts = new ArrayList<>();
944         for (int ix = 0; ix < count; ix++) {
945             PhoneAccountHandle handle = new PhoneAccountHandle(
946                     new ComponentName(packageName, component), getRandomUuid(random).toString());
947             PhoneAccount acct = new PhoneAccount.Builder(handle, "TelecommTests")
948                     .setAddress(Uri.parse("sip:test@test.com"))
949                     .setSubscriptionAddress(Uri.parse("sip:test@test.com"))
950                     .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED
951                             | PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING
952                             | PhoneAccount.CAPABILITY_VIDEO_CALLING)
953                     .setHighlightColor(Color.BLUE)
954                     .setShortDescription(TestUtils.SELF_MANAGED_ACCOUNT_LABEL)
955                     .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
956                     .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
957                     .setExtras(TestUtils.SELF_MANAGED_ACCOUNT_1_EXTRAS)
958                     .build();
959             accounts.add(acct);
960         }
961         return accounts;
962     }
963 
964     /**
965      * Returns a random UUID based on the passed in Random generator.
966      * @param random Random generator.
967      * @return The UUID.
968      */
getRandomUuid(Random random)969     public static UUID getRandomUuid(Random random) {
970         byte[] array = new byte[16];
971         random.nextBytes(array);
972         return UUID.nameUUIDFromBytes(array);
973     }
974 
makePhoneAccountHandle(String id)975     public static PhoneAccountHandle makePhoneAccountHandle(String id) {
976         return new PhoneAccountHandle(TELECOM_CTS_COMPONENT_NAME, id);
977     }
978 
979 
980 }
981