[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;
+}