1664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal/*
2664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * Copyright 2014, The Android Open Source Project
3664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal *
4664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * Licensed under the Apache License, Version 2.0 (the "License");
5664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * you may not use this file except in compliance with the License.
6664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * You may obtain a copy of the License at
7664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal *
8664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal *     http://www.apache.org/licenses/LICENSE-2.0
9664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal *
10664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * Unless required by applicable law or agreed to in writing, software
11664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * distributed under the License is distributed on an "AS IS" BASIS,
12664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * See the License for the specific language governing permissions and
14664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * limitations under the License.
15664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal */
16664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
177cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnpackage com.android.server.telecom;
18664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
1991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunnimport android.content.Context;
20701dc006ac11625b55d872f1639107b028933895Andrew Leeimport android.telecom.DisconnectCause;
21a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebingerimport android.telecom.Log;
227cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.ParcelableConnection;
237cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.PhoneAccount;
247cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.PhoneAccountHandle;
25664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
2691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn// TODO: Needed for move to system service: import com.android.internal.R;
2791d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn
28f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebingerimport com.android.internal.annotations.VisibleForTesting;
29f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger
30664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.ArrayList;
31646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepalimport java.util.Collection;
32646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepalimport java.util.HashSet;
33664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.Iterator;
34664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.List;
35293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awadimport java.util.Objects;
36664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
37664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal/**
389250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee * This class creates connections to place new outgoing calls or to attach to an existing incoming
39664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * call. In either case, this class cycles through a set of connection services until:
40664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal *   - a connection service returns a newly created connection in which case the call is displayed
41664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal *     to the user
42664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal *   - a connection service cancels the process, in which case the call is aborted
43664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal */
44f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger@VisibleForTesting
45f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebingerpublic class CreateConnectionProcessor implements CreateConnectionResponse {
46293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
47293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    // Describes information required to attempt to make a phone call
48293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    private static class CallAttemptRecord {
49293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        // The PhoneAccount describing the target connection service which we will
50293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        // contact in order to process an attempt
51b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        public final PhoneAccountHandle connectionManagerPhoneAccount;
52293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        // The PhoneAccount which we will tell the target connection service to use
53293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        // for attempting to make the actual phone call
54b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        public final PhoneAccountHandle targetPhoneAccount;
55293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
56293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        public CallAttemptRecord(
57b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                PhoneAccountHandle connectionManagerPhoneAccount,
58b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                PhoneAccountHandle targetPhoneAccount) {
59b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            this.connectionManagerPhoneAccount = connectionManagerPhoneAccount;
60b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            this.targetPhoneAccount = targetPhoneAccount;
61293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        }
62293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
63293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        @Override
64293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        public String toString() {
65293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad            return "CallAttemptRecord("
66b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    + Objects.toString(connectionManagerPhoneAccount) + ","
67b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    + Objects.toString(targetPhoneAccount) + ")";
68293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        }
696e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn
706e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn        /**
716e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn         * Determines if this instance of {@code CallAttemptRecord} has the same underlying
726e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn         * {@code PhoneAccountHandle}s as another instance.
736e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn         *
746e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn         * @param obj The other instance to compare against.
756e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn         * @return {@code True} if the {@code CallAttemptRecord}s are equal.
766e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn         */
776e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn        @Override
786e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn        public boolean equals(Object obj) {
796e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn            if (obj instanceof CallAttemptRecord) {
806e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn                CallAttemptRecord other = (CallAttemptRecord) obj;
816e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn                return Objects.equals(connectionManagerPhoneAccount,
826e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn                        other.connectionManagerPhoneAccount) &&
836e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn                        Objects.equals(targetPhoneAccount, other.targetPhoneAccount);
846e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn            }
856e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn            return false;
866e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn        }
87293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    }
88293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
89664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private final Call mCall;
90664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private final ConnectionServiceRepository mRepository;
91293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    private List<CallAttemptRecord> mAttemptRecords;
92293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    private Iterator<CallAttemptRecord> mAttemptRecordIterator;
93f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger    private CreateConnectionResponse mCallResponse;
94701dc006ac11625b55d872f1639107b028933895Andrew Lee    private DisconnectCause mLastErrorDisconnectCause;
9591d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
9691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn    private final Context mContext;
97646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal    private CreateConnectionTimeout mTimeout;
98f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger    private ConnectionServiceWrapper mService;
996e8f3d70ac7397afb4cb5ab276d1cd385c92dd21Brad Ebinger    private int mConnectionAttempt;
100664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
101f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger    @VisibleForTesting
102f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger    public CreateConnectionProcessor(
10391d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn            Call call, ConnectionServiceRepository repository, CreateConnectionResponse response,
10491d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn            PhoneAccountRegistrar phoneAccountRegistrar, Context context) {
1058de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad        Log.v(this, "CreateConnectionProcessor created for Call = %s", call);
106664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mCall = call;
107664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mRepository = repository;
108f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        mCallResponse = response;
10991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        mPhoneAccountRegistrar = phoneAccountRegistrar;
11091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        mContext = context;
1116e8f3d70ac7397afb4cb5ab276d1cd385c92dd21Brad Ebinger        mConnectionAttempt = 0;
112664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    }
113664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
114752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal    boolean isProcessingComplete() {
115f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        return mCallResponse == null;
116752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal    }
117752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal
118646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal    boolean isCallTimedOut() {
119646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        return mTimeout != null && mTimeout.isCallTimedOut();
120646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal    }
121646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal
1226e8f3d70ac7397afb4cb5ab276d1cd385c92dd21Brad Ebinger    public int getConnectionAttempt() {
1236e8f3d70ac7397afb4cb5ab276d1cd385c92dd21Brad Ebinger        return mConnectionAttempt;
1246e8f3d70ac7397afb4cb5ab276d1cd385c92dd21Brad Ebinger    }
1256e8f3d70ac7397afb4cb5ab276d1cd385c92dd21Brad Ebinger
126f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger    @VisibleForTesting
127f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger    public void process() {
128664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        Log.v(this, "process");
129646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        clearTimeout();
130293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        mAttemptRecords = new ArrayList<>();
131b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        if (mCall.getTargetPhoneAccount() != null) {
1327957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            mAttemptRecords.add(new CallAttemptRecord(
1337957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal                    mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount()));
134664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
135a90ba73e6ca2e7e3ef88e41477bf595e03f9359fTyler Gunn        if (!mCall.isSelfManaged()) {
136a90ba73e6ca2e7e3ef88e41477bf595e03f9359fTyler Gunn            adjustAttemptsForConnectionManager();
137a90ba73e6ca2e7e3ef88e41477bf595e03f9359fTyler Gunn            adjustAttemptsForEmergency(mCall.getTargetPhoneAccount());
138a90ba73e6ca2e7e3ef88e41477bf595e03f9359fTyler Gunn        }
139293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        mAttemptRecordIterator = mAttemptRecords.iterator();
14069eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad        attemptNextPhoneAccount();
141664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    }
142664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
143752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal    boolean hasMorePhoneAccounts() {
144752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal        return mAttemptRecordIterator.hasNext();
145752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal    }
146752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal
147752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal    void continueProcessingIfPossible(CreateConnectionResponse response,
148752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal            DisconnectCause disconnectCause) {
149752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal        Log.v(this, "continueProcessingIfPossible");
150f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        mCallResponse = response;
151752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal        mLastErrorDisconnectCause = disconnectCause;
152752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal        attemptNextPhoneAccount();
153752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal    }
154752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal
155664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    void abort() {
156664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        Log.v(this, "abort");
157664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
158664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        // Clear the response first to prevent attemptNextConnectionService from attempting any
159664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        // more services.
160f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        CreateConnectionResponse response = mCallResponse;
161f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        mCallResponse = null;
162646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        clearTimeout();
163664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
164664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        ConnectionServiceWrapper service = mCall.getConnectionService();
165664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        if (service != null) {
166664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            service.abort(mCall);
167664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            mCall.clearConnectionService();
168664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
169664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        if (response != null) {
170701dc006ac11625b55d872f1639107b028933895Andrew Lee            response.handleCreateConnectionFailure(new DisconnectCause(DisconnectCause.LOCAL));
171664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
172664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    }
173664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
17469eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad    private void attemptNextPhoneAccount() {
17569eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad        Log.v(this, "attemptNextPhoneAccount");
176cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn        CallAttemptRecord attempt = null;
177cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn        if (mAttemptRecordIterator.hasNext()) {
178cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn            attempt = mAttemptRecordIterator.next();
179664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
1806a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            if (!mPhoneAccountRegistrar.phoneAccountRequiresBindPermission(
18191d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                    attempt.connectionManagerPhoneAccount)) {
182cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                Log.w(this,
1837bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee                        "Connection mgr does not have BIND_TELECOM_CONNECTION_SERVICE for "
1847bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee                                + "attempt: %s", attempt);
185cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                attemptNextPhoneAccount();
186cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                return;
187cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn            }
188cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn
189cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn            // If the target PhoneAccount differs from the ConnectionManager phone acount, ensure it
1907bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee            // also requires the BIND_TELECOM_CONNECTION_SERVICE permission.
191cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn            if (!attempt.connectionManagerPhoneAccount.equals(attempt.targetPhoneAccount) &&
1926a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon                    !mPhoneAccountRegistrar.phoneAccountRequiresBindPermission(
1936a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon                            attempt.targetPhoneAccount)) {
194cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                Log.w(this,
1957bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee                        "Target PhoneAccount does not have BIND_TELECOM_CONNECTION_SERVICE for "
1967bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee                                + "attempt: %s", attempt);
197cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                attemptNextPhoneAccount();
198cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                return;
199cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn            }
200cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn        }
201cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn
202f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        if (mCallResponse != null && attempt != null) {
203293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad            Log.i(this, "Trying attempt %s", attempt);
204105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            PhoneAccountHandle phoneAccount = attempt.connectionManagerPhoneAccount;
205f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            mService = mRepository.getService(phoneAccount.getComponentName(),
206f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger                    phoneAccount.getUserHandle());
207f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            if (mService == null) {
208293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad                Log.i(this, "Found no connection service for attempt %s", attempt);
20969eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad                attemptNextPhoneAccount();
210664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            } else {
2116e8f3d70ac7397afb4cb5ab276d1cd385c92dd21Brad Ebinger                mConnectionAttempt++;
212b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount);
213b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                mCall.setTargetPhoneAccount(attempt.targetPhoneAccount);
214f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger                mCall.setConnectionService(mService);
215f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger                setTimeoutIfNeeded(mService, attempt);
216606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                if (mCall.isIncoming()) {
217606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                    mService.createConnection(mCall, CreateConnectionProcessor.this);
218606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                } else {
219606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                    // Start to create the connection for outgoing call after the ConnectionService
220606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                    // of the call has gained the focus.
221606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                    mCall.getConnectionServiceFocusManager().requestFocus(
222606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                            mCall,
223606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                            new CallsManager.RequestCallback(new CallsManager.PendingAction() {
224606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                                @Override
225606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                                public void performAction() {
226606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                                    Log.d(this, "perform create connection");
227606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                                    mService.createConnection(
228606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                                            mCall,
229606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                                            CreateConnectionProcessor.this);
230606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                                }
231606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                            }));
232646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal
233606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng                }
234664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
235664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        } else {
23669eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad            Log.v(this, "attemptNextPhoneAccount, no more accounts, failing");
237f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            DisconnectCause disconnectCause = mLastErrorDisconnectCause != null ?
238f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger                    mLastErrorDisconnectCause : new DisconnectCause(DisconnectCause.ERROR);
239f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            notifyCallConnectionFailure(disconnectCause);
240664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
241664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    }
242664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
243646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal    private void setTimeoutIfNeeded(ConnectionServiceWrapper service, CallAttemptRecord attempt) {
244646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        clearTimeout();
245646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal
246646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        CreateConnectionTimeout timeout = new CreateConnectionTimeout(
247646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal                mContext, mPhoneAccountRegistrar, service, mCall);
248646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        if (timeout.isTimeoutNeededForCall(getConnectionServices(mAttemptRecords),
249646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal                attempt.connectionManagerPhoneAccount)) {
250646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal            mTimeout = timeout;
251646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal            timeout.registerTimeout();
252646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        }
253646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal    }
254646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal
255646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal    private void clearTimeout() {
256646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        if (mTimeout != null) {
257646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal            mTimeout.unregisterTimeout();
258646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal            mTimeout = null;
259646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        }
260646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal    }
261646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal
2627957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal    private boolean shouldSetConnectionManager() {
2637957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        if (mAttemptRecords.size() == 0) {
2647957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            return false;
265293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        }
2667957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal
2677957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        if (mAttemptRecords.size() > 1) {
2687957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            Log.d(this, "shouldSetConnectionManager, error, mAttemptRecords should not have more "
2697957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal                    + "than 1 record");
2707957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            return false;
2717957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        }
2727957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal
273240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        PhoneAccountHandle connectionManager =
274240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                mPhoneAccountRegistrar.getSimCallManagerFromCall(mCall);
2757957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        if (connectionManager == null) {
2767957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            return false;
2777957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        }
2787957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal
2797957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        PhoneAccountHandle targetPhoneAccountHandle = mAttemptRecords.get(0).targetPhoneAccount;
2807957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        if (Objects.equals(connectionManager, targetPhoneAccountHandle)) {
2817957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            return false;
2827957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        }
2837957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal
2847957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        // Connection managers are only allowed to manage SIM subscriptions.
2856a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        // TODO: Should this really be checking the "calling user" test for phone account?
286240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        PhoneAccount targetPhoneAccount = mPhoneAccountRegistrar
287240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                .getPhoneAccountUnchecked(targetPhoneAccountHandle);
28891fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal        if (targetPhoneAccount == null) {
28991fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal            Log.d(this, "shouldSetConnectionManager, phone account not found");
29091fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal            return false;
29191fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal        }
2927957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        boolean isSimSubscription = (targetPhoneAccount.getCapabilities() &
2937957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal                PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) != 0;
2947957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        if (!isSimSubscription) {
2957957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            return false;
2967957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        }
2977957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal
2987957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        return true;
2997957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal    }
3007957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal
3017957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal    // If there exists a registered connection manager then use it.
3027957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal    private void adjustAttemptsForConnectionManager() {
3037957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        if (shouldSetConnectionManager()) {
3047957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            CallAttemptRecord record = new CallAttemptRecord(
305240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                    mPhoneAccountRegistrar.getSimCallManagerFromCall(mCall),
3067957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal                    mAttemptRecords.get(0).targetPhoneAccount);
30710a5831cf61b3ab3b126329044ea05dc3181fa63mike dooley            Log.v(this, "setConnectionManager, changing %s -> %s", mAttemptRecords.get(0), record);
308f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            mAttemptRecords.add(0, record);
3097957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        } else {
3107957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            Log.v(this, "setConnectionManager, not changing");
311293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        }
312293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    }
313293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
314664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    // If we are possibly attempting to call a local emergency number, ensure that the
31569eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad    // plain PSTN connection services are listed, and nothing else.
316e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger    private void adjustAttemptsForEmergency(PhoneAccountHandle preferredPAH) {
3176ffe531cc43849b5ca22a23647f5e729fae01c25Tyler Gunn        if (mCall.isEmergencyCall()) {
31869eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad            Log.i(this, "Emergency number detected");
319293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad            mAttemptRecords.clear();
320240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            // Phone accounts in profile do not handle emergency call, use phone accounts in
321240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            // current user.
322240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            List<PhoneAccount> allAccounts = mPhoneAccountRegistrar
323240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                    .getAllPhoneAccountsOfCurrentUser();
324c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee
325c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee            if (allAccounts.isEmpty()) {
326c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee                // If the list of phone accounts is empty at this point, it means Telephony hasn't
327c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee                // registered any phone accounts yet. Add a fallback emergency phone account so
328c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee                // that emergency calls can still go through. We create a new ArrayLists here just
329c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee                // in case the implementation of PhoneAccountRegistrar ever returns an unmodifiable
330c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee                // list.
331c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee                allAccounts = new ArrayList<PhoneAccount>();
332c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee                allAccounts.add(TelephonyUtil.getDefaultEmergencyPhoneAccount());
333c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee            }
334c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee
335e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger            // First, possibly add the SIM phone account that the user prefers
336e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger            PhoneAccount preferredPA = mPhoneAccountRegistrar.getPhoneAccountUnchecked(
337e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger                    preferredPAH);
338e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger            if (preferredPA != null &&
339e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger                    preferredPA.hasCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS) &&
340e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger                    preferredPA.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
341e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger                Log.i(this, "Will try PSTN account %s for emergency",
342e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger                        preferredPA.getAccountHandle());
343e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger                mAttemptRecords.add(new CallAttemptRecord(preferredPAH, preferredPAH));
344e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger            }
345e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger
346e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger            // Next, add all SIM phone accounts which can place emergency calls.
347e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger            TelephonyUtil.sortSimPhoneAccounts(mContext, allAccounts);
348a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala
349a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala            // If preferredPA already has an emergency PhoneAccount, do not add others since the
350a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala            // emergency call be redialed in Telephony.
351a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala            if (mAttemptRecords.isEmpty()) {
352a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala                for (PhoneAccount phoneAccount : allAccounts) {
353a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala                    if (phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)
354a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala                            && phoneAccount.hasCapabilities(
355a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala                            PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
356a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala                        PhoneAccountHandle phoneAccountHandle = phoneAccount.getAccountHandle();
357e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger                        Log.i(this, "Will try PSTN account %s for emergency", phoneAccountHandle);
358e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger                        mAttemptRecords.add(new CallAttemptRecord(phoneAccountHandle,
359e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger                                phoneAccountHandle));
360a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala                        // Add only one emergency SIM PhoneAccount to the attempt list.
361a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala                        break;
362e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger                    }
363664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                }
364664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
3656e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn
3668e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn            // Next, add the connection manager account as a backup if it can place emergency calls.
367240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            PhoneAccountHandle callManagerHandle =
368240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                    mPhoneAccountRegistrar.getSimCallManagerOfCurrentUser();
369f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            if (callManagerHandle != null) {
370f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger                // TODO: Should this really be checking the "calling user" test for phone account?
37191d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                PhoneAccount callManager = mPhoneAccountRegistrar
372240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                        .getPhoneAccountUnchecked(callManagerHandle);
37391fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal                if (callManager != null && callManager.hasCapabilities(
37491fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal                        PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)) {
3758e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                    CallAttemptRecord callAttemptRecord = new CallAttemptRecord(callManagerHandle,
376240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                            mPhoneAccountRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
37762630f727fa055e5d79c8194ed5db697104f116cHall Liu                                    mCall.getHandle() == null
37862630f727fa055e5d79c8194ed5db697104f116cHall Liu                                            ? null : mCall.getHandle().getScheme()));
3798e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                    if (!mAttemptRecords.contains(callAttemptRecord)) {
3808e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                        Log.i(this, "Will try Connection Manager account %s for emergency",
3818e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                                callManager);
3828e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                        mAttemptRecords.add(callAttemptRecord);
3838e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                    }
3848e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                }
3856e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn            }
386664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
387664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    }
388664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
389646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal    /** Returns all connection services used by the call attempt records. */
390646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal    private static Collection<PhoneAccountHandle> getConnectionServices(
391646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal            List<CallAttemptRecord> records) {
392646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        HashSet<PhoneAccountHandle> result = new HashSet<>();
393646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        for (CallAttemptRecord record : records) {
394646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal            result.add(record.connectionManagerPhoneAccount);
395646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        }
396646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        return result;
397646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal    }
398646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal
399664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
400f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger    private void notifyCallConnectionFailure(DisconnectCause errorDisconnectCause) {
401f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        if (mCallResponse != null) {
402f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            clearTimeout();
403f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            mCallResponse.handleCreateConnectionFailure(errorDisconnectCause);
404f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            mCallResponse = null;
405f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            mCall.clearConnectionService();
406664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
407f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger    }
408664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
409f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger    @Override
410f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger    public void handleCreateConnectionSuccess(
411f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            CallIdMapper idMapper,
412f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            ParcelableConnection connection) {
413f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        if (mCallResponse == null) {
414f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            // Nobody is listening for this connection attempt any longer; ask the responsible
415f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            // ConnectionService to tear down any resources associated with the call
416f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            mService.abort(mCall);
417f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        } else {
418f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            // Success -- share the good news and remember that we are no longer interested
419f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            // in hearing about any more attempts
420f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            mCallResponse.handleCreateConnectionSuccess(idMapper, connection);
421f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            mCallResponse = null;
422f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            // If there's a timeout running then don't clear it. The timeout can be triggered
423f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            // after the call has successfully been created but before it has become active.
424664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
425f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger    }
426664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
427f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger    private boolean shouldFailCallIfConnectionManagerFails(DisconnectCause cause) {
428f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        // Connection Manager does not exist or does not match registered Connection Manager
429f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        // Since Connection manager is a proxy for SIM, fall back to SIM
430f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        PhoneAccountHandle handle = mCall.getConnectionManagerPhoneAccount();
431f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        if (handle == null || !handle.equals(mPhoneAccountRegistrar.getSimCallManagerFromCall(
432f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger                mCall))) {
433f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            return false;
434f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        }
435bafadce53332c7e0f7be0482cf04333c72487a70Sailesh Nepal
436f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        // The Call's Connection Service does not exist
437f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        ConnectionServiceWrapper connectionManager = mCall.getConnectionService();
438f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        if (connectionManager == null) {
439f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            return true;
440f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        }
441bafadce53332c7e0f7be0482cf04333c72487a70Sailesh Nepal
442f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        // In this case, fall back to a sim because connection manager declined
443f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        if (cause.getCode() == DisconnectCause.CONNECTION_MANAGER_NOT_SUPPORTED) {
444f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            Log.d(CreateConnectionProcessor.this, "Connection manager declined to handle the "
445f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger                    + "call, falling back to not using a connection manager");
446f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            return false;
447f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        }
448bafadce53332c7e0f7be0482cf04333c72487a70Sailesh Nepal
449f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        if (!connectionManager.isServiceValid("createConnection")) {
450f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            Log.d(CreateConnectionProcessor.this, "Connection manager unbound while trying "
451f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger                    + "create a connection, falling back to not using a connection manager");
452bafadce53332c7e0f7be0482cf04333c72487a70Sailesh Nepal            return false;
453bafadce53332c7e0f7be0482cf04333c72487a70Sailesh Nepal        }
454bafadce53332c7e0f7be0482cf04333c72487a70Sailesh Nepal
455f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        // Do not fall back from connection manager and simply fail call if the failure reason is
456f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        // other
457f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        Log.d(CreateConnectionProcessor.this, "Connection Manager denied call with the following " +
458f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger                "error: " + cause.getReason() + ". Not falling back to SIM.");
459f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        return true;
460f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger    }
461f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger
462f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger    @Override
463f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger    public void handleCreateConnectionFailure(DisconnectCause errorDisconnectCause) {
464f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        // Failure of some sort; record the reasons for failure and try again if possible
465f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        Log.d(CreateConnectionProcessor.this, "Connection failed: (%s)", errorDisconnectCause);
466e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger        if (shouldFailCallIfConnectionManagerFails(errorDisconnectCause)) {
467f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            notifyCallConnectionFailure(errorDisconnectCause);
468f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger            return;
469664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
4708ff99f3751fcdd662932317ca45f886f6883e196Santos Cordon        mLastErrorDisconnectCause = errorDisconnectCause;
471f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger        attemptNextPhoneAccount();
472664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    }
473664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal}
474