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