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