1a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/*
22b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville * Copyright (C) 2013 The Android Open Source Project
3a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
42b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
52b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville * you may not use this file except in compliance with the License.
62b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville * You may obtain a copy of the License at
7a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
82b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
92b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville *
102b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville * Unless required by applicable law or agreed to in writing, software
112b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
122b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville * See the License for the specific language governing permissions and
142b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville * limitations under the License.
15a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */
16a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
17a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillepackage com.android.internal.telephony;
18a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
19a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.Context;
202b40e6226b4b71408964bca46f0a9f256cd4f523Wink Savilleimport android.content.Intent;
212b40e6226b4b71408964bca46f0a9f256cd4f523Wink Savilleimport android.os.AsyncResult;
22a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Handler;
23a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Message;
242b40e6226b4b71408964bca46f0a9f256cd4f523Wink Savilleimport android.os.PowerManager;
252b40e6226b4b71408964bca46f0a9f256cd4f523Wink Savilleimport android.os.PowerManager.WakeLock;
262b40e6226b4b71408964bca46f0a9f256cd4f523Wink Savilleimport android.telephony.RadioAccessFamily;
27a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.Rlog;
28a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.TelephonyManager;
294c4b8afa802e537bafd691704193f4b3812de738Stuart Scottimport android.util.Log;
30a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
31a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.uicc.UiccController;
32a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
330db00d61d6b53b480235cc1567d5b06f55d15046Jack Yuimport java.util.ArrayList;
344c4b8afa802e537bafd691704193f4b3812de738Stuart Scottimport java.util.HashSet;
350db00d61d6b53b480235cc1567d5b06f55d15046Jack Yuimport java.util.Random;
360db00d61d6b53b480235cc1567d5b06f55d15046Jack Yuimport java.util.concurrent.atomic.AtomicInteger;
37e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville
38a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillepublic class ProxyController {
39a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final String LOG_TAG = "ProxyController";
40a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
412b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int EVENT_NOTIFICATION_RC_CHANGED        = 1;
422b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int EVENT_START_RC_RESPONSE        = 2;
432b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int EVENT_APPLY_RC_RESPONSE        = 3;
442b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int EVENT_FINISH_RC_RESPONSE       = 4;
45a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt    private static final int EVENT_TIMEOUT                  = 5;
462b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
472b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int SET_RC_STATUS_IDLE             = 0;
482b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int SET_RC_STATUS_STARTING         = 1;
492b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int SET_RC_STATUS_STARTED          = 2;
502b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int SET_RC_STATUS_APPLYING         = 3;
512b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int SET_RC_STATUS_SUCCESS          = 4;
522b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int SET_RC_STATUS_FAIL             = 5;
532b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
542b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // The entire transaction must complete within this amount of time
552b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // or a FINISH will be issued to each Logical Modem with the old
562b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // Radio Access Family.
572b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int SET_RC_TIMEOUT_WAITING_MSEC    = (45 * 1000);
582b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
59a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Class Variables
60a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static ProxyController sProxyController;
61a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
626c806ef816f8ae0a1849ba05f3128a04577b32d0Amit Mahajan    private Phone[] mPhones;
63a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
64a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private UiccController mUiccController;
65a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
66a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private CommandsInterface[] mCi;
67a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
68a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Context mContext;
69a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
70e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt    private PhoneSwitcher mPhoneSwitcher;
71a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
72a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //UiccPhoneBookController to use proper IccPhoneBookInterfaceManagerProxy object
73a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private UiccPhoneBookController mUiccPhoneBookController;
74a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
75aa48e77d9b817a4749c49551632bd8eb7888d121Amit Mahajan    //PhoneSubInfoController to use proper PhoneSubInfoProxy object
76aa48e77d9b817a4749c49551632bd8eb7888d121Amit Mahajan    private PhoneSubInfoController mPhoneSubInfoController;
77aa48e77d9b817a4749c49551632bd8eb7888d121Amit Mahajan
78a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //UiccSmsController to use proper IccSmsInterfaceManager object
79a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private UiccSmsController mUiccSmsController;
80a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
812b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    WakeLock mWakeLock;
822b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
832b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // record each phone's set radio capability status
842b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private int[] mSetRadioAccessFamilyStatus;
852b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private int mRadioAccessFamilyStatusCounter;
8611c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt    private boolean mTransactionFailed = false;
872b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
8832dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    private String[] mCurrentLogicalModemIds;
8932dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    private String[] mNewLogicalModemIds;
902b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
912b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // Allows the generation of unique Id's for radio capability request session  id
922b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private AtomicInteger mUniqueIdGenerator = new AtomicInteger(new Random().nextInt());
932b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
942b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // on-going radio capability request session id
952b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private int mRadioCapabilitySessionId;
962b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
972b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // Record new and old Radio Access Family (raf) configuration.
982b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // The old raf configuration is used to restore each logical modem raf when FINISH is
992b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // issued if any requests fail.
1002b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private int[] mNewRadioAccessFamily;
1012b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private int[] mOldRadioAccessFamily;
1022b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
1032b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
104a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Class Methods
1056c806ef816f8ae0a1849ba05f3128a04577b32d0Amit Mahajan    public static ProxyController getInstance(Context context, Phone[] phone,
106e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt            UiccController uiccController, CommandsInterface[] ci, PhoneSwitcher ps) {
107a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (sProxyController == null) {
108e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt            sProxyController = new ProxyController(context, phone, uiccController, ci, ps);
109a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
110a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return sProxyController;
111a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
112a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1134e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott    public static ProxyController getInstance() {
114a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return sProxyController;
115a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
116a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1176c806ef816f8ae0a1849ba05f3128a04577b32d0Amit Mahajan    private ProxyController(Context context, Phone[] phone, UiccController uiccController,
118e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt            CommandsInterface[] ci, PhoneSwitcher phoneSwitcher) {
119a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        logd("Constructor - Enter");
120a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
121a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mContext = context;
1223a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mPhones = phone;
123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mUiccController = uiccController;
124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCi = ci;
125e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        mPhoneSwitcher = phoneSwitcher;
126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1273a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mUiccPhoneBookController = new UiccPhoneBookController(mPhones);
1282549bbfd0439b8b549712a2d255dcf05bca7f1ebAmit Mahajan        mPhoneSubInfoController = new PhoneSubInfoController(mContext, mPhones);
1290db00d61d6b53b480235cc1567d5b06f55d15046Jack Yu        mUiccSmsController = new UiccSmsController();
1303a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mSetRadioAccessFamilyStatus = new int[mPhones.length];
1313a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mNewRadioAccessFamily = new int[mPhones.length];
1323a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mOldRadioAccessFamily = new int[mPhones.length];
1333a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mCurrentLogicalModemIds = new String[mPhones.length];
1343a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mNewLogicalModemIds = new String[mPhones.length];
1352b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
1362b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // wake lock for set radio capability
1372b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
1382b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
1392b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        mWakeLock.setReferenceCounted(false);
1402b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
1412b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Clear to be sure we're in the initial state
1422b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        clearTransaction();
1433a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        for (int i = 0; i < mPhones.length; i++) {
1443a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            mPhones[i].registerForRadioCapabilityChanged(
1454e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                    mHandler, EVENT_NOTIFICATION_RC_CHANGED, null);
1464e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott        }
147a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        logd("Constructor - Exit");
148a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
149a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1502b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    public void updateDataConnectionTracker(int sub) {
1513a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mPhones[sub].updateDataConnectionTracker();
1522b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
1532b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
1542b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    public void enableDataConnectivity(int sub) {
1553a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mPhones[sub].setInternalDataEnabled(true, null);
1562b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
1572b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
1582b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    public void disableDataConnectivity(int sub,
1592b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            Message dataCleanedUpMsg) {
1603a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mPhones[sub].setInternalDataEnabled(false, dataCleanedUpMsg);
1612b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
1622b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
1632b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    public void updateCurrentCarrierInProvider(int sub) {
1643a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mPhones[sub].updateCurrentCarrierInProvider();
1652b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
1662b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
167b237a11044ed842d2865ff8c8716befb06b6ca25Wink Saville    public void registerForAllDataDisconnected(int subId, Handler h, int what, Object obj) {
168a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int phoneId = SubscriptionController.getInstance().getPhoneId(subId);
169a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
170a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount()) {
1713a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            mPhones[phoneId].registerForAllDataDisconnected(h, what, obj);
172a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
173a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
174a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
175b237a11044ed842d2865ff8c8716befb06b6ca25Wink Saville    public void unregisterForAllDataDisconnected(int subId, Handler h) {
176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int phoneId = SubscriptionController.getInstance().getPhoneId(subId);
177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount()) {
1793a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            mPhones[phoneId].unregisterForAllDataDisconnected(h);
180a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
181a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
183b237a11044ed842d2865ff8c8716befb06b6ca25Wink Saville    public boolean isDataDisconnected(int subId) {
184a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int phoneId = SubscriptionController.getInstance().getPhoneId(subId);
185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
186a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount()) {
1873a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            return mPhones[phoneId].mDcTracker.isDisconnected();
188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
1894255481b2c36b884cfc97e44ce4479f312610136Robert Greenwalt            // if we can't find a phone for the given subId, it is disconnected.
1904255481b2c36b884cfc97e44ce4479f312610136Robert Greenwalt            return true;
191a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
192a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
193a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1942b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    /**
1952b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * Get phone radio type and access technology.
1962b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     *
1972b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * @param phoneId which phone you want to get
1982b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * @return phone radio type and access technology for input phone ID
1992b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     */
2002b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    public int getRadioAccessFamily(int phoneId) {
2013a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        if (phoneId >= mPhones.length) {
2022b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            return RadioAccessFamily.RAF_UNKNOWN;
2032b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        } else {
2043a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            return mPhones[phoneId].getRadioAccessFamily();
2052b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
2062b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
2072b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
2082b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    /**
2092b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * Set phone radio type and access technology for each phone.
2102b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     *
2112b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * @param rafs an RadioAccessFamily array to indicate all phone's
2122b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     *        new radio access family. The length of RadioAccessFamily
2132b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     *        must equal to phone count.
21412fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal     * @return false if another session is already active and the request is rejected.
2152b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     */
21612fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal    public boolean setRadioCapability(RadioAccessFamily[] rafs) {
2173a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        if (rafs.length != mPhones.length) {
2182b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            throw new RuntimeException("Length of input rafs must equal to total phone count");
2192b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
2202b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Check if there is any ongoing transaction and throw an exception if there
2212b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // is one as this is a programming error.
2222b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        synchronized (mSetRadioAccessFamilyStatus) {
2233a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            for (int i = 0; i < mPhones.length; i++) {
2242b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                if (mSetRadioAccessFamilyStatus[i] != SET_RC_STATUS_IDLE) {
22512fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal                    // TODO: The right behaviour is to cancel previous request and send this.
22612fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal                    loge("setRadioCapability: Phone[" + i + "] is not idle. Rejecting request.");
22712fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal                    return false;
2282b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                }
2292b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
2302b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
2312b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
232e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott        // Check we actually need to do anything
233e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott        boolean same = true;
2343a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        for (int i = 0; i < mPhones.length; i++) {
2353a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            if (mPhones[i].getRadioAccessFamily() != rafs[i].getRadioAccessFamily()) {
236e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott                same = false;
237e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott            }
238e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott        }
239e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott        if (same) {
240e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott            // All phones are already set to the requested raf
241e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott            logd("setRadioCapability: Already in requested configuration, nothing to do.");
242e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott            // It isn't really an error, so return true - everything is OK.
243e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott            return true;
244e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott        }
245e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott
2462b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Clear to be sure we're in the initial state
2472b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        clearTransaction();
2482b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
2492b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Keep a wake lock until we finish radio capability changed
2502b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        mWakeLock.acquire();
2512b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
25211c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt        return doSetRadioCapabilities(rafs);
25311c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt    }
25411c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt
25511c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt    private boolean doSetRadioCapabilities(RadioAccessFamily[] rafs) {
25611c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt        // A new sessionId for this transaction
25711c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt        mRadioCapabilitySessionId = mUniqueIdGenerator.getAndIncrement();
25811c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt
2592b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Start timer to make sure all phones respond within a specific time interval.
2602b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Will send FINISH if a timeout occurs.
261a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        Message msg = mHandler.obtainMessage(EVENT_TIMEOUT, mRadioCapabilitySessionId, 0);
262a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        mHandler.sendMessageDelayed(msg, SET_RC_TIMEOUT_WAITING_MSEC);
2632b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
2642b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        synchronized (mSetRadioAccessFamilyStatus) {
2654e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott            logd("setRadioCapability: new request session id=" + mRadioCapabilitySessionId);
26611c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt            resetRadioAccessFamilyStatusCounter();
2672b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            for (int i = 0; i < rafs.length; i++) {
2682b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                int phoneId = rafs[i].getPhoneId();
2694e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("setRadioCapability: phoneId=" + phoneId + " status=STARTING");
2702b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                mSetRadioAccessFamilyStatus[phoneId] = SET_RC_STATUS_STARTING;
2713a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                mOldRadioAccessFamily[phoneId] = mPhones[phoneId].getRadioAccessFamily();
2727e7d2b34010bf24a70bbf40303c7a4606c438adaStuart Scott                int requestedRaf = rafs[i].getRadioAccessFamily();
273972efd34f867b7803688c3f831106f59244a11f0Stuart Scott                // TODO Set the new radio access family to the maximum of the requested & supported
2743a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                // int supportedRaf = mPhones[i].getRadioAccessFamily();
275972efd34f867b7803688c3f831106f59244a11f0Stuart Scott                // mNewRadioAccessFamily[phoneId] = requestedRaf & supportedRaf;
276972efd34f867b7803688c3f831106f59244a11f0Stuart Scott                mNewRadioAccessFamily[phoneId] = requestedRaf;
27732dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
2783a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                mCurrentLogicalModemIds[phoneId] = mPhones[phoneId].getModemUuId();
27932dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                // get the logical mode corresponds to new raf requested and pass the
28032dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                // same as part of SET_RADIO_CAP APPLY phase
28132dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                mNewLogicalModemIds[phoneId] = getLogicalModemIdFromRaf(requestedRaf);
2822b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                logd("setRadioCapability: mOldRadioAccessFamily[" + phoneId + "]="
2832b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        + mOldRadioAccessFamily[phoneId]);
2842b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                logd("setRadioCapability: mNewRadioAccessFamily[" + phoneId + "]="
2852b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        + mNewRadioAccessFamily[phoneId]);
2862b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                sendRadioCapabilityRequest(
2872b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        phoneId,
2882b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        mRadioCapabilitySessionId,
2892b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        RadioCapability.RC_PHASE_START,
2902b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        mOldRadioAccessFamily[phoneId],
29132dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                        mCurrentLogicalModemIds[phoneId],
2922b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        RadioCapability.RC_STATUS_NONE,
2932b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        EVENT_START_RC_RESPONSE);
2942b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
2952b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
29612fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal
29712fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal        return true;
2982b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
2992b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
3002b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private Handler mHandler = new Handler() {
3012b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        @Override
3022b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        public void handleMessage(Message msg) {
3034e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott            logd("handleMessage msg.what=" + msg.what);
3042b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            switch (msg.what) {
3052b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                case EVENT_START_RC_RESPONSE:
3062b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    onStartRadioCapabilityResponse(msg);
3072b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    break;
3082b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
3092b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                case EVENT_APPLY_RC_RESPONSE:
3102b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    onApplyRadioCapabilityResponse(msg);
3112b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    break;
3122b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
3132b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                case EVENT_NOTIFICATION_RC_CHANGED:
3142b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    onNotificationRadioCapabilityChanged(msg);
3152b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    break;
3162b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
3172b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                case EVENT_FINISH_RC_RESPONSE:
3182b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    onFinishRadioCapabilityResponse(msg);
3192b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    break;
3202b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
321a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                case EVENT_TIMEOUT:
322a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                    onTimeoutRadioCapability(msg);
323a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                    break;
324a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt
3252b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                default:
3262b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    break;
3272b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
3282b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
3292b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    };
3302b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
3312b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    /**
3322b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * Handle START response
3332b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * @param msg obj field isa RadioCapability
3342b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     */
3352b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private void onStartRadioCapabilityResponse(Message msg) {
3362b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        synchronized (mSetRadioAccessFamilyStatus) {
3379414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt            AsyncResult ar = (AsyncResult)msg.obj;
33811cb63b1966838a971828f1915823e7106bd7fe8Sandeep Gutta            // Abort here only in Single SIM case, in Multi SIM cases
33911cb63b1966838a971828f1915823e7106bd7fe8Sandeep Gutta            // send FINISH with failure so that below layers can re-bind
34011cb63b1966838a971828f1915823e7106bd7fe8Sandeep Gutta            // old logical modems.
34111cb63b1966838a971828f1915823e7106bd7fe8Sandeep Gutta            if ((TelephonyManager.getDefault().getPhoneCount() == 1) && (ar.exception != null)) {
3429414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt                // just abort now.  They didn't take our start so we don't have to revert
3439414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt                logd("onStartRadioCapabilityResponse got exception=" + ar.exception);
3449414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt                mRadioCapabilitySessionId = mUniqueIdGenerator.getAndIncrement();
3459414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt                Intent intent = new Intent(TelephonyIntents.ACTION_SET_RADIO_CAPABILITY_FAILED);
3469414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt                mContext.sendBroadcast(intent);
3479414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt                clearTransaction();
3489414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt                return;
3499414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt            }
3502b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            RadioCapability rc = (RadioCapability) ((AsyncResult) msg.obj).result;
3512b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if ((rc == null) || (rc.getSession() != mRadioCapabilitySessionId)) {
3522b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                logd("onStartRadioCapabilityResponse: Ignore session=" + mRadioCapabilitySessionId
3532b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        + " rc=" + rc);
3542b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                return;
3552b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
3562b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            mRadioAccessFamilyStatusCounter--;
3574e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott            int id = rc.getPhoneId();
3582b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if (((AsyncResult) msg.obj).exception != null) {
3592b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                logd("onStartRadioCapabilityResponse: Error response session=" + rc.getSession());
3604e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("onStartRadioCapabilityResponse: phoneId=" + id + " status=FAIL");
3614e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_FAIL;
36211c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                mTransactionFailed = true;
3632b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            } else {
3644e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("onStartRadioCapabilityResponse: phoneId=" + id + " status=STARTED");
3654e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_STARTED;
3662b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
3672b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
3682b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if (mRadioAccessFamilyStatusCounter == 0) {
3694c4b8afa802e537bafd691704193f4b3812de738Stuart Scott                HashSet<String> modemsInUse = new HashSet<String>(mNewLogicalModemIds.length);
3704c4b8afa802e537bafd691704193f4b3812de738Stuart Scott                for (String modemId : mNewLogicalModemIds) {
371057a3dfbc3c46138d2251d592cda55581a38c0d7Nicholas Sauer                    if (!modemsInUse.add(modemId)) {
3724c4b8afa802e537bafd691704193f4b3812de738Stuart Scott                        mTransactionFailed = true;
3734c4b8afa802e537bafd691704193f4b3812de738Stuart Scott                        Log.wtf(LOG_TAG, "ERROR: sending down the same id for different phones");
3744c4b8afa802e537bafd691704193f4b3812de738Stuart Scott                    }
3754c4b8afa802e537bafd691704193f4b3812de738Stuart Scott                }
37611c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                logd("onStartRadioCapabilityResponse: success=" + !mTransactionFailed);
37711c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                if (mTransactionFailed) {
37811c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                    // Sends a variable number of requests, so don't resetRadioAccessFamilyCounter
37911c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                    // here.
38011c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                    issueFinish(mRadioCapabilitySessionId);
3812b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                } else {
3822b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    // All logical modem accepted the new radio access family, issue the APPLY
38311c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                    resetRadioAccessFamilyStatusCounter();
3843a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                    for (int i = 0; i < mPhones.length; i++) {
3852b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        sendRadioCapabilityRequest(
3862b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                            i,
3872b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                            mRadioCapabilitySessionId,
3882b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                            RadioCapability.RC_PHASE_APPLY,
3892b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                            mNewRadioAccessFamily[i],
39032dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                            mNewLogicalModemIds[i],
3912b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                            RadioCapability.RC_STATUS_NONE,
3922b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                            EVENT_APPLY_RC_RESPONSE);
3934e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott
3944e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                        logd("onStartRadioCapabilityResponse: phoneId=" + i + " status=APPLYING");
3952b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        mSetRadioAccessFamilyStatus[i] = SET_RC_STATUS_APPLYING;
3962b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    }
3972b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                }
3982b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
3992b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
4002b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
4012b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
4022b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    /**
4032b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * Handle APPLY response
4042b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * @param msg obj field isa RadioCapability
4052b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     */
4062b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private void onApplyRadioCapabilityResponse(Message msg) {
4072b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        RadioCapability rc = (RadioCapability) ((AsyncResult) msg.obj).result;
4082b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        if ((rc == null) || (rc.getSession() != mRadioCapabilitySessionId)) {
4092b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            logd("onApplyRadioCapabilityResponse: Ignore session=" + mRadioCapabilitySessionId
4102b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    + " rc=" + rc);
4112b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            return;
4122b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
4132b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        logd("onApplyRadioCapabilityResponse: rc=" + rc);
4142b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        if (((AsyncResult) msg.obj).exception != null) {
4152b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            synchronized (mSetRadioAccessFamilyStatus) {
4162b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                logd("onApplyRadioCapabilityResponse: Error response session=" + rc.getSession());
4174e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                int id = rc.getPhoneId();
4184e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("onApplyRadioCapabilityResponse: phoneId=" + id + " status=FAIL");
4194e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_FAIL;
42011c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                mTransactionFailed = true;
4212b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
4222b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        } else {
4232b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            logd("onApplyRadioCapabilityResponse: Valid start expecting notification rc=" + rc);
4242b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
4252b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
4262b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
4272b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    /**
4282b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * Handle the notification unsolicited response associated with the APPLY
4292b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * @param msg obj field isa RadioCapability
4302b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     */
4312b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private void onNotificationRadioCapabilityChanged(Message msg) {
4322b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        RadioCapability rc = (RadioCapability) ((AsyncResult) msg.obj).result;
4332b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        if ((rc == null) || (rc.getSession() != mRadioCapabilitySessionId)) {
4342b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            logd("onNotificationRadioCapabilityChanged: Ignore session=" + mRadioCapabilitySessionId
4352b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    + " rc=" + rc);
4362b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            return;
4372b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
4382b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        synchronized (mSetRadioAccessFamilyStatus) {
4392b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            logd("onNotificationRadioCapabilityChanged: rc=" + rc);
4402b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            // skip the overdue response by checking sessionId
4412b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if (rc.getSession() != mRadioCapabilitySessionId) {
4422b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                logd("onNotificationRadioCapabilityChanged: Ignore session="
4432b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        + mRadioCapabilitySessionId + " rc=" + rc);
4442b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                return;
4452b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
4462b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
4474e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott            int id = rc.getPhoneId();
4482b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if ((((AsyncResult) msg.obj).exception != null) ||
4492b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    (rc.getStatus() == RadioCapability.RC_STATUS_FAIL)) {
4504e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("onNotificationRadioCapabilityChanged: phoneId=" + id + " status=FAIL");
4514e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_FAIL;
45211c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                mTransactionFailed = true;
4532b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            } else {
4544e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("onNotificationRadioCapabilityChanged: phoneId=" + id + " status=SUCCESS");
4554e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_SUCCESS;
456a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                // The modems may have been restarted and forgotten this
45785953e2a7e5bc75cf1f5353feee97b3993dad5b3Robert Greenwalt                mPhoneSwitcher.resendDataAllowed(id);
4583a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                mPhones[id].radioCapabilityUpdated(rc);
4592b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
4602b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
4612b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            mRadioAccessFamilyStatusCounter--;
4622b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if (mRadioAccessFamilyStatusCounter == 0) {
46311c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                logd("onNotificationRadioCapabilityChanged: APPLY URC success=" +
46411c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                        mTransactionFailed);
46511c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                issueFinish(mRadioCapabilitySessionId);
4662b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
4672b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
4682b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
4692b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
4702b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    /**
4712b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * Handle the FINISH Phase response
4722b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * @param msg obj field isa RadioCapability
4732b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     */
4742b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    void onFinishRadioCapabilityResponse(Message msg) {
4752b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        RadioCapability rc = (RadioCapability) ((AsyncResult) msg.obj).result;
4762b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        if ((rc == null) || (rc.getSession() != mRadioCapabilitySessionId)) {
4772b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            logd("onFinishRadioCapabilityResponse: Ignore session=" + mRadioCapabilitySessionId
4782b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    + " rc=" + rc);
4792b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            return;
4802b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
4812b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        synchronized (mSetRadioAccessFamilyStatus) {
4824e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott            logd(" onFinishRadioCapabilityResponse mRadioAccessFamilyStatusCounter="
4832b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    + mRadioAccessFamilyStatusCounter);
4842b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            mRadioAccessFamilyStatusCounter--;
4852b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if (mRadioAccessFamilyStatusCounter == 0) {
4862b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                completeRadioCapabilityTransaction();
4872b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
4882b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
4892b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
4902b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
491a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt    private void onTimeoutRadioCapability(Message msg) {
492a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        if (msg.arg1 != mRadioCapabilitySessionId) {
493a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt           logd("RadioCapability timeout: Ignore msg.arg1=" + msg.arg1 +
494a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                   "!= mRadioCapabilitySessionId=" + mRadioCapabilitySessionId);
495a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            return;
496a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        }
497a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt
498a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        synchronized(mSetRadioAccessFamilyStatus) {
499a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            // timed-out.  Clean up as best we can
5003a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            for (int i = 0; i < mPhones.length; i++) {
501a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                logd("RadioCapability timeout: mSetRadioAccessFamilyStatus[" + i + "]=" +
502a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                        mSetRadioAccessFamilyStatus[i]);
503a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            }
504a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt
505a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            // Increment the sessionId as we are completing the transaction below
506a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            // so we don't want it completed when the FINISH phase is done.
50711cb63b1966838a971828f1915823e7106bd7fe8Sandeep Gutta            mRadioCapabilitySessionId = mUniqueIdGenerator.getAndIncrement();
50811cb63b1966838a971828f1915823e7106bd7fe8Sandeep Gutta
50911cb63b1966838a971828f1915823e7106bd7fe8Sandeep Gutta            // Reset the status counter as existing session failed
51011cb63b1966838a971828f1915823e7106bd7fe8Sandeep Gutta            mRadioAccessFamilyStatusCounter = 0;
51111cb63b1966838a971828f1915823e7106bd7fe8Sandeep Gutta
512a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            // send FINISH request with fail status and then uniqueDifferentId
513a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            mTransactionFailed = true;
51411cb63b1966838a971828f1915823e7106bd7fe8Sandeep Gutta            issueFinish(mRadioCapabilitySessionId);
515a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        }
516a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt    }
517a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt
51811c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt    private void issueFinish(int sessionId) {
5192b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Issue FINISH
5202b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        synchronized(mSetRadioAccessFamilyStatus) {
5213a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            for (int i = 0; i < mPhones.length; i++) {
522fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                logd("issueFinish: phoneId=" + i + " sessionId=" + sessionId
523fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                        + " mTransactionFailed=" + mTransactionFailed);
524fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                mRadioAccessFamilyStatusCounter++;
525fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                sendRadioCapabilityRequest(
5262b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        i,
5272b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        sessionId,
5282b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        RadioCapability.RC_PHASE_FINISH,
52911cb63b1966838a971828f1915823e7106bd7fe8Sandeep Gutta                        (mTransactionFailed ? mOldRadioAccessFamily[i] :
53011cb63b1966838a971828f1915823e7106bd7fe8Sandeep Gutta                        mNewRadioAccessFamily[i]),
53111cb63b1966838a971828f1915823e7106bd7fe8Sandeep Gutta                        (mTransactionFailed ? mCurrentLogicalModemIds[i] :
53211cb63b1966838a971828f1915823e7106bd7fe8Sandeep Gutta                        mNewLogicalModemIds[i]),
53311c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                        (mTransactionFailed ? RadioCapability.RC_STATUS_FAIL :
53411c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                        RadioCapability.RC_STATUS_SUCCESS),
5352b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        EVENT_FINISH_RC_RESPONSE);
536fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                if (mTransactionFailed) {
537fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                    logd("issueFinish: phoneId: " + i + " status: FAIL");
538fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                    // At least one failed, mark them all failed.
539fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                    mSetRadioAccessFamilyStatus[i] = SET_RC_STATUS_FAIL;
5402b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                }
5412b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
5422b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
5432b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
5442b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
5452b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private void completeRadioCapabilityTransaction() {
5462b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Create the intent to broadcast
5472b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        Intent intent;
54811c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt        logd("onFinishRadioCapabilityResponse: success=" + !mTransactionFailed);
54911c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt        if (!mTransactionFailed) {
5502b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            ArrayList<RadioAccessFamily> phoneRAFList = new ArrayList<RadioAccessFamily>();
5513a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            for (int i = 0; i < mPhones.length; i++) {
5523a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                int raf = mPhones[i].getRadioAccessFamily();
5534e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("radioAccessFamily[" + i + "]=" + raf);
5542b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                RadioAccessFamily phoneRC = new RadioAccessFamily(i, raf);
5552b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                phoneRAFList.add(phoneRC);
5562b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
5572b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            intent = new Intent(TelephonyIntents.ACTION_SET_RADIO_CAPABILITY_DONE);
5582b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            intent.putParcelableArrayListExtra(TelephonyIntents.EXTRA_RADIO_ACCESS_FAMILY,
5592b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    phoneRAFList);
56011c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt
561a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            // make messages about the old transaction obsolete (specifically the timeout)
562a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            mRadioCapabilitySessionId = mUniqueIdGenerator.getAndIncrement();
563a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt
56411c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt            // Reinitialize
56511c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt            clearTransaction();
5662b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        } else {
5672b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            intent = new Intent(TelephonyIntents.ACTION_SET_RADIO_CAPABILITY_FAILED);
5682b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
56911c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt            // now revert.
57011c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt            mTransactionFailed = false;
5713a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            RadioAccessFamily[] rafs = new RadioAccessFamily[mPhones.length];
5723a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            for (int phoneId = 0; phoneId < mPhones.length; phoneId++) {
57311c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                rafs[phoneId] = new RadioAccessFamily(phoneId, mOldRadioAccessFamily[phoneId]);
57411c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt            }
57511c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt            doSetRadioCapabilities(rafs);
57611c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt        }
5772b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
5782b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Broadcast that we're done
579da646a06d4f889c0591f118ccf246c65eb2cff91Sanket Padawe        mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
5802b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
5812b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
5822b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // Clear this transaction
5832b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private void clearTransaction() {
5844e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott        logd("clearTransaction");
5852b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        synchronized(mSetRadioAccessFamilyStatus) {
5863a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            for (int i = 0; i < mPhones.length; i++) {
5874e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("clearTransaction: phoneId=" + i + " status=IDLE");
5882b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                mSetRadioAccessFamilyStatus[i] = SET_RC_STATUS_IDLE;
5892b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                mOldRadioAccessFamily[i] = 0;
5902b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                mNewRadioAccessFamily[i] = 0;
59111c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                mTransactionFailed = false;
5922b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
5934e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott
5942b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if (mWakeLock.isHeld()) {
5952b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                mWakeLock.release();
5962b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
5972b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
5982b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
5992b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
6002b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private void resetRadioAccessFamilyStatusCounter() {
6013a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mRadioAccessFamilyStatusCounter = mPhones.length;
6022b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
6032b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
6042b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private void sendRadioCapabilityRequest(int phoneId, int sessionId, int rcPhase,
6052b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            int radioFamily, String logicalModemId, int status, int eventId) {
6062b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        RadioCapability requestRC = new RadioCapability(
6072b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                phoneId, sessionId, rcPhase, radioFamily, logicalModemId, status);
6083a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mPhones[phoneId].setRadioCapability(
6092b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                requestRC, mHandler.obtainMessage(eventId));
6102b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
6112b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
61232dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    // This method will return max number of raf bits supported from the raf
61332dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    // values currently stored in all phone objects
61432dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    public int getMaxRafSupported() {
6153a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        int[] numRafSupported = new int[mPhones.length];
61632dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        int maxNumRafBit = 0;
61732dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        int maxRaf = RadioAccessFamily.RAF_UNKNOWN;
61832dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
6193a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        for (int len = 0; len < mPhones.length; len++) {
6203a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            numRafSupported[len] = Integer.bitCount(mPhones[len].getRadioAccessFamily());
62132dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta            if (maxNumRafBit < numRafSupported[len]) {
62232dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                maxNumRafBit = numRafSupported[len];
6233a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                maxRaf = mPhones[len].getRadioAccessFamily();
62432dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta            }
62532dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        }
62632dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
62732dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        return maxRaf;
62832dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    }
62932dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
63032dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    // This method will return minimum number of raf bits supported from the raf
63132dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    // values currently stored in all phone objects
63232dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    public int getMinRafSupported() {
6333a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        int[] numRafSupported = new int[mPhones.length];
63432dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        int minNumRafBit = 0;
63532dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        int minRaf = RadioAccessFamily.RAF_UNKNOWN;
63632dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
6373a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        for (int len = 0; len < mPhones.length; len++) {
6383a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            numRafSupported[len] = Integer.bitCount(mPhones[len].getRadioAccessFamily());
63932dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta            if ((minNumRafBit == 0) || (minNumRafBit > numRafSupported[len])) {
64032dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                minNumRafBit = numRafSupported[len];
6413a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                minRaf = mPhones[len].getRadioAccessFamily();
64232dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta            }
64332dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        }
64432dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        return minRaf;
64532dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    }
64632dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
64732dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    // This method checks current raf values stored in all phones and
64832dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    // whicheve phone raf matches with input raf, returns modemId from that phone
64932dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    private String getLogicalModemIdFromRaf(int raf) {
65032dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        String modemUuid = null;
65132dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
6523a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        for (int phoneId = 0; phoneId < mPhones.length; phoneId++) {
6533a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            if (mPhones[phoneId].getRadioAccessFamily() == raf) {
6543a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                modemUuid = mPhones[phoneId].getModemUuId();
65532dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                break;
65632dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta            }
65732dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        }
65832dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        return modemUuid;
65932dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    }
66032dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
661a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void logd(String string) {
662a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, string);
663a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
664e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville
66512fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal    private void loge(String string) {
66612fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal        Rlog.e(LOG_TAG, string);
66712fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal    }
668a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
669