CreateConnectionProcessor.java revision 91d43cf9c985cc5a83795f256ef5c46ebb8fbdc1
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;
217cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.ParcelableConnection;
2291d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunnimport android.telecom.Phone;
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
28664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.ArrayList;
29664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.Iterator;
30664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.List;
31293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awadimport java.util.Objects;
32664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
33664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal/**
34664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * This class creates connections to place new outgoing calls to attached to an existing incoming
35664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * call. In either case, this class cycles through a set of connection services until:
36664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal *   - a connection service returns a newly created connection in which case the call is displayed
37664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal *     to the user
38664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal *   - a connection service cancels the process, in which case the call is aborted
39664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal */
40664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalfinal class CreateConnectionProcessor {
41293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
42293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    // Describes information required to attempt to make a phone call
43293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    private static class CallAttemptRecord {
44293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        // The PhoneAccount describing the target connection service which we will
45293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        // contact in order to process an attempt
46b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        public final PhoneAccountHandle connectionManagerPhoneAccount;
47293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        // The PhoneAccount which we will tell the target connection service to use
48293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        // for attempting to make the actual phone call
49b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        public final PhoneAccountHandle targetPhoneAccount;
50293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
51293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        public CallAttemptRecord(
52b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                PhoneAccountHandle connectionManagerPhoneAccount,
53b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                PhoneAccountHandle targetPhoneAccount) {
54b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            this.connectionManagerPhoneAccount = connectionManagerPhoneAccount;
55b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            this.targetPhoneAccount = targetPhoneAccount;
56293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        }
57293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
58293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        @Override
59293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        public String toString() {
60293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad            return "CallAttemptRecord("
61b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    + Objects.toString(connectionManagerPhoneAccount) + ","
62b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    + Objects.toString(targetPhoneAccount) + ")";
63293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        }
646e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn
656e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn        /**
666e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn         * Determines if this instance of {@code CallAttemptRecord} has the same underlying
676e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn         * {@code PhoneAccountHandle}s as another instance.
686e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn         *
696e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn         * @param obj The other instance to compare against.
706e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn         * @return {@code True} if the {@code CallAttemptRecord}s are equal.
716e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn         */
726e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn        @Override
736e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn        public boolean equals(Object obj) {
746e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn            if (obj instanceof CallAttemptRecord) {
756e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn                CallAttemptRecord other = (CallAttemptRecord) obj;
766e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn                return Objects.equals(connectionManagerPhoneAccount,
776e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn                        other.connectionManagerPhoneAccount) &&
786e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn                        Objects.equals(targetPhoneAccount, other.targetPhoneAccount);
796e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn            }
806e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn            return false;
816e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn        }
82293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    }
83293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
84664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private final Call mCall;
85664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private final ConnectionServiceRepository mRepository;
86293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    private List<CallAttemptRecord> mAttemptRecords;
87293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    private Iterator<CallAttemptRecord> mAttemptRecordIterator;
88664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private CreateConnectionResponse mResponse;
89701dc006ac11625b55d872f1639107b028933895Andrew Lee    private DisconnectCause mLastErrorDisconnectCause;
9091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
9191d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn    private final Context mContext;
92664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
93664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    CreateConnectionProcessor(
9491d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn            Call call, ConnectionServiceRepository repository, CreateConnectionResponse response,
9591d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn            PhoneAccountRegistrar phoneAccountRegistrar, Context context) {
96664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mCall = call;
97664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mRepository = repository;
98664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mResponse = response;
9991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        mPhoneAccountRegistrar = phoneAccountRegistrar;
10091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        mContext = context;
101664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    }
102664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
103664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    void process() {
104664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        Log.v(this, "process");
105293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        mAttemptRecords = new ArrayList<>();
106b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        if (mCall.getTargetPhoneAccount() != null) {
1077957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            mAttemptRecords.add(new CallAttemptRecord(
1087957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal                    mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount()));
109664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
1107957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        adjustAttemptsForConnectionManager();
111293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        adjustAttemptsForEmergency();
112293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        mAttemptRecordIterator = mAttemptRecords.iterator();
11369eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad        attemptNextPhoneAccount();
114664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    }
115664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
116664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    void abort() {
117664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        Log.v(this, "abort");
118664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
119664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        // Clear the response first to prevent attemptNextConnectionService from attempting any
120664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        // more services.
121664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        CreateConnectionResponse response = mResponse;
122664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mResponse = null;
123664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
124664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        ConnectionServiceWrapper service = mCall.getConnectionService();
125664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        if (service != null) {
126664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            service.abort(mCall);
127664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            mCall.clearConnectionService();
128664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
129664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        if (response != null) {
130701dc006ac11625b55d872f1639107b028933895Andrew Lee            response.handleCreateConnectionFailure(new DisconnectCause(DisconnectCause.LOCAL));
131664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
132664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    }
133664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
13469eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad    private void attemptNextPhoneAccount() {
13569eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad        Log.v(this, "attemptNextPhoneAccount");
136cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn        CallAttemptRecord attempt = null;
137cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn        if (mAttemptRecordIterator.hasNext()) {
138cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn            attempt = mAttemptRecordIterator.next();
139664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
14091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn            if (!mPhoneAccountRegistrar.phoneAccountHasPermission(
14191d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                    attempt.connectionManagerPhoneAccount)) {
142cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                Log.w(this,
143cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                        "Connection mgr does not have BIND_CONNECTION_SERVICE for attempt: %s",
144cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                        attempt);
145cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                attemptNextPhoneAccount();
146cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                return;
147cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn            }
148cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn
149cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn            // If the target PhoneAccount differs from the ConnectionManager phone acount, ensure it
150cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn            // also has BIND_CONNECTION_SERVICE permission.
151cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn            if (!attempt.connectionManagerPhoneAccount.equals(attempt.targetPhoneAccount) &&
15291d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                    !mPhoneAccountRegistrar.phoneAccountHasPermission(attempt.targetPhoneAccount)) {
153cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                Log.w(this,
154cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                        "Target PhoneAccount does not have BIND_CONNECTION_SERVICE for attempt: %s",
155cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                        attempt);
156cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                attemptNextPhoneAccount();
157cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                return;
158cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn            }
159cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn        }
160cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn
161cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn        if (mResponse != null && attempt != null) {
162293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad            Log.i(this, "Trying attempt %s", attempt);
16394d01629010a61f6112713f22330d5fd4baae851Evan Charlton            ConnectionServiceWrapper service =
164b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    mRepository.getService(
165b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                            attempt.connectionManagerPhoneAccount.getComponentName());
166664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            if (service == null) {
167293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad                Log.i(this, "Found no connection service for attempt %s", attempt);
16869eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad                attemptNextPhoneAccount();
169664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            } else {
170b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount);
171b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                mCall.setTargetPhoneAccount(attempt.targetPhoneAccount);
172664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                mCall.setConnectionService(service);
173664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                Log.i(this, "Attempting to call from %s", service.getComponentName());
174664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                service.createConnection(mCall, new Response(service));
175664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
176664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        } else {
17769eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad            Log.v(this, "attemptNextPhoneAccount, no more accounts, failing");
178664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            if (mResponse != null) {
179701dc006ac11625b55d872f1639107b028933895Andrew Lee                mResponse.handleCreateConnectionFailure(mLastErrorDisconnectCause);
180664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                mResponse = null;
181664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                mCall.clearConnectionService();
182664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
183664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
184664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    }
185664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
1867957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal    private boolean shouldSetConnectionManager() {
1877957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        if (mAttemptRecords.size() == 0) {
1887957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            return false;
189293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        }
1907957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal
1917957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        if (mAttemptRecords.size() > 1) {
1927957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            Log.d(this, "shouldSetConnectionManager, error, mAttemptRecords should not have more "
1937957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal                    + "than 1 record");
1947957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            return false;
1957957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        }
1967957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal
19791d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        PhoneAccountHandle connectionManager = mPhoneAccountRegistrar.getSimCallManager();
1987957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        if (connectionManager == null) {
1997957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            return false;
2007957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        }
2017957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal
2027957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        PhoneAccountHandle targetPhoneAccountHandle = mAttemptRecords.get(0).targetPhoneAccount;
2037957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        if (Objects.equals(connectionManager, targetPhoneAccountHandle)) {
2047957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            return false;
2057957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        }
2067957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal
2077957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        // Connection managers are only allowed to manage SIM subscriptions.
20891d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        PhoneAccount targetPhoneAccount = mPhoneAccountRegistrar.getPhoneAccount(
20991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                targetPhoneAccountHandle);
2107957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        boolean isSimSubscription = (targetPhoneAccount.getCapabilities() &
2117957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal                PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) != 0;
2127957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        if (!isSimSubscription) {
2137957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            return false;
2147957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        }
2157957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal
2167957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        return true;
2177957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal    }
2187957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal
2197957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal    // If there exists a registered connection manager then use it.
2207957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal    private void adjustAttemptsForConnectionManager() {
2217957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        if (shouldSetConnectionManager()) {
2227957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            CallAttemptRecord record = new CallAttemptRecord(
22391d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                    mPhoneAccountRegistrar.getSimCallManager(),
2247957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal                    mAttemptRecords.get(0).targetPhoneAccount);
2257957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            Log.v(this, "setConnectionManager, changing %s -> %s",
2267957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal                    mAttemptRecords.get(0).targetPhoneAccount, record);
2277957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            mAttemptRecords.set(0, record);
2287957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal        } else {
2297957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal            Log.v(this, "setConnectionManager, not changing");
230293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        }
231293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    }
232293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
233664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    // If we are possibly attempting to call a local emergency number, ensure that the
23469eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad    // plain PSTN connection services are listed, and nothing else.
235293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    private void adjustAttemptsForEmergency()  {
23691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        if (TelephonyUtil.shouldProcessAsEmergency(mContext, mCall.getHandle())) {
23769eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad            Log.i(this, "Emergency number detected");
238293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad            mAttemptRecords.clear();
23991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn            List<PhoneAccount> allAccounts = mPhoneAccountRegistrar.getAllPhoneAccounts();
2408e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn            // First, add SIM phone accounts which can place emergency calls.
2418e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn            for (PhoneAccount phoneAccount : allAccounts) {
2428e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                if (phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS) &&
2438e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                        phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
2448e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                    Log.i(this, "Will try PSTN account %s for emergency",
2458e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                            phoneAccount.getAccountHandle());
246293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad                    mAttemptRecords.add(
247293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad                            new CallAttemptRecord(
2488e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                                    phoneAccount.getAccountHandle(),
2498e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                                    phoneAccount.getAccountHandle()));
250664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                }
251664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
2526e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn
2538e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn            // Next, add the connection manager account as a backup if it can place emergency calls.
25491d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn            PhoneAccountHandle callManagerHandle = mPhoneAccountRegistrar.getSimCallManager();
2558e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn            if (callManagerHandle != null) {
25691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                PhoneAccount callManager = mPhoneAccountRegistrar
25791d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                        .getPhoneAccount(callManagerHandle);
2588e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                if (callManager.hasCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)) {
2598e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                    CallAttemptRecord callAttemptRecord = new CallAttemptRecord(callManagerHandle,
26091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                            mPhoneAccountRegistrar.
2618e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                                    getDefaultOutgoingPhoneAccount(mCall.getHandle().getScheme())
2628e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                    );
2638e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn
2648e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                    if (!mAttemptRecords.contains(callAttemptRecord)) {
2658e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                        Log.i(this, "Will try Connection Manager account %s for emergency",
2668e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                                callManager);
2678e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                        mAttemptRecords.add(callAttemptRecord);
2688e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                    }
2698e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                }
2706e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn            }
271664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
272664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    }
273664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
274664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private class Response implements CreateConnectionResponse {
275664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        private final ConnectionServiceWrapper mService;
276664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
277664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        Response(ConnectionServiceWrapper service) {
278664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            mService = service;
279664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
280664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
281664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        @Override
2828000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad        public void handleCreateConnectionSuccess(
2838000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad                CallIdMapper idMapper,
2848000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad                ParcelableConnection connection) {
285664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            if (mResponse == null) {
286fb5560d634aef745466e8869f8acf496447da17bIhab Awad                // Nobody is listening for this connection attempt any longer; ask the responsible
287fb5560d634aef745466e8869f8acf496447da17bIhab Awad                // ConnectionService to tear down any resources associated with the call
288664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                mService.abort(mCall);
289664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            } else {
290fb5560d634aef745466e8869f8acf496447da17bIhab Awad                // Success -- share the good news and remember that we are no longer interested
291fb5560d634aef745466e8869f8acf496447da17bIhab Awad                // in hearing about any more attempts
2928000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad                mResponse.handleCreateConnectionSuccess(idMapper, connection);
29372890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon                mResponse = null;
294664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
295664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
296664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
297664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        @Override
298701dc006ac11625b55d872f1639107b028933895Andrew Lee        public void handleCreateConnectionFailure(DisconnectCause errorDisconnectCause) {
299fb5560d634aef745466e8869f8acf496447da17bIhab Awad            // Failure of some sort; record the reasons for failure and try again if possible
300701dc006ac11625b55d872f1639107b028933895Andrew Lee            Log.d(CreateConnectionProcessor.this, "Connection failed: (%s)", errorDisconnectCause);
301701dc006ac11625b55d872f1639107b028933895Andrew Lee            mLastErrorDisconnectCause = errorDisconnectCause;
30269eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad            attemptNextPhoneAccount();
303664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
304664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    }
305664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal}
306