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
192b40e6226b4b71408964bca46f0a9f256cd4f523Wink Savilleimport java.util.ArrayList;
202b40e6226b4b71408964bca46f0a9f256cd4f523Wink Savilleimport java.util.Random;
212b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
22a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.Context;
232b40e6226b4b71408964bca46f0a9f256cd4f523Wink Savilleimport android.content.Intent;
242b40e6226b4b71408964bca46f0a9f256cd4f523Wink Savilleimport android.os.AsyncResult;
25a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Handler;
26a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Message;
272b40e6226b4b71408964bca46f0a9f256cd4f523Wink Savilleimport android.os.PowerManager;
282b40e6226b4b71408964bca46f0a9f256cd4f523Wink Savilleimport android.os.PowerManager.WakeLock;
292b40e6226b4b71408964bca46f0a9f256cd4f523Wink Savilleimport android.telephony.RadioAccessFamily;
30a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.Rlog;
31a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.TelephonyManager;
324c4b8afa802e537bafd691704193f4b3812de738Stuart Scottimport android.util.Log;
33a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
34e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwaltimport com.android.internal.telephony.PhoneSwitcher;
35a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.uicc.UiccController;
36a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
37e97be3971cb6b55e019433c32524cc60ce0d037bWink Savilleimport java.io.FileDescriptor;
38e97be3971cb6b55e019433c32524cc60ce0d037bWink Savilleimport java.io.PrintWriter;
392b40e6226b4b71408964bca46f0a9f256cd4f523Wink Savilleimport java.util.concurrent.atomic.AtomicInteger;
404c4b8afa802e537bafd691704193f4b3812de738Stuart Scottimport java.util.HashSet;
41e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville
42a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillepublic class ProxyController {
43a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final String LOG_TAG = "ProxyController";
44a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
452b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int EVENT_NOTIFICATION_RC_CHANGED        = 1;
462b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int EVENT_START_RC_RESPONSE        = 2;
472b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int EVENT_APPLY_RC_RESPONSE        = 3;
482b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int EVENT_FINISH_RC_RESPONSE       = 4;
49a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt    private static final int EVENT_TIMEOUT                  = 5;
502b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
512b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int SET_RC_STATUS_IDLE             = 0;
522b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int SET_RC_STATUS_STARTING         = 1;
532b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int SET_RC_STATUS_STARTED          = 2;
542b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int SET_RC_STATUS_APPLYING         = 3;
552b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int SET_RC_STATUS_SUCCESS          = 4;
562b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int SET_RC_STATUS_FAIL             = 5;
572b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
582b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // The entire transaction must complete within this amount of time
592b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // or a FINISH will be issued to each Logical Modem with the old
602b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // Radio Access Family.
612b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private static final int SET_RC_TIMEOUT_WAITING_MSEC    = (45 * 1000);
622b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
63a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Class Variables
64a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static ProxyController sProxyController;
65a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
666c806ef816f8ae0a1849ba05f3128a04577b32d0Amit Mahajan    private Phone[] mPhones;
67a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
68a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private UiccController mUiccController;
69a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
70a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private CommandsInterface[] mCi;
71a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
72a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Context mContext;
73a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
74e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt    private PhoneSwitcher mPhoneSwitcher;
75a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
76a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //UiccPhoneBookController to use proper IccPhoneBookInterfaceManagerProxy object
77a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private UiccPhoneBookController mUiccPhoneBookController;
78a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
79aa48e77d9b817a4749c49551632bd8eb7888d121Amit Mahajan    //PhoneSubInfoController to use proper PhoneSubInfoProxy object
80aa48e77d9b817a4749c49551632bd8eb7888d121Amit Mahajan    private PhoneSubInfoController mPhoneSubInfoController;
81aa48e77d9b817a4749c49551632bd8eb7888d121Amit Mahajan
82a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //UiccSmsController to use proper IccSmsInterfaceManager object
83a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private UiccSmsController mUiccSmsController;
84a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
852b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    WakeLock mWakeLock;
862b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
872b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // record each phone's set radio capability status
882b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private int[] mSetRadioAccessFamilyStatus;
892b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private int mRadioAccessFamilyStatusCounter;
9011c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt    private boolean mTransactionFailed = false;
912b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
9232dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    private String[] mCurrentLogicalModemIds;
9332dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    private String[] mNewLogicalModemIds;
942b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
952b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // Allows the generation of unique Id's for radio capability request session  id
962b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private AtomicInteger mUniqueIdGenerator = new AtomicInteger(new Random().nextInt());
972b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
982b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // on-going radio capability request session id
992b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private int mRadioCapabilitySessionId;
1002b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
1012b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // Record new and old Radio Access Family (raf) configuration.
1022b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // The old raf configuration is used to restore each logical modem raf when FINISH is
1032b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // issued if any requests fail.
1042b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private int[] mNewRadioAccessFamily;
1052b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private int[] mOldRadioAccessFamily;
1062b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
1072b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
108a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Class Methods
1096c806ef816f8ae0a1849ba05f3128a04577b32d0Amit Mahajan    public static ProxyController getInstance(Context context, Phone[] phone,
110e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt            UiccController uiccController, CommandsInterface[] ci, PhoneSwitcher ps) {
111a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (sProxyController == null) {
112e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt            sProxyController = new ProxyController(context, phone, uiccController, ci, ps);
113a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
114a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return sProxyController;
115a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
116a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1174e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott    public static ProxyController getInstance() {
118a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return sProxyController;
119a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
120a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1216c806ef816f8ae0a1849ba05f3128a04577b32d0Amit Mahajan    private ProxyController(Context context, Phone[] phone, UiccController uiccController,
122e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt            CommandsInterface[] ci, PhoneSwitcher phoneSwitcher) {
123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        logd("Constructor - Enter");
124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mContext = context;
1263a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mPhones = phone;
127a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mUiccController = uiccController;
128a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCi = ci;
129e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        mPhoneSwitcher = phoneSwitcher;
130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1313a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mUiccPhoneBookController = new UiccPhoneBookController(mPhones);
1322549bbfd0439b8b549712a2d255dcf05bca7f1ebAmit Mahajan        mPhoneSubInfoController = new PhoneSubInfoController(mContext, mPhones);
1333a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mUiccSmsController = new UiccSmsController(mPhones);
1343a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mSetRadioAccessFamilyStatus = new int[mPhones.length];
1353a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mNewRadioAccessFamily = new int[mPhones.length];
1363a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mOldRadioAccessFamily = new int[mPhones.length];
1373a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mCurrentLogicalModemIds = new String[mPhones.length];
1383a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mNewLogicalModemIds = new String[mPhones.length];
1392b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
1402b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // wake lock for set radio capability
1412b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
1422b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
1432b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        mWakeLock.setReferenceCounted(false);
1442b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
1452b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Clear to be sure we're in the initial state
1462b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        clearTransaction();
1473a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        for (int i = 0; i < mPhones.length; i++) {
1483a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            mPhones[i].registerForRadioCapabilityChanged(
1494e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                    mHandler, EVENT_NOTIFICATION_RC_CHANGED, null);
1504e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott        }
151a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        logd("Constructor - Exit");
152a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
153a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1542b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    public void updateDataConnectionTracker(int sub) {
1553a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mPhones[sub].updateDataConnectionTracker();
1562b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
1572b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
1582b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    public void enableDataConnectivity(int sub) {
1593a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mPhones[sub].setInternalDataEnabled(true, null);
1602b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
1612b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
1622b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    public void disableDataConnectivity(int sub,
1632b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            Message dataCleanedUpMsg) {
1643a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mPhones[sub].setInternalDataEnabled(false, dataCleanedUpMsg);
1652b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
1662b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
1672b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    public void updateCurrentCarrierInProvider(int sub) {
1683a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mPhones[sub].updateCurrentCarrierInProvider();
1692b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
1702b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
171b237a11044ed842d2865ff8c8716befb06b6ca25Wink Saville    public void registerForAllDataDisconnected(int subId, Handler h, int what, Object obj) {
172a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int phoneId = SubscriptionController.getInstance().getPhoneId(subId);
173a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
174a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount()) {
1753a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            mPhones[phoneId].registerForAllDataDisconnected(h, what, obj);
176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
179b237a11044ed842d2865ff8c8716befb06b6ca25Wink Saville    public void unregisterForAllDataDisconnected(int subId, Handler h) {
180a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int phoneId = SubscriptionController.getInstance().getPhoneId(subId);
181a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount()) {
1833a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            mPhones[phoneId].unregisterForAllDataDisconnected(h);
184a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
186a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
187b237a11044ed842d2865ff8c8716befb06b6ca25Wink Saville    public boolean isDataDisconnected(int subId) {
188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int phoneId = SubscriptionController.getInstance().getPhoneId(subId);
189a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount()) {
1913a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            return mPhones[phoneId].mDcTracker.isDisconnected();
192a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
1934255481b2c36b884cfc97e44ce4479f312610136Robert Greenwalt            // if we can't find a phone for the given subId, it is disconnected.
1944255481b2c36b884cfc97e44ce4479f312610136Robert Greenwalt            return true;
195a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
196a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
197a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1982b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    /**
1992b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * Get phone radio type and access technology.
2002b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     *
2012b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * @param phoneId which phone you want to get
2022b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * @return phone radio type and access technology for input phone ID
2032b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     */
2042b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    public int getRadioAccessFamily(int phoneId) {
2053a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        if (phoneId >= mPhones.length) {
2062b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            return RadioAccessFamily.RAF_UNKNOWN;
2072b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        } else {
2083a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            return mPhones[phoneId].getRadioAccessFamily();
2092b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
2102b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
2112b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
2122b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    /**
2132b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * Set phone radio type and access technology for each phone.
2142b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     *
2152b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * @param rafs an RadioAccessFamily array to indicate all phone's
2162b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     *        new radio access family. The length of RadioAccessFamily
2172b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     *        must equal to phone count.
21812fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal     * @return false if another session is already active and the request is rejected.
2192b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     */
22012fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal    public boolean setRadioCapability(RadioAccessFamily[] rafs) {
2213a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        if (rafs.length != mPhones.length) {
2222b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            throw new RuntimeException("Length of input rafs must equal to total phone count");
2232b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
2242b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Check if there is any ongoing transaction and throw an exception if there
2252b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // is one as this is a programming error.
2262b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        synchronized (mSetRadioAccessFamilyStatus) {
2273a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            for (int i = 0; i < mPhones.length; i++) {
2282b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                if (mSetRadioAccessFamilyStatus[i] != SET_RC_STATUS_IDLE) {
22912fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal                    // TODO: The right behaviour is to cancel previous request and send this.
23012fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal                    loge("setRadioCapability: Phone[" + i + "] is not idle. Rejecting request.");
23112fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal                    return false;
2322b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                }
2332b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
2342b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
2352b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
236e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott        // Check we actually need to do anything
237e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott        boolean same = true;
2383a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        for (int i = 0; i < mPhones.length; i++) {
2393a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            if (mPhones[i].getRadioAccessFamily() != rafs[i].getRadioAccessFamily()) {
240e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott                same = false;
241e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott            }
242e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott        }
243e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott        if (same) {
244e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott            // All phones are already set to the requested raf
245e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott            logd("setRadioCapability: Already in requested configuration, nothing to do.");
246e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott            // It isn't really an error, so return true - everything is OK.
247e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott            return true;
248e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott        }
249e50e6c1d03701f579fb558324425bc3d6f64c4eaStuart Scott
2502b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Clear to be sure we're in the initial state
2512b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        clearTransaction();
2522b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
2532b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Keep a wake lock until we finish radio capability changed
2542b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        mWakeLock.acquire();
2552b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
25611c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt        return doSetRadioCapabilities(rafs);
25711c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt    }
25811c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt
25911c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt    private boolean doSetRadioCapabilities(RadioAccessFamily[] rafs) {
26011c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt        // A new sessionId for this transaction
26111c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt        mRadioCapabilitySessionId = mUniqueIdGenerator.getAndIncrement();
26211c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt
2632b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Start timer to make sure all phones respond within a specific time interval.
2642b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Will send FINISH if a timeout occurs.
265a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        Message msg = mHandler.obtainMessage(EVENT_TIMEOUT, mRadioCapabilitySessionId, 0);
266a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        mHandler.sendMessageDelayed(msg, SET_RC_TIMEOUT_WAITING_MSEC);
2672b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
2682b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        synchronized (mSetRadioAccessFamilyStatus) {
2694e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott            logd("setRadioCapability: new request session id=" + mRadioCapabilitySessionId);
27011c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt            resetRadioAccessFamilyStatusCounter();
2712b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            for (int i = 0; i < rafs.length; i++) {
2722b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                int phoneId = rafs[i].getPhoneId();
2734e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("setRadioCapability: phoneId=" + phoneId + " status=STARTING");
2742b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                mSetRadioAccessFamilyStatus[phoneId] = SET_RC_STATUS_STARTING;
2753a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                mOldRadioAccessFamily[phoneId] = mPhones[phoneId].getRadioAccessFamily();
2767e7d2b34010bf24a70bbf40303c7a4606c438adaStuart Scott                int requestedRaf = rafs[i].getRadioAccessFamily();
277972efd34f867b7803688c3f831106f59244a11f0Stuart Scott                // TODO Set the new radio access family to the maximum of the requested & supported
2783a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                // int supportedRaf = mPhones[i].getRadioAccessFamily();
279972efd34f867b7803688c3f831106f59244a11f0Stuart Scott                // mNewRadioAccessFamily[phoneId] = requestedRaf & supportedRaf;
280972efd34f867b7803688c3f831106f59244a11f0Stuart Scott                mNewRadioAccessFamily[phoneId] = requestedRaf;
28132dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
2823a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                mCurrentLogicalModemIds[phoneId] = mPhones[phoneId].getModemUuId();
28332dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                // get the logical mode corresponds to new raf requested and pass the
28432dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                // same as part of SET_RADIO_CAP APPLY phase
28532dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                mNewLogicalModemIds[phoneId] = getLogicalModemIdFromRaf(requestedRaf);
2862b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                logd("setRadioCapability: mOldRadioAccessFamily[" + phoneId + "]="
2872b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        + mOldRadioAccessFamily[phoneId]);
2882b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                logd("setRadioCapability: mNewRadioAccessFamily[" + phoneId + "]="
2892b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        + mNewRadioAccessFamily[phoneId]);
2902b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                sendRadioCapabilityRequest(
2912b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        phoneId,
2922b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        mRadioCapabilitySessionId,
2932b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        RadioCapability.RC_PHASE_START,
2942b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        mOldRadioAccessFamily[phoneId],
29532dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                        mCurrentLogicalModemIds[phoneId],
2962b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        RadioCapability.RC_STATUS_NONE,
2972b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        EVENT_START_RC_RESPONSE);
2982b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
2992b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
30012fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal
30112fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal        return true;
3022b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
3032b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
3042b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private Handler mHandler = new Handler() {
3052b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        @Override
3062b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        public void handleMessage(Message msg) {
3074e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott            logd("handleMessage msg.what=" + msg.what);
3082b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            switch (msg.what) {
3092b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                case EVENT_START_RC_RESPONSE:
3102b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    onStartRadioCapabilityResponse(msg);
3112b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    break;
3122b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
3132b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                case EVENT_APPLY_RC_RESPONSE:
3142b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    onApplyRadioCapabilityResponse(msg);
3152b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    break;
3162b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
3172b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                case EVENT_NOTIFICATION_RC_CHANGED:
3182b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    onNotificationRadioCapabilityChanged(msg);
3192b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    break;
3202b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
3212b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                case EVENT_FINISH_RC_RESPONSE:
3222b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    onFinishRadioCapabilityResponse(msg);
3232b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    break;
3242b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
325a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                case EVENT_TIMEOUT:
326a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                    onTimeoutRadioCapability(msg);
327a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                    break;
328a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt
3292b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                default:
3302b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    break;
3312b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
3322b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
3332b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    };
3342b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
3352b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    /**
3362b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * Handle START response
3372b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * @param msg obj field isa RadioCapability
3382b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     */
3392b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private void onStartRadioCapabilityResponse(Message msg) {
3402b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        synchronized (mSetRadioAccessFamilyStatus) {
3419414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt            AsyncResult ar = (AsyncResult)msg.obj;
3429414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt            if (ar.exception != null) {
3439414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt                // just abort now.  They didn't take our start so we don't have to revert
3449414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt                logd("onStartRadioCapabilityResponse got exception=" + ar.exception);
3459414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt                mRadioCapabilitySessionId = mUniqueIdGenerator.getAndIncrement();
3469414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt                Intent intent = new Intent(TelephonyIntents.ACTION_SET_RADIO_CAPABILITY_FAILED);
3479414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt                mContext.sendBroadcast(intent);
3489414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt                clearTransaction();
3499414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt                return;
3509414f24cd6c870f131d90d609243fc21cb91f3faRobert Greenwalt            }
3512b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            RadioCapability rc = (RadioCapability) ((AsyncResult) msg.obj).result;
3522b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if ((rc == null) || (rc.getSession() != mRadioCapabilitySessionId)) {
3532b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                logd("onStartRadioCapabilityResponse: Ignore session=" + mRadioCapabilitySessionId
3542b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        + " rc=" + rc);
3552b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                return;
3562b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
3572b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            mRadioAccessFamilyStatusCounter--;
3584e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott            int id = rc.getPhoneId();
3592b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if (((AsyncResult) msg.obj).exception != null) {
3602b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                logd("onStartRadioCapabilityResponse: Error response session=" + rc.getSession());
3614e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("onStartRadioCapabilityResponse: phoneId=" + id + " status=FAIL");
3624e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_FAIL;
36311c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                mTransactionFailed = true;
3642b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            } else {
3654e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("onStartRadioCapabilityResponse: phoneId=" + id + " status=STARTED");
3664e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_STARTED;
3672b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
3682b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
3692b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if (mRadioAccessFamilyStatusCounter == 0) {
3704c4b8afa802e537bafd691704193f4b3812de738Stuart Scott                HashSet<String> modemsInUse = new HashSet<String>(mNewLogicalModemIds.length);
3714c4b8afa802e537bafd691704193f4b3812de738Stuart Scott                for (String modemId : mNewLogicalModemIds) {
372057a3dfbc3c46138d2251d592cda55581a38c0d7Nicholas Sauer                    if (!modemsInUse.add(modemId)) {
3734c4b8afa802e537bafd691704193f4b3812de738Stuart Scott                        mTransactionFailed = true;
3744c4b8afa802e537bafd691704193f4b3812de738Stuart Scott                        Log.wtf(LOG_TAG, "ERROR: sending down the same id for different phones");
3754c4b8afa802e537bafd691704193f4b3812de738Stuart Scott                    }
3764c4b8afa802e537bafd691704193f4b3812de738Stuart Scott                }
37711c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                logd("onStartRadioCapabilityResponse: success=" + !mTransactionFailed);
37811c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                if (mTransactionFailed) {
37911c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                    // Sends a variable number of requests, so don't resetRadioAccessFamilyCounter
38011c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                    // here.
38111c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                    issueFinish(mRadioCapabilitySessionId);
3822b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                } else {
3832b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    // All logical modem accepted the new radio access family, issue the APPLY
38411c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                    resetRadioAccessFamilyStatusCounter();
3853a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                    for (int i = 0; i < mPhones.length; i++) {
3862b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        sendRadioCapabilityRequest(
3872b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                            i,
3882b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                            mRadioCapabilitySessionId,
3892b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                            RadioCapability.RC_PHASE_APPLY,
3902b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                            mNewRadioAccessFamily[i],
39132dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                            mNewLogicalModemIds[i],
3922b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                            RadioCapability.RC_STATUS_NONE,
3932b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                            EVENT_APPLY_RC_RESPONSE);
3944e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott
3954e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                        logd("onStartRadioCapabilityResponse: phoneId=" + i + " status=APPLYING");
3962b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        mSetRadioAccessFamilyStatus[i] = SET_RC_STATUS_APPLYING;
3972b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    }
3982b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                }
3992b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
4002b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
4012b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
4022b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
4032b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    /**
4042b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * Handle APPLY response
4052b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * @param msg obj field isa RadioCapability
4062b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     */
4072b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private void onApplyRadioCapabilityResponse(Message msg) {
4082b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        RadioCapability rc = (RadioCapability) ((AsyncResult) msg.obj).result;
4092b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        if ((rc == null) || (rc.getSession() != mRadioCapabilitySessionId)) {
4102b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            logd("onApplyRadioCapabilityResponse: Ignore session=" + mRadioCapabilitySessionId
4112b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    + " rc=" + rc);
4122b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            return;
4132b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
4142b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        logd("onApplyRadioCapabilityResponse: rc=" + rc);
4152b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        if (((AsyncResult) msg.obj).exception != null) {
4162b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            synchronized (mSetRadioAccessFamilyStatus) {
4172b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                logd("onApplyRadioCapabilityResponse: Error response session=" + rc.getSession());
4184e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                int id = rc.getPhoneId();
4194e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("onApplyRadioCapabilityResponse: phoneId=" + id + " status=FAIL");
4204e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_FAIL;
42111c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                mTransactionFailed = true;
4222b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
4232b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        } else {
4242b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            logd("onApplyRadioCapabilityResponse: Valid start expecting notification rc=" + rc);
4252b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
4262b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
4272b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
4282b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    /**
4292b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * Handle the notification unsolicited response associated with the APPLY
4302b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * @param msg obj field isa RadioCapability
4312b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     */
4322b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private void onNotificationRadioCapabilityChanged(Message msg) {
4332b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        RadioCapability rc = (RadioCapability) ((AsyncResult) msg.obj).result;
4342b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        if ((rc == null) || (rc.getSession() != mRadioCapabilitySessionId)) {
4352b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            logd("onNotificationRadioCapabilityChanged: Ignore session=" + mRadioCapabilitySessionId
4362b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    + " rc=" + rc);
4372b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            return;
4382b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
4392b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        synchronized (mSetRadioAccessFamilyStatus) {
4402b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            logd("onNotificationRadioCapabilityChanged: rc=" + rc);
4412b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            // skip the overdue response by checking sessionId
4422b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if (rc.getSession() != mRadioCapabilitySessionId) {
4432b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                logd("onNotificationRadioCapabilityChanged: Ignore session="
4442b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        + mRadioCapabilitySessionId + " rc=" + rc);
4452b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                return;
4462b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
4472b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
4484e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott            int id = rc.getPhoneId();
4492b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if ((((AsyncResult) msg.obj).exception != null) ||
4502b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    (rc.getStatus() == RadioCapability.RC_STATUS_FAIL)) {
4514e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("onNotificationRadioCapabilityChanged: phoneId=" + id + " status=FAIL");
4524e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_FAIL;
45311c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                mTransactionFailed = true;
4542b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            } else {
4554e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("onNotificationRadioCapabilityChanged: phoneId=" + id + " status=SUCCESS");
4564e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_SUCCESS;
457a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                // The modems may have been restarted and forgotten this
45885953e2a7e5bc75cf1f5353feee97b3993dad5b3Robert Greenwalt                mPhoneSwitcher.resendDataAllowed(id);
4593a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                mPhones[id].radioCapabilityUpdated(rc);
4602b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
4612b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
4622b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            mRadioAccessFamilyStatusCounter--;
4632b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if (mRadioAccessFamilyStatusCounter == 0) {
46411c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                logd("onNotificationRadioCapabilityChanged: APPLY URC success=" +
46511c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                        mTransactionFailed);
46611c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                issueFinish(mRadioCapabilitySessionId);
4672b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
4682b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
4692b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
4702b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
4712b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    /**
4722b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * Handle the FINISH Phase response
4732b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     * @param msg obj field isa RadioCapability
4742b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville     */
4752b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    void onFinishRadioCapabilityResponse(Message msg) {
4762b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        RadioCapability rc = (RadioCapability) ((AsyncResult) msg.obj).result;
4772b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        if ((rc == null) || (rc.getSession() != mRadioCapabilitySessionId)) {
4782b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            logd("onFinishRadioCapabilityResponse: Ignore session=" + mRadioCapabilitySessionId
4792b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    + " rc=" + rc);
4802b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            return;
4812b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
4822b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        synchronized (mSetRadioAccessFamilyStatus) {
4834e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott            logd(" onFinishRadioCapabilityResponse mRadioAccessFamilyStatusCounter="
4842b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    + mRadioAccessFamilyStatusCounter);
4852b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            mRadioAccessFamilyStatusCounter--;
4862b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if (mRadioAccessFamilyStatusCounter == 0) {
4872b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                completeRadioCapabilityTransaction();
4882b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
4892b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
4902b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
4912b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
492a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt    private void onTimeoutRadioCapability(Message msg) {
493a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        if (msg.arg1 != mRadioCapabilitySessionId) {
494a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt           logd("RadioCapability timeout: Ignore msg.arg1=" + msg.arg1 +
495a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                   "!= mRadioCapabilitySessionId=" + mRadioCapabilitySessionId);
496a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            return;
497a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        }
498a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt
499a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        synchronized(mSetRadioAccessFamilyStatus) {
500a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            // timed-out.  Clean up as best we can
5013a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            for (int i = 0; i < mPhones.length; i++) {
502a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                logd("RadioCapability timeout: mSetRadioAccessFamilyStatus[" + i + "]=" +
503a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt                        mSetRadioAccessFamilyStatus[i]);
504a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            }
505a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt
506a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            // Increment the sessionId as we are completing the transaction below
507a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            // so we don't want it completed when the FINISH phase is done.
508a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            int uniqueDifferentId = mUniqueIdGenerator.getAndIncrement();
509a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            // send FINISH request with fail status and then uniqueDifferentId
510a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            mTransactionFailed = true;
511a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            issueFinish(uniqueDifferentId);
512a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt        }
513a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt    }
514a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt
51511c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt    private void issueFinish(int sessionId) {
5162b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Issue FINISH
5172b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        synchronized(mSetRadioAccessFamilyStatus) {
5183a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            for (int i = 0; i < mPhones.length; i++) {
519fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                logd("issueFinish: phoneId=" + i + " sessionId=" + sessionId
520fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                        + " mTransactionFailed=" + mTransactionFailed);
521fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                mRadioAccessFamilyStatusCounter++;
522fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                sendRadioCapabilityRequest(
5232b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        i,
5242b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        sessionId,
5252b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        RadioCapability.RC_PHASE_FINISH,
5262b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        mOldRadioAccessFamily[i],
52732dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                        mCurrentLogicalModemIds[i],
52811c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                        (mTransactionFailed ? RadioCapability.RC_STATUS_FAIL :
52911c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                        RadioCapability.RC_STATUS_SUCCESS),
5302b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                        EVENT_FINISH_RC_RESPONSE);
531fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                if (mTransactionFailed) {
532fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                    logd("issueFinish: phoneId: " + i + " status: FAIL");
533fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                    // At least one failed, mark them all failed.
534fd7db44af3dcbba5f6da372d0b30dff07baba97bSooraj Sasindran                    mSetRadioAccessFamilyStatus[i] = SET_RC_STATUS_FAIL;
5352b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                }
5362b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
5372b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
5382b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
5392b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
5402b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private void completeRadioCapabilityTransaction() {
5412b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Create the intent to broadcast
5422b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        Intent intent;
54311c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt        logd("onFinishRadioCapabilityResponse: success=" + !mTransactionFailed);
54411c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt        if (!mTransactionFailed) {
5452b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            ArrayList<RadioAccessFamily> phoneRAFList = new ArrayList<RadioAccessFamily>();
5463a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            for (int i = 0; i < mPhones.length; i++) {
5473a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                int raf = mPhones[i].getRadioAccessFamily();
5484e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("radioAccessFamily[" + i + "]=" + raf);
5492b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                RadioAccessFamily phoneRC = new RadioAccessFamily(i, raf);
5502b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                phoneRAFList.add(phoneRC);
5512b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
5522b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            intent = new Intent(TelephonyIntents.ACTION_SET_RADIO_CAPABILITY_DONE);
5532b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            intent.putParcelableArrayListExtra(TelephonyIntents.EXTRA_RADIO_ACCESS_FAMILY,
5542b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                    phoneRAFList);
55511c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt
556a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            // make messages about the old transaction obsolete (specifically the timeout)
557a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt            mRadioCapabilitySessionId = mUniqueIdGenerator.getAndIncrement();
558a5ea9112a448ee8a51df1a2317457ae560a191f2Robert Greenwalt
55911c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt            // Reinitialize
56011c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt            clearTransaction();
5612b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        } else {
5622b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            intent = new Intent(TelephonyIntents.ACTION_SET_RADIO_CAPABILITY_FAILED);
5632b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
56411c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt            // now revert.
56511c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt            mTransactionFailed = false;
5663a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            RadioAccessFamily[] rafs = new RadioAccessFamily[mPhones.length];
5673a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            for (int phoneId = 0; phoneId < mPhones.length; phoneId++) {
56811c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                rafs[phoneId] = new RadioAccessFamily(phoneId, mOldRadioAccessFamily[phoneId]);
56911c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt            }
57011c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt            doSetRadioCapabilities(rafs);
57111c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt        }
5722b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
5732b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        // Broadcast that we're done
574da646a06d4f889c0591f118ccf246c65eb2cff91Sanket Padawe        mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
5752b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
5762b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
5772b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    // Clear this transaction
5782b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private void clearTransaction() {
5794e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott        logd("clearTransaction");
5802b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        synchronized(mSetRadioAccessFamilyStatus) {
5813a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            for (int i = 0; i < mPhones.length; i++) {
5824e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott                logd("clearTransaction: phoneId=" + i + " status=IDLE");
5832b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                mSetRadioAccessFamilyStatus[i] = SET_RC_STATUS_IDLE;
5842b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                mOldRadioAccessFamily[i] = 0;
5852b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                mNewRadioAccessFamily[i] = 0;
58611c94f3da98661b53ebbc81872b39b20cbe76223Robert Greenwalt                mTransactionFailed = false;
5872b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
5884e7f34de0e226703fadd1f30f9976bb426c5166bStuart Scott
5892b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            if (mWakeLock.isHeld()) {
5902b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                mWakeLock.release();
5912b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            }
5922b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        }
5932b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
5942b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
5952b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private void resetRadioAccessFamilyStatusCounter() {
5963a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mRadioAccessFamilyStatusCounter = mPhones.length;
5972b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
5982b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
5992b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    private void sendRadioCapabilityRequest(int phoneId, int sessionId, int rcPhase,
6002b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville            int radioFamily, String logicalModemId, int status, int eventId) {
6012b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville        RadioCapability requestRC = new RadioCapability(
6022b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                phoneId, sessionId, rcPhase, radioFamily, logicalModemId, status);
6033a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        mPhones[phoneId].setRadioCapability(
6042b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville                requestRC, mHandler.obtainMessage(eventId));
6052b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville    }
6062b40e6226b4b71408964bca46f0a9f256cd4f523Wink Saville
60732dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    // This method will return max number of raf bits supported from the raf
60832dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    // values currently stored in all phone objects
60932dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    public int getMaxRafSupported() {
6103a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        int[] numRafSupported = new int[mPhones.length];
61132dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        int maxNumRafBit = 0;
61232dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        int maxRaf = RadioAccessFamily.RAF_UNKNOWN;
61332dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
6143a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        for (int len = 0; len < mPhones.length; len++) {
6153a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            numRafSupported[len] = Integer.bitCount(mPhones[len].getRadioAccessFamily());
61632dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta            if (maxNumRafBit < numRafSupported[len]) {
61732dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                maxNumRafBit = numRafSupported[len];
6183a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                maxRaf = mPhones[len].getRadioAccessFamily();
61932dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta            }
62032dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        }
62132dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
62232dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        return maxRaf;
62332dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    }
62432dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
62532dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    // This method will return minimum number of raf bits supported from the raf
62632dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    // values currently stored in all phone objects
62732dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    public int getMinRafSupported() {
6283a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        int[] numRafSupported = new int[mPhones.length];
62932dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        int minNumRafBit = 0;
63032dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        int minRaf = RadioAccessFamily.RAF_UNKNOWN;
63132dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
6323a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        for (int len = 0; len < mPhones.length; len++) {
6333a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            numRafSupported[len] = Integer.bitCount(mPhones[len].getRadioAccessFamily());
63432dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta            if ((minNumRafBit == 0) || (minNumRafBit > numRafSupported[len])) {
63532dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                minNumRafBit = numRafSupported[len];
6363a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                minRaf = mPhones[len].getRadioAccessFamily();
63732dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta            }
63832dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        }
63932dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        return minRaf;
64032dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    }
64132dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
64232dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    // This method checks current raf values stored in all phones and
64332dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    // whicheve phone raf matches with input raf, returns modemId from that phone
64432dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    private String getLogicalModemIdFromRaf(int raf) {
64532dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        String modemUuid = null;
64632dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
6473a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan        for (int phoneId = 0; phoneId < mPhones.length; phoneId++) {
6483a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan            if (mPhones[phoneId].getRadioAccessFamily() == raf) {
6493a96b0ee1d152549279c58ba24a0a035cc9a557bAmit Mahajan                modemUuid = mPhones[phoneId].getModemUuId();
65032dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta                break;
65132dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta            }
65232dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        }
65332dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta        return modemUuid;
65432dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta    }
65532dfb14dd5469ea4e65c08a9e3be4ff97a136c6bSandeep Gutta
656a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void logd(String string) {
657a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, string);
658a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
659e97be3971cb6b55e019433c32524cc60ce0d037bWink Saville
66012fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal    private void loge(String string) {
66112fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal        Rlog.e(LOG_TAG, string);
66212fe7c9dce4807d482bf1bcb8472dacae9aa34fdShishir Agrawal    }
663a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
664