1cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng/* 2066bd684a9c318ca9b85492dc3aa7a9384ae353eBrian Attwell * Copyright (C) 2015 The Android Open Source Project 3cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * 4cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * Licensed under the Apache License, Version 2.0 (the "License"); 5cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * you may not use this file except in compliance with the License. 6cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * You may obtain a copy of the License at 7cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * 8cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * http://www.apache.org/licenses/LICENSE-2.0 9cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * 10cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * Unless required by applicable law or agreed to in writing, software 11cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * distributed under the License is distributed on an "AS IS" BASIS, 12cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * See the License for the specific language governing permissions and 14cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * limitations under the License 15cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng */ 16cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng 170a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maipackage com.android.contacts; 18066bd684a9c318ca9b85492dc3aa7a9384ae353eBrian Attwell 197e558dcdb3af3f8a1ef57f0c445d4ef5172ee935Andrew Leeimport android.content.Context; 20cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Chengimport android.content.Intent; 21cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Chengimport android.net.Uri; 228e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Maiimport android.os.Bundle; 238e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Maiimport android.os.PersistableBundle; 245cf7f01aa00d67edbcd9d65fbfcbc1a4c56f60c3Tyler Gunnimport android.telecom.PhoneAccount; 25ca6b31e23c5f30602fb1d4a959726a91e0e4241bVinit Deshpandeimport android.telecom.PhoneAccountHandle; 265cf7f01aa00d67edbcd9d65fbfcbc1a4c56f60c3Tyler Gunnimport android.telecom.TelecomManager; 275cf7f01aa00d67edbcd9d65fbfcbc1a4c56f60c3Tyler Gunnimport android.telecom.VideoProfile; 288e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Maiimport android.telephony.CarrierConfigManager; 2918417a4f13cd231a5076043d10d1c89b8303ada6yaoluimport android.telephony.PhoneNumberUtils; 30066bd684a9c318ca9b85492dc3aa7a9384ae353eBrian Attwellimport android.text.TextUtils; 318e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Maiimport android.util.Log; 32cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng 330a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.compat.CompatUtils; 340a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.compat.PhoneAccountSdkCompat; 350a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.util.PermissionsUtil; 360a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.util.PhoneNumberHelper; 370a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contactsbind.FeedbackHelper; 388e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Maiimport com.android.contactsbind.experiments.Flags; 390a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.phone.common.PhoneConstants; 400a49afa2ad697307cc04ef4cb86570574fa720f2Gary Mai 419028db0d258947de2426db9bf62c18dc7c6fea87Yorke Leeimport java.util.List; 429028db0d258947de2426db9bf62c18dc7c6fea87Yorke Lee 43cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng/** 44066bd684a9c318ca9b85492dc3aa7a9384ae353eBrian Attwell * Utilities related to calls that can be used by non system apps. These 45066bd684a9c318ca9b85492dc3aa7a9384ae353eBrian Attwell * use {@link Intent#ACTION_CALL} instead of ACTION_CALL_PRIVILEGED. 46066bd684a9c318ca9b85492dc3aa7a9384ae353eBrian Attwell * 47066bd684a9c318ca9b85492dc3aa7a9384ae353eBrian Attwell * The privileged version of this util exists inside Dialer. 48cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng */ 49cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Chengpublic class CallUtil { 50cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng 517a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang public static final String TAG = "CallUtil"; 527a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang 53cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng /** 54001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn * Indicates that the video calling is not available. 55001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn */ 56001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn public static final int VIDEO_CALLING_DISABLED = 0; 57001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn 58001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn /** 59001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn * Indicates that video calling is enabled, regardless of presence status. 60001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn */ 61001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn public static final int VIDEO_CALLING_ENABLED = 1; 62001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn 63001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn /** 64001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn * Indicates that video calling is enabled, but the availability of video call affordances is 65001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn * determined by the presence status associated with contacts. 66001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn */ 67001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn public static final int VIDEO_CALLING_PRESENCE = 2; 68001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn 698e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai /** {@link PhoneAccount#EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK} */ 708e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai private static final String EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK = 718e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai "android.telecom.extra.SUPPORTS_VIDEO_CALLING_FALLBACK"; 728e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai 738e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai /** {@link CarrierConfigManager#CONFIG_ALLOW_VIDEO_CALLING_FALLBACK} */ 748e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai private static final String CONFIG_ALLOW_VIDEO_CALLING_FALLBACK = 758e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai "allow_video_calling_fallback_bool"; 768e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai 77001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn /** 78cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * Return an Intent for making a phone call. Scheme (e.g. tel, sip) will be determined 79cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * automatically. 80cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng */ 819e0c14e59650a45e31b60da254091d4ce13b3e49Tyler Gunn public static Intent getCallWithSubjectIntent(String number, 829e0c14e59650a45e31b60da254091d4ce13b3e49Tyler Gunn PhoneAccountHandle phoneAccountHandle, String callSubject) { 839e0c14e59650a45e31b60da254091d4ce13b3e49Tyler Gunn 849e0c14e59650a45e31b60da254091d4ce13b3e49Tyler Gunn final Intent intent = getCallIntent(getCallUri(number)); 859e0c14e59650a45e31b60da254091d4ce13b3e49Tyler Gunn intent.putExtra(TelecomManager.EXTRA_CALL_SUBJECT, callSubject); 869e0c14e59650a45e31b60da254091d4ce13b3e49Tyler Gunn if (phoneAccountHandle != null) { 879e0c14e59650a45e31b60da254091d4ce13b3e49Tyler Gunn intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); 889e0c14e59650a45e31b60da254091d4ce13b3e49Tyler Gunn } 899e0c14e59650a45e31b60da254091d4ce13b3e49Tyler Gunn return intent; 909e0c14e59650a45e31b60da254091d4ce13b3e49Tyler Gunn } 919e0c14e59650a45e31b60da254091d4ce13b3e49Tyler Gunn 929e0c14e59650a45e31b60da254091d4ce13b3e49Tyler Gunn /** 939e0c14e59650a45e31b60da254091d4ce13b3e49Tyler Gunn * Return an Intent for making a phone call. Scheme (e.g. tel, sip) will be determined 949e0c14e59650a45e31b60da254091d4ce13b3e49Tyler Gunn * automatically. 959e0c14e59650a45e31b60da254091d4ce13b3e49Tyler Gunn */ 96cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng public static Intent getCallIntent(String number) { 9718417a4f13cd231a5076043d10d1c89b8303ada6yaolu Uri uri = getCallUri(number); 9818417a4f13cd231a5076043d10d1c89b8303ada6yaolu return PhoneNumberUtils.isEmergencyNumber(number) 9918417a4f13cd231a5076043d10d1c89b8303ada6yaolu ? getCallIntentForEmergencyNumber(uri) : getCallIntent(uri); 10018417a4f13cd231a5076043d10d1c89b8303ada6yaolu } 10118417a4f13cd231a5076043d10d1c89b8303ada6yaolu 10218417a4f13cd231a5076043d10d1c89b8303ada6yaolu /** 10318417a4f13cd231a5076043d10d1c89b8303ada6yaolu * Return an Intent to directly start Dialer when calling an emergency number. Scheme is always 10418417a4f13cd231a5076043d10d1c89b8303ada6yaolu * PhoneAccount.SCHEME_TEL. 10518417a4f13cd231a5076043d10d1c89b8303ada6yaolu */ 10618417a4f13cd231a5076043d10d1c89b8303ada6yaolu private static Intent getCallIntentForEmergencyNumber(Uri uri) { 10718417a4f13cd231a5076043d10d1c89b8303ada6yaolu return new Intent(Intent.ACTION_DIAL, uri); 108cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng } 109cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng 110cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng /** 111cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * Return an Intent for making a phone call. A given Uri will be used as is (without any 112cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * sanity check). 113cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng */ 114cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng public static Intent getCallIntent(Uri uri) { 115066bd684a9c318ca9b85492dc3aa7a9384ae353eBrian Attwell return new Intent(Intent.ACTION_CALL, uri); 116ac51a8788f5ecf755784d00e1ef40a1a87b437c1Nancy Chen } 117ac51a8788f5ecf755784d00e1ef40a1a87b437c1Nancy Chen 118ac51a8788f5ecf755784d00e1ef40a1a87b437c1Nancy Chen /** 119066bd684a9c318ca9b85492dc3aa7a9384ae353eBrian Attwell * A variant of {@link #getCallIntent} for starting a video call. 120c18a7548cc07635f52575309d28a1f465748b717Andrew Lee */ 121c095aee097899239c8ec427cc640f9870edad1eeNancy Chen public static Intent getVideoCallIntent(String number, String callOrigin) { 122066bd684a9c318ca9b85492dc3aa7a9384ae353eBrian Attwell final Intent intent = new Intent(Intent.ACTION_CALL, getCallUri(number)); 123066bd684a9c318ca9b85492dc3aa7a9384ae353eBrian Attwell intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, 124cb93d46d7863da14b22481c05f551f1105a2684bYorke Lee VideoProfile.STATE_BIDIRECTIONAL); 125066bd684a9c318ca9b85492dc3aa7a9384ae353eBrian Attwell if (!TextUtils.isEmpty(callOrigin)) { 126cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng intent.putExtra(PhoneConstants.EXTRA_CALL_ORIGIN, callOrigin); 127cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng } 128cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng return intent; 129cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng } 130cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng 131cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng /** 132ed1a3b2598d3aafb3f9ec8583e231cbe72ea8020Jay Shrauner * Return Uri with an appropriate scheme, accepting both SIP and usual phone call 133cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng * numbers. 134cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng */ 135cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng public static Uri getCallUri(String number) { 1369e8e7cb9ec53b46ff476336e1b40f7dfa6ccb61cYorke Lee if (PhoneNumberHelper.isUriNumber(number)) { 137ed1a3b2598d3aafb3f9ec8583e231cbe72ea8020Jay Shrauner return Uri.fromParts(PhoneAccount.SCHEME_SIP, number, null); 138cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng } 139ed1a3b2598d3aafb3f9ec8583e231cbe72ea8020Jay Shrauner return Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null); 1409028db0d258947de2426db9bf62c18dc7c6fea87Yorke Lee } 14156046089a707f905482ea01eac697d36fcde4556Paul Soulos 1429028db0d258947de2426db9bf62c18dc7c6fea87Yorke Lee /** 143001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn * Determines if video calling is available, and if so whether presence checking is available 144001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn * as well. 1459028db0d258947de2426db9bf62c18dc7c6fea87Yorke Lee * 146001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn * Returns a bitmask with {@link #VIDEO_CALLING_ENABLED} to indicate that video calling is 147001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn * available, and {@link #VIDEO_CALLING_PRESENCE} if presence indication is also available. 148001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn * 149001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn * @param context The context 150001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn * @return A bit-mask describing the current video capabilities. 1519028db0d258947de2426db9bf62c18dc7c6fea87Yorke Lee */ 152001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn public static int getVideoCallingAvailability(Context context) { 1535fe647dc40b039501f52878607c418d807587bc6Nancy Chen if (!PermissionsUtil.hasPermission(context, android.Manifest.permission.READ_PHONE_STATE) 1545fe647dc40b039501f52878607c418d807587bc6Nancy Chen || !CompatUtils.isVideoCompatible()) { 155001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn return VIDEO_CALLING_DISABLED; 156d2c96928181af43c2e93f1236e4f8f251b1cfb9eYorke Lee } 1575cf7f01aa00d67edbcd9d65fbfcbc1a4c56f60c3Tyler Gunn TelecomManager telecommMgr = (TelecomManager) 1585cf7f01aa00d67edbcd9d65fbfcbc1a4c56f60c3Tyler Gunn context.getSystemService(Context.TELECOM_SERVICE); 159998492107a7907ef4bc0e992aec6196ce4db3b76Nancy Chen if (telecommMgr == null) { 160001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn return VIDEO_CALLING_DISABLED; 1617e558dcdb3af3f8a1ef57f0c445d4ef5172ee935Andrew Lee } 1627e558dcdb3af3f8a1ef57f0c445d4ef5172ee935Andrew Lee 1637a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang try { 1647a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang List<PhoneAccountHandle> accountHandles = telecommMgr.getCallCapablePhoneAccounts(); 1657a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang for (PhoneAccountHandle accountHandle : accountHandles) { 1667a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang PhoneAccount account = telecommMgr.getPhoneAccount(accountHandle); 1677a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang if (account != null) { 1687a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang if (account.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING)) { 1697a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang // Builds prior to N do not have presence support. 1707a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang if (!CompatUtils.isVideoPresenceCompatible()) { 1717a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang return VIDEO_CALLING_ENABLED; 1727a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang } 1737a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang 1747a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang int videoCapabilities = VIDEO_CALLING_ENABLED; 1757a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang if (account.hasCapabilities(PhoneAccountSdkCompat 1767a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang .CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)) { 1777a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang videoCapabilities |= VIDEO_CALLING_PRESENCE; 1787a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang } 1797a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang return videoCapabilities; 180001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn } 181001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn } 1829028db0d258947de2426db9bf62c18dc7c6fea87Yorke Lee } 1837a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang return VIDEO_CALLING_DISABLED; 1847a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang } catch (SecurityException e) { 1857a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang FeedbackHelper.sendFeedback(context, TAG, 186969c595dd845afa5f3b13d4e50c9d9a2165aac83Wenyi Wang "Security exception when getting call capable phone accounts", e); 1877a27b85c663171cf6ff95e25e27de7af9d95abeeWenyi Wang return VIDEO_CALLING_DISABLED; 1889028db0d258947de2426db9bf62c18dc7c6fea87Yorke Lee } 189001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn } 190001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn 191001d9740977421058daf3fca799e7bb8f1e7e58eTyler Gunn /** 192a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn * Determines if one of the call capable phone accounts defined supports calling with a subject 193a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn * specified. 194a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn * 195a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn * @param context The context. 196a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn * @return {@code true} if one of the call capable phone accounts supports calling with a 197a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn * subject specified, {@code false} otherwise. 198a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn */ 199a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn public static boolean isCallWithSubjectSupported(Context context) { 2005fe647dc40b039501f52878607c418d807587bc6Nancy Chen if (!PermissionsUtil.hasPermission(context, android.Manifest.permission.READ_PHONE_STATE) 2015fe647dc40b039501f52878607c418d807587bc6Nancy Chen || !CompatUtils.isCallSubjectCompatible()) { 202d2c96928181af43c2e93f1236e4f8f251b1cfb9eYorke Lee return false; 203d2c96928181af43c2e93f1236e4f8f251b1cfb9eYorke Lee } 204a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn TelecomManager telecommMgr = (TelecomManager) 205a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn context.getSystemService(Context.TELECOM_SERVICE); 206a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn if (telecommMgr == null) { 207a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn return false; 208a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn } 209a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn 210969c595dd845afa5f3b13d4e50c9d9a2165aac83Wenyi Wang try { 211969c595dd845afa5f3b13d4e50c9d9a2165aac83Wenyi Wang List<PhoneAccountHandle> accountHandles = telecommMgr.getCallCapablePhoneAccounts(); 212969c595dd845afa5f3b13d4e50c9d9a2165aac83Wenyi Wang for (PhoneAccountHandle accountHandle : accountHandles) { 213969c595dd845afa5f3b13d4e50c9d9a2165aac83Wenyi Wang PhoneAccount account = telecommMgr.getPhoneAccount(accountHandle); 214969c595dd845afa5f3b13d4e50c9d9a2165aac83Wenyi Wang if (account != null && account.hasCapabilities(PhoneAccount.CAPABILITY_CALL_SUBJECT)) { 215969c595dd845afa5f3b13d4e50c9d9a2165aac83Wenyi Wang return true; 216969c595dd845afa5f3b13d4e50c9d9a2165aac83Wenyi Wang } 217a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn } 218969c595dd845afa5f3b13d4e50c9d9a2165aac83Wenyi Wang return false; 219969c595dd845afa5f3b13d4e50c9d9a2165aac83Wenyi Wang } catch (SecurityException e) { 220969c595dd845afa5f3b13d4e50c9d9a2165aac83Wenyi Wang FeedbackHelper.sendFeedback(context, TAG, 221969c595dd845afa5f3b13d4e50c9d9a2165aac83Wenyi Wang "Security exception when getting call capable phone accounts", e); 222969c595dd845afa5f3b13d4e50c9d9a2165aac83Wenyi Wang return false; 223a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn } 224969c595dd845afa5f3b13d4e50c9d9a2165aac83Wenyi Wang 225a05f1535ab8dc7efa1d6454b5418259a6a513b64Tyler Gunn } 2268e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai 2278e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai /** 2288e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai * Determines if we're able to use Tachyon as a fallback for video calling. 2298e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai * 2308e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai * @param context The context. 2318e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai * @return {@code true} if there exists a call capable phone account which supports using a 2328e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai * fallback for video calling, the carrier configuration supports a fallback, and the 2338e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai * experiment for using a fallback is enabled. Otherwise {@code false} is returned. 2348e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai */ 2358e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai public static boolean isTachyonEnabled(Context context) { 2368e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai // Need to be able to read phone state, and be on at least N to check PhoneAccount extras. 2378e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai if (!PermissionsUtil.hasPermission(context, android.Manifest.permission.READ_PHONE_STATE) 2388e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai || !CompatUtils.isNCompatible()) { 2398e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai return false; 2408e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai } 2418e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai TelecomManager telecommMgr = (TelecomManager) 2428e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai context.getSystemService(Context.TELECOM_SERVICE); 2438e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai if (telecommMgr == null) { 2448e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai return false; 2458e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai } 2468e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai try { 2478e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai List<PhoneAccountHandle> accountHandles = telecommMgr.getCallCapablePhoneAccounts(); 2488e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai for (PhoneAccountHandle accountHandle : accountHandles) { 2498e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai PhoneAccount account = telecommMgr.getPhoneAccount(accountHandle); 2508e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai if (account == null) { 2518e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai continue; 2528e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai } 2538e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai // Check availability for the device config. 2548e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai final Bundle accountExtras = account.getExtras(); 2558e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai final boolean deviceEnabled = accountExtras != null && accountExtras.getBoolean( 2568e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK); 2578e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai if (Log.isLoggable(TAG, Log.DEBUG)) { 2588e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai Log.d(TAG, "Device video fallback config: " + deviceEnabled); 2598e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai } 2608e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai 2618e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai // Check availability from carrier config. 2628e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai final PersistableBundle carrierConfig = context.getSystemService( 2638e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai CarrierConfigManager.class).getConfig(); 2648e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai final boolean carrierEnabled = 2658e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai carrierConfig != null && carrierConfig.getBoolean( 2668e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai CONFIG_ALLOW_VIDEO_CALLING_FALLBACK); 2678e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai if (Log.isLoggable(TAG, Log.DEBUG)) { 2688e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai Log.d(TAG, "Carrier video fallback config: " + carrierEnabled); 2698e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai } 2708e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai 2718e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai // Check experiment value. 2728e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai final boolean experimentEnabled = Flags.getInstance().getBoolean( 2738e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai Experiments.QUICK_CONTACT_VIDEO_CALL); 2748e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai if (Log.isLoggable(TAG, Log.DEBUG)) { 2758e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai Log.d(TAG, "Experiment video fallback config: " + experimentEnabled); 2768e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai } 2778e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai 2788e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai // All three checks above must be true to enable Tachyon calling. 2798e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai return deviceEnabled && carrierEnabled && experimentEnabled; 2808e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai } 2818e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai return false; 2828e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai } catch (SecurityException e) { 2838e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai FeedbackHelper.sendFeedback(context, TAG, 2848e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai "Security exception when getting call capable phone accounts", e); 2858e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai return false; 2868e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai } 2878e6856b89d5708b3d20d4f9b12017c15303b5f82Gary Mai } 288cb5b270471f8cd27ba666268d11c60ffd9819b95Chiao Cheng} 289