1a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/*
2bda761320929f714951c328bfec6a51a1978db97Wink Saville * Copyright (C) 2014 The Android Open Source Project
3a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
4a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * you may not use this file except in compliance with the License.
6a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * You may obtain a copy of the License at
7a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
8a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *      http://www.apache.org/licenses/LICENSE-2.0
9a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
10a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Unless required by applicable law or agreed to in writing, software
11a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * See the License for the specific language governing permissions and
14a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * limitations under the License.
15a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */
16a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
17a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillepackage com.android.internal.telephony.dataconnection;
18a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1946c4302b8f52fbd62d7000848cd2bb3d36d15725Robert Greenwaltimport static android.telephony.SubscriptionManager.DEFAULT_PHONE_INDEX;
2046c4302b8f52fbd62d7000848cd2bb3d36d15725Robert Greenwaltimport static android.telephony.SubscriptionManager.INVALID_PHONE_INDEX;
2146c4302b8f52fbd62d7000848cd2bb3d36d15725Robert Greenwalt
22a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.Context;
23bda761320929f714951c328bfec6a51a1978db97Wink Savilleimport android.database.ContentObserver;
24bda761320929f714951c328bfec6a51a1978db97Wink Savilleimport android.net.ConnectivityManager;
25bda761320929f714951c328bfec6a51a1978db97Wink Savilleimport android.net.NetworkCapabilities;
26bda761320929f714951c328bfec6a51a1978db97Wink Savilleimport android.net.NetworkFactory;
27bda761320929f714951c328bfec6a51a1978db97Wink Savilleimport android.net.NetworkRequest;
28f3cb9192272e4ddd68970352e998690f6c80e393Amit Mahajanimport android.os.AsyncResult;
29a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Handler;
30bda761320929f714951c328bfec6a51a1978db97Wink Savilleimport android.os.Looper;
31a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Message;
32bda761320929f714951c328bfec6a51a1978db97Wink Savilleimport android.os.Messenger;
33bda761320929f714951c328bfec6a51a1978db97Wink Savilleimport android.provider.Settings;
34bda761320929f714951c328bfec6a51a1978db97Wink Savilleimport android.telephony.Rlog;
35a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.SubscriptionManager;
364b09dff383ae7dfca595aeeea886a594a1947340Wink Savilleimport android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
37a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwaltimport android.text.TextUtils;
382dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwaltimport android.util.LocalLog;
39bda761320929f714951c328bfec6a51a1978db97Wink Savilleimport android.util.SparseArray;
40a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
41a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Phone;
42a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.PhoneBase;
43bda761320929f714951c328bfec6a51a1978db97Wink Savilleimport com.android.internal.telephony.PhoneConstants;
44a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.PhoneProxy;
45bda761320929f714951c328bfec6a51a1978db97Wink Savilleimport com.android.internal.telephony.SubscriptionController;
46bda761320929f714951c328bfec6a51a1978db97Wink Savilleimport com.android.internal.telephony.dataconnection.DcSwitchAsyncChannel.RequestInfo;
47a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.util.AsyncChannel;
48be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwaltimport com.android.internal.util.IndentingPrintWriter;
49a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
50e97be3971cb6b55e019433c32524cc60ce0d037bWink Savilleimport java.io.FileDescriptor;
51e97be3971cb6b55e019433c32524cc60ce0d037bWink Savilleimport java.io.PrintWriter;
522dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwaltimport java.util.ArrayDeque;
53bda761320929f714951c328bfec6a51a1978db97Wink Savilleimport java.util.HashMap;
54a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport java.util.Iterator;
55e97be3971cb6b55e019433c32524cc60ce0d037bWink Savilleimport java.util.Map.Entry;
56a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
57a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillepublic class DctController extends Handler {
58a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final String LOG_TAG = "DctController";
59a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final boolean DBG = true;
60a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
61bda761320929f714951c328bfec6a51a1978db97Wink Saville    private static final int EVENT_PROCESS_REQUESTS = 100;
62bda761320929f714951c328bfec6a51a1978db97Wink Saville    private static final int EVENT_EXECUTE_REQUEST = 101;
63bda761320929f714951c328bfec6a51a1978db97Wink Saville    private static final int EVENT_EXECUTE_ALL_REQUESTS = 102;
64bda761320929f714951c328bfec6a51a1978db97Wink Saville    private static final int EVENT_RELEASE_REQUEST = 103;
65bda761320929f714951c328bfec6a51a1978db97Wink Saville    private static final int EVENT_RELEASE_ALL_REQUESTS = 104;
66a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt    private static final int EVENT_RETRY_ATTACH = 105;
675bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt    private static final int EVENT_SETTINGS_CHANGED = 106;
685bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt    private static final int EVENT_SUBSCRIPTIONS_CHANGED = 107;
69a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
70bda761320929f714951c328bfec6a51a1978db97Wink Saville    private static final int EVENT_DATA_ATTACHED = 500;
71bda761320929f714951c328bfec6a51a1978db97Wink Saville    private static final int EVENT_DATA_DETACHED = 600;
72f3cb9192272e4ddd68970352e998690f6c80e393Amit Mahajan    private static final int EVENT_EMERGENCY_CALL_TOGGLED = 700;
73a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
74bda761320929f714951c328bfec6a51a1978db97Wink Saville    private static DctController sDctController;
75a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
76a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int mPhoneNum;
77a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private PhoneProxy[] mPhones;
786bac33f472fbf66697b8eedd9b54a40daaba3086Wink Saville    private DcSwitchStateMachine[] mDcSwitchStateMachine;
79a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private DcSwitchAsyncChannel[] mDcSwitchAsyncChannel;
80a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Handler[] mDcSwitchStateHandler;
81bda761320929f714951c328bfec6a51a1978db97Wink Saville    private HashMap<Integer, RequestInfo> mRequestInfos = new HashMap<Integer, RequestInfo>();
82a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Context mContext;
83a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
84bda761320929f714951c328bfec6a51a1978db97Wink Saville    /** Used to send us NetworkRequests from ConnectivityService.  Remember it so we can
85bda761320929f714951c328bfec6a51a1978db97Wink Saville     * unregister on dispose. */
86bda761320929f714951c328bfec6a51a1978db97Wink Saville    private Messenger[] mNetworkFactoryMessenger;
87bda761320929f714951c328bfec6a51a1978db97Wink Saville    private NetworkFactory[] mNetworkFactory;
88bda761320929f714951c328bfec6a51a1978db97Wink Saville    private NetworkCapabilities[] mNetworkFilter;
89a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
90bda761320929f714951c328bfec6a51a1978db97Wink Saville    private SubscriptionController mSubController = SubscriptionController.getInstance();
91a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
924b09dff383ae7dfca595aeeea886a594a1947340Wink Saville    private SubscriptionManager mSubMgr;
934b09dff383ae7dfca595aeeea886a594a1947340Wink Saville
944b09dff383ae7dfca595aeeea886a594a1947340Wink Saville    private OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
954b09dff383ae7dfca595aeeea886a594a1947340Wink Saville            new OnSubscriptionsChangedListener() {
96bda761320929f714951c328bfec6a51a1978db97Wink Saville        @Override
974b09dff383ae7dfca595aeeea886a594a1947340Wink Saville        public void onSubscriptionsChanged() {
985bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt            DctController.this.obtainMessage(EVENT_SUBSCRIPTIONS_CHANGED).sendToTarget();
99a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
100a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
101a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
102299dad50409e907993fa96c7401d4f10c58018b1Wink Saville    private ContentObserver mObserver = new ContentObserver(new Handler()) {
103bda761320929f714951c328bfec6a51a1978db97Wink Saville        @Override
104299dad50409e907993fa96c7401d4f10c58018b1Wink Saville        public void onChange(boolean selfChange) {
105299dad50409e907993fa96c7401d4f10c58018b1Wink Saville            logd("Settings change");
1065bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt            DctController.this.obtainMessage(EVENT_SETTINGS_CHANGED).sendToTarget();
107a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
108a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
109a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
110e27408ec980c598a29d2122ce157037c4707eb81Wink Saville    public void updatePhoneObject(PhoneProxy phone) {
11126a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        if (phone == null) {
112e27408ec980c598a29d2122ce157037c4707eb81Wink Saville            loge("updatePhoneObject phone = null");
113e27408ec980c598a29d2122ce157037c4707eb81Wink Saville            return;
114e27408ec980c598a29d2122ce157037c4707eb81Wink Saville        }
11526a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal
116e27408ec980c598a29d2122ce157037c4707eb81Wink Saville        PhoneBase phoneBase = (PhoneBase)phone.getActivePhone();
11726a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        if (phoneBase == null) {
118e27408ec980c598a29d2122ce157037c4707eb81Wink Saville            loge("updatePhoneObject phoneBase = null");
119e27408ec980c598a29d2122ce157037c4707eb81Wink Saville            return;
120e27408ec980c598a29d2122ce157037c4707eb81Wink Saville        }
121e27408ec980c598a29d2122ce157037c4707eb81Wink Saville
12226a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        for (int i = 0; i < mPhoneNum; i++) {
12326a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal            if (mPhones[i] == phone) {
12426a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal                updatePhoneBaseForIndex(i, phoneBase);
125e27408ec980c598a29d2122ce157037c4707eb81Wink Saville                break;
126e27408ec980c598a29d2122ce157037c4707eb81Wink Saville            }
127e27408ec980c598a29d2122ce157037c4707eb81Wink Saville        }
128e27408ec980c598a29d2122ce157037c4707eb81Wink Saville    }
129e27408ec980c598a29d2122ce157037c4707eb81Wink Saville
13026a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal    private void updatePhoneBaseForIndex(int index, PhoneBase phoneBase) {
13126a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        logd("updatePhoneBaseForIndex for phone index=" + index);
13226a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal
13326a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        phoneBase.getServiceStateTracker().registerForDataConnectionAttached(mRspHandler,
13426a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal                   EVENT_DATA_ATTACHED + index, null);
13526a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        phoneBase.getServiceStateTracker().registerForDataConnectionDetached(mRspHandler,
13626a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal                   EVENT_DATA_DETACHED + index, null);
137f3cb9192272e4ddd68970352e998690f6c80e393Amit Mahajan        phoneBase.registerForEmergencyCallToggle(mRspHandler,
138f3cb9192272e4ddd68970352e998690f6c80e393Amit Mahajan                EVENT_EMERGENCY_CALL_TOGGLED + index, null);
13926a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal
14026a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        ConnectivityManager cm = (ConnectivityManager)mPhones[index].getContext()
14126a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal            .getSystemService(Context.CONNECTIVITY_SERVICE);
14226a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal
14326a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        if (mNetworkFactoryMessenger != null) {
14426a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal            logd("unregister TelephonyNetworkFactory for phone index=" + index);
14526a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal            cm.unregisterNetworkFactory(mNetworkFactoryMessenger[index]);
14626a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal            mNetworkFactoryMessenger[index] = null;
14726a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal            mNetworkFactory[index] = null;
14826a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal            mNetworkFilter[index] = null;
14926a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        }
15026a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal
151a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt        // TODO - just make this a singleton.  It'll be simpler
15226a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFilter[index] = new NetworkCapabilities();
15326a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFilter[index].addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
15426a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
15526a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
15626a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
15726a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
15826a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
15926a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_CBS);
16026a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_IA);
16126a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_RCS);
16226a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_XCAP);
16326a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
16426a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
16526a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
16626a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal
16726a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFactory[index] = new TelephonyNetworkFactory(this.getLooper(),
16826a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal                mPhones[index].getContext(), "TelephonyNetworkFactory", phoneBase,
16926a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal                mNetworkFilter[index]);
17026a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFactory[index].setScoreFilter(50);
17126a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        mNetworkFactoryMessenger[index] = new Messenger(mNetworkFactory[index]);
17226a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal        cm.registerNetworkFactory(mNetworkFactoryMessenger[index], "Telephony");
17326a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal    }
17426a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal
175bda761320929f714951c328bfec6a51a1978db97Wink Saville    private Handler mRspHandler = new Handler() {
176bda761320929f714951c328bfec6a51a1978db97Wink Saville        @Override
177bda761320929f714951c328bfec6a51a1978db97Wink Saville        public void handleMessage(Message msg){
178f3cb9192272e4ddd68970352e998690f6c80e393Amit Mahajan            if (msg.what >= EVENT_EMERGENCY_CALL_TOGGLED) {
179f3cb9192272e4ddd68970352e998690f6c80e393Amit Mahajan                logd("EVENT_PHONE" + (msg.what - EVENT_EMERGENCY_CALL_TOGGLED + 1)
180f3cb9192272e4ddd68970352e998690f6c80e393Amit Mahajan                        + "_EMERGENCY_CALL_END.");
181f3cb9192272e4ddd68970352e998690f6c80e393Amit Mahajan                AsyncResult ar = (AsyncResult) msg.obj;
182f3cb9192272e4ddd68970352e998690f6c80e393Amit Mahajan                Integer toggle = (Integer) ar.result;
183f3cb9192272e4ddd68970352e998690f6c80e393Amit Mahajan                mDcSwitchAsyncChannel[msg.what - EVENT_EMERGENCY_CALL_TOGGLED].
184f3cb9192272e4ddd68970352e998690f6c80e393Amit Mahajan                        notifyEmergencyCallToggled(toggle.intValue());
185f3cb9192272e4ddd68970352e998690f6c80e393Amit Mahajan            } else if (msg.what >= EVENT_DATA_DETACHED) {
186bda761320929f714951c328bfec6a51a1978db97Wink Saville                logd("EVENT_PHONE" + (msg.what - EVENT_DATA_DETACHED + 1)
187bda761320929f714951c328bfec6a51a1978db97Wink Saville                        + "_DATA_DETACH.");
188bda761320929f714951c328bfec6a51a1978db97Wink Saville                mDcSwitchAsyncChannel[msg.what - EVENT_DATA_DETACHED].notifyDataDetached();
189bda761320929f714951c328bfec6a51a1978db97Wink Saville
190bda761320929f714951c328bfec6a51a1978db97Wink Saville            } else if (msg.what >= EVENT_DATA_ATTACHED) {
191bda761320929f714951c328bfec6a51a1978db97Wink Saville                logd("EVENT_PHONE" + (msg.what - EVENT_DATA_ATTACHED + 1)
192bda761320929f714951c328bfec6a51a1978db97Wink Saville                        + "_DATA_ATTACH.");
193bda761320929f714951c328bfec6a51a1978db97Wink Saville                mDcSwitchAsyncChannel[msg.what - EVENT_DATA_ATTACHED].notifyDataAttached();
194a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
195a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
196bda761320929f714951c328bfec6a51a1978db97Wink Saville    };
197a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
198a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public static DctController getInstance() {
199a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville       if (sDctController == null) {
200a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        throw new RuntimeException(
201bda761320929f714951c328bfec6a51a1978db97Wink Saville            "DctController.getInstance can't be called before makeDCTController()");
202a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
203a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville       return sDctController;
204a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
205a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
206a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public static DctController makeDctController(PhoneProxy[] phones) {
207a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (sDctController == null) {
2086bac33f472fbf66697b8eedd9b54a40daaba3086Wink Saville            logd("makeDctController: new DctController phones.length=" + phones.length);
209a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            sDctController = new DctController(phones);
210a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2116bac33f472fbf66697b8eedd9b54a40daaba3086Wink Saville        logd("makeDctController: X sDctController=" + sDctController);
212a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return sDctController;
213a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
214a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
215a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private DctController(PhoneProxy[] phones) {
2166bac33f472fbf66697b8eedd9b54a40daaba3086Wink Saville        logd("DctController(): phones.length=" + phones.length);
217f54d520ee2eaeb081c208b3d33b0d1fb6ae49254Wink Saville        if (phones == null || phones.length == 0) {
218f54d520ee2eaeb081c208b3d33b0d1fb6ae49254Wink Saville            if (phones == null) {
219f54d520ee2eaeb081c208b3d33b0d1fb6ae49254Wink Saville                loge("DctController(phones): UNEXPECTED phones=null, ignore");
220f54d520ee2eaeb081c208b3d33b0d1fb6ae49254Wink Saville            } else {
221f54d520ee2eaeb081c208b3d33b0d1fb6ae49254Wink Saville                loge("DctController(phones): UNEXPECTED phones.length=0, ignore");
222f54d520ee2eaeb081c208b3d33b0d1fb6ae49254Wink Saville            }
223f54d520ee2eaeb081c208b3d33b0d1fb6ae49254Wink Saville            return;
224f54d520ee2eaeb081c208b3d33b0d1fb6ae49254Wink Saville        }
225f54d520ee2eaeb081c208b3d33b0d1fb6ae49254Wink Saville        mPhoneNum = phones.length;
226a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhones = phones;
227a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2286bac33f472fbf66697b8eedd9b54a40daaba3086Wink Saville        mDcSwitchStateMachine = new DcSwitchStateMachine[mPhoneNum];
229a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDcSwitchAsyncChannel = new DcSwitchAsyncChannel[mPhoneNum];
230a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDcSwitchStateHandler = new Handler[mPhoneNum];
231bda761320929f714951c328bfec6a51a1978db97Wink Saville        mNetworkFactoryMessenger = new Messenger[mPhoneNum];
232bda761320929f714951c328bfec6a51a1978db97Wink Saville        mNetworkFactory = new NetworkFactory[mPhoneNum];
233bda761320929f714951c328bfec6a51a1978db97Wink Saville        mNetworkFilter = new NetworkCapabilities[mPhoneNum];
234a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
235a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0; i < mPhoneNum; ++i) {
236a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            int phoneId = i;
2376bac33f472fbf66697b8eedd9b54a40daaba3086Wink Saville            mDcSwitchStateMachine[i] = new DcSwitchStateMachine(mPhones[i],
2386bac33f472fbf66697b8eedd9b54a40daaba3086Wink Saville                    "DcSwitchStateMachine-" + phoneId, phoneId);
2396bac33f472fbf66697b8eedd9b54a40daaba3086Wink Saville            mDcSwitchStateMachine[i].start();
2406bac33f472fbf66697b8eedd9b54a40daaba3086Wink Saville            mDcSwitchAsyncChannel[i] = new DcSwitchAsyncChannel(mDcSwitchStateMachine[i], phoneId);
241a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDcSwitchStateHandler[i] = new Handler();
242a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
243a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            int status = mDcSwitchAsyncChannel[i].fullyConnectSync(mPhones[i].getContext(),
2446bac33f472fbf66697b8eedd9b54a40daaba3086Wink Saville                mDcSwitchStateHandler[i], mDcSwitchStateMachine[i].getHandler());
245a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
246a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (status == AsyncChannel.STATUS_SUCCESSFUL) {
247f54d520ee2eaeb081c208b3d33b0d1fb6ae49254Wink Saville                logd("DctController(phones): Connect success: " + i);
248a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
249f54d520ee2eaeb081c208b3d33b0d1fb6ae49254Wink Saville                loge("DctController(phones): Could not connect to " + i);
250a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
251a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
252a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Register for radio state change
253bda761320929f714951c328bfec6a51a1978db97Wink Saville            PhoneBase phoneBase = (PhoneBase)mPhones[i].getActivePhone();
25426a0a93d610130e2a6f11a49f2f4b454617fcd55Shishir Agrawal            updatePhoneBaseForIndex(i, phoneBase);
255a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
256a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
257bda761320929f714951c328bfec6a51a1978db97Wink Saville        mContext = mPhones[0].getContext();
2584b09dff383ae7dfca595aeeea886a594a1947340Wink Saville        mSubMgr = SubscriptionManager.from(mContext);
25933d14d71f4b43d82d6c1b87d1d30cd86d13c5372Wink Saville        mSubMgr.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
260bda761320929f714951c328bfec6a51a1978db97Wink Saville
261bda761320929f714951c328bfec6a51a1978db97Wink Saville        //Register for settings change.
262bda761320929f714951c328bfec6a51a1978db97Wink Saville        mContext.getContentResolver().registerContentObserver(
263bda761320929f714951c328bfec6a51a1978db97Wink Saville                Settings.Global.getUriFor(
264bda761320929f714951c328bfec6a51a1978db97Wink Saville                Settings.Global.MULTI_SIM_DATA_CALL_SUBSCRIPTION),
265bda761320929f714951c328bfec6a51a1978db97Wink Saville                false, mObserver);
266bda761320929f714951c328bfec6a51a1978db97Wink Saville    }
267a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
268bda761320929f714951c328bfec6a51a1978db97Wink Saville    public void dispose() {
269bda761320929f714951c328bfec6a51a1978db97Wink Saville        logd("DctController.dispose");
270bda761320929f714951c328bfec6a51a1978db97Wink Saville        for (int i = 0; i < mPhoneNum; ++i) {
271bda761320929f714951c328bfec6a51a1978db97Wink Saville            ConnectivityManager cm = (ConnectivityManager)mPhones[i].getContext()
272bda761320929f714951c328bfec6a51a1978db97Wink Saville                .getSystemService(Context.CONNECTIVITY_SERVICE);
273bda761320929f714951c328bfec6a51a1978db97Wink Saville            cm.unregisterNetworkFactory(mNetworkFactoryMessenger[i]);
274bda761320929f714951c328bfec6a51a1978db97Wink Saville            mNetworkFactoryMessenger[i] = null;
275bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
276bda761320929f714951c328bfec6a51a1978db97Wink Saville
27733d14d71f4b43d82d6c1b87d1d30cd86d13c5372Wink Saville        mSubMgr.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
278bda761320929f714951c328bfec6a51a1978db97Wink Saville        mContext.getContentResolver().unregisterContentObserver(mObserver);
279a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
280a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
281bda761320929f714951c328bfec6a51a1978db97Wink Saville
282bda761320929f714951c328bfec6a51a1978db97Wink Saville    @Override
283bda761320929f714951c328bfec6a51a1978db97Wink Saville    public void handleMessage (Message msg) {
284bda761320929f714951c328bfec6a51a1978db97Wink Saville        logd("handleMessage msg=" + msg);
285bda761320929f714951c328bfec6a51a1978db97Wink Saville        switch (msg.what) {
286bda761320929f714951c328bfec6a51a1978db97Wink Saville            case EVENT_PROCESS_REQUESTS:
287bda761320929f714951c328bfec6a51a1978db97Wink Saville                onProcessRequest();
288bda761320929f714951c328bfec6a51a1978db97Wink Saville                break;
289bda761320929f714951c328bfec6a51a1978db97Wink Saville            case EVENT_EXECUTE_REQUEST:
290bda761320929f714951c328bfec6a51a1978db97Wink Saville                onExecuteRequest((RequestInfo)msg.obj);
291bda761320929f714951c328bfec6a51a1978db97Wink Saville                break;
292bda761320929f714951c328bfec6a51a1978db97Wink Saville            case EVENT_EXECUTE_ALL_REQUESTS:
293bda761320929f714951c328bfec6a51a1978db97Wink Saville                onExecuteAllRequests(msg.arg1);
294bda761320929f714951c328bfec6a51a1978db97Wink Saville                break;
295bda761320929f714951c328bfec6a51a1978db97Wink Saville            case EVENT_RELEASE_REQUEST:
2962f5e0f602beab84c8ba1a9c8ee7736c9df62b0beRobert Greenwalt                onReleaseRequest((RequestInfo)msg.obj);
297bda761320929f714951c328bfec6a51a1978db97Wink Saville                break;
298bda761320929f714951c328bfec6a51a1978db97Wink Saville            case EVENT_RELEASE_ALL_REQUESTS:
299bda761320929f714951c328bfec6a51a1978db97Wink Saville                onReleaseAllRequests(msg.arg1);
300bda761320929f714951c328bfec6a51a1978db97Wink Saville                break;
301a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            case EVENT_RETRY_ATTACH:
302a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                onRetryAttach(msg.arg1);
303a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                break;
3045bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt            case EVENT_SETTINGS_CHANGED:
3055bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt                onSettingsChanged();
3065bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt                break;
3075bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt            case EVENT_SUBSCRIPTIONS_CHANGED:
3085bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt                onSubInfoReady();
3095bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt                break;
310bda761320929f714951c328bfec6a51a1978db97Wink Saville            default:
311bda761320929f714951c328bfec6a51a1978db97Wink Saville                loge("Un-handled message [" + msg.what + "]");
312bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
313a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
314a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
315a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt    private int requestNetwork(NetworkRequest request, int priority, LocalLog l) {
316a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt        logd("requestNetwork request=" + request + ", priority=" + priority);
3172dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt        l.log("Dctc.requestNetwork, priority=" + priority);
318a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
31992760e1668917ad234d7283fc47d4c99f8c427c8Pavel Zhamaitsiak        if (mRequestInfos.containsKey(request.requestId)) {
32092760e1668917ad234d7283fc47d4c99f8c427c8Pavel Zhamaitsiak            logd("requestNetwork replacing " + mRequestInfos.get(request.requestId));
32192760e1668917ad234d7283fc47d4c99f8c427c8Pavel Zhamaitsiak            // NOTE: executedPhoneId might be reset
322a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt        }
323bda761320929f714951c328bfec6a51a1978db97Wink Saville
32492760e1668917ad234d7283fc47d4c99f8c427c8Pavel Zhamaitsiak        RequestInfo requestInfo = new RequestInfo(request, priority, l);
32592760e1668917ad234d7283fc47d4c99f8c427c8Pavel Zhamaitsiak        mRequestInfos.put(request.requestId, requestInfo);
32692760e1668917ad234d7283fc47d4c99f8c427c8Pavel Zhamaitsiak        processRequests();
32792760e1668917ad234d7283fc47d4c99f8c427c8Pavel Zhamaitsiak
328bda761320929f714951c328bfec6a51a1978db97Wink Saville        return PhoneConstants.APN_REQUEST_STARTED;
329bda761320929f714951c328bfec6a51a1978db97Wink Saville    }
330bda761320929f714951c328bfec6a51a1978db97Wink Saville
331bda761320929f714951c328bfec6a51a1978db97Wink Saville    private int releaseNetwork(NetworkRequest request) {
332bda761320929f714951c328bfec6a51a1978db97Wink Saville        RequestInfo requestInfo = mRequestInfos.get(request.requestId);
333bda761320929f714951c328bfec6a51a1978db97Wink Saville        logd("releaseNetwork request=" + request + ", requestInfo=" + requestInfo);
334592359ae17a17d92bdaad8fb1757a769649ee7fbRobert Greenwalt        if (requestInfo != null) requestInfo.log("DctController.releaseNetwork");
335bda761320929f714951c328bfec6a51a1978db97Wink Saville
336bda761320929f714951c328bfec6a51a1978db97Wink Saville        mRequestInfos.remove(request.requestId);
3372f5e0f602beab84c8ba1a9c8ee7736c9df62b0beRobert Greenwalt        releaseRequest(requestInfo);
338bda761320929f714951c328bfec6a51a1978db97Wink Saville        processRequests();
339bda761320929f714951c328bfec6a51a1978db97Wink Saville        return PhoneConstants.APN_REQUEST_STARTED;
340bda761320929f714951c328bfec6a51a1978db97Wink Saville    }
341bda761320929f714951c328bfec6a51a1978db97Wink Saville
342bda761320929f714951c328bfec6a51a1978db97Wink Saville    void processRequests() {
343bda761320929f714951c328bfec6a51a1978db97Wink Saville        logd("processRequests");
344bda761320929f714951c328bfec6a51a1978db97Wink Saville        sendMessage(obtainMessage(EVENT_PROCESS_REQUESTS));
345bda761320929f714951c328bfec6a51a1978db97Wink Saville    }
346bda761320929f714951c328bfec6a51a1978db97Wink Saville
347bda761320929f714951c328bfec6a51a1978db97Wink Saville    void executeRequest(RequestInfo request) {
348bda761320929f714951c328bfec6a51a1978db97Wink Saville        logd("executeRequest, request= " + request);
349bda761320929f714951c328bfec6a51a1978db97Wink Saville        sendMessage(obtainMessage(EVENT_EXECUTE_REQUEST, request));
350bda761320929f714951c328bfec6a51a1978db97Wink Saville    }
351bda761320929f714951c328bfec6a51a1978db97Wink Saville
352bda761320929f714951c328bfec6a51a1978db97Wink Saville    void executeAllRequests(int phoneId) {
353bda761320929f714951c328bfec6a51a1978db97Wink Saville        logd("executeAllRequests, phone:" + phoneId);
354bda761320929f714951c328bfec6a51a1978db97Wink Saville        sendMessage(obtainMessage(EVENT_EXECUTE_ALL_REQUESTS, phoneId,0));
355bda761320929f714951c328bfec6a51a1978db97Wink Saville    }
356bda761320929f714951c328bfec6a51a1978db97Wink Saville
3572f5e0f602beab84c8ba1a9c8ee7736c9df62b0beRobert Greenwalt    void releaseRequest(RequestInfo request) {
358bda761320929f714951c328bfec6a51a1978db97Wink Saville        logd("releaseRequest, request= " + request);
3592f5e0f602beab84c8ba1a9c8ee7736c9df62b0beRobert Greenwalt        sendMessage(obtainMessage(EVENT_RELEASE_REQUEST, request));
360bda761320929f714951c328bfec6a51a1978db97Wink Saville    }
361bda761320929f714951c328bfec6a51a1978db97Wink Saville
362bda761320929f714951c328bfec6a51a1978db97Wink Saville    void releaseAllRequests(int phoneId) {
363bda761320929f714951c328bfec6a51a1978db97Wink Saville        logd("releaseAllRequests, phone:" + phoneId);
364bda761320929f714951c328bfec6a51a1978db97Wink Saville        sendMessage(obtainMessage(EVENT_RELEASE_ALL_REQUESTS, phoneId, 0));
365bda761320929f714951c328bfec6a51a1978db97Wink Saville    }
366bda761320929f714951c328bfec6a51a1978db97Wink Saville
367a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt    public void retryAttach(int phoneId) {
368a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        logd("retryAttach, phone:" + phoneId);
369a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        sendMessage(obtainMessage(EVENT_RETRY_ATTACH, phoneId, 0));
370a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt    }
371a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt
372bda761320929f714951c328bfec6a51a1978db97Wink Saville    private void onProcessRequest() {
373bda761320929f714951c328bfec6a51a1978db97Wink Saville        //process all requests
374bda761320929f714951c328bfec6a51a1978db97Wink Saville        //1. Check all requests and find subscription of the top priority
375bda761320929f714951c328bfec6a51a1978db97Wink Saville        //   request
376bda761320929f714951c328bfec6a51a1978db97Wink Saville        //2. Is current data allowed on the selected subscription
377bda761320929f714951c328bfec6a51a1978db97Wink Saville        //2-1. If yes, execute all the requests of the sub
378bda761320929f714951c328bfec6a51a1978db97Wink Saville        //2-2. If no, set data not allow on the current PS subscription
379bda761320929f714951c328bfec6a51a1978db97Wink Saville        //2-2-1. Set data allow on the selected subscription
380bda761320929f714951c328bfec6a51a1978db97Wink Saville
381682afe07527c6042e34b14fc29bf058e5b2cd7ccRobert Greenwalt        final int requestedPhoneId = getTopPriorityRequestPhoneId();
38246c4302b8f52fbd62d7000848cd2bb3d36d15725Robert Greenwalt        int activePhoneId = INVALID_PHONE_INDEX;
383bda761320929f714951c328bfec6a51a1978db97Wink Saville
3846bac33f472fbf66697b8eedd9b54a40daaba3086Wink Saville        for (int i=0; i<mDcSwitchStateMachine.length; i++) {
385bda761320929f714951c328bfec6a51a1978db97Wink Saville            if (!mDcSwitchAsyncChannel[i].isIdleSync()) {
386bda761320929f714951c328bfec6a51a1978db97Wink Saville                activePhoneId = i;
387bda761320929f714951c328bfec6a51a1978db97Wink Saville                break;
388a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
389a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
390a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
39146c4302b8f52fbd62d7000848cd2bb3d36d15725Robert Greenwalt        logd("onProcessRequest requestedPhoneId=" + requestedPhoneId
392bda761320929f714951c328bfec6a51a1978db97Wink Saville                + ", activePhoneId=" + activePhoneId);
393a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
39446c4302b8f52fbd62d7000848cd2bb3d36d15725Robert Greenwalt        if (requestedPhoneId == INVALID_PHONE_INDEX) {
39592760e1668917ad234d7283fc47d4c99f8c427c8Pavel Zhamaitsiak            // either we have no network request
39692760e1668917ad234d7283fc47d4c99f8c427c8Pavel Zhamaitsiak            // or there is no valid subscription at the moment
39792760e1668917ad234d7283fc47d4c99f8c427c8Pavel Zhamaitsiak            if (activePhoneId != INVALID_PHONE_INDEX) {
39892760e1668917ad234d7283fc47d4c99f8c427c8Pavel Zhamaitsiak                // detatch so we can try connecting later
39992760e1668917ad234d7283fc47d4c99f8c427c8Pavel Zhamaitsiak                mDcSwitchAsyncChannel[activePhoneId].disconnectAll();
40092760e1668917ad234d7283fc47d4c99f8c427c8Pavel Zhamaitsiak            }
40146c4302b8f52fbd62d7000848cd2bb3d36d15725Robert Greenwalt            return;
40246c4302b8f52fbd62d7000848cd2bb3d36d15725Robert Greenwalt        }
40346c4302b8f52fbd62d7000848cd2bb3d36d15725Robert Greenwalt
40446c4302b8f52fbd62d7000848cd2bb3d36d15725Robert Greenwalt        // if we have no active phones or the active phone is the desired, make requests
40546c4302b8f52fbd62d7000848cd2bb3d36d15725Robert Greenwalt        if (activePhoneId == INVALID_PHONE_INDEX || activePhoneId == requestedPhoneId) {
406bda761320929f714951c328bfec6a51a1978db97Wink Saville            Iterator<Integer> iterator = mRequestInfos.keySet().iterator();
407bda761320929f714951c328bfec6a51a1978db97Wink Saville            while (iterator.hasNext()) {
408bda761320929f714951c328bfec6a51a1978db97Wink Saville                RequestInfo requestInfo = mRequestInfos.get(iterator.next());
409a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt                if (requestInfo.executedPhoneId != INVALID_PHONE_INDEX) continue;
410a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt                if (getRequestPhoneId(requestInfo.request) == requestedPhoneId) {
41146c4302b8f52fbd62d7000848cd2bb3d36d15725Robert Greenwalt                    mDcSwitchAsyncChannel[requestedPhoneId].connect(requestInfo);
412a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
413a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
414bda761320929f714951c328bfec6a51a1978db97Wink Saville        } else {
41546c4302b8f52fbd62d7000848cd2bb3d36d15725Robert Greenwalt            // otherwise detatch so we can try connecting to the high-priority phone
416a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            mDcSwitchAsyncChannel[activePhoneId].disconnectAll();
417a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
418a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
419a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
420bda761320929f714951c328bfec6a51a1978db97Wink Saville    private void onExecuteRequest(RequestInfo requestInfo) {
421a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt        if (requestInfo.executedPhoneId == INVALID_PHONE_INDEX &&
422a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt                mRequestInfos.containsKey(requestInfo.request.requestId)) {
4232dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            logd("onExecuteRequest request=" + requestInfo);
424a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt            requestInfo.log("DctController.onExecuteRequest");
425bda761320929f714951c328bfec6a51a1978db97Wink Saville            String apn = apnForNetworkRequest(requestInfo.request);
426a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt            final int phoneId = getRequestPhoneId(requestInfo.request);
427a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt            requestInfo.executedPhoneId = phoneId;
428bda761320929f714951c328bfec6a51a1978db97Wink Saville            PhoneBase phoneBase = (PhoneBase)mPhones[phoneId].getActivePhone();
429bda761320929f714951c328bfec6a51a1978db97Wink Saville            DcTrackerBase dcTracker = phoneBase.mDcTracker;
4302f5e0f602beab84c8ba1a9c8ee7736c9df62b0beRobert Greenwalt            dcTracker.incApnRefCount(apn, requestInfo.getLog());
431bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
432a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
433a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
434bda761320929f714951c328bfec6a51a1978db97Wink Saville    private void onExecuteAllRequests(int phoneId) {
435bda761320929f714951c328bfec6a51a1978db97Wink Saville        logd("onExecuteAllRequests phoneId=" + phoneId);
436bda761320929f714951c328bfec6a51a1978db97Wink Saville        Iterator<Integer> iterator = mRequestInfos.keySet().iterator();
437bda761320929f714951c328bfec6a51a1978db97Wink Saville        while (iterator.hasNext()) {
438bda761320929f714951c328bfec6a51a1978db97Wink Saville            RequestInfo requestInfo = mRequestInfos.get(iterator.next());
439a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt            if (getRequestPhoneId(requestInfo.request) == phoneId) {
440bda761320929f714951c328bfec6a51a1978db97Wink Saville                onExecuteRequest(requestInfo);
441bda761320929f714951c328bfec6a51a1978db97Wink Saville            }
442a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
443a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
444a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
4452f5e0f602beab84c8ba1a9c8ee7736c9df62b0beRobert Greenwalt    private void onReleaseRequest(RequestInfo requestInfo) {
446bda761320929f714951c328bfec6a51a1978db97Wink Saville        logd("onReleaseRequest request=" + requestInfo);
447592359ae17a17d92bdaad8fb1757a769649ee7fbRobert Greenwalt        if (requestInfo != null) {
448592359ae17a17d92bdaad8fb1757a769649ee7fbRobert Greenwalt            requestInfo.log("DctController.onReleaseRequest");
449a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt            if (requestInfo.executedPhoneId != INVALID_PHONE_INDEX) {
450592359ae17a17d92bdaad8fb1757a769649ee7fbRobert Greenwalt                String apn = apnForNetworkRequest(requestInfo.request);
451a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt                int phoneId = requestInfo.executedPhoneId;
452a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt                requestInfo.executedPhoneId = INVALID_PHONE_INDEX;
453592359ae17a17d92bdaad8fb1757a769649ee7fbRobert Greenwalt                PhoneBase phoneBase = (PhoneBase)mPhones[phoneId].getActivePhone();
454592359ae17a17d92bdaad8fb1757a769649ee7fbRobert Greenwalt                DcTrackerBase dcTracker = phoneBase.mDcTracker;
4552f5e0f602beab84c8ba1a9c8ee7736c9df62b0beRobert Greenwalt                dcTracker.decApnRefCount(apn, requestInfo.getLog());
456592359ae17a17d92bdaad8fb1757a769649ee7fbRobert Greenwalt            }
457a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
458a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
459a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
460bda761320929f714951c328bfec6a51a1978db97Wink Saville    private void onReleaseAllRequests(int phoneId) {
461bda761320929f714951c328bfec6a51a1978db97Wink Saville        logd("onReleaseAllRequests phoneId=" + phoneId);
462bda761320929f714951c328bfec6a51a1978db97Wink Saville        Iterator<Integer> iterator = mRequestInfos.keySet().iterator();
463bda761320929f714951c328bfec6a51a1978db97Wink Saville        while (iterator.hasNext()) {
464bda761320929f714951c328bfec6a51a1978db97Wink Saville            RequestInfo requestInfo = mRequestInfos.get(iterator.next());
465a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt            if (requestInfo.executedPhoneId == phoneId) {
4662f5e0f602beab84c8ba1a9c8ee7736c9df62b0beRobert Greenwalt                onReleaseRequest(requestInfo);
467bda761320929f714951c328bfec6a51a1978db97Wink Saville            }
468bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
469a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
470a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
471a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt    private void onRetryAttach(int phoneId) {
472a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        final int topPriPhone = getTopPriorityRequestPhoneId();
473a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        logd("onRetryAttach phoneId=" + phoneId + " topPri phone = " + topPriPhone);
474a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt
47546c4302b8f52fbd62d7000848cd2bb3d36d15725Robert Greenwalt        if (phoneId != INVALID_PHONE_INDEX && phoneId == topPriPhone) {
476a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            mDcSwitchAsyncChannel[phoneId].retryConnect();
477a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        }
478a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt    }
479a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt
4805bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt    private void onSettingsChanged() {
481bda761320929f714951c328bfec6a51a1978db97Wink Saville        //Sub Selection
4821321ae8e44e3339ace5dabc4daf9512347c0fcc4Etan Cohen        long dataSubId = mSubController.getDefaultDataSubId();
483bda761320929f714951c328bfec6a51a1978db97Wink Saville
484bda761320929f714951c328bfec6a51a1978db97Wink Saville        int activePhoneId = -1;
4856bac33f472fbf66697b8eedd9b54a40daaba3086Wink Saville        for (int i=0; i<mDcSwitchStateMachine.length; i++) {
486bda761320929f714951c328bfec6a51a1978db97Wink Saville            if (!mDcSwitchAsyncChannel[i].isIdleSync()) {
487bda761320929f714951c328bfec6a51a1978db97Wink Saville                activePhoneId = i;
488bda761320929f714951c328bfec6a51a1978db97Wink Saville                break;
489bda761320929f714951c328bfec6a51a1978db97Wink Saville            }
490a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
491bda761320929f714951c328bfec6a51a1978db97Wink Saville
492b237a11044ed842d2865ff8c8716befb06b6ca25Wink Saville        int[] subIds = SubscriptionManager.getSubId(activePhoneId);
4931321ae8e44e3339ace5dabc4daf9512347c0fcc4Etan Cohen        if (subIds ==  null || subIds.length == 0) {
4941321ae8e44e3339ace5dabc4daf9512347c0fcc4Etan Cohen            loge("onSettingsChange, subIds null or length 0 for activePhoneId " + activePhoneId);
4951321ae8e44e3339ace5dabc4daf9512347c0fcc4Etan Cohen            return;
4961321ae8e44e3339ace5dabc4daf9512347c0fcc4Etan Cohen        }
497bda761320929f714951c328bfec6a51a1978db97Wink Saville        logd("onSettingsChange, data sub: " + dataSubId + ", active data sub: " + subIds[0]);
498bda761320929f714951c328bfec6a51a1978db97Wink Saville
499bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (subIds[0] != dataSubId) {
500bda761320929f714951c328bfec6a51a1978db97Wink Saville            Iterator<Integer> iterator = mRequestInfos.keySet().iterator();
501bda761320929f714951c328bfec6a51a1978db97Wink Saville            while (iterator.hasNext()) {
502bda761320929f714951c328bfec6a51a1978db97Wink Saville                RequestInfo requestInfo = mRequestInfos.get(iterator.next());
503bda761320929f714951c328bfec6a51a1978db97Wink Saville                String specifier = requestInfo.request.networkCapabilities.getNetworkSpecifier();
504bda761320929f714951c328bfec6a51a1978db97Wink Saville                if (specifier == null || specifier.equals("")) {
505a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt                    onReleaseRequest(requestInfo);
506bda761320929f714951c328bfec6a51a1978db97Wink Saville                }
507bda761320929f714951c328bfec6a51a1978db97Wink Saville            }
508bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
509bda761320929f714951c328bfec6a51a1978db97Wink Saville
510bda761320929f714951c328bfec6a51a1978db97Wink Saville        // Some request maybe pending due to invalid settings
511bda761320929f714951c328bfec6a51a1978db97Wink Saville        // Try to handle pending request when settings changed
512bda761320929f714951c328bfec6a51a1978db97Wink Saville        for (int i = 0; i < mPhoneNum; ++i) {
513bda761320929f714951c328bfec6a51a1978db97Wink Saville            ((DctController.TelephonyNetworkFactory)mNetworkFactory[i]).evalPendingRequest();
514bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
515bda761320929f714951c328bfec6a51a1978db97Wink Saville
516bda761320929f714951c328bfec6a51a1978db97Wink Saville        processRequests();
517a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
518a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
519bda761320929f714951c328bfec6a51a1978db97Wink Saville    private int getTopPriorityRequestPhoneId() {
520a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt        String topSubId = null;
521bda761320929f714951c328bfec6a51a1978db97Wink Saville        int priority = -1;
522a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt        int subId;
523bda761320929f714951c328bfec6a51a1978db97Wink Saville
524a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt        for (RequestInfo requestInfo : mRequestInfos.values()) {
525a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt            logd("getTopPriorityRequestPhoneId requestInfo=" + requestInfo);
526a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt            if (requestInfo.priority > priority) {
527a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt                priority = requestInfo.priority;
528a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt                topSubId = requestInfo.request.networkCapabilities.getNetworkSpecifier();
529bda761320929f714951c328bfec6a51a1978db97Wink Saville            }
530bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
531a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt        if (TextUtils.isEmpty(topSubId)) {
532a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt            subId = mSubController.getDefaultDataSubId();
533a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt        } else {
534a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt            subId = Integer.parseInt(topSubId);
535a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt        }
536682afe07527c6042e34b14fc29bf058e5b2cd7ccRobert Greenwalt        final int phoneId = mSubController.getPhoneId(subId);
537682afe07527c6042e34b14fc29bf058e5b2cd7ccRobert Greenwalt        if (phoneId == DEFAULT_PHONE_INDEX) {
538682afe07527c6042e34b14fc29bf058e5b2cd7ccRobert Greenwalt            // that means there isn't a phone for the default sub
539682afe07527c6042e34b14fc29bf058e5b2cd7ccRobert Greenwalt            return INVALID_PHONE_INDEX;
540682afe07527c6042e34b14fc29bf058e5b2cd7ccRobert Greenwalt        }
541682afe07527c6042e34b14fc29bf058e5b2cd7ccRobert Greenwalt        return phoneId;
542a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
543a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
544bda761320929f714951c328bfec6a51a1978db97Wink Saville    private void onSubInfoReady() {
545299dad50409e907993fa96c7401d4f10c58018b1Wink Saville        logd("onSubInfoReady mPhoneNum=" + mPhoneNum);
546bda761320929f714951c328bfec6a51a1978db97Wink Saville        for (int i = 0; i < mPhoneNum; ++i) {
547299dad50409e907993fa96c7401d4f10c58018b1Wink Saville            int subId = mPhones[i].getSubId();
548299dad50409e907993fa96c7401d4f10c58018b1Wink Saville            logd("onSubInfoReady handle pending requests subId=" + subId);
549299dad50409e907993fa96c7401d4f10c58018b1Wink Saville            mNetworkFilter[i].setNetworkSpecifier(String.valueOf(subId));
550bda761320929f714951c328bfec6a51a1978db97Wink Saville            ((DctController.TelephonyNetworkFactory)mNetworkFactory[i]).evalPendingRequest();
551bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
5521392c6c61aaff0f52f8d21423956aef6fa80f46bLegler Wu        processRequests();
553a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
554a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
555bda761320929f714951c328bfec6a51a1978db97Wink Saville    private String apnForNetworkRequest(NetworkRequest nr) {
556bda761320929f714951c328bfec6a51a1978db97Wink Saville        NetworkCapabilities nc = nr.networkCapabilities;
557bda761320929f714951c328bfec6a51a1978db97Wink Saville        // For now, ignore the bandwidth stuff
558bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (nc.getTransportTypes().length > 0 &&
559bda761320929f714951c328bfec6a51a1978db97Wink Saville                nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == false) {
560bda761320929f714951c328bfec6a51a1978db97Wink Saville            return null;
561bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
562bda761320929f714951c328bfec6a51a1978db97Wink Saville
563bda761320929f714951c328bfec6a51a1978db97Wink Saville        // in the near term just do 1-1 matches.
564bda761320929f714951c328bfec6a51a1978db97Wink Saville        // TODO - actually try to match the set of capabilities
565bda761320929f714951c328bfec6a51a1978db97Wink Saville        int type = -1;
566bda761320929f714951c328bfec6a51a1978db97Wink Saville        String name = null;
567bda761320929f714951c328bfec6a51a1978db97Wink Saville
568bda761320929f714951c328bfec6a51a1978db97Wink Saville        boolean error = false;
569bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
570bda761320929f714951c328bfec6a51a1978db97Wink Saville            if (name != null) error = true;
571bda761320929f714951c328bfec6a51a1978db97Wink Saville            name = PhoneConstants.APN_TYPE_DEFAULT;
572bda761320929f714951c328bfec6a51a1978db97Wink Saville            type = ConnectivityManager.TYPE_MOBILE;
573bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
574bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
575bda761320929f714951c328bfec6a51a1978db97Wink Saville            if (name != null) error = true;
576bda761320929f714951c328bfec6a51a1978db97Wink Saville            name = PhoneConstants.APN_TYPE_MMS;
577bda761320929f714951c328bfec6a51a1978db97Wink Saville            type = ConnectivityManager.TYPE_MOBILE_MMS;
578bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
579bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
580bda761320929f714951c328bfec6a51a1978db97Wink Saville            if (name != null) error = true;
581bda761320929f714951c328bfec6a51a1978db97Wink Saville            name = PhoneConstants.APN_TYPE_SUPL;
582bda761320929f714951c328bfec6a51a1978db97Wink Saville            type = ConnectivityManager.TYPE_MOBILE_SUPL;
583bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
584bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) {
585bda761320929f714951c328bfec6a51a1978db97Wink Saville            if (name != null) error = true;
586bda761320929f714951c328bfec6a51a1978db97Wink Saville            name = PhoneConstants.APN_TYPE_DUN;
587bda761320929f714951c328bfec6a51a1978db97Wink Saville            type = ConnectivityManager.TYPE_MOBILE_DUN;
588bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
589bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) {
590bda761320929f714951c328bfec6a51a1978db97Wink Saville            if (name != null) error = true;
591bda761320929f714951c328bfec6a51a1978db97Wink Saville            name = PhoneConstants.APN_TYPE_FOTA;
592bda761320929f714951c328bfec6a51a1978db97Wink Saville            type = ConnectivityManager.TYPE_MOBILE_FOTA;
593bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
594bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
595bda761320929f714951c328bfec6a51a1978db97Wink Saville            if (name != null) error = true;
596bda761320929f714951c328bfec6a51a1978db97Wink Saville            name = PhoneConstants.APN_TYPE_IMS;
597bda761320929f714951c328bfec6a51a1978db97Wink Saville            type = ConnectivityManager.TYPE_MOBILE_IMS;
598bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
599bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) {
600bda761320929f714951c328bfec6a51a1978db97Wink Saville            if (name != null) error = true;
601bda761320929f714951c328bfec6a51a1978db97Wink Saville            name = PhoneConstants.APN_TYPE_CBS;
602bda761320929f714951c328bfec6a51a1978db97Wink Saville            type = ConnectivityManager.TYPE_MOBILE_CBS;
603bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
604bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_IA)) {
605bda761320929f714951c328bfec6a51a1978db97Wink Saville            if (name != null) error = true;
606bda761320929f714951c328bfec6a51a1978db97Wink Saville            name = PhoneConstants.APN_TYPE_IA;
607bda761320929f714951c328bfec6a51a1978db97Wink Saville            type = ConnectivityManager.TYPE_MOBILE_IA;
608bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
609bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_RCS)) {
610bda761320929f714951c328bfec6a51a1978db97Wink Saville            if (name != null) error = true;
611bda761320929f714951c328bfec6a51a1978db97Wink Saville            name = null;
612bda761320929f714951c328bfec6a51a1978db97Wink Saville            loge("RCS APN type not yet supported");
613bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
614bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_XCAP)) {
615bda761320929f714951c328bfec6a51a1978db97Wink Saville            if (name != null) error = true;
616bda761320929f714951c328bfec6a51a1978db97Wink Saville            name = null;
617bda761320929f714951c328bfec6a51a1978db97Wink Saville            loge("XCAP APN type not yet supported");
618bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
619bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)) {
620bda761320929f714951c328bfec6a51a1978db97Wink Saville            if (name != null) error = true;
62119736f6fbee4d3079dc2debf9fb6a54bf7686161Robert Greenwalt            name = PhoneConstants.APN_TYPE_EMERGENCY;
62219736f6fbee4d3079dc2debf9fb6a54bf7686161Robert Greenwalt            type = ConnectivityManager.TYPE_MOBILE_EMERGENCY;
623bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
624bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (error) {
625af171aa4dcf294bf2d1b9bed54ef9a6b0ec76361Paul Jensen            // TODO: If this error condition is removed, the framework's handling of
626af171aa4dcf294bf2d1b9bed54ef9a6b0ec76361Paul Jensen            // NET_CAPABILITY_NOT_RESTRICTED will need to be updated so requests for
627af171aa4dcf294bf2d1b9bed54ef9a6b0ec76361Paul Jensen            // say FOTA and INTERNET are marked as restricted.  This is not how
628af171aa4dcf294bf2d1b9bed54ef9a6b0ec76361Paul Jensen            // NetworkCapabilities.maybeMarkCapabilitiesRestricted currently works.
629bda761320929f714951c328bfec6a51a1978db97Wink Saville            loge("Multiple apn types specified in request - result is unspecified!");
630bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
631bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (type == -1 || name == null) {
632bda761320929f714951c328bfec6a51a1978db97Wink Saville            loge("Unsupported NetworkRequest in Telephony: nr=" + nr);
633bda761320929f714951c328bfec6a51a1978db97Wink Saville            return null;
634bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
635bda761320929f714951c328bfec6a51a1978db97Wink Saville        return name;
636a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
637a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
638bda761320929f714951c328bfec6a51a1978db97Wink Saville    private int getRequestPhoneId(NetworkRequest networkRequest) {
639bda761320929f714951c328bfec6a51a1978db97Wink Saville        String specifier = networkRequest.networkCapabilities.getNetworkSpecifier();
640b237a11044ed842d2865ff8c8716befb06b6ca25Wink Saville        int subId;
641bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (specifier == null || specifier.equals("")) {
642bda761320929f714951c328bfec6a51a1978db97Wink Saville            subId = mSubController.getDefaultDataSubId();
643bda761320929f714951c328bfec6a51a1978db97Wink Saville        } else {
644b237a11044ed842d2865ff8c8716befb06b6ca25Wink Saville            subId = Integer.parseInt(specifier);
645bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
646bda761320929f714951c328bfec6a51a1978db97Wink Saville        int phoneId = mSubController.getPhoneId(subId);
647bda761320929f714951c328bfec6a51a1978db97Wink Saville        return phoneId;
648bda761320929f714951c328bfec6a51a1978db97Wink Saville    }
649bda761320929f714951c328bfec6a51a1978db97Wink Saville
650bda761320929f714951c328bfec6a51a1978db97Wink Saville    private static void logd(String s) {
651bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (DBG) Rlog.d(LOG_TAG, s);
652a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
653a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
654a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static void loge(String s) {
655bda761320929f714951c328bfec6a51a1978db97Wink Saville        if (DBG) Rlog.e(LOG_TAG, s);
656a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
657a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
658bda761320929f714951c328bfec6a51a1978db97Wink Saville    private class TelephonyNetworkFactory extends NetworkFactory {
659bda761320929f714951c328bfec6a51a1978db97Wink Saville        private final SparseArray<NetworkRequest> mPendingReq = new SparseArray<NetworkRequest>();
660bda761320929f714951c328bfec6a51a1978db97Wink Saville        private Phone mPhone;
661bda761320929f714951c328bfec6a51a1978db97Wink Saville
6622dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt        private class RequestLogger {
6632dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            public NetworkRequest request;
6642dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            public LocalLog log;
6652dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt
6662dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            public RequestLogger(NetworkRequest r, LocalLog log) {
6672dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                request = r;
6682dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                this.log = log;
6692dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            }
6702dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt        }
6712dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt
6722dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt        private static final int MAX_REQUESTS_LOGGED = 20;
6732dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt        private static final int MAX_LOG_LINES_PER_REQUEST = 50;
6742dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt
6752dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt        private ArrayDeque<RequestLogger> mRequestLogs = new ArrayDeque<RequestLogger>();
6762dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt
677bda761320929f714951c328bfec6a51a1978db97Wink Saville        public TelephonyNetworkFactory(Looper l, Context c, String TAG, Phone phone,
678bda761320929f714951c328bfec6a51a1978db97Wink Saville                NetworkCapabilities nc) {
679bda761320929f714951c328bfec6a51a1978db97Wink Saville            super(l, c, TAG, nc);
680bda761320929f714951c328bfec6a51a1978db97Wink Saville            mPhone = phone;
681bda761320929f714951c328bfec6a51a1978db97Wink Saville            log("NetworkCapabilities: " + nc);
682bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
683bda761320929f714951c328bfec6a51a1978db97Wink Saville
6842dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt        public LocalLog requestLog(int requestId, String l) {
6852dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            synchronized(mRequestLogs) {
6862dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                for (RequestLogger r : mRequestLogs) {
6872dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                    if (r.request.requestId == requestId) {
6882dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                        r.log.log(l);
6892dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                        return r.log;
6902dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                    }
6912dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                }
6922dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            }
6932dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            return null;
6942dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt        }
6952dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt
6962dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt        private LocalLog addLogger(NetworkRequest request) {
6972dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            synchronized(mRequestLogs) {
6982dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                for (RequestLogger r : mRequestLogs) {
6992dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                    if (r.request.requestId == request.requestId) {
7002dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                        return r.log;
7012dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                    }
7022dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                }
7032dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                LocalLog l = new LocalLog(MAX_LOG_LINES_PER_REQUEST);
7042dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                RequestLogger logger = new RequestLogger(request, l);
7052dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                while (mRequestLogs.size() >= MAX_REQUESTS_LOGGED) {
7062dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                    mRequestLogs.removeFirst();
7072dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                }
7082dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                mRequestLogs.addLast(logger);
7092dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                return l;
7102dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            }
7112dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt        }
7122dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt
713bda761320929f714951c328bfec6a51a1978db97Wink Saville        @Override
714bda761320929f714951c328bfec6a51a1978db97Wink Saville        protected void needNetworkFor(NetworkRequest networkRequest, int score) {
715bda761320929f714951c328bfec6a51a1978db97Wink Saville            // figure out the apn type and enable it
716bda761320929f714951c328bfec6a51a1978db97Wink Saville            log("Cellular needs Network for " + networkRequest);
717bda761320929f714951c328bfec6a51a1978db97Wink Saville
7182dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            final LocalLog l = addLogger(networkRequest);
7192dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt
7205bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt            if (!SubscriptionManager.isUsableSubIdValue(mPhone.getSubId()) ||
7215bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt                    getRequestPhoneId(networkRequest) != mPhone.getPhoneId()) {
7225bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt                final String str = "Request not useable, pending request.";
7232dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                log(str);
7242dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                l.log(str);
725bda761320929f714951c328bfec6a51a1978db97Wink Saville                mPendingReq.put(networkRequest.requestId, networkRequest);
726bda761320929f714951c328bfec6a51a1978db97Wink Saville                return;
727bda761320929f714951c328bfec6a51a1978db97Wink Saville            }
728bda761320929f714951c328bfec6a51a1978db97Wink Saville
7295bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt            DcTrackerBase dcTracker =((PhoneBase)mPhone).mDcTracker;
7305bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt            String apn = apnForNetworkRequest(networkRequest);
7315bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt            if (dcTracker.isApnSupported(apn)) {
732a7228870e5203c8c0d73ea506ebac0a34e25b78aRobert Greenwalt                requestNetwork(networkRequest, dcTracker.getApnPriority(apn), l);
733bda761320929f714951c328bfec6a51a1978db97Wink Saville            } else {
7345bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt                final String str = "Unsupported APN";
7352dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                log(str);
7362dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                l.log(str);
737bda761320929f714951c328bfec6a51a1978db97Wink Saville            }
738bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
739bda761320929f714951c328bfec6a51a1978db97Wink Saville
740bda761320929f714951c328bfec6a51a1978db97Wink Saville        @Override
741bda761320929f714951c328bfec6a51a1978db97Wink Saville        protected void releaseNetworkFor(NetworkRequest networkRequest) {
7422dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            String str = "Cellular releasing Network for ";
7432dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            log(str + networkRequest);
7442dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            final LocalLog l = requestLog(networkRequest.requestId, str);
745bda761320929f714951c328bfec6a51a1978db97Wink Saville
7465bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt            if (mPendingReq.get(networkRequest.requestId) != null) {
7472dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                str = "Sub Info has not been ready, remove request.";
7482dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                log(str);
7492dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                if (l != null) l.log(str);
750bda761320929f714951c328bfec6a51a1978db97Wink Saville                mPendingReq.remove(networkRequest.requestId);
751bda761320929f714951c328bfec6a51a1978db97Wink Saville                return;
752bda761320929f714951c328bfec6a51a1978db97Wink Saville            }
753bda761320929f714951c328bfec6a51a1978db97Wink Saville
7545bc4a86f7d58a18a65c71e9227b0f09a6338ce0cRobert Greenwalt            releaseNetwork(networkRequest);
755bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
756bda761320929f714951c328bfec6a51a1978db97Wink Saville
757bda761320929f714951c328bfec6a51a1978db97Wink Saville        @Override
758bda761320929f714951c328bfec6a51a1978db97Wink Saville        protected void log(String s) {
759bda761320929f714951c328bfec6a51a1978db97Wink Saville            if (DBG) Rlog.d(LOG_TAG, "[TNF " + mPhone.getSubId() + "]" + s);
760bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
761bda761320929f714951c328bfec6a51a1978db97Wink Saville
762bda761320929f714951c328bfec6a51a1978db97Wink Saville        public void evalPendingRequest() {
763bda761320929f714951c328bfec6a51a1978db97Wink Saville            log("evalPendingRequest, pending request size is " + mPendingReq.size());
764bda761320929f714951c328bfec6a51a1978db97Wink Saville            int key = 0;
765bda761320929f714951c328bfec6a51a1978db97Wink Saville            for(int i = 0; i < mPendingReq.size(); i++) {
766bda761320929f714951c328bfec6a51a1978db97Wink Saville                key = mPendingReq.keyAt(i);
767bda761320929f714951c328bfec6a51a1978db97Wink Saville                NetworkRequest request = mPendingReq.get(key);
768bda761320929f714951c328bfec6a51a1978db97Wink Saville                log("evalPendingRequest: request = " + request);
769bda761320929f714951c328bfec6a51a1978db97Wink Saville
770bda761320929f714951c328bfec6a51a1978db97Wink Saville                mPendingReq.remove(request.requestId);
771bda761320929f714951c328bfec6a51a1978db97Wink Saville                needNetworkFor(request, 0);
772bda761320929f714951c328bfec6a51a1978db97Wink Saville            }
773bda761320929f714951c328bfec6a51a1978db97Wink Saville        }
774be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwalt
775be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwalt        @Override
776be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwalt        public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
777be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwalt            super.dump(fd, writer, args);
778be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwalt            final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
779be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwalt            pw.increaseIndent();
780be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwalt            pw.println("Pending Requests:");
781be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwalt            pw.increaseIndent();
782be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwalt            for (int i = 0; i < mPendingReq.size(); i++) {
783be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwalt                NetworkRequest request = mPendingReq.valueAt(i);
784be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwalt                pw.println(request);
785be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwalt            }
786be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwalt            pw.decreaseIndent();
7872dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt
7882dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            pw.println("Request History:");
7892dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            pw.increaseIndent();
7902dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            synchronized(mRequestLogs) {
7912dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                for (RequestLogger r : mRequestLogs) {
7922dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                    pw.println(r.request);
7932dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                    pw.increaseIndent();
7942dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                    r.log.dump(fd, pw, args);
7952dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                    pw.decreaseIndent();
7962dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt                }
7972dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            }
7982dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt            pw.decreaseIndent();
799be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwalt            pw.decreaseIndent();
800be2a6a25317c857290e486c0d9903c6cb658f9b5Robert Greenwalt        }
801bda761320929f714951c328bfec6a51a1978db97Wink Saville    }
802e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville
803e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
804e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville        pw.println("DctController:");
805e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville        try {
8066bac33f472fbf66697b8eedd9b54a40daaba3086Wink Saville            for (DcSwitchStateMachine dssm : mDcSwitchStateMachine) {
807e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville                dssm.dump(fd, pw, args);
808e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville            }
809e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville        } catch (Exception e) {
810e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville            e.printStackTrace();
811e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville        }
812e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville        pw.flush();
813e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville        pw.println("++++++++++++++++++++++++++++++++");
814e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville
815e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville        try {
816e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville            for (Entry<Integer, RequestInfo> entry : mRequestInfos.entrySet()) {
817e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville                pw.println("mRequestInfos[" + entry.getKey() + "]=" + entry.getValue());
818e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville            }
819e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville        } catch (Exception e) {
820e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville            e.printStackTrace();
821e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville        }
822e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville        pw.flush();
823e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville        pw.println("++++++++++++++++++++++++++++++++");
824e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville        pw.flush();
8258bb75423745b09a92688919f5b32d49695a61abbRobert Greenwalt        pw.println("TelephonyNetworkFactories:");
8268bb75423745b09a92688919f5b32d49695a61abbRobert Greenwalt        for (NetworkFactory tnf : mNetworkFactory) {
827dabb160754d8266ed97d819ba30d95b0d3dd6bb8Robert Greenwalt            tnf.dump(fd, pw, args);
8288bb75423745b09a92688919f5b32d49695a61abbRobert Greenwalt        }
8298bb75423745b09a92688919f5b32d49695a61abbRobert Greenwalt        pw.flush();
8308bb75423745b09a92688919f5b32d49695a61abbRobert Greenwalt        pw.println("++++++++++++++++++++++++++++++++");
8318bb75423745b09a92688919f5b32d49695a61abbRobert Greenwalt        pw.flush();
832e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville    }
833a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
834