[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/lynq/lib/liblynq-tele-ril/lynq-riltel/util/Proxycontroller.cpp b/src/lynq/lib/liblynq-tele-ril/lynq-riltel/util/Proxycontroller.cpp
new file mode 100644
index 0000000..d173c71
--- /dev/null
+++ b/src/lynq/lib/liblynq-tele-ril/lynq-riltel/util/Proxycontroller.cpp
@@ -0,0 +1,772 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <log/log.h>
+#include <set>
+#include <stdexcept>
+
+#include "Proxycontroller.h"
+#include "common.h"
+#include "network.h"
+#include "data.h"
+#include "bitset"
+#include "utils.h"
+#include "WorldPhoneUtil.h"
+
+#define LOG_TAG "DEMO_Proxy_controller"
+
+constexpr int Proxy_controller::EVENT_NOTIFICATION_RC_CHANGED;
+constexpr int Proxy_controller::EVENT_START_RC_RESPONSE;
+constexpr int Proxy_controller::EVENT_APPLY_RC_RESPONSE;
+constexpr int Proxy_controller::EVENT_FINISH_RC_RESPONSE;
+constexpr int Proxy_controller::EVENT_TIMEOUT;
+
+const int Proxy_controller::SET_RC_STATUS_IDLE             = 0;
+const int Proxy_controller::SET_RC_STATUS_STARTING         = 1;
+const int Proxy_controller::SET_RC_STATUS_STARTED          = 2;
+const int Proxy_controller::SET_RC_STATUS_APPLYING         = 3;
+const int Proxy_controller::SET_RC_STATUS_SUCCESS          = 4;
+const int Proxy_controller::SET_RC_STATUS_FAIL             = 5;
+
+const std::string Proxy_controller::PROPERTY_CAPABILITY_SWITCH = "persist.vendor.radio.simswitch";
+const std::string Proxy_controller::PROPERTY_CAPABILITY_SWITCH_STATE = "persist.vendor.radio.simswitchstate";
+
+// event 1-5 is defined in ProxyController
+const int Proxy_controller::EVENT_RADIO_AVAILABLE = 6;
+const int Proxy_controller::EVENT_RIL_CONNECTED = 7;
+
+// marker for retry cause
+const int Proxy_controller::RC_RETRY_CAUSE_NONE                  = 0;
+const int Proxy_controller::RC_RETRY_CAUSE_WORLD_MODE_SWITCHING  = 1;
+const int Proxy_controller::RC_RETRY_CAUSE_CAPABILITY_SWITCHING  = 2;
+const int Proxy_controller::RC_RETRY_CAUSE_IN_CALL               = 3;
+const int Proxy_controller::RC_RETRY_CAUSE_RADIO_UNAVAILABLE     = 4;
+const int Proxy_controller::RC_RETRY_CAUSE_AIRPLANE_MODE         = 5;
+const int Proxy_controller::RC_RETRY_CAUSE_RESULT_ERROR          = 6;
+
+    // marker for switch conditions pre-checking
+const int Proxy_controller::RC_DO_SWITCH       = 0;
+const int Proxy_controller::RC_NO_NEED_SWITCH  = 1;
+const int Proxy_controller::RC_CANNOT_SWITCH   = 2;
+
+Proxy_controller* Proxy_controller::sInstance = nullptr;
+    // The entire transaction must complete within this amount of time
+    // or a FINISH will be issued to each Logical Modem with the old
+    // Radio Access Family.
+const int Proxy_controller::SET_RC_TIMEOUT_WAITING_MSEC    = (45 * 1000);
+
+Proxy_controller::Proxy_controller() :mRadioCapabilitySessionId(0), mTransactionFailed(false){
+    //***** Class Variables
+    mIsCapSwitching = false;
+    mHasRegisterWorldModeReceiver = false;
+    mHasRegisterPhoneStateReceiver = false;
+    mHasRegisterEccStateReceiver = false;
+    mIsRildReconnected = false;
+    mSetRafRetryCause = RC_RETRY_CAUSE_NONE;
+    // Exception counter
+    onExceptionCount = 0;
+    clearTransaction();
+}
+
+Proxy_controller::~Proxy_controller() {
+    // TODO Auto-generated destructor stub
+}
+
+Proxy_controller::Handle_thread::Handle_thread(): m_looper(NULL){
+    RLOGD("RequestHandleThread created");
+}
+
+Proxy_controller::Handle_thread::~Handle_thread() {
+    RLOGD("RequestHandleThread destroyed");
+}
+
+sp<Looper> Proxy_controller::Handle_thread::getLooper() {
+    return m_looper;
+}
+
+bool Proxy_controller::Handle_thread::threadLoop() {
+    RLOGD("Handler threadLoop");
+    m_looper = Looper::prepare(0);
+    int result;
+    do {
+        result = m_looper->pollAll(-1);
+        RLOGD("Handler threadLoop, pull message result = %d", result);
+    } while (result == Looper::POLL_WAKE || result == Looper::POLL_CALLBACK);
+    return true;
+}
+
+Proxy_controller::Request_message::Request_message(): what(0), slot(-1),e(RIL_E_SUCCESS), is_rc_set(true),id(-1){
+
+}
+
+void Proxy_controller::init() {
+    handle_thread = new Handle_thread();
+    handle_thread->run();
+}
+
+Proxy_controller *Proxy_controller::getInstance() {
+    if (sInstance == NULL) {
+        sInstance = new Proxy_controller();
+        sInstance->init();
+    }
+    return sInstance;
+}
+
+sp<Proxy_controller::Request_handler> Proxy_controller::sendMessage(sp<Request_message> msg, int delayms) {
+    RLOGD("sendMessage msg what=%d delayms=%d", msg->what, delayms);
+    // Create a handler to handle this message
+    sp<Request_handler> handler = new Request_handler(this);
+    handler->msg = msg;
+    // Sand message to looper
+    if(handle_thread.get()) {
+        sp<Looper> looper = handle_thread->getLooper();
+        if(looper.get()) {
+            if (delayms > 0) {
+                looper->sendMessageDelayed(ms2ns(delayms),handler, handler->m_dummyMsg);
+            } else {
+                looper->sendMessage(handler, handler->m_dummyMsg);
+            }
+        } else {
+            RLOGD("looper");
+        }
+    } else {
+        RLOGD("handle_thread");
+    }
+
+    return handler;
+}
+
+void Proxy_controller::handle_request_resp(RIL_RadioCapability* cap, RIL_Errno e, int slot) {
+    if(m_eventId[slot] < 0) {
+        RLOGD("handle_request_resp cap is null.m_eventId[%d]=%d", slot, m_eventId[slot]);
+        return;
+    }
+    RLOGD("handle_request_resp what[%d]: %d , phase: %d", slot,m_eventId[slot], cap->phase);
+    // Create a request message
+    sp<Request_message> msg = new Request_message();
+    msg->what = m_eventId[slot];
+    if(cap != NULL) {
+        msg->cap = (*cap);
+    } else {
+        msg->is_rc_set = false;
+        RLOGD("handle_request_resp[slot%d]: cap is null", slot);
+    }
+    msg->e = e;
+    msg->slot = slot;
+    RLOGD("handle_request_resp logicalModemUuid: %s , phase: %d, rat: %d, session: %d, status: %d, version: %d",
+            msg->cap.logicalModemUuid, msg->cap.phase, msg->cap.rat, msg->cap.session, msg->cap.status, msg->cap.version);
+    sendMessage(msg, 0);
+}
+
+void Proxy_controller::issueFinish(int sessionId) {
+    m_mutex.lock();
+    for (int i = 0; i < SIM_COUNT; i++) {
+        RLOGD("issueFinish: phoneId=%d sessionId= %d  mTransactionFailed=%d", i, sessionId, mTransactionFailed);
+        mRadioAccessFamilyStatusCounter++;
+        sendRadioCapabilityRequest(
+                i,
+                sessionId,
+                RadioCapabilityPhase(RC_PHASE_FINISH),
+                (mTransactionFailed ? mOldRadioAccessFamily[i] :
+                mNewRadioAccessFamily[i]),
+                (mTransactionFailed ? mCurrentLogicalModemIds[i] :
+                mNewLogicalModemIds[i]),
+                (mTransactionFailed ? RadioCapabilityStatus(RC_STATUS_FAIL) :
+                        RadioCapabilityStatus(RC_STATUS_SUCCESS)),
+                EVENT_FINISH_RC_RESPONSE);
+        if (mTransactionFailed) {
+            RLOGD("issueFinish: phoneId: %d status: FAIL", i);
+            // At least one failed, mark them all failed.
+            mSetRadioAccessFamilyStatus[i] = SET_RC_STATUS_FAIL;
+        }
+    }
+    m_mutex.unlock();
+}
+
+void Proxy_controller::onStartRadioCapabilityResponse(sp<Request_message> msg) {
+    m_mutex.lock();
+
+    RIL_RadioCapability rc = msg->cap;
+    if ((rc.session != mRadioCapabilitySessionId.load())) {
+        RLOGD("onStartRadioCapabilityResponse: Ignore session=%d,rc.logicalModemUuid = %d, rc.phase = %d, rc.rat = %d, rc.session = %d, rc.status = %d, rc.version = %d",
+                mRadioCapabilitySessionId.load(), rc.logicalModemUuid,rc.phase,rc.rat,rc.session,rc.status,rc.version);
+        return;
+    }
+    mRadioAccessFamilyStatusCounter--;
+    int id = msg->slot;
+    if (msg->e != RIL_E_SUCCESS) {
+        RLOGD("onStartRadioCapabilityResponse: Error response session=%d", rc.session);
+        RLOGD("onStartRadioCapabilityResponse: phoneId=%d status=FAIL", id);
+        mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_FAIL;
+        mTransactionFailed = true;
+    } else {
+        RLOGD("onStartRadioCapabilityResponse: phoneId=%d status=STARTED", id);
+        mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_STARTED;
+    }
+
+    if (mRadioAccessFamilyStatusCounter == 0) {
+        /**
+        std::set<std::string> modemsInUse;
+        for (auto modemId : mNewLogicalModemIds) {
+            if (!(modemsInUse.insert(modemId).second)) {
+                mTransactionFailed = true;
+                RLOGD("ERROR: sending down the same id for different phones");
+            }
+        }
+        **/
+        RLOGD("onStartRadioCapabilityResponse: success=%d", !mTransactionFailed);
+        if (mTransactionFailed) {
+            // Sends a variable number of requests, so don't resetRadioAccessFamilyCounter
+            // here.
+            m_mutex.unlock();
+            issueFinish(mRadioCapabilitySessionId.load());
+            return;
+        } else {
+            // All logical modem accepted the new radio access family, issue the APPLY
+            resetRadioAccessFamilyStatusCounter();
+            for (int i = 0; i < SIM_COUNT; i++) {
+                sendRadioCapabilityRequest(
+                    i,
+                    mRadioCapabilitySessionId.load(),
+                    RadioCapabilityPhase(RC_PHASE_APPLY),
+                    mNewRadioAccessFamily[i],
+                    mNewLogicalModemIds[i],
+                    RadioCapabilityStatus(RC_STATUS_NONE),
+                    EVENT_APPLY_RC_RESPONSE);
+
+               RLOGD("onStartRadioCapabilityResponse: phoneId=%d status=APPLYING", i);
+                mSetRadioAccessFamilyStatus[i] = SET_RC_STATUS_APPLYING;
+            }
+        }
+    }
+    m_mutex.unlock();
+}
+
+void Proxy_controller::onApplyRadioCapabilityErrorHandler(sp<Request_message> msg){
+
+}
+void Proxy_controller::onApplyExceptionHandler(sp<Request_message> msg){
+
+}
+
+void Proxy_controller::onApplyRadioCapabilityResponse(sp<Request_message> msg) {
+    RIL_RadioCapability rc = msg->cap;
+    if ((rc.session != mRadioCapabilitySessionId.load())) {
+        RLOGD("onApplyRadioCapabilityResponse: Ignore session=%d,rc.logicalModemUuid = %d, rc.phase = %d, rc.rat = %d, rc.session = %d, rc.status = %d, rc.version = %d",
+                mRadioCapabilitySessionId.load(), rc.logicalModemUuid,rc.phase,rc.rat,rc.session,rc.status,rc.version);
+        /// M: handle rc error, retry sim switch if possible. @{
+        onApplyRadioCapabilityErrorHandler(msg);
+        /// @}
+        return;
+    }
+    RLOGD("onApplyRadioCapabilityResponse: rc.logicalModemUuid = %d, rc.phase = %d, rc.rat = %d, rc.session = %d, rc.status = %d, rc.version = %d",
+                mRadioCapabilitySessionId.load(), rc.logicalModemUuid,rc.phase,rc.rat,rc.session,rc.status,rc.version);
+    if (msg->e != RIL_E_SUCCESS) {
+        m_mutex.lock();
+        RLOGD("onApplyRadioCapabilityResponse: Error response session=%d",rc.session);
+        int id = msg->slot;
+        /// M: handle exception, retry sim switch if possible. @{
+        onApplyExceptionHandler(msg);
+        /// @}
+        RLOGD("onApplyRadioCapabilityResponse: phoneId=%d status=FAIL", id);
+        mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_FAIL;
+        mTransactionFailed = true;
+        m_mutex.unlock();
+    } else {
+        RLOGD("onApplyRadioCapabilityResponse: Valid start expecting notification rc.logicalModemUuid = %d, rc.phase = %d, rc.rat = %d, rc.session = %d, rc.status = %d, rc.version = %d",
+                mRadioCapabilitySessionId.load(), rc.logicalModemUuid,rc.phase,rc.rat,rc.session,rc.status,rc.version);
+    }
+}
+
+void Proxy_controller::handle_message_notify(RIL_RadioCapability* cap,int slot) {
+    sp<Request_message> msg = new Request_message();
+    msg->what = EVENT_NOTIFICATION_RC_CHANGED;
+    if(cap != NULL) {
+        msg->cap = (*cap);
+    } else {
+        msg->is_rc_set = false;
+        RLOGD("handle_request_resp[slot%d]: cap is null", slot);
+    }
+    msg->slot = slot;
+    RLOGD("handle_request_resp logicalModemUuid: %s , phase: %d, rat: %d, session: %d, status: %d, version: %d",
+            msg->cap.logicalModemUuid, msg->cap.phase, msg->cap.rat, msg->cap.session, msg->cap.status, msg->cap.version);
+    sendMessage(msg, 0);
+}
+
+void Proxy_controller::onNotificationRadioCapabilityChanged(sp<Request_message> msg) {
+    RIL_RadioCapability rc = msg->cap;
+    if (msg->is_rc_set == false || (rc.session != mRadioCapabilitySessionId.load())) {
+        RLOGD("onNotificationRadioCapabilityChanged: Ignore session=%d,rc.logicalModemUuid = %d, rc.phase = %d, rc.rat = %d, rc.session = %d, rc.status = %d, rc.version = %d",
+                mRadioCapabilitySessionId.load(), rc.logicalModemUuid,rc.phase,rc.rat,rc.session,rc.status,rc.version);
+        return;
+    }
+    m_mutex.lock();
+    RLOGD("onNotificationRadioCapabilityChanged: rc.logicalModemUuid = %d, rc.phase = %d, rc.rat = %d, rc.session = %d, rc.status = %d, rc.version = %d",
+            rc.logicalModemUuid,rc.phase,rc.rat,rc.session,rc.status,rc.version);
+
+    int id = msg->slot;
+    if (msg-> e != RIL_E_SUCCESS ||
+            (rc.status == RadioCapabilityStatus(RC_STATUS_FAIL))) {
+        RLOGD("onNotificationRadioCapabilityChanged: phoneId=%d status=FAIL", id);
+        mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_FAIL;
+        mTransactionFailed = true;
+    } else {
+        RLOGD("onNotificationRadioCapabilityChanged: phoneId=%d status=SUCCESS(%d)", id, !mTransactionFailed);
+        mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_SUCCESS;
+        // The modems may have been restarted and forgotten this
+
+        RequestInfo *info = creatRILInfoAndInit(RIL_REQUEST_ALLOW_DATA, OTHER, (RIL_SOCKET_ID)id);
+
+        int switch_id = get_default_sim_data_for_switch();
+        RLOGD("onNotificationRadioCapabilityChanged: phoneId=%d switch_id=%d", id, switch_id);
+        char* argv[2] = {"RIL_REQUEST_ALLOW_DATA","0"};
+        if(id == switch_id) {
+            argv[1] = "1";
+        }
+        setDataAllowed(2, argv, RIL_SOCKET_ID(id), info);
+    }
+
+    mRadioAccessFamilyStatusCounter--;
+    if (mRadioAccessFamilyStatusCounter == 0) {
+        RLOGD("onNotificationRadioCapabilityChanged: APPLY URC success=%d",!mTransactionFailed);
+        m_mutex.unlock();
+        issueFinish(mRadioCapabilitySessionId.load());
+        return;
+    }
+    m_mutex.unlock();
+}
+
+void Proxy_controller::completeRadioCapabilityTransaction() {
+    RLOGD("completeRadioCapabilityTransaction: success=%d" , !mTransactionFailed);
+    if (!mTransactionFailed) {
+
+
+        // make messages about the old transaction obsolete (specifically the timeout)
+        //mRadioCapabilitySessionId++;
+
+        // Reinitialize
+        clearTransaction();
+        android::emResultNotify("default data slot switch success\n");
+    } else {
+        android::emResultNotify("default data slot switch fail, now retry\n");
+        // now revert.
+        mTransactionFailed = false;
+        std::vector<RIL_RadioAccessFamily> rafs = {RAF_UNKNOWN, RAF_UNKNOWN};
+        for (int phoneId = 0; phoneId < SIM_COUNT; phoneId++) {
+            rafs[phoneId] = (RIL_RadioAccessFamily)mOldRadioAccessFamily[phoneId];
+        }
+        doSetRadioCapabilities(rafs);
+    }
+
+}
+
+void Proxy_controller::onFinishRadioCapabilityResponse(sp<Request_message> msg){
+    RIL_RadioCapability rc = msg->cap;;
+    if (msg->is_rc_set == false || (rc.session != mRadioCapabilitySessionId.load())) {
+        RLOGD("onFinishRadioCapabilityResponse: Ignore session=%d,rc.logicalModemUuid = %d, rc.phase = %d, rc.rat = %d, rc.session = %d, rc.status = %d, rc.version = %d",
+                mRadioCapabilitySessionId.load(), rc.logicalModemUuid,rc.phase,rc.rat,rc.session,rc.status,rc.version);
+        return;
+    }
+    m_mutex.lock();
+    RLOGD("onFinishRadioCapabilityResponse mRadioAccessFamilyStatusCounter=%d",mRadioAccessFamilyStatusCounter);
+    mRadioAccessFamilyStatusCounter--;
+    if (mRadioAccessFamilyStatusCounter == 0) {
+        m_mutex.unlock();
+        completeRadioCapabilityTransaction();
+        return;
+    }
+    m_mutex.unlock();
+}
+
+void Proxy_controller::onTimeoutRadioCapability(sp<Request_message> msg){
+    if (msg->id != mRadioCapabilitySessionId.load()) {
+       RLOGD("RadioCapability timeout: Ignore msg->id=%d != mRadioCapabilitySessionId.load()=%d", msg->id,mRadioCapabilitySessionId.load());
+        return;
+    }
+
+    m_mutex.lock();
+    // timed-out.  Clean up as best we can
+    for (int i = 0; i < SIM_COUNT; i++) {
+        RLOGD("RadioCapability timeout: mSetRadioAccessFamilyStatus[%d]=%d",i,mSetRadioAccessFamilyStatus[i]);
+    }
+
+    // Increment the sessionId as we are completing the transaction below
+    // so we don't want it completed when the FINISH phase is done.
+    mRadioCapabilitySessionId++;
+
+    // Reset the status counter as existing session failed
+    mRadioAccessFamilyStatusCounter = 0;
+
+    // send FINISH request with fail status and then uniqueDifferentId
+    mTransactionFailed = true;
+    m_mutex.unlock();
+    issueFinish(mRadioCapabilitySessionId.load());
+}
+
+void Proxy_controller::Request_handler::sendMessage(sp<Request_message> msg, int delayms) {
+    RLOGD("Proxy_controller::Request_handler, sendMessage msg what=%d delayms=%d", msg->what, delayms);
+    // Sand message to looper
+    this->msg = msg;
+    if (delayms > 0) {
+        proxy_controller->handle_thread->getLooper()->sendMessageDelayed(ms2ns(delayms),
+                this, this->m_dummyMsg);
+    } else {
+        proxy_controller->handle_thread->getLooper()->sendMessage(this, this->m_dummyMsg);
+    }
+    return ;
+}
+
+void Proxy_controller::Request_handler::handleMessage(const Message& message) {
+
+    RLOGD("handleMessage msg->what: %d", msg->what);
+    switch( msg->what){
+    case EVENT_START_RC_RESPONSE:
+    {
+        proxy_controller->onStartRadioCapabilityResponse(msg);
+        break;
+    }
+    case EVENT_APPLY_RC_RESPONSE:
+    {
+        proxy_controller->onApplyRadioCapabilityResponse(msg);
+        break;
+    }
+    case EVENT_NOTIFICATION_RC_CHANGED:
+    {
+        proxy_controller->onNotificationRadioCapabilityChanged(msg);
+        break;
+    }
+    case EVENT_FINISH_RC_RESPONSE:
+    {
+        proxy_controller->onFinishRadioCapabilityResponse(msg);
+        break;
+    }
+    case EVENT_TIMEOUT:
+    {
+        proxy_controller->onTimeoutRadioCapability(msg);
+        break;
+    }
+    default:
+        break;
+    }
+}
+
+void Proxy_controller::clearTransaction() {
+    RLOGD("clearTransaction");
+    m_mutex.lock();
+    mSetRadioAccessFamilyStatus.clear();
+    mOldRadioAccessFamily.clear();
+    mNewRadioAccessFamily.clear();
+    m_eventId.clear();
+    mCurrentLogicalModemIds.clear();
+    mNewLogicalModemIds.clear();
+    for (int i = 0; i < 2; i++) {
+        RLOGD("clearTransaction: phoneId=%d status=IDLE",i);
+        mSetRadioAccessFamilyStatus.push_back(SET_RC_STATUS_IDLE);
+        mOldRadioAccessFamily.push_back(0);
+        mNewRadioAccessFamily.push_back(0);
+        mCurrentLogicalModemIds.push_back("");
+        mNewLogicalModemIds.push_back("");
+        mTransactionFailed = false;
+        m_eventId.push_back(-1);
+    }
+    if(handle_thread.get()) {
+        sp<Looper> looper = handle_thread->getLooper();
+        if(looper.get()) {
+            if(timeout_handle.get()) {
+                looper->removeMessages(timeout_handle);
+            } else {
+                RLOGD("clearTransaction,timeout_handle");
+            }
+        } else {
+            RLOGD("clearTransaction,looper");
+        }
+    } else {
+        RLOGD("clearTransaction,handle_thread");
+    }
+    m_mutex.unlock();
+}
+
+int Proxy_controller::checkRadioCapabilitySwitchConditions(std::vector<RIL_RadioAccessFamily> rafs) {
+    m_mutex.lock();
+    mNextRafs = rafs;
+
+    // check if still switching
+    if (mIsCapSwitching == true) {
+        //throw new RuntimeException("is still switching");
+        RLOGD("keep it and return,because capability swithing");
+        mSetRafRetryCause = RC_RETRY_CAUSE_CAPABILITY_SWITCHING;
+        return RC_NO_NEED_SWITCH;
+    } else if (mSetRafRetryCause == RC_RETRY_CAUSE_CAPABILITY_SWITCHING) {
+        RLOGD("setCapability, mIsCapSwitching is not switching, can switch");
+        mSetRafRetryCause = RC_RETRY_CAUSE_NONE;
+    }
+    mIsCapSwitching = true;
+    m_mutex.lock();
+
+    // check if capability switch disabled
+    if (utils::mtk_property_get_bool("ro.vendor.mtk_disable_cap_switch", false) == true) {
+        mNextRafs.clear();
+        completeRadioCapabilityTransaction();
+        RLOGD("skip switching because mtk_disable_cap_switch is true");
+        return RC_NO_NEED_SWITCH;
+    }
+    // check FTA mode
+    if (utils::mtk_property_get_int32("vendor.gsm.gcf.testmode", 0) == 2) {
+        mNextRafs.clear();
+        completeRadioCapabilityTransaction();
+        RLOGD("skip switching because FTA mode");
+        return RC_NO_NEED_SWITCH;
+    }
+    // check EM disable mode
+    if (utils::mtk_property_get_int32("persist.vendor.radio.simswitch.emmode", 1) == 0) {
+        mNextRafs.clear();
+        completeRadioCapabilityTransaction();
+        RLOGD("skip switching because EM disable mode");
+        return RC_NO_NEED_SWITCH;
+    }
+
+    // check world mode switching
+    if (WorldPhoneUtil::isWorldPhoneSupport()) {
+        if (!WorldPhoneUtil::isWorldModeSupport()) {
+            if (/*ModemSwitchHandler.isModemTypeSwitching()*/!isRadioAvailable((RIL_SOCKET_ID)Radio_capability_switch_util::get_main_capability_phone_id())) {
+                RLOGD("world mode switching.");
+                if (!mHasRegisterWorldModeReceiver) {
+                    mHasRegisterWorldModeReceiver = true;
+                }
+                mSetRafRetryCause = RC_RETRY_CAUSE_WORLD_MODE_SWITCHING;
+                m_mutex.lock();
+                mIsCapSwitching = false;
+                m_mutex.unlock();
+                return RC_CANNOT_SWITCH;
+            }
+        } else if (mSetRafRetryCause == RC_RETRY_CAUSE_WORLD_MODE_SWITCHING) {
+            if (mHasRegisterWorldModeReceiver) {
+                mHasRegisterWorldModeReceiver = false;
+                mSetRafRetryCause = RC_RETRY_CAUSE_NONE;
+            }
+        }
+    }
+
+    // check call state
+    if (!(is_call_state_idle(0) || is_call_state_idle(1))) {
+        //throw new RuntimeException("in call, fail to set RAT for phones");
+        RLOGD("setCapability in calling, fail to set RAT for phones");
+        if (!mHasRegisterPhoneStateReceiver) {
+            mHasRegisterPhoneStateReceiver = true;
+        }
+        mSetRafRetryCause = RC_RETRY_CAUSE_IN_CALL;
+        m_mutex.lock();
+        mIsCapSwitching = false;
+        m_mutex.unlock();
+        return RC_CANNOT_SWITCH;
+    } else if (isEccInProgress()) {
+        RLOGD("setCapability in ECC, fail to set RAT for phones");
+        if (!mHasRegisterEccStateReceiver) {
+            mHasRegisterEccStateReceiver = true;
+        }
+        mSetRafRetryCause = RC_RETRY_CAUSE_IN_CALL;
+        m_mutex.lock();
+        mIsCapSwitching = false;
+        m_mutex.unlock();
+        return RC_CANNOT_SWITCH;
+    } else if (mSetRafRetryCause == RC_RETRY_CAUSE_IN_CALL) {
+        if (mHasRegisterPhoneStateReceiver) {
+            mHasRegisterPhoneStateReceiver = false;
+            mSetRafRetryCause = RC_RETRY_CAUSE_NONE;
+        }
+        if (mHasRegisterEccStateReceiver) {
+            mHasRegisterEccStateReceiver = false;
+            mSetRafRetryCause = RC_RETRY_CAUSE_NONE;
+        }
+    }
+
+    // check radio available
+    for (int i = 0; i < SIM_COUNT; i++) {
+        if (!isRadioAvailable((RIL_SOCKET_ID)i)) {
+            //throw new RuntimeException("Phone" + i + " is not available");
+            mSetRafRetryCause = RC_RETRY_CAUSE_RADIO_UNAVAILABLE;
+            //mCi[i].registerForAvailable(mMtkHandler, EVENT_RADIO_AVAILABLE, null);
+            RLOGD("setCapability fail,Phone%d is not available", i);
+            m_mutex.lock();
+            mIsCapSwitching = false;
+            m_mutex.unlock();
+            return RC_CANNOT_SWITCH;
+        } else if (mSetRafRetryCause == RC_RETRY_CAUSE_RADIO_UNAVAILABLE) {
+            //mCi[i].unregisterForAvailable(mMtkHandler);
+            if (i == SIM_COUNT - 1) {
+                mSetRafRetryCause = RC_RETRY_CAUSE_NONE;
+            }
+        }
+    }
+
+    int switchStatus = utils::mtk_property_get_int32(PROPERTY_CAPABILITY_SWITCH.c_str(), 1);
+    // check parameter
+    bool bIsboth3G = false;
+    bool bIsMajorPhone = false;
+    int newMajorPhoneId = 0;
+    for (int i = 0; i < rafs.size(); i++) {
+        bIsMajorPhone = false;
+        if ((rafs[i] & RIL_RadioAccessFamily::RAF_GPRS) > 0) {
+            bIsMajorPhone = true;
+        }
+
+        if (bIsMajorPhone) {
+            newMajorPhoneId = i;
+            if (newMajorPhoneId == (switchStatus - 1)) {
+                RLOGD("no change, skip setRadioCapability");
+                mSetRafRetryCause = RC_RETRY_CAUSE_NONE;
+                mNextRafs.clear();
+                completeRadioCapabilityTransaction();
+                return RC_NO_NEED_SWITCH;
+            }
+            if (bIsboth3G) {
+                RLOGD("set more than one 3G phone, fail");
+                m_mutex.lock();
+                mIsCapSwitching = false;
+                m_mutex.unlock();
+                throw std::runtime_error("input parameter is incorrect");
+            } else {
+                bIsboth3G = true;
+            }
+        }
+    }
+    if (bIsboth3G == false) {
+        m_mutex.lock();
+        mIsCapSwitching = false;
+        m_mutex.unlock();
+        throw std::runtime_error("input parameter is incorrect - no 3g phone");
+    }
+
+    // check operator spec
+    if (!isNeedSimSwitch(newMajorPhoneId, SIM_COUNT)) {
+        RLOGD("check sim card type and skip setRadioCapability");
+        mSetRafRetryCause = RC_RETRY_CAUSE_NONE;
+        mNextRafs.clear();
+        completeRadioCapabilityTransaction();
+        return RC_NO_NEED_SWITCH;
+    }
+
+//    if (!WorldPhoneUtil::isWorldModeSupport() && WorldPhoneUtil::isWorldPhoneSupport()) {
+//        WorldPhoneUtil.getWorldPhone().notifyRadioCapabilityChange(newMajorPhoneId);
+//    }
+    RLOGD("checkRadioCapabilitySwitchConditions, do switch");
+    return RC_DO_SWITCH;
+}
+
+bool Proxy_controller::isEccInProgress() {
+    bool inEcm = utils::mtk_property_get_bool("ril.cdma.inecmmode", false);
+    return inEcm;
+}
+
+bool Proxy_controller::isNeedSimSwitch(int majorPhoneId, int phoneNum) {
+    RLOGD("OMisNeedSimSwitch, majorPhoneId = %d ", majorPhoneId);
+    return !Radio_capability_switch_util::isSkipCapabilitySwitch(majorPhoneId, phoneNum);
+}
+
+bool Proxy_controller::set_Radio_Capability(std::vector<RIL_RadioAccessFamily> rafs) {
+    if (rafs.size() != SIM_COUNT) {
+        RLOGD("Length of input rafs must equal to total phone count");
+    }
+    // Check if there is any ongoing transaction and throw an exception if there
+    // is one as this is a programming error.
+    m_mutex.lock();
+    for (int i = 0; i < rafs.size(); i++) {
+        if (mSetRadioAccessFamilyStatus[i] != SET_RC_STATUS_IDLE) {
+            // TODO: The right behaviour is to cancel previous request and send this.
+            RLOGE("setRadioCapability: Phone[%d] is not idle. Rejecting request.", i);
+            return false;
+        }
+    }
+    m_mutex.unlock();
+
+    // Clear to be sure we're in the initial state
+    clearTransaction();
+
+    return doSetRadioCapabilities(rafs);
+}
+
+void Proxy_controller::resetRadioAccessFamilyStatusCounter() {
+    mRadioAccessFamilyStatusCounter = SIM_COUNT;
+}
+
+std::string Proxy_controller::getLogicalModemIdFromRaf(int raf) {
+    std::string modemUui;
+
+    for (int phoneId = 0; phoneId < SIM_COUNT; phoneId++) {
+        if (get_radio_capa(phoneId).rat == raf) {
+            modemUui = get_radio_capa(phoneId).logicalModemUuid;
+            break;
+        }
+    }
+    return modemUui;
+}
+
+void Proxy_controller::sendRadioCapabilityRequest(int phoneId, int sessionId, int rcPhase,
+            int radioFamily, std::string logicalModemId, int status, int eventId){
+    RequestInfo *info = creatRILInfoAndInit(RIL_REQUEST_SET_RADIO_CAPABILITY, OTHER, (RIL_SOCKET_ID)phoneId);
+
+    char* argv[7] = {"RIL_REQUEST_SET_RADIO_CAPABILITY",
+            const_cast<char*>(std::to_string(RIL_RADIO_CAPABILITY_VERSION).c_str()),
+            const_cast<char*>(std::to_string(sessionId).c_str()),
+            const_cast<char*>(std::to_string(rcPhase).c_str()),
+            const_cast<char*>(std::to_string(radioFamily).c_str()),
+            const_cast<char*>(logicalModemId.c_str()),
+            const_cast<char*>(std::to_string(status).c_str())
+    };
+    setRadioCapability(7, argv,(RIL_SOCKET_ID)phoneId, info);
+    m_eventId[phoneId] = eventId;
+}
+
+bool Proxy_controller::doSetRadioCapabilities(std::vector<RIL_RadioAccessFamily> rafs) {
+    // A new sessionId for this transaction
+    mRadioCapabilitySessionId++;
+    // Start timer to make sure all phones respond within a specific time interval.
+    // Will send FINISH if a timeout occurs.
+    sp<Request_message> msg = new Request_message();
+    msg->what = EVENT_TIMEOUT;
+    msg->id = mRadioCapabilitySessionId.load();
+    timeout_handle = sendMessage(msg, SET_RC_TIMEOUT_WAITING_MSEC);
+
+    m_mutex.lock();
+    RLOGD("setRadioCapability: new request session id=%d", mRadioCapabilitySessionId.load());
+    resetRadioAccessFamilyStatusCounter();
+    for (int i = 0; i < rafs.size(); i++) {
+        RLOGD("setRadioCapability: phoneId=%d status=STARTING", i);
+        mSetRadioAccessFamilyStatus[i] = SET_RC_STATUS_STARTING;
+        mOldRadioAccessFamily[i] = get_radio_capa(i).rat;
+        int requestedRaf = rafs[i];
+        // TODO Set the new radio access family to the maximum of the requested & supported
+        // int supportedRaf = mPhones[i].getRadioAccessFamily();
+        // mNewRadioAccessFamily[i] = requestedRaf & supportedRaf;
+        mNewRadioAccessFamily[i] = requestedRaf;
+
+        mCurrentLogicalModemIds[i] = get_radio_capa(i).logicalModemUuid;
+        // get the logical mode corresponds to new raf requested and pass the
+        // same as part of SET_RADIO_CAP APPLY phase
+        mNewLogicalModemIds[i] = getLogicalModemIdFromRaf(requestedRaf);
+        RLOGD("setRadioCapability: mOldRadioAccessFamily[%d]=%d", i,mOldRadioAccessFamily[i]);
+        RLOGD("setRadioCapability: mNewRadioAccessFamily[%d]=%d", i,mNewRadioAccessFamily[i]);
+        sendRadioCapabilityRequest(
+                i,
+                mRadioCapabilitySessionId.load(),
+                RadioCapabilityPhase(RC_PHASE_START),
+                mOldRadioAccessFamily[i],
+                mCurrentLogicalModemIds[i],
+                RadioCapabilityStatus(RC_STATUS_NONE),
+                EVENT_START_RC_RESPONSE);
+    }
+    m_mutex.unlock();
+    return true;
+}