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 31 public class AttributesUtil { 32 private static final Random sRandom = new Random(0); 33 private static final Uri TEST_URI_OUT = Uri.parse("tel:123-TEST"); 34 private static final String TEST_NAME_OUT = "Mike Tyson"; 35 private static final Uri TEST_URI_IN = Uri.parse("tel:456-TEST"); 36 private static final String TEST_NAME_IN = "Alan Turing"; 37 38 /** 39 * @return true if the call is holdable according to the CallAttributes 40 */ hasSetInactiveCapabilities(CallAttributes callAttributes)41 public static boolean hasSetInactiveCapabilities(CallAttributes callAttributes) { 42 return (callAttributes.getCallCapabilities() & CallAttributes.SUPPORTS_SET_INACTIVE) 43 == CallAttributes.SUPPORTS_SET_INACTIVE; 44 } 45 46 /** 47 * @return a CallAttributes object for the given TelecomAppName. The Name and Address are 48 * defaulted depending on the direction. 49 */ getDefaultAttributesForApp(TelecomTestApp name, boolean isOutgoing)50 public static CallAttributes getDefaultAttributesForApp(TelecomTestApp name, boolean isOutgoing) 51 throws Exception { 52 return new CallAttributes.Builder( 53 getPhoneAccountHandleForApp(name), 54 getDirectionFromBool(isOutgoing), 55 getDefaultName(isOutgoing), getDefaultAddress(isOutgoing)) 56 .setCallType(CallAttributes.AUDIO_CALL) 57 .setCallCapabilities(CallAttributes.SUPPORTS_SET_INACTIVE) 58 .build(); 59 } 60 61 /** 62 * @return a CallAttributes object for the given TelecomAppName. The Name and Address are 63 * randomized! 64 */ getRandomAttributesForApp(TelecomTestApp name, boolean isOutgoing, boolean isHoldable)65 public static CallAttributes getRandomAttributesForApp(TelecomTestApp name, 66 boolean isOutgoing, 67 boolean isHoldable) 68 throws Exception { 69 return new CallAttributes.Builder( 70 getPhoneAccountHandleForApp(name), 71 getDirectionFromBool(isOutgoing), 72 getRandomName(), getRandomAddress()) 73 .setCallType(CallAttributes.AUDIO_CALL) 74 .setCallCapabilities(setCallCapabilities(isHoldable)) 75 .build(); 76 } 77 78 /** 79 * @return a CallAttributes object for the MANAGED_APP. The Name and Address are 80 * defaulted depending on the direction. 81 */ getDefaultAttributesForManaged(PhoneAccountHandle handle, boolean isOutgoing)82 public static CallAttributes getDefaultAttributesForManaged(PhoneAccountHandle handle, 83 boolean isOutgoing) { 84 return new CallAttributes.Builder( 85 handle, 86 getDirectionFromBool(isOutgoing), 87 TEST_NAME_IN, getDefaultAddress(isOutgoing)) 88 .setCallType(CallAttributes.AUDIO_CALL) 89 .setCallCapabilities(CallAttributes.SUPPORTS_SET_INACTIVE) 90 .build(); 91 } 92 93 /** 94 * @return a CallAttributes object for the MANAGED_APP. The Name and Address are 95 * randomized! 96 */ getRandomAttributesForManaged(PhoneAccountHandle handle, boolean isOutgoing, boolean isHoldable)97 public static CallAttributes getRandomAttributesForManaged(PhoneAccountHandle handle, 98 boolean isOutgoing, 99 boolean isHoldable) { 100 return new CallAttributes.Builder( 101 handle, 102 getDirectionFromBool(isOutgoing), 103 getRandomName(), getRandomAddress()) 104 .setCallType(CallAttributes.AUDIO_CALL) 105 .setCallCapabilities(setCallCapabilities(isHoldable)) 106 .build(); 107 } 108 109 /** 110 * This method should help set the CallCapabilities that are defined in the CallAttributes 111 * class 112 */ setCallCapabilities(boolean isHoldable)113 public static int setCallCapabilities(boolean isHoldable) { 114 return isHoldable ? CallAttributes.SUPPORTS_SET_INACTIVE : 0; 115 } 116 117 /** 118 * @return The [PhoneAccountHandle] for the given TelecomAppName that is defined in the 119 * application.info package 120 */ getPhoneAccountHandleForApp(TelecomTestApp name)121 public static PhoneAccountHandle getPhoneAccountHandleForApp(TelecomTestApp name) 122 throws Exception { 123 switch (name) { 124 case TransactionalVoipAppMain -> { 125 return TelecomTestApp.TRANSACTIONAL_APP_DEFAULT_HANDLE; 126 } 127 case TransactionalVoipAppClone -> { 128 return TelecomTestApp.TRANSACTIONAL_APP_CLONE_DEFAULT_HANDLE; 129 } 130 case ConnectionServiceVoipAppMain -> { 131 return TelecomTestApp.SELF_MANAGED_CS_MAIN_HANDLE; 132 } 133 case ConnectionServiceVoipAppClone -> { 134 return TelecomTestApp.SELF_MANAGED_CS_CLONE_HANDLE; 135 } 136 case ManagedConnectionServiceApp -> { 137 throw new Exception("The PhoneAccount for ManagedConnectionServiceApp is not" 138 + " is kept in BaseAppVerifier"); 139 } 140 } 141 throw new Exception(String.format("%s does not have a PhoneAccount mapping", name)); 142 } 143 144 /** 145 * @return injects the [PhoneAccountHandle] that is defined in the [CallAttribute]s object into 146 * a Bundle. 147 */ getExtrasWithPhoneAccount(CallAttributes callAttributes)148 public static Bundle getExtrasWithPhoneAccount(CallAttributes callAttributes) { 149 Bundle extras = new Bundle(); 150 extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, 151 callAttributes.getPhoneAccountHandle()); 152 if (!isOutgoing(callAttributes)) { 153 extras.putParcelable( 154 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, 155 callAttributes.getAddress() 156 ); 157 } 158 return extras; 159 } 160 161 /** 162 * @return true if the call is outgoing bases on the [CallAttribute]s object 163 */ isOutgoing(CallAttributes callAttributes)164 public static boolean isOutgoing(CallAttributes callAttributes) { 165 return callAttributes.getDirection() == DIRECTION_OUTGOING; 166 } 167 getDirectionFromBool(boolean isOutgoing)168 private static int getDirectionFromBool(boolean isOutgoing) { 169 return isOutgoing ? DIRECTION_OUTGOING : DIRECTION_INCOMING; 170 } 171 getDefaultAddress(boolean isOutgoing)172 private static Uri getDefaultAddress(boolean isOutgoing) { 173 return isOutgoing ? TEST_URI_OUT : TEST_URI_IN; 174 } 175 getDefaultName(boolean isOutgoing)176 private static String getDefaultName(boolean isOutgoing) { 177 return isOutgoing ? TEST_NAME_IN : TEST_NAME_OUT; 178 } 179 getRandomName()180 private static String getRandomName() { 181 byte[] array = new byte[16]; 182 sRandom.nextBytes(array); 183 return sRandom.toString(); 184 } 185 getRandomAddress()186 private static Uri getRandomAddress() { 187 byte[] array = new byte[11]; 188 sRandom.nextBytes(array); 189 return Uri.parse("tel:" + sRandom); 190 } 191 } 192