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