rjw | 1f88458 | 2022-01-06 17:20:42 +0800 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (C) 2013 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | #include <log/log.h> |
| 17 | #include <set> |
| 18 | #include <stdexcept> |
| 19 | |
| 20 | #include "Proxycontroller.h" |
| 21 | #include "common.h" |
| 22 | #include "network.h" |
| 23 | #include "data.h" |
| 24 | #include "bitset" |
| 25 | #include "utils.h" |
| 26 | #include "WorldPhoneUtil.h" |
| 27 | |
| 28 | #define LOG_TAG "DEMO_Proxy_controller" |
| 29 | |
| 30 | constexpr int Proxy_controller::EVENT_NOTIFICATION_RC_CHANGED; |
| 31 | constexpr int Proxy_controller::EVENT_START_RC_RESPONSE; |
| 32 | constexpr int Proxy_controller::EVENT_APPLY_RC_RESPONSE; |
| 33 | constexpr int Proxy_controller::EVENT_FINISH_RC_RESPONSE; |
| 34 | constexpr int Proxy_controller::EVENT_TIMEOUT; |
| 35 | |
| 36 | const int Proxy_controller::SET_RC_STATUS_IDLE = 0; |
| 37 | const int Proxy_controller::SET_RC_STATUS_STARTING = 1; |
| 38 | const int Proxy_controller::SET_RC_STATUS_STARTED = 2; |
| 39 | const int Proxy_controller::SET_RC_STATUS_APPLYING = 3; |
| 40 | const int Proxy_controller::SET_RC_STATUS_SUCCESS = 4; |
| 41 | const int Proxy_controller::SET_RC_STATUS_FAIL = 5; |
| 42 | |
| 43 | const std::string Proxy_controller::PROPERTY_CAPABILITY_SWITCH = "persist.vendor.radio.simswitch"; |
| 44 | const std::string Proxy_controller::PROPERTY_CAPABILITY_SWITCH_STATE = "persist.vendor.radio.simswitchstate"; |
| 45 | |
| 46 | // event 1-5 is defined in ProxyController |
| 47 | const int Proxy_controller::EVENT_RADIO_AVAILABLE = 6; |
| 48 | const int Proxy_controller::EVENT_RIL_CONNECTED = 7; |
| 49 | |
| 50 | // marker for retry cause |
| 51 | const int Proxy_controller::RC_RETRY_CAUSE_NONE = 0; |
| 52 | const int Proxy_controller::RC_RETRY_CAUSE_WORLD_MODE_SWITCHING = 1; |
| 53 | const int Proxy_controller::RC_RETRY_CAUSE_CAPABILITY_SWITCHING = 2; |
| 54 | const int Proxy_controller::RC_RETRY_CAUSE_IN_CALL = 3; |
| 55 | const int Proxy_controller::RC_RETRY_CAUSE_RADIO_UNAVAILABLE = 4; |
| 56 | const int Proxy_controller::RC_RETRY_CAUSE_AIRPLANE_MODE = 5; |
| 57 | const int Proxy_controller::RC_RETRY_CAUSE_RESULT_ERROR = 6; |
| 58 | |
| 59 | // marker for switch conditions pre-checking |
| 60 | const int Proxy_controller::RC_DO_SWITCH = 0; |
| 61 | const int Proxy_controller::RC_NO_NEED_SWITCH = 1; |
| 62 | const int Proxy_controller::RC_CANNOT_SWITCH = 2; |
| 63 | |
| 64 | Proxy_controller* Proxy_controller::sInstance = nullptr; |
| 65 | // The entire transaction must complete within this amount of time |
| 66 | // or a FINISH will be issued to each Logical Modem with the old |
| 67 | // Radio Access Family. |
| 68 | const int Proxy_controller::SET_RC_TIMEOUT_WAITING_MSEC = (45 * 1000); |
| 69 | |
| 70 | Proxy_controller::Proxy_controller() :mRadioCapabilitySessionId(0), mTransactionFailed(false){ |
| 71 | //***** Class Variables |
| 72 | mIsCapSwitching = false; |
| 73 | mHasRegisterWorldModeReceiver = false; |
| 74 | mHasRegisterPhoneStateReceiver = false; |
| 75 | mHasRegisterEccStateReceiver = false; |
| 76 | mIsRildReconnected = false; |
| 77 | mSetRafRetryCause = RC_RETRY_CAUSE_NONE; |
| 78 | // Exception counter |
| 79 | onExceptionCount = 0; |
| 80 | clearTransaction(); |
| 81 | } |
| 82 | |
| 83 | Proxy_controller::~Proxy_controller() { |
| 84 | // TODO Auto-generated destructor stub |
| 85 | } |
| 86 | |
| 87 | Proxy_controller::Handle_thread::Handle_thread(): m_looper(NULL){ |
| 88 | RLOGD("RequestHandleThread created"); |
| 89 | } |
| 90 | |
| 91 | Proxy_controller::Handle_thread::~Handle_thread() { |
| 92 | RLOGD("RequestHandleThread destroyed"); |
| 93 | } |
| 94 | |
| 95 | sp<Looper> Proxy_controller::Handle_thread::getLooper() { |
| 96 | return m_looper; |
| 97 | } |
| 98 | |
| 99 | bool Proxy_controller::Handle_thread::threadLoop() { |
| 100 | RLOGD("Handler threadLoop"); |
| 101 | m_looper = Looper::prepare(0); |
| 102 | int result; |
| 103 | do { |
| 104 | result = m_looper->pollAll(-1); |
| 105 | RLOGD("Handler threadLoop, pull message result = %d", result); |
| 106 | } while (result == Looper::POLL_WAKE || result == Looper::POLL_CALLBACK); |
| 107 | return true; |
| 108 | } |
| 109 | |
| 110 | Proxy_controller::Request_message::Request_message(): what(0), slot(-1),e(RIL_E_SUCCESS), is_rc_set(true),id(-1){ |
| 111 | |
| 112 | } |
| 113 | |
| 114 | void Proxy_controller::init() { |
| 115 | handle_thread = new Handle_thread(); |
| 116 | handle_thread->run(); |
| 117 | } |
| 118 | |
| 119 | Proxy_controller *Proxy_controller::getInstance() { |
| 120 | if (sInstance == NULL) { |
| 121 | sInstance = new Proxy_controller(); |
| 122 | sInstance->init(); |
| 123 | } |
| 124 | return sInstance; |
| 125 | } |
| 126 | |
| 127 | sp<Proxy_controller::Request_handler> Proxy_controller::sendMessage(sp<Request_message> msg, int delayms) { |
| 128 | RLOGD("sendMessage msg what=%d delayms=%d", msg->what, delayms); |
| 129 | // Create a handler to handle this message |
| 130 | sp<Request_handler> handler = new Request_handler(this); |
| 131 | handler->msg = msg; |
| 132 | // Sand message to looper |
| 133 | if(handle_thread.get()) { |
| 134 | sp<Looper> looper = handle_thread->getLooper(); |
| 135 | if(looper.get()) { |
| 136 | if (delayms > 0) { |
| 137 | looper->sendMessageDelayed(ms2ns(delayms),handler, handler->m_dummyMsg); |
| 138 | } else { |
| 139 | looper->sendMessage(handler, handler->m_dummyMsg); |
| 140 | } |
| 141 | } else { |
| 142 | RLOGD("looper"); |
| 143 | } |
| 144 | } else { |
| 145 | RLOGD("handle_thread"); |
| 146 | } |
| 147 | |
| 148 | return handler; |
| 149 | } |
| 150 | |
| 151 | void Proxy_controller::handle_request_resp(RIL_RadioCapability* cap, RIL_Errno e, int slot) { |
| 152 | if(m_eventId[slot] < 0) { |
| 153 | RLOGD("handle_request_resp cap is null.m_eventId[%d]=%d", slot, m_eventId[slot]); |
| 154 | return; |
| 155 | } |
| 156 | RLOGD("handle_request_resp what[%d]: %d , phase: %d", slot,m_eventId[slot], cap->phase); |
| 157 | // Create a request message |
| 158 | sp<Request_message> msg = new Request_message(); |
| 159 | msg->what = m_eventId[slot]; |
| 160 | if(cap != NULL) { |
| 161 | msg->cap = (*cap); |
| 162 | } else { |
| 163 | msg->is_rc_set = false; |
| 164 | RLOGD("handle_request_resp[slot%d]: cap is null", slot); |
| 165 | } |
| 166 | msg->e = e; |
| 167 | msg->slot = slot; |
| 168 | RLOGD("handle_request_resp logicalModemUuid: %s , phase: %d, rat: %d, session: %d, status: %d, version: %d", |
| 169 | msg->cap.logicalModemUuid, msg->cap.phase, msg->cap.rat, msg->cap.session, msg->cap.status, msg->cap.version); |
| 170 | sendMessage(msg, 0); |
| 171 | } |
| 172 | |
| 173 | void Proxy_controller::issueFinish(int sessionId) { |
| 174 | m_mutex.lock(); |
| 175 | for (int i = 0; i < SIM_COUNT; i++) { |
| 176 | RLOGD("issueFinish: phoneId=%d sessionId= %d mTransactionFailed=%d", i, sessionId, mTransactionFailed); |
| 177 | mRadioAccessFamilyStatusCounter++; |
| 178 | sendRadioCapabilityRequest( |
| 179 | i, |
| 180 | sessionId, |
| 181 | RadioCapabilityPhase(RC_PHASE_FINISH), |
| 182 | (mTransactionFailed ? mOldRadioAccessFamily[i] : |
| 183 | mNewRadioAccessFamily[i]), |
| 184 | (mTransactionFailed ? mCurrentLogicalModemIds[i] : |
| 185 | mNewLogicalModemIds[i]), |
| 186 | (mTransactionFailed ? RadioCapabilityStatus(RC_STATUS_FAIL) : |
| 187 | RadioCapabilityStatus(RC_STATUS_SUCCESS)), |
| 188 | EVENT_FINISH_RC_RESPONSE); |
| 189 | if (mTransactionFailed) { |
| 190 | RLOGD("issueFinish: phoneId: %d status: FAIL", i); |
| 191 | // At least one failed, mark them all failed. |
| 192 | mSetRadioAccessFamilyStatus[i] = SET_RC_STATUS_FAIL; |
| 193 | } |
| 194 | } |
| 195 | m_mutex.unlock(); |
| 196 | } |
| 197 | |
| 198 | void Proxy_controller::onStartRadioCapabilityResponse(sp<Request_message> msg) { |
| 199 | m_mutex.lock(); |
| 200 | |
| 201 | RIL_RadioCapability rc = msg->cap; |
| 202 | if ((rc.session != mRadioCapabilitySessionId.load())) { |
| 203 | RLOGD("onStartRadioCapabilityResponse: Ignore session=%d,rc.logicalModemUuid = %d, rc.phase = %d, rc.rat = %d, rc.session = %d, rc.status = %d, rc.version = %d", |
| 204 | mRadioCapabilitySessionId.load(), rc.logicalModemUuid,rc.phase,rc.rat,rc.session,rc.status,rc.version); |
| 205 | return; |
| 206 | } |
| 207 | mRadioAccessFamilyStatusCounter--; |
| 208 | int id = msg->slot; |
| 209 | if (msg->e != RIL_E_SUCCESS) { |
| 210 | RLOGD("onStartRadioCapabilityResponse: Error response session=%d", rc.session); |
| 211 | RLOGD("onStartRadioCapabilityResponse: phoneId=%d status=FAIL", id); |
| 212 | mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_FAIL; |
| 213 | mTransactionFailed = true; |
| 214 | } else { |
| 215 | RLOGD("onStartRadioCapabilityResponse: phoneId=%d status=STARTED", id); |
| 216 | mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_STARTED; |
| 217 | } |
| 218 | |
| 219 | if (mRadioAccessFamilyStatusCounter == 0) { |
| 220 | /** |
| 221 | std::set<std::string> modemsInUse; |
| 222 | for (auto modemId : mNewLogicalModemIds) { |
| 223 | if (!(modemsInUse.insert(modemId).second)) { |
| 224 | mTransactionFailed = true; |
| 225 | RLOGD("ERROR: sending down the same id for different phones"); |
| 226 | } |
| 227 | } |
| 228 | **/ |
| 229 | RLOGD("onStartRadioCapabilityResponse: success=%d", !mTransactionFailed); |
| 230 | if (mTransactionFailed) { |
| 231 | // Sends a variable number of requests, so don't resetRadioAccessFamilyCounter |
| 232 | // here. |
| 233 | m_mutex.unlock(); |
| 234 | issueFinish(mRadioCapabilitySessionId.load()); |
| 235 | return; |
| 236 | } else { |
| 237 | // All logical modem accepted the new radio access family, issue the APPLY |
| 238 | resetRadioAccessFamilyStatusCounter(); |
| 239 | for (int i = 0; i < SIM_COUNT; i++) { |
| 240 | sendRadioCapabilityRequest( |
| 241 | i, |
| 242 | mRadioCapabilitySessionId.load(), |
| 243 | RadioCapabilityPhase(RC_PHASE_APPLY), |
| 244 | mNewRadioAccessFamily[i], |
| 245 | mNewLogicalModemIds[i], |
| 246 | RadioCapabilityStatus(RC_STATUS_NONE), |
| 247 | EVENT_APPLY_RC_RESPONSE); |
| 248 | |
| 249 | RLOGD("onStartRadioCapabilityResponse: phoneId=%d status=APPLYING", i); |
| 250 | mSetRadioAccessFamilyStatus[i] = SET_RC_STATUS_APPLYING; |
| 251 | } |
| 252 | } |
| 253 | } |
| 254 | m_mutex.unlock(); |
| 255 | } |
| 256 | |
| 257 | void Proxy_controller::onApplyRadioCapabilityErrorHandler(sp<Request_message> msg){ |
| 258 | |
| 259 | } |
| 260 | void Proxy_controller::onApplyExceptionHandler(sp<Request_message> msg){ |
| 261 | |
| 262 | } |
| 263 | |
| 264 | void Proxy_controller::onApplyRadioCapabilityResponse(sp<Request_message> msg) { |
| 265 | RIL_RadioCapability rc = msg->cap; |
| 266 | if ((rc.session != mRadioCapabilitySessionId.load())) { |
| 267 | RLOGD("onApplyRadioCapabilityResponse: Ignore session=%d,rc.logicalModemUuid = %d, rc.phase = %d, rc.rat = %d, rc.session = %d, rc.status = %d, rc.version = %d", |
| 268 | mRadioCapabilitySessionId.load(), rc.logicalModemUuid,rc.phase,rc.rat,rc.session,rc.status,rc.version); |
| 269 | /// M: handle rc error, retry sim switch if possible. @{ |
| 270 | onApplyRadioCapabilityErrorHandler(msg); |
| 271 | /// @} |
| 272 | return; |
| 273 | } |
| 274 | RLOGD("onApplyRadioCapabilityResponse: rc.logicalModemUuid = %d, rc.phase = %d, rc.rat = %d, rc.session = %d, rc.status = %d, rc.version = %d", |
| 275 | mRadioCapabilitySessionId.load(), rc.logicalModemUuid,rc.phase,rc.rat,rc.session,rc.status,rc.version); |
| 276 | if (msg->e != RIL_E_SUCCESS) { |
| 277 | m_mutex.lock(); |
| 278 | RLOGD("onApplyRadioCapabilityResponse: Error response session=%d",rc.session); |
| 279 | int id = msg->slot; |
| 280 | /// M: handle exception, retry sim switch if possible. @{ |
| 281 | onApplyExceptionHandler(msg); |
| 282 | /// @} |
| 283 | RLOGD("onApplyRadioCapabilityResponse: phoneId=%d status=FAIL", id); |
| 284 | mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_FAIL; |
| 285 | mTransactionFailed = true; |
| 286 | m_mutex.unlock(); |
| 287 | } else { |
| 288 | RLOGD("onApplyRadioCapabilityResponse: Valid start expecting notification rc.logicalModemUuid = %d, rc.phase = %d, rc.rat = %d, rc.session = %d, rc.status = %d, rc.version = %d", |
| 289 | mRadioCapabilitySessionId.load(), rc.logicalModemUuid,rc.phase,rc.rat,rc.session,rc.status,rc.version); |
| 290 | } |
| 291 | } |
| 292 | |
| 293 | void Proxy_controller::handle_message_notify(RIL_RadioCapability* cap,int slot) { |
| 294 | sp<Request_message> msg = new Request_message(); |
| 295 | msg->what = EVENT_NOTIFICATION_RC_CHANGED; |
| 296 | if(cap != NULL) { |
| 297 | msg->cap = (*cap); |
| 298 | } else { |
| 299 | msg->is_rc_set = false; |
| 300 | RLOGD("handle_request_resp[slot%d]: cap is null", slot); |
| 301 | } |
| 302 | msg->slot = slot; |
| 303 | RLOGD("handle_request_resp logicalModemUuid: %s , phase: %d, rat: %d, session: %d, status: %d, version: %d", |
| 304 | msg->cap.logicalModemUuid, msg->cap.phase, msg->cap.rat, msg->cap.session, msg->cap.status, msg->cap.version); |
| 305 | sendMessage(msg, 0); |
| 306 | } |
| 307 | |
| 308 | void Proxy_controller::onNotificationRadioCapabilityChanged(sp<Request_message> msg) { |
| 309 | RIL_RadioCapability rc = msg->cap; |
| 310 | if (msg->is_rc_set == false || (rc.session != mRadioCapabilitySessionId.load())) { |
| 311 | RLOGD("onNotificationRadioCapabilityChanged: Ignore session=%d,rc.logicalModemUuid = %d, rc.phase = %d, rc.rat = %d, rc.session = %d, rc.status = %d, rc.version = %d", |
| 312 | mRadioCapabilitySessionId.load(), rc.logicalModemUuid,rc.phase,rc.rat,rc.session,rc.status,rc.version); |
| 313 | return; |
| 314 | } |
| 315 | m_mutex.lock(); |
| 316 | RLOGD("onNotificationRadioCapabilityChanged: rc.logicalModemUuid = %d, rc.phase = %d, rc.rat = %d, rc.session = %d, rc.status = %d, rc.version = %d", |
| 317 | rc.logicalModemUuid,rc.phase,rc.rat,rc.session,rc.status,rc.version); |
| 318 | |
| 319 | int id = msg->slot; |
| 320 | if (msg-> e != RIL_E_SUCCESS || |
| 321 | (rc.status == RadioCapabilityStatus(RC_STATUS_FAIL))) { |
| 322 | RLOGD("onNotificationRadioCapabilityChanged: phoneId=%d status=FAIL", id); |
| 323 | mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_FAIL; |
| 324 | mTransactionFailed = true; |
| 325 | } else { |
| 326 | RLOGD("onNotificationRadioCapabilityChanged: phoneId=%d status=SUCCESS(%d)", id, !mTransactionFailed); |
| 327 | mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_SUCCESS; |
| 328 | // The modems may have been restarted and forgotten this |
| 329 | |
| 330 | RequestInfo *info = creatRILInfoAndInit(RIL_REQUEST_ALLOW_DATA, OTHER, (RIL_SOCKET_ID)id); |
| 331 | |
| 332 | int switch_id = get_default_sim_data_for_switch(); |
| 333 | RLOGD("onNotificationRadioCapabilityChanged: phoneId=%d switch_id=%d", id, switch_id); |
| 334 | char* argv[2] = {"RIL_REQUEST_ALLOW_DATA","0"}; |
| 335 | if(id == switch_id) { |
| 336 | argv[1] = "1"; |
| 337 | } |
| 338 | setDataAllowed(2, argv, RIL_SOCKET_ID(id), info); |
| 339 | } |
| 340 | |
| 341 | mRadioAccessFamilyStatusCounter--; |
| 342 | if (mRadioAccessFamilyStatusCounter == 0) { |
| 343 | RLOGD("onNotificationRadioCapabilityChanged: APPLY URC success=%d",!mTransactionFailed); |
| 344 | m_mutex.unlock(); |
| 345 | issueFinish(mRadioCapabilitySessionId.load()); |
| 346 | return; |
| 347 | } |
| 348 | m_mutex.unlock(); |
| 349 | } |
| 350 | |
| 351 | void Proxy_controller::completeRadioCapabilityTransaction() { |
| 352 | RLOGD("completeRadioCapabilityTransaction: success=%d" , !mTransactionFailed); |
| 353 | if (!mTransactionFailed) { |
| 354 | |
| 355 | |
| 356 | // make messages about the old transaction obsolete (specifically the timeout) |
| 357 | //mRadioCapabilitySessionId++; |
| 358 | |
| 359 | // Reinitialize |
| 360 | clearTransaction(); |
| 361 | android::emResultNotify("default data slot switch success\n"); |
| 362 | } else { |
| 363 | android::emResultNotify("default data slot switch fail, now retry\n"); |
| 364 | // now revert. |
| 365 | mTransactionFailed = false; |
| 366 | std::vector<RIL_RadioAccessFamily> rafs = {RAF_UNKNOWN, RAF_UNKNOWN}; |
| 367 | for (int phoneId = 0; phoneId < SIM_COUNT; phoneId++) { |
| 368 | rafs[phoneId] = (RIL_RadioAccessFamily)mOldRadioAccessFamily[phoneId]; |
| 369 | } |
| 370 | doSetRadioCapabilities(rafs); |
| 371 | } |
| 372 | |
| 373 | } |
| 374 | |
| 375 | void Proxy_controller::onFinishRadioCapabilityResponse(sp<Request_message> msg){ |
| 376 | RIL_RadioCapability rc = msg->cap;; |
| 377 | if (msg->is_rc_set == false || (rc.session != mRadioCapabilitySessionId.load())) { |
| 378 | RLOGD("onFinishRadioCapabilityResponse: Ignore session=%d,rc.logicalModemUuid = %d, rc.phase = %d, rc.rat = %d, rc.session = %d, rc.status = %d, rc.version = %d", |
| 379 | mRadioCapabilitySessionId.load(), rc.logicalModemUuid,rc.phase,rc.rat,rc.session,rc.status,rc.version); |
| 380 | return; |
| 381 | } |
| 382 | m_mutex.lock(); |
| 383 | RLOGD("onFinishRadioCapabilityResponse mRadioAccessFamilyStatusCounter=%d",mRadioAccessFamilyStatusCounter); |
| 384 | mRadioAccessFamilyStatusCounter--; |
| 385 | if (mRadioAccessFamilyStatusCounter == 0) { |
| 386 | m_mutex.unlock(); |
| 387 | completeRadioCapabilityTransaction(); |
| 388 | return; |
| 389 | } |
| 390 | m_mutex.unlock(); |
| 391 | } |
| 392 | |
| 393 | void Proxy_controller::onTimeoutRadioCapability(sp<Request_message> msg){ |
| 394 | if (msg->id != mRadioCapabilitySessionId.load()) { |
| 395 | RLOGD("RadioCapability timeout: Ignore msg->id=%d != mRadioCapabilitySessionId.load()=%d", msg->id,mRadioCapabilitySessionId.load()); |
| 396 | return; |
| 397 | } |
| 398 | |
| 399 | m_mutex.lock(); |
| 400 | // timed-out. Clean up as best we can |
| 401 | for (int i = 0; i < SIM_COUNT; i++) { |
| 402 | RLOGD("RadioCapability timeout: mSetRadioAccessFamilyStatus[%d]=%d",i,mSetRadioAccessFamilyStatus[i]); |
| 403 | } |
| 404 | |
| 405 | // Increment the sessionId as we are completing the transaction below |
| 406 | // so we don't want it completed when the FINISH phase is done. |
| 407 | mRadioCapabilitySessionId++; |
| 408 | |
| 409 | // Reset the status counter as existing session failed |
| 410 | mRadioAccessFamilyStatusCounter = 0; |
| 411 | |
| 412 | // send FINISH request with fail status and then uniqueDifferentId |
| 413 | mTransactionFailed = true; |
| 414 | m_mutex.unlock(); |
| 415 | issueFinish(mRadioCapabilitySessionId.load()); |
| 416 | } |
| 417 | |
| 418 | void Proxy_controller::Request_handler::sendMessage(sp<Request_message> msg, int delayms) { |
| 419 | RLOGD("Proxy_controller::Request_handler, sendMessage msg what=%d delayms=%d", msg->what, delayms); |
| 420 | // Sand message to looper |
| 421 | this->msg = msg; |
| 422 | if (delayms > 0) { |
| 423 | proxy_controller->handle_thread->getLooper()->sendMessageDelayed(ms2ns(delayms), |
| 424 | this, this->m_dummyMsg); |
| 425 | } else { |
| 426 | proxy_controller->handle_thread->getLooper()->sendMessage(this, this->m_dummyMsg); |
| 427 | } |
| 428 | return ; |
| 429 | } |
| 430 | |
| 431 | void Proxy_controller::Request_handler::handleMessage(const Message& message) { |
| 432 | |
| 433 | RLOGD("handleMessage msg->what: %d", msg->what); |
| 434 | switch( msg->what){ |
| 435 | case EVENT_START_RC_RESPONSE: |
| 436 | { |
| 437 | proxy_controller->onStartRadioCapabilityResponse(msg); |
| 438 | break; |
| 439 | } |
| 440 | case EVENT_APPLY_RC_RESPONSE: |
| 441 | { |
| 442 | proxy_controller->onApplyRadioCapabilityResponse(msg); |
| 443 | break; |
| 444 | } |
| 445 | case EVENT_NOTIFICATION_RC_CHANGED: |
| 446 | { |
| 447 | proxy_controller->onNotificationRadioCapabilityChanged(msg); |
| 448 | break; |
| 449 | } |
| 450 | case EVENT_FINISH_RC_RESPONSE: |
| 451 | { |
| 452 | proxy_controller->onFinishRadioCapabilityResponse(msg); |
| 453 | break; |
| 454 | } |
| 455 | case EVENT_TIMEOUT: |
| 456 | { |
| 457 | proxy_controller->onTimeoutRadioCapability(msg); |
| 458 | break; |
| 459 | } |
| 460 | default: |
| 461 | break; |
| 462 | } |
| 463 | } |
| 464 | |
| 465 | void Proxy_controller::clearTransaction() { |
| 466 | RLOGD("clearTransaction"); |
| 467 | m_mutex.lock(); |
| 468 | mSetRadioAccessFamilyStatus.clear(); |
| 469 | mOldRadioAccessFamily.clear(); |
| 470 | mNewRadioAccessFamily.clear(); |
| 471 | m_eventId.clear(); |
| 472 | mCurrentLogicalModemIds.clear(); |
| 473 | mNewLogicalModemIds.clear(); |
| 474 | for (int i = 0; i < 2; i++) { |
| 475 | RLOGD("clearTransaction: phoneId=%d status=IDLE",i); |
| 476 | mSetRadioAccessFamilyStatus.push_back(SET_RC_STATUS_IDLE); |
| 477 | mOldRadioAccessFamily.push_back(0); |
| 478 | mNewRadioAccessFamily.push_back(0); |
| 479 | mCurrentLogicalModemIds.push_back(""); |
| 480 | mNewLogicalModemIds.push_back(""); |
| 481 | mTransactionFailed = false; |
| 482 | m_eventId.push_back(-1); |
| 483 | } |
| 484 | if(handle_thread.get()) { |
| 485 | sp<Looper> looper = handle_thread->getLooper(); |
| 486 | if(looper.get()) { |
| 487 | if(timeout_handle.get()) { |
| 488 | looper->removeMessages(timeout_handle); |
| 489 | } else { |
| 490 | RLOGD("clearTransaction,timeout_handle"); |
| 491 | } |
| 492 | } else { |
| 493 | RLOGD("clearTransaction,looper"); |
| 494 | } |
| 495 | } else { |
| 496 | RLOGD("clearTransaction,handle_thread"); |
| 497 | } |
| 498 | m_mutex.unlock(); |
| 499 | } |
| 500 | |
| 501 | int Proxy_controller::checkRadioCapabilitySwitchConditions(std::vector<RIL_RadioAccessFamily> rafs) { |
| 502 | m_mutex.lock(); |
| 503 | mNextRafs = rafs; |
| 504 | |
| 505 | // check if still switching |
| 506 | if (mIsCapSwitching == true) { |
| 507 | //throw new RuntimeException("is still switching"); |
| 508 | RLOGD("keep it and return,because capability swithing"); |
| 509 | mSetRafRetryCause = RC_RETRY_CAUSE_CAPABILITY_SWITCHING; |
| 510 | return RC_NO_NEED_SWITCH; |
| 511 | } else if (mSetRafRetryCause == RC_RETRY_CAUSE_CAPABILITY_SWITCHING) { |
| 512 | RLOGD("setCapability, mIsCapSwitching is not switching, can switch"); |
| 513 | mSetRafRetryCause = RC_RETRY_CAUSE_NONE; |
| 514 | } |
| 515 | mIsCapSwitching = true; |
| 516 | m_mutex.lock(); |
| 517 | |
| 518 | // check if capability switch disabled |
| 519 | if (utils::mtk_property_get_bool("ro.vendor.mtk_disable_cap_switch", false) == true) { |
| 520 | mNextRafs.clear(); |
| 521 | completeRadioCapabilityTransaction(); |
| 522 | RLOGD("skip switching because mtk_disable_cap_switch is true"); |
| 523 | return RC_NO_NEED_SWITCH; |
| 524 | } |
| 525 | // check FTA mode |
| 526 | if (utils::mtk_property_get_int32("vendor.gsm.gcf.testmode", 0) == 2) { |
| 527 | mNextRafs.clear(); |
| 528 | completeRadioCapabilityTransaction(); |
| 529 | RLOGD("skip switching because FTA mode"); |
| 530 | return RC_NO_NEED_SWITCH; |
| 531 | } |
| 532 | // check EM disable mode |
| 533 | if (utils::mtk_property_get_int32("persist.vendor.radio.simswitch.emmode", 1) == 0) { |
| 534 | mNextRafs.clear(); |
| 535 | completeRadioCapabilityTransaction(); |
| 536 | RLOGD("skip switching because EM disable mode"); |
| 537 | return RC_NO_NEED_SWITCH; |
| 538 | } |
| 539 | |
| 540 | // check world mode switching |
| 541 | if (WorldPhoneUtil::isWorldPhoneSupport()) { |
| 542 | if (!WorldPhoneUtil::isWorldModeSupport()) { |
| 543 | if (/*ModemSwitchHandler.isModemTypeSwitching()*/!isRadioAvailable((RIL_SOCKET_ID)Radio_capability_switch_util::get_main_capability_phone_id())) { |
| 544 | RLOGD("world mode switching."); |
| 545 | if (!mHasRegisterWorldModeReceiver) { |
| 546 | mHasRegisterWorldModeReceiver = true; |
| 547 | } |
| 548 | mSetRafRetryCause = RC_RETRY_CAUSE_WORLD_MODE_SWITCHING; |
| 549 | m_mutex.lock(); |
| 550 | mIsCapSwitching = false; |
| 551 | m_mutex.unlock(); |
| 552 | return RC_CANNOT_SWITCH; |
| 553 | } |
| 554 | } else if (mSetRafRetryCause == RC_RETRY_CAUSE_WORLD_MODE_SWITCHING) { |
| 555 | if (mHasRegisterWorldModeReceiver) { |
| 556 | mHasRegisterWorldModeReceiver = false; |
| 557 | mSetRafRetryCause = RC_RETRY_CAUSE_NONE; |
| 558 | } |
| 559 | } |
| 560 | } |
| 561 | |
| 562 | // check call state |
| 563 | if (!(is_call_state_idle(0) || is_call_state_idle(1))) { |
| 564 | //throw new RuntimeException("in call, fail to set RAT for phones"); |
| 565 | RLOGD("setCapability in calling, fail to set RAT for phones"); |
| 566 | if (!mHasRegisterPhoneStateReceiver) { |
| 567 | mHasRegisterPhoneStateReceiver = true; |
| 568 | } |
| 569 | mSetRafRetryCause = RC_RETRY_CAUSE_IN_CALL; |
| 570 | m_mutex.lock(); |
| 571 | mIsCapSwitching = false; |
| 572 | m_mutex.unlock(); |
| 573 | return RC_CANNOT_SWITCH; |
| 574 | } else if (isEccInProgress()) { |
| 575 | RLOGD("setCapability in ECC, fail to set RAT for phones"); |
| 576 | if (!mHasRegisterEccStateReceiver) { |
| 577 | mHasRegisterEccStateReceiver = true; |
| 578 | } |
| 579 | mSetRafRetryCause = RC_RETRY_CAUSE_IN_CALL; |
| 580 | m_mutex.lock(); |
| 581 | mIsCapSwitching = false; |
| 582 | m_mutex.unlock(); |
| 583 | return RC_CANNOT_SWITCH; |
| 584 | } else if (mSetRafRetryCause == RC_RETRY_CAUSE_IN_CALL) { |
| 585 | if (mHasRegisterPhoneStateReceiver) { |
| 586 | mHasRegisterPhoneStateReceiver = false; |
| 587 | mSetRafRetryCause = RC_RETRY_CAUSE_NONE; |
| 588 | } |
| 589 | if (mHasRegisterEccStateReceiver) { |
| 590 | mHasRegisterEccStateReceiver = false; |
| 591 | mSetRafRetryCause = RC_RETRY_CAUSE_NONE; |
| 592 | } |
| 593 | } |
| 594 | |
| 595 | // check radio available |
| 596 | for (int i = 0; i < SIM_COUNT; i++) { |
| 597 | if (!isRadioAvailable((RIL_SOCKET_ID)i)) { |
| 598 | //throw new RuntimeException("Phone" + i + " is not available"); |
| 599 | mSetRafRetryCause = RC_RETRY_CAUSE_RADIO_UNAVAILABLE; |
| 600 | //mCi[i].registerForAvailable(mMtkHandler, EVENT_RADIO_AVAILABLE, null); |
| 601 | RLOGD("setCapability fail,Phone%d is not available", i); |
| 602 | m_mutex.lock(); |
| 603 | mIsCapSwitching = false; |
| 604 | m_mutex.unlock(); |
| 605 | return RC_CANNOT_SWITCH; |
| 606 | } else if (mSetRafRetryCause == RC_RETRY_CAUSE_RADIO_UNAVAILABLE) { |
| 607 | //mCi[i].unregisterForAvailable(mMtkHandler); |
| 608 | if (i == SIM_COUNT - 1) { |
| 609 | mSetRafRetryCause = RC_RETRY_CAUSE_NONE; |
| 610 | } |
| 611 | } |
| 612 | } |
| 613 | |
| 614 | int switchStatus = utils::mtk_property_get_int32(PROPERTY_CAPABILITY_SWITCH.c_str(), 1); |
| 615 | // check parameter |
| 616 | bool bIsboth3G = false; |
| 617 | bool bIsMajorPhone = false; |
| 618 | int newMajorPhoneId = 0; |
| 619 | for (int i = 0; i < rafs.size(); i++) { |
| 620 | bIsMajorPhone = false; |
| 621 | if ((rafs[i] & RIL_RadioAccessFamily::RAF_GPRS) > 0) { |
| 622 | bIsMajorPhone = true; |
| 623 | } |
| 624 | |
| 625 | if (bIsMajorPhone) { |
| 626 | newMajorPhoneId = i; |
| 627 | if (newMajorPhoneId == (switchStatus - 1)) { |
| 628 | RLOGD("no change, skip setRadioCapability"); |
| 629 | mSetRafRetryCause = RC_RETRY_CAUSE_NONE; |
| 630 | mNextRafs.clear(); |
| 631 | completeRadioCapabilityTransaction(); |
| 632 | return RC_NO_NEED_SWITCH; |
| 633 | } |
| 634 | if (bIsboth3G) { |
| 635 | RLOGD("set more than one 3G phone, fail"); |
| 636 | m_mutex.lock(); |
| 637 | mIsCapSwitching = false; |
| 638 | m_mutex.unlock(); |
| 639 | throw std::runtime_error("input parameter is incorrect"); |
| 640 | } else { |
| 641 | bIsboth3G = true; |
| 642 | } |
| 643 | } |
| 644 | } |
| 645 | if (bIsboth3G == false) { |
| 646 | m_mutex.lock(); |
| 647 | mIsCapSwitching = false; |
| 648 | m_mutex.unlock(); |
| 649 | throw std::runtime_error("input parameter is incorrect - no 3g phone"); |
| 650 | } |
| 651 | |
| 652 | // check operator spec |
| 653 | if (!isNeedSimSwitch(newMajorPhoneId, SIM_COUNT)) { |
| 654 | RLOGD("check sim card type and skip setRadioCapability"); |
| 655 | mSetRafRetryCause = RC_RETRY_CAUSE_NONE; |
| 656 | mNextRafs.clear(); |
| 657 | completeRadioCapabilityTransaction(); |
| 658 | return RC_NO_NEED_SWITCH; |
| 659 | } |
| 660 | |
| 661 | // if (!WorldPhoneUtil::isWorldModeSupport() && WorldPhoneUtil::isWorldPhoneSupport()) { |
| 662 | // WorldPhoneUtil.getWorldPhone().notifyRadioCapabilityChange(newMajorPhoneId); |
| 663 | // } |
| 664 | RLOGD("checkRadioCapabilitySwitchConditions, do switch"); |
| 665 | return RC_DO_SWITCH; |
| 666 | } |
| 667 | |
| 668 | bool Proxy_controller::isEccInProgress() { |
| 669 | bool inEcm = utils::mtk_property_get_bool("ril.cdma.inecmmode", false); |
| 670 | return inEcm; |
| 671 | } |
| 672 | |
| 673 | bool Proxy_controller::isNeedSimSwitch(int majorPhoneId, int phoneNum) { |
| 674 | RLOGD("OMisNeedSimSwitch, majorPhoneId = %d ", majorPhoneId); |
| 675 | return !Radio_capability_switch_util::isSkipCapabilitySwitch(majorPhoneId, phoneNum); |
| 676 | } |
| 677 | |
| 678 | bool Proxy_controller::set_Radio_Capability(std::vector<RIL_RadioAccessFamily> rafs) { |
| 679 | if (rafs.size() != SIM_COUNT) { |
| 680 | RLOGD("Length of input rafs must equal to total phone count"); |
| 681 | } |
| 682 | // Check if there is any ongoing transaction and throw an exception if there |
| 683 | // is one as this is a programming error. |
| 684 | m_mutex.lock(); |
| 685 | for (int i = 0; i < rafs.size(); i++) { |
| 686 | if (mSetRadioAccessFamilyStatus[i] != SET_RC_STATUS_IDLE) { |
| 687 | // TODO: The right behaviour is to cancel previous request and send this. |
| 688 | RLOGE("setRadioCapability: Phone[%d] is not idle. Rejecting request.", i); |
| 689 | return false; |
| 690 | } |
| 691 | } |
| 692 | m_mutex.unlock(); |
| 693 | |
| 694 | // Clear to be sure we're in the initial state |
| 695 | clearTransaction(); |
| 696 | |
| 697 | return doSetRadioCapabilities(rafs); |
| 698 | } |
| 699 | |
| 700 | void Proxy_controller::resetRadioAccessFamilyStatusCounter() { |
| 701 | mRadioAccessFamilyStatusCounter = SIM_COUNT; |
| 702 | } |
| 703 | |
| 704 | std::string Proxy_controller::getLogicalModemIdFromRaf(int raf) { |
| 705 | std::string modemUui; |
| 706 | |
| 707 | for (int phoneId = 0; phoneId < SIM_COUNT; phoneId++) { |
| 708 | if (get_radio_capa(phoneId).rat == raf) { |
| 709 | modemUui = get_radio_capa(phoneId).logicalModemUuid; |
| 710 | break; |
| 711 | } |
| 712 | } |
| 713 | return modemUui; |
| 714 | } |
| 715 | |
| 716 | void Proxy_controller::sendRadioCapabilityRequest(int phoneId, int sessionId, int rcPhase, |
| 717 | int radioFamily, std::string logicalModemId, int status, int eventId){ |
| 718 | RequestInfo *info = creatRILInfoAndInit(RIL_REQUEST_SET_RADIO_CAPABILITY, OTHER, (RIL_SOCKET_ID)phoneId); |
| 719 | |
| 720 | char* argv[7] = {"RIL_REQUEST_SET_RADIO_CAPABILITY", |
| 721 | const_cast<char*>(std::to_string(RIL_RADIO_CAPABILITY_VERSION).c_str()), |
| 722 | const_cast<char*>(std::to_string(sessionId).c_str()), |
| 723 | const_cast<char*>(std::to_string(rcPhase).c_str()), |
| 724 | const_cast<char*>(std::to_string(radioFamily).c_str()), |
| 725 | const_cast<char*>(logicalModemId.c_str()), |
| 726 | const_cast<char*>(std::to_string(status).c_str()) |
| 727 | }; |
| 728 | setRadioCapability(7, argv,(RIL_SOCKET_ID)phoneId, info); |
| 729 | m_eventId[phoneId] = eventId; |
| 730 | } |
| 731 | |
| 732 | bool Proxy_controller::doSetRadioCapabilities(std::vector<RIL_RadioAccessFamily> rafs) { |
| 733 | // A new sessionId for this transaction |
| 734 | mRadioCapabilitySessionId++; |
| 735 | // Start timer to make sure all phones respond within a specific time interval. |
| 736 | // Will send FINISH if a timeout occurs. |
| 737 | sp<Request_message> msg = new Request_message(); |
| 738 | msg->what = EVENT_TIMEOUT; |
| 739 | msg->id = mRadioCapabilitySessionId.load(); |
| 740 | timeout_handle = sendMessage(msg, SET_RC_TIMEOUT_WAITING_MSEC); |
| 741 | |
| 742 | m_mutex.lock(); |
| 743 | RLOGD("setRadioCapability: new request session id=%d", mRadioCapabilitySessionId.load()); |
| 744 | resetRadioAccessFamilyStatusCounter(); |
| 745 | for (int i = 0; i < rafs.size(); i++) { |
| 746 | RLOGD("setRadioCapability: phoneId=%d status=STARTING", i); |
| 747 | mSetRadioAccessFamilyStatus[i] = SET_RC_STATUS_STARTING; |
| 748 | mOldRadioAccessFamily[i] = get_radio_capa(i).rat; |
| 749 | int requestedRaf = rafs[i]; |
| 750 | // TODO Set the new radio access family to the maximum of the requested & supported |
| 751 | // int supportedRaf = mPhones[i].getRadioAccessFamily(); |
| 752 | // mNewRadioAccessFamily[i] = requestedRaf & supportedRaf; |
| 753 | mNewRadioAccessFamily[i] = requestedRaf; |
| 754 | |
| 755 | mCurrentLogicalModemIds[i] = get_radio_capa(i).logicalModemUuid; |
| 756 | // get the logical mode corresponds to new raf requested and pass the |
| 757 | // same as part of SET_RADIO_CAP APPLY phase |
| 758 | mNewLogicalModemIds[i] = getLogicalModemIdFromRaf(requestedRaf); |
| 759 | RLOGD("setRadioCapability: mOldRadioAccessFamily[%d]=%d", i,mOldRadioAccessFamily[i]); |
| 760 | RLOGD("setRadioCapability: mNewRadioAccessFamily[%d]=%d", i,mNewRadioAccessFamily[i]); |
| 761 | sendRadioCapabilityRequest( |
| 762 | i, |
| 763 | mRadioCapabilitySessionId.load(), |
| 764 | RadioCapabilityPhase(RC_PHASE_START), |
| 765 | mOldRadioAccessFamily[i], |
| 766 | mCurrentLogicalModemIds[i], |
| 767 | RadioCapabilityStatus(RC_STATUS_NONE), |
| 768 | EVENT_START_RC_RESPONSE); |
| 769 | } |
| 770 | m_mutex.unlock(); |
| 771 | return true; |
| 772 | } |