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.content.ComponentName; 20 import android.content.Context; 21 import android.content.pm.PackageManager; 22 import android.os.Build; 23 import android.os.ParcelFileDescriptor; 24 import android.os.Process; 25 import android.telecom.PhoneAccountHandle; 26 27 import java.io.BufferedReader; 28 import java.io.FileInputStream; 29 import java.io.InputStream; 30 import java.io.InputStreamReader; 31 import java.nio.charset.StandardCharsets; 32 33 public class TestUtils { 34 static final String TAG = "TelecomCTSTests"; 35 static final boolean HAS_TELECOM = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; 36 static final long WAIT_FOR_STATE_CHANGE_TIMEOUT_MS = 10000; 37 static final long WAIT_FOR_CALL_ADDED_TIMEOUT_S = 15; 38 static final long WAIT_FOR_STATE_CHANGE_TIMEOUT_CALLBACK = 50; 39 40 // Non-final to allow modification by tests not in this package (e.g. permission-related 41 // tests in the Telecom2 test package. 42 public static String PACKAGE = "android.telecom.cts"; 43 public static final String COMPONENT = "android.telecom.cts.CtsConnectionService"; 44 public static final String REMOTE_COMPONENT = "android.telecom.cts.CtsRemoteConnectionService"; 45 public static final String ACCOUNT_ID = "xtstest_CALL_PROVIDER_ID"; 46 public static final String REMOTE_ACCOUNT_ID = "xtstest_REMOTE_CALL_PROVIDER_ID"; 47 48 public static final String ACCOUNT_LABEL = "CTSConnectionService"; 49 public static final String REMOTE_ACCOUNT_LABEL = "CTSRemoteConnectionService"; 50 51 private static final String COMMAND_SET_DEFAULT_DIALER = "telecom set-default-dialer "; 52 53 private static final String COMMAND_GET_DEFAULT_DIALER = "telecom get-default-dialer"; 54 55 private static final String COMMAND_GET_SYSTEM_DIALER = "telecom get-system-dialer"; 56 57 private static final String COMMAND_ENABLE = "telecom set-phone-account-enabled "; 58 59 private static final String COMMAND_REGISTER_SIM = "telecom register-sim-phone-account "; 60 61 public static final String MERGE_CALLER_NAME = "calls-merged"; 62 public static final String SWAP_CALLER_NAME = "calls-swapped"; 63 private static final String PRIMARY_USER_SN = "0"; 64 shouldTestTelecom(Context context)65 public static boolean shouldTestTelecom(Context context) { 66 if (!HAS_TELECOM) { 67 return false; 68 } 69 final PackageManager pm = context.getPackageManager(); 70 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) && 71 pm.hasSystemFeature(PackageManager.FEATURE_CONNECTION_SERVICE); 72 } 73 setDefaultDialer(Instrumentation instrumentation, String packageName)74 public static String setDefaultDialer(Instrumentation instrumentation, String packageName) 75 throws Exception { 76 return executeShellCommand(instrumentation, COMMAND_SET_DEFAULT_DIALER + packageName); 77 } 78 getDefaultDialer(Instrumentation instrumentation)79 public static String getDefaultDialer(Instrumentation instrumentation) throws Exception { 80 return executeShellCommand(instrumentation, COMMAND_GET_DEFAULT_DIALER); 81 } 82 getSystemDialer(Instrumentation instrumentation)83 public static String getSystemDialer(Instrumentation instrumentation) throws Exception { 84 return executeShellCommand(instrumentation, COMMAND_GET_SYSTEM_DIALER); 85 } 86 enablePhoneAccount(Instrumentation instrumentation, PhoneAccountHandle handle)87 public static void enablePhoneAccount(Instrumentation instrumentation, 88 PhoneAccountHandle handle) throws Exception { 89 final ComponentName component = handle.getComponentName(); 90 executeShellCommand(instrumentation, COMMAND_ENABLE 91 + component.getPackageName() + "/" + component.getClassName() + " " 92 + handle.getId() + " " + PRIMARY_USER_SN); 93 } 94 registerSimPhoneAccount(Instrumentation instrumentation, PhoneAccountHandle handle, String label, String address)95 public static void registerSimPhoneAccount(Instrumentation instrumentation, 96 PhoneAccountHandle handle, String label, String address) throws Exception { 97 final ComponentName component = handle.getComponentName(); 98 executeShellCommand(instrumentation, COMMAND_REGISTER_SIM 99 + component.getPackageName() + "/" + component.getClassName() + " " 100 + handle.getId() + " " + PRIMARY_USER_SN + " " + label + " " + address); 101 } 102 103 /** 104 * Executes the given shell command and returns the output in a string. Note that even 105 * if we don't care about the output, we have to read the stream completely to make the 106 * command execute. 107 */ executeShellCommand(Instrumentation instrumentation, String command)108 public static String executeShellCommand(Instrumentation instrumentation, 109 String command) throws Exception { 110 final ParcelFileDescriptor pfd = 111 instrumentation.getUiAutomation().executeShellCommand(command); 112 BufferedReader br = null; 113 try (InputStream in = new FileInputStream(pfd.getFileDescriptor())) { 114 br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); 115 String str = null; 116 StringBuilder out = new StringBuilder(); 117 while ((str = br.readLine()) != null) { 118 out.append(str); 119 } 120 return out.toString(); 121 } finally { 122 if (br != null) { 123 closeQuietly(br); 124 } 125 closeQuietly(pfd); 126 } 127 } 128 closeQuietly(AutoCloseable closeable)129 private static void closeQuietly(AutoCloseable closeable) { 130 if (closeable != null) { 131 try { 132 closeable.close(); 133 } catch (RuntimeException rethrown) { 134 throw rethrown; 135 } catch (Exception ignored) { 136 } 137 } 138 } 139 } 140