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 
17 package com.android.contacts.common;
18 
19 import com.android.contacts.common.compat.CompatUtils;
20 import com.android.contacts.common.compat.PhoneAccountSdkCompat;
21 import com.android.contacts.common.util.PermissionsUtil;
22 import com.android.contacts.common.util.PhoneNumberHelper;
23 import com.android.phone.common.PhoneConstants;
24 
25 import android.content.Context;
26 import android.content.Intent;
27 import android.net.Uri;
28 import android.telecom.PhoneAccount;
29 import android.telecom.PhoneAccountHandle;
30 import android.telecom.TelecomManager;
31 import android.telecom.VideoProfile;
32 import android.text.TextUtils;
33 
34 import java.util.List;
35 
36 /**
37  * Utilities related to calls that can be used by non system apps. These
38  * use {@link Intent#ACTION_CALL} instead of ACTION_CALL_PRIVILEGED.
39  *
40  * The privileged version of this util exists inside Dialer.
41  */
42 public class CallUtil {
43 
44     /**
45      * Indicates that the video calling is not available.
46      */
47     public static final int VIDEO_CALLING_DISABLED = 0;
48 
49     /**
50      * Indicates that video calling is enabled, regardless of presence status.
51      */
52     public static final int VIDEO_CALLING_ENABLED = 1;
53 
54     /**
55      * Indicates that video calling is enabled, but the availability of video call affordances is
56      * determined by the presence status associated with contacts.
57      */
58     public static final int VIDEO_CALLING_PRESENCE = 2;
59 
60     /**
61      * Return an Intent for making a phone call. Scheme (e.g. tel, sip) will be determined
62      * automatically.
63      */
getCallWithSubjectIntent(String number, PhoneAccountHandle phoneAccountHandle, String callSubject)64     public static Intent getCallWithSubjectIntent(String number,
65             PhoneAccountHandle phoneAccountHandle, String callSubject) {
66 
67         final Intent intent = getCallIntent(getCallUri(number));
68         intent.putExtra(TelecomManager.EXTRA_CALL_SUBJECT, callSubject);
69         if (phoneAccountHandle != null) {
70             intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
71         }
72         return intent;
73     }
74 
75     /**
76      * Return an Intent for making a phone call. Scheme (e.g. tel, sip) will be determined
77      * automatically.
78      */
getCallIntent(String number)79     public static Intent getCallIntent(String number) {
80         return getCallIntent(getCallUri(number));
81     }
82 
83     /**
84      * Return an Intent for making a phone call. A given Uri will be used as is (without any
85      * sanity check).
86      */
getCallIntent(Uri uri)87     public static Intent getCallIntent(Uri uri) {
88         return new Intent(Intent.ACTION_CALL, uri);
89     }
90 
91     /**
92      * A variant of {@link #getCallIntent} for starting a video call.
93      */
getVideoCallIntent(String number, String callOrigin)94     public static Intent getVideoCallIntent(String number, String callOrigin) {
95         final Intent intent = new Intent(Intent.ACTION_CALL, getCallUri(number));
96         intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
97                 VideoProfile.STATE_BIDIRECTIONAL);
98         if (!TextUtils.isEmpty(callOrigin)) {
99             intent.putExtra(PhoneConstants.EXTRA_CALL_ORIGIN, callOrigin);
100         }
101         return intent;
102     }
103 
104     /**
105      * Return Uri with an appropriate scheme, accepting both SIP and usual phone call
106      * numbers.
107      */
getCallUri(String number)108     public static Uri getCallUri(String number) {
109         if (PhoneNumberHelper.isUriNumber(number)) {
110              return Uri.fromParts(PhoneAccount.SCHEME_SIP, number, null);
111         }
112         return Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null);
113     }
114 
115     /**
116      * @return Uri that directly dials a user's voicemail inbox.
117      */
getVoicemailUri()118     public static Uri getVoicemailUri() {
119         return Uri.fromParts(PhoneAccount.SCHEME_VOICEMAIL, "", null);
120     }
121 
122     /**
123      * Determines if video calling is available, and if so whether presence checking is available
124      * as well.
125      *
126      * Returns a bitmask with {@link #VIDEO_CALLING_ENABLED} to indicate that video calling is
127      * available, and {@link #VIDEO_CALLING_PRESENCE} if presence indication is also available.
128      *
129      * @param context The context
130      * @return A bit-mask describing the current video capabilities.
131      */
getVideoCallingAvailability(Context context)132     public static int getVideoCallingAvailability(Context context) {
133         if (!PermissionsUtil.hasPermission(context, android.Manifest.permission.READ_PHONE_STATE)
134                 || !CompatUtils.isVideoCompatible()) {
135             return VIDEO_CALLING_DISABLED;
136         }
137         TelecomManager telecommMgr = (TelecomManager)
138                 context.getSystemService(Context.TELECOM_SERVICE);
139         if (telecommMgr == null) {
140             return VIDEO_CALLING_DISABLED;
141         }
142 
143         List<PhoneAccountHandle> accountHandles = telecommMgr.getCallCapablePhoneAccounts();
144         for (PhoneAccountHandle accountHandle : accountHandles) {
145             PhoneAccount account = telecommMgr.getPhoneAccount(accountHandle);
146             if (account != null) {
147                 if (account.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING)) {
148                     // Builds prior to N do not have presence support.
149                     if (!CompatUtils.isVideoPresenceCompatible()) {
150                         return VIDEO_CALLING_ENABLED;
151                     }
152 
153                     int videoCapabilities = VIDEO_CALLING_ENABLED;
154                     if (account.hasCapabilities(
155                             PhoneAccountSdkCompat.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)) {
156                         videoCapabilities |= VIDEO_CALLING_PRESENCE;
157                     }
158                     return videoCapabilities;
159                 }
160             }
161         }
162         return VIDEO_CALLING_DISABLED;
163     }
164 
165     /**
166      * Determines if one of the call capable phone accounts defined supports video calling.
167      *
168      * @param context The context.
169      * @return {@code true} if one of the call capable phone accounts supports video calling,
170      *      {@code false} otherwise.
171      */
isVideoEnabled(Context context)172     public static boolean isVideoEnabled(Context context) {
173         return (getVideoCallingAvailability(context) & VIDEO_CALLING_ENABLED) != 0;
174     }
175 
176     /**
177      * Determines if one of the call capable phone accounts defined supports calling with a subject
178      * specified.
179      *
180      * @param context The context.
181      * @return {@code true} if one of the call capable phone accounts supports calling with a
182      *      subject specified, {@code false} otherwise.
183      */
isCallWithSubjectSupported(Context context)184     public static boolean isCallWithSubjectSupported(Context context) {
185         if (!PermissionsUtil.hasPermission(context, android.Manifest.permission.READ_PHONE_STATE)
186                 || !CompatUtils.isCallSubjectCompatible()) {
187             return false;
188         }
189         TelecomManager telecommMgr = (TelecomManager)
190                 context.getSystemService(Context.TELECOM_SERVICE);
191         if (telecommMgr == null) {
192             return false;
193         }
194 
195         List<PhoneAccountHandle> accountHandles = telecommMgr.getCallCapablePhoneAccounts();
196         for (PhoneAccountHandle accountHandle : accountHandles) {
197             PhoneAccount account = telecommMgr.getPhoneAccount(accountHandle);
198             if (account != null && account.hasCapabilities(PhoneAccount.CAPABILITY_CALL_SUBJECT)) {
199                 return true;
200             }
201         }
202         return false;
203     }
204 }
205