1 /* 2 * Copyright (C) 2023 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.telecom.cts.apps; 18 19 import static android.telecom.CallAttributes.DIRECTION_INCOMING; 20 import static android.telecom.CallAttributes.DIRECTION_OUTGOING; 21 22 import android.net.Uri; 23 import android.os.Bundle; 24 import android.telecom.CallAttributes; 25 import android.telecom.PhoneAccountHandle; 26 import android.telecom.TelecomManager; 27 28 import java.util.Random; 29 30 public class AttributesUtil { 31 private static final Random sRandom = new Random(0); 32 private static final Uri TEST_URI_OUT = Uri.parse("tel:123-TEST"); 33 private static final String TEST_NAME_OUT = "Mike Tyson"; 34 private static final Uri TEST_URI_IN = Uri.parse("tel:456-TEST"); 35 private static final String TEST_NAME_IN = "Alan Turing"; 36 public static final String TEST_EMERGENCY_NUMBER = "5553637"; 37 private static final Uri TEST_EMERGENCY_URI = Uri.fromParts("tel", TEST_EMERGENCY_NUMBER, null); 38 public static final String SYSTEM_DIALER_PKG_NAME = "android.telecom.cts.cuj/.CujInCallService"; 39 public static final String TEST_EMERGENCY_MANAGED_PHONE_ACCOUNT_PKG_NAME = 40 "android.telecom.cts.apps.managedapp"; 41 public static final String TEST_EMERGENCY_MANAGED_CLONE_PHONE_ACCOUNT_PKG_NAME = 42 "android.telecom.cts.apps.managedappclone"; 43 private static final Uri TEST_IN_CALL_MMI_URI = Uri.parse("tel:0"); 44 private static final Uri TEST_MMI_URI = Uri.parse("tel:*%2306%23"); 45 46 /** 47 * @return true if the call is holdable according to the CallAttributes 48 */ hasSetInactiveCapabilities(CallAttributes callAttributes)49 public static boolean hasSetInactiveCapabilities(CallAttributes callAttributes) { 50 return (callAttributes.getCallCapabilities() & CallAttributes.SUPPORTS_SET_INACTIVE) 51 == CallAttributes.SUPPORTS_SET_INACTIVE; 52 } 53 54 /** 55 * @return a CallAttributes object for the given TelecomAppName. The Name and Address are 56 * defaulted depending on the direction. 57 */ getDefaultAttributesForApp(TelecomTestApp name, boolean isOutgoing)58 public static CallAttributes getDefaultAttributesForApp(TelecomTestApp name, boolean isOutgoing) 59 throws Exception { 60 return new CallAttributes.Builder( 61 getPhoneAccountHandleForApp(name), 62 getDirectionFromBool(isOutgoing), 63 getDefaultName(isOutgoing), getDefaultAddress(isOutgoing)) 64 .setCallType(CallAttributes.AUDIO_CALL) 65 .setCallCapabilities(CallAttributes.SUPPORTS_SET_INACTIVE) 66 .build(); 67 } 68 69 /** 70 * @return a CallAttributes object for the given TelecomAppName. The Name and Address are 71 * randomized! 72 */ getRandomAttributesForApp(TelecomTestApp name, boolean isOutgoing, boolean isHoldable)73 public static CallAttributes getRandomAttributesForApp(TelecomTestApp name, 74 boolean isOutgoing, 75 boolean isHoldable) 76 throws Exception { 77 return new CallAttributes.Builder( 78 getPhoneAccountHandleForApp(name), 79 getDirectionFromBool(isOutgoing), 80 getRandomName(), getRandomAddress()) 81 .setCallType(CallAttributes.AUDIO_CALL) 82 .setCallCapabilities(setCallCapabilities(isHoldable)) 83 .build(); 84 } 85 86 /** 87 * @return a CallAttributes object for the MANAGED_APP. The Name and Address are defaulted 88 * depending on the direction. 89 */ getDefaultAttributesForManaged( PhoneAccountHandle handle, boolean isOutgoing, boolean isEmergency)90 public static CallAttributes getDefaultAttributesForManaged( 91 PhoneAccountHandle handle, boolean isOutgoing, boolean isEmergency) { 92 return new CallAttributes.Builder( 93 handle, 94 getDirectionFromBool(isOutgoing), 95 TEST_NAME_IN, 96 isEmergency 97 ? getDefaultAddressForEmergency() 98 : getDefaultAddress(isOutgoing)) 99 .setCallType(CallAttributes.AUDIO_CALL) 100 .setCallCapabilities(CallAttributes.SUPPORTS_SET_INACTIVE) 101 .build(); 102 } 103 104 /** 105 * @return a CallAttributes object for verifying MMI codes. 106 */ getDefaultMmiAttributesForApp( TelecomTestApp name, PhoneAccountHandle handle, boolean inCallMmi)107 public static CallAttributes getDefaultMmiAttributesForApp( 108 TelecomTestApp name, PhoneAccountHandle handle, boolean inCallMmi) throws Exception { 109 if (handle == null) { 110 handle = getPhoneAccountHandleForApp(name); 111 } 112 return new CallAttributes.Builder( 113 handle, DIRECTION_OUTGOING, TEST_NAME_OUT, getDefaultMmiAddress(inCallMmi)) 114 .setCallType(CallAttributes.AUDIO_CALL) 115 .setCallCapabilities(CallAttributes.SUPPORTS_SET_INACTIVE) 116 .build(); 117 } 118 119 /** 120 * @return a CallAttributes object for the MANAGED_APP. The Name and Address are 121 * randomized! 122 */ getRandomAttributesForManaged(PhoneAccountHandle handle, boolean isOutgoing, boolean isHoldable)123 public static CallAttributes getRandomAttributesForManaged(PhoneAccountHandle handle, 124 boolean isOutgoing, 125 boolean isHoldable) { 126 return new CallAttributes.Builder( 127 handle, 128 getDirectionFromBool(isOutgoing), 129 getRandomName(), getRandomAddress()) 130 .setCallType(CallAttributes.AUDIO_CALL) 131 .setCallCapabilities(setCallCapabilities(isHoldable)) 132 .build(); 133 } 134 135 /** 136 * This method should help set the CallCapabilities that are defined in the CallAttributes 137 * class 138 */ setCallCapabilities(boolean isHoldable)139 public static int setCallCapabilities(boolean isHoldable) { 140 return isHoldable ? CallAttributes.SUPPORTS_SET_INACTIVE : 0; 141 } 142 143 /** 144 * @return The [PhoneAccountHandle] for the given TelecomAppName that is defined in the 145 * application.info package 146 */ getPhoneAccountHandleForApp(TelecomTestApp name)147 public static PhoneAccountHandle getPhoneAccountHandleForApp(TelecomTestApp name) 148 throws Exception { 149 switch (name) { 150 case TransactionalVoipAppMain -> { 151 return TelecomTestApp.TRANSACTIONAL_APP_DEFAULT_HANDLE; 152 } 153 case TransactionalVoipAppClone -> { 154 return TelecomTestApp.TRANSACTIONAL_APP_CLONE_DEFAULT_HANDLE; 155 } 156 case ConnectionServiceVoipAppMain -> { 157 return TelecomTestApp.SELF_MANAGED_CS_MAIN_HANDLE; 158 } 159 case ConnectionServiceVoipAppClone -> { 160 return TelecomTestApp.SELF_MANAGED_CS_CLONE_HANDLE; 161 } 162 case ManagedConnectionServiceApp -> { 163 throw new Exception("The PhoneAccount for ManagedConnectionServiceApp is not" 164 + " is kept in BaseAppVerifier"); 165 } 166 case ManagedConnectionServiceAppClone -> { 167 throw new Exception("The PhoneAccount for ManagedConnectionServiceAppClone is not" 168 + " is kept in BaseAppVerifier"); 169 } 170 } 171 throw new Exception(String.format("%s does not have a PhoneAccount mapping", name)); 172 } 173 174 /** 175 * @return injects the [PhoneAccountHandle] that is defined in the [CallAttribute]s object into 176 * a Bundle. 177 */ getExtrasWithPhoneAccount(CallAttributes callAttributes)178 public static Bundle getExtrasWithPhoneAccount(CallAttributes callAttributes) { 179 Bundle extras = new Bundle(); 180 extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, 181 callAttributes.getPhoneAccountHandle()); 182 if (!isOutgoing(callAttributes)) { 183 extras.putParcelable( 184 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, 185 callAttributes.getAddress() 186 ); 187 } 188 return extras; 189 } 190 191 /** 192 * @return true if the call is outgoing bases on the [CallAttribute]s object 193 */ isOutgoing(CallAttributes callAttributes)194 public static boolean isOutgoing(CallAttributes callAttributes) { 195 return callAttributes.getDirection() == DIRECTION_OUTGOING; 196 } 197 getDirectionFromBool(boolean isOutgoing)198 private static int getDirectionFromBool(boolean isOutgoing) { 199 return isOutgoing ? DIRECTION_OUTGOING : DIRECTION_INCOMING; 200 } 201 getDefaultAddress(boolean isOutgoing)202 private static Uri getDefaultAddress(boolean isOutgoing) { 203 return isOutgoing ? TEST_URI_OUT : TEST_URI_IN; 204 } 205 getDefaultAddressForEmergency()206 private static Uri getDefaultAddressForEmergency() { 207 return TEST_EMERGENCY_URI; 208 } 209 getDefaultMmiAddress(boolean inCallMmi)210 private static Uri getDefaultMmiAddress(boolean inCallMmi) { 211 return inCallMmi ? TEST_IN_CALL_MMI_URI : TEST_MMI_URI; 212 } 213 getDefaultName(boolean isOutgoing)214 private static String getDefaultName(boolean isOutgoing) { 215 return isOutgoing ? TEST_NAME_IN : TEST_NAME_OUT; 216 } 217 getRandomName()218 private static String getRandomName() { 219 StringBuilder builder = new StringBuilder(); 220 for (int i = 0; i < 16; i++) { 221 builder.append((char) sRandom.nextInt('a', 'z')); 222 } 223 return builder.toString(); 224 } 225 getRandomAddress()226 private static Uri getRandomAddress() { 227 StringBuilder builder = new StringBuilder("tel:"); 228 for (int i = 0; i < 11; i++) { 229 builder.append(sRandom.nextInt(10)); 230 } 231 return Uri.parse(builder.toString()); 232 } 233 } 234