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 17package com.android.internal.telephony; 18 19import java.util.ArrayList; 20import java.util.Random; 21 22import android.content.Context; 23import android.content.Intent; 24import android.os.AsyncResult; 25import android.os.Handler; 26import android.os.Message; 27import android.os.PowerManager; 28import android.os.PowerManager.WakeLock; 29import android.telephony.RadioAccessFamily; 30import android.telephony.Rlog; 31import android.telephony.TelephonyManager; 32 33import com.android.internal.telephony.CommandsInterface; 34import com.android.internal.telephony.Phone; 35import com.android.internal.telephony.PhoneBase; 36import com.android.internal.telephony.PhoneProxy; 37import com.android.internal.telephony.dataconnection.DctController; 38import com.android.internal.telephony.RadioCapability; 39import com.android.internal.telephony.uicc.UiccController; 40import com.android.internal.telephony.TelephonyIntents; 41 42import java.io.FileDescriptor; 43import java.io.PrintWriter; 44import java.util.concurrent.atomic.AtomicInteger; 45 46public class ProxyController { 47 static final String LOG_TAG = "ProxyController"; 48 49 private static final int EVENT_NOTIFICATION_RC_CHANGED = 1; 50 private static final int EVENT_START_RC_RESPONSE = 2; 51 private static final int EVENT_APPLY_RC_RESPONSE = 3; 52 private static final int EVENT_FINISH_RC_RESPONSE = 4; 53 54 private static final int SET_RC_STATUS_IDLE = 0; 55 private static final int SET_RC_STATUS_STARTING = 1; 56 private static final int SET_RC_STATUS_STARTED = 2; 57 private static final int SET_RC_STATUS_APPLYING = 3; 58 private static final int SET_RC_STATUS_SUCCESS = 4; 59 private static final int SET_RC_STATUS_FAIL = 5; 60 61 // The entire transaction must complete within this amount of time 62 // or a FINISH will be issued to each Logical Modem with the old 63 // Radio Access Family. 64 private static final int SET_RC_TIMEOUT_WAITING_MSEC = (45 * 1000); 65 66 //***** Class Variables 67 private static ProxyController sProxyController; 68 69 private PhoneProxy[] mProxyPhones; 70 71 private UiccController mUiccController; 72 73 private CommandsInterface[] mCi; 74 75 private Context mContext; 76 77 private DctController mDctController; 78 79 //UiccPhoneBookController to use proper IccPhoneBookInterfaceManagerProxy object 80 private UiccPhoneBookController mUiccPhoneBookController; 81 82 //PhoneSubInfoController to use proper PhoneSubInfoProxy object 83 private PhoneSubInfoController mPhoneSubInfoController; 84 85 //UiccSmsController to use proper IccSmsInterfaceManager object 86 private UiccSmsController mUiccSmsController; 87 88 WakeLock mWakeLock; 89 90 // record each phone's set radio capability status 91 private int[] mSetRadioAccessFamilyStatus; 92 private int mRadioAccessFamilyStatusCounter; 93 94 private String[] mLogicalModemIds; 95 96 // Allows the generation of unique Id's for radio capability request session id 97 private AtomicInteger mUniqueIdGenerator = new AtomicInteger(new Random().nextInt()); 98 99 // on-going radio capability request session id 100 private int mRadioCapabilitySessionId; 101 102 // Record new and old Radio Access Family (raf) configuration. 103 // The old raf configuration is used to restore each logical modem raf when FINISH is 104 // issued if any requests fail. 105 private int[] mNewRadioAccessFamily; 106 private int[] mOldRadioAccessFamily; 107 108 // runnable for radio capability request timeout handling 109 RadioCapabilityRunnable mSetRadioCapabilityRunnable; 110 111 //***** Class Methods 112 public static ProxyController getInstance(Context context, PhoneProxy[] phoneProxy, 113 UiccController uiccController, CommandsInterface[] ci) { 114 if (sProxyController == null) { 115 sProxyController = new ProxyController(context, phoneProxy, uiccController, ci); 116 } 117 return sProxyController; 118 } 119 120 public static ProxyController getInstance() { 121 return sProxyController; 122 } 123 124 private ProxyController(Context context, PhoneProxy[] phoneProxy, UiccController uiccController, 125 CommandsInterface[] ci) { 126 logd("Constructor - Enter"); 127 128 mContext = context; 129 mProxyPhones = phoneProxy; 130 mUiccController = uiccController; 131 mCi = ci; 132 133 mDctController = DctController.makeDctController(phoneProxy); 134 mUiccPhoneBookController = new UiccPhoneBookController(mProxyPhones); 135 mPhoneSubInfoController = new PhoneSubInfoController(mProxyPhones); 136 mUiccSmsController = new UiccSmsController(mProxyPhones); 137 mSetRadioAccessFamilyStatus = new int[mProxyPhones.length]; 138 mNewRadioAccessFamily = new int[mProxyPhones.length]; 139 mOldRadioAccessFamily = new int[mProxyPhones.length]; 140 mLogicalModemIds = new String[mProxyPhones.length]; 141 142 // TODO Get logical modem ids assume its just the phoneId as a string for now 143 for (int i = 0; i < mProxyPhones.length; i++) { 144 mLogicalModemIds[i] = Integer.toString(i); 145 } 146 147 mSetRadioCapabilityRunnable = new RadioCapabilityRunnable(); 148 149 // wake lock for set radio capability 150 PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 151 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG); 152 mWakeLock.setReferenceCounted(false); 153 154 // Clear to be sure we're in the initial state 155 clearTransaction(); 156 for (int i = 0; i < mProxyPhones.length; i++) { 157 mProxyPhones[i].registerForRadioCapabilityChanged( 158 mHandler, EVENT_NOTIFICATION_RC_CHANGED, null); 159 } 160 logd("Constructor - Exit"); 161 } 162 163 public void updateDataConnectionTracker(int sub) { 164 mProxyPhones[sub].updateDataConnectionTracker(); 165 } 166 167 public void enableDataConnectivity(int sub) { 168 mProxyPhones[sub].setInternalDataEnabled(true); 169 } 170 171 public void disableDataConnectivity(int sub, 172 Message dataCleanedUpMsg) { 173 mProxyPhones[sub].setInternalDataEnabled(false, dataCleanedUpMsg); 174 } 175 176 public void updateCurrentCarrierInProvider(int sub) { 177 mProxyPhones[sub].updateCurrentCarrierInProvider(); 178 } 179 180 public void registerForAllDataDisconnected(int subId, Handler h, int what, Object obj) { 181 int phoneId = SubscriptionController.getInstance().getPhoneId(subId); 182 183 if (phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount()) { 184 mProxyPhones[phoneId].registerForAllDataDisconnected(h, what, obj); 185 } 186 } 187 188 public void unregisterForAllDataDisconnected(int subId, Handler h) { 189 int phoneId = SubscriptionController.getInstance().getPhoneId(subId); 190 191 if (phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount()) { 192 mProxyPhones[phoneId].unregisterForAllDataDisconnected(h); 193 } 194 } 195 196 public boolean isDataDisconnected(int subId) { 197 int phoneId = SubscriptionController.getInstance().getPhoneId(subId); 198 199 if (phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount()) { 200 Phone activePhone = mProxyPhones[phoneId].getActivePhone(); 201 return ((PhoneBase) activePhone).mDcTracker.isDisconnected(); 202 } else { 203 return false; 204 } 205 } 206 207 /** 208 * Get phone radio type and access technology. 209 * 210 * @param phoneId which phone you want to get 211 * @return phone radio type and access technology for input phone ID 212 */ 213 public int getRadioAccessFamily(int phoneId) { 214 if (phoneId >= mProxyPhones.length) { 215 return RadioAccessFamily.RAF_UNKNOWN; 216 } else { 217 return mProxyPhones[phoneId].getRadioAccessFamily(); 218 } 219 } 220 221 /** 222 * Set phone radio type and access technology for each phone. 223 * 224 * @param rafs an RadioAccessFamily array to indicate all phone's 225 * new radio access family. The length of RadioAccessFamily 226 * must equal to phone count. 227 * @return false if another session is already active and the request is rejected. 228 */ 229 public boolean setRadioCapability(RadioAccessFamily[] rafs) { 230 if (rafs.length != mProxyPhones.length) { 231 throw new RuntimeException("Length of input rafs must equal to total phone count"); 232 } 233 234 // Check if there is any ongoing transaction and throw an exception if there 235 // is one as this is a programming error. 236 synchronized (mSetRadioAccessFamilyStatus) { 237 for (int i = 0; i < mProxyPhones.length; i++) { 238 logd("setRadioCapability: mSetRadioAccessFamilyStatus[" + i + "]=" 239 + mSetRadioAccessFamilyStatus[i]); 240 if (mSetRadioAccessFamilyStatus[i] != SET_RC_STATUS_IDLE) { 241 // TODO: The right behaviour is to cancel previous request and send this. 242 loge("setRadioCapability: Phone[" + i + "] is not idle. Rejecting request."); 243 return false; 244 } 245 } 246 } 247 248 // Clear to be sure we're in the initial state 249 clearTransaction(); 250 251 // A new sessionId for this transaction 252 mRadioCapabilitySessionId = mUniqueIdGenerator.getAndIncrement(); 253 254 // Keep a wake lock until we finish radio capability changed 255 mWakeLock.acquire(); 256 257 // Start timer to make sure all phones respond within a specific time interval. 258 // Will send FINISH if a timeout occurs. 259 mSetRadioCapabilityRunnable.setTimeoutState(mRadioCapabilitySessionId); 260 mHandler.postDelayed(mSetRadioCapabilityRunnable, SET_RC_TIMEOUT_WAITING_MSEC); 261 262 synchronized (mSetRadioAccessFamilyStatus) { 263 logd("setRadioCapability: new request session id=" + mRadioCapabilitySessionId); 264 mRadioAccessFamilyStatusCounter = rafs.length; 265 for (int i = 0; i < rafs.length; i++) { 266 int phoneId = rafs[i].getPhoneId(); 267 logd("setRadioCapability: phoneId=" + phoneId + " status=STARTING"); 268 mSetRadioAccessFamilyStatus[phoneId] = SET_RC_STATUS_STARTING; 269 mOldRadioAccessFamily[phoneId] = mProxyPhones[phoneId].getRadioAccessFamily(); 270 int requestedRaf = rafs[i].getRadioAccessFamily(); 271 // TODO Set the new radio access family to the maximum of the requested & supported 272 // int supportedRaf = mProxyPhones[i].getSupportedRadioAccessFamily(); 273 // mNewRadioAccessFamily[phoneId] = requestedRaf & supportedRaf; 274 mNewRadioAccessFamily[phoneId] = requestedRaf; 275 logd("setRadioCapability: mOldRadioAccessFamily[" + phoneId + "]=" 276 + mOldRadioAccessFamily[phoneId]); 277 logd("setRadioCapability: mNewRadioAccessFamily[" + phoneId + "]=" 278 + mNewRadioAccessFamily[phoneId]); 279 sendRadioCapabilityRequest( 280 phoneId, 281 mRadioCapabilitySessionId, 282 RadioCapability.RC_PHASE_START, 283 mOldRadioAccessFamily[phoneId], 284 mLogicalModemIds[phoneId], 285 RadioCapability.RC_STATUS_NONE, 286 EVENT_START_RC_RESPONSE); 287 } 288 } 289 290 return true; 291 } 292 293 private Handler mHandler = new Handler() { 294 @Override 295 public void handleMessage(Message msg) { 296 logd("handleMessage msg.what=" + msg.what); 297 switch (msg.what) { 298 case EVENT_START_RC_RESPONSE: 299 onStartRadioCapabilityResponse(msg); 300 break; 301 302 case EVENT_APPLY_RC_RESPONSE: 303 onApplyRadioCapabilityResponse(msg); 304 break; 305 306 case EVENT_NOTIFICATION_RC_CHANGED: 307 onNotificationRadioCapabilityChanged(msg); 308 break; 309 310 case EVENT_FINISH_RC_RESPONSE: 311 onFinishRadioCapabilityResponse(msg); 312 break; 313 314 default: 315 break; 316 } 317 } 318 }; 319 320 /** 321 * Handle START response 322 * @param msg obj field isa RadioCapability 323 */ 324 private void onStartRadioCapabilityResponse(Message msg) { 325 synchronized (mSetRadioAccessFamilyStatus) { 326 RadioCapability rc = (RadioCapability) ((AsyncResult) msg.obj).result; 327 if ((rc == null) || (rc.getSession() != mRadioCapabilitySessionId)) { 328 logd("onStartRadioCapabilityResponse: Ignore session=" + mRadioCapabilitySessionId 329 + " rc=" + rc); 330 return; 331 } 332 mRadioAccessFamilyStatusCounter--; 333 int id = rc.getPhoneId(); 334 if (((AsyncResult) msg.obj).exception != null) { 335 logd("onStartRadioCapabilityResponse: Error response session=" + rc.getSession()); 336 logd("onStartRadioCapabilityResponse: phoneId=" + id + " status=FAIL"); 337 mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_FAIL; 338 } else { 339 logd("onStartRadioCapabilityResponse: phoneId=" + id + " status=STARTED"); 340 mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_STARTED; 341 } 342 343 if (mRadioAccessFamilyStatusCounter == 0) { 344 resetRadioAccessFamilyStatusCounter(); 345 boolean success = checkAllRadioCapabilitySuccess(); 346 logd("onStartRadioCapabilityResponse: success=" + success); 347 if (!success) { 348 issueFinish(RadioCapability.RC_STATUS_FAIL, 349 mRadioCapabilitySessionId); 350 } else { 351 // All logical modem accepted the new radio access family, issue the APPLY 352 for (int i = 0; i < mProxyPhones.length; i++) { 353 sendRadioCapabilityRequest( 354 i, 355 mRadioCapabilitySessionId, 356 RadioCapability.RC_PHASE_APPLY, 357 mNewRadioAccessFamily[i], 358 mLogicalModemIds[i], 359 RadioCapability.RC_STATUS_NONE, 360 EVENT_APPLY_RC_RESPONSE); 361 362 logd("onStartRadioCapabilityResponse: phoneId=" + i + " status=APPLYING"); 363 mSetRadioAccessFamilyStatus[i] = SET_RC_STATUS_APPLYING; 364 } 365 } 366 } 367 } 368 } 369 370 /** 371 * Handle APPLY response 372 * @param msg obj field isa RadioCapability 373 */ 374 private void onApplyRadioCapabilityResponse(Message msg) { 375 RadioCapability rc = (RadioCapability) ((AsyncResult) msg.obj).result; 376 if ((rc == null) || (rc.getSession() != mRadioCapabilitySessionId)) { 377 logd("onApplyRadioCapabilityResponse: Ignore session=" + mRadioCapabilitySessionId 378 + " rc=" + rc); 379 return; 380 } 381 logd("onApplyRadioCapabilityResponse: rc=" + rc); 382 if (((AsyncResult) msg.obj).exception != null) { 383 synchronized (mSetRadioAccessFamilyStatus) { 384 logd("onApplyRadioCapabilityResponse: Error response session=" + rc.getSession()); 385 int id = rc.getPhoneId(); 386 logd("onApplyRadioCapabilityResponse: phoneId=" + id + " status=FAIL"); 387 mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_FAIL; 388 } 389 } else { 390 logd("onApplyRadioCapabilityResponse: Valid start expecting notification rc=" + rc); 391 } 392 } 393 394 /** 395 * Handle the notification unsolicited response associated with the APPLY 396 * @param msg obj field isa RadioCapability 397 */ 398 private void onNotificationRadioCapabilityChanged(Message msg) { 399 RadioCapability rc = (RadioCapability) ((AsyncResult) msg.obj).result; 400 if ((rc == null) || (rc.getSession() != mRadioCapabilitySessionId)) { 401 logd("onNotificationRadioCapabilityChanged: Ignore session=" + mRadioCapabilitySessionId 402 + " rc=" + rc); 403 return; 404 } 405 synchronized (mSetRadioAccessFamilyStatus) { 406 logd("onNotificationRadioCapabilityChanged: rc=" + rc); 407 // skip the overdue response by checking sessionId 408 if (rc.getSession() != mRadioCapabilitySessionId) { 409 logd("onNotificationRadioCapabilityChanged: Ignore session=" 410 + mRadioCapabilitySessionId + " rc=" + rc); 411 return; 412 } 413 414 int id = rc.getPhoneId(); 415 if ((((AsyncResult) msg.obj).exception != null) || 416 (rc.getStatus() == RadioCapability.RC_STATUS_FAIL)) { 417 logd("onNotificationRadioCapabilityChanged: phoneId=" + id + " status=FAIL"); 418 mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_FAIL; 419 } else { 420 logd("onNotificationRadioCapabilityChanged: phoneId=" + id + " status=SUCCESS"); 421 mSetRadioAccessFamilyStatus[id] = SET_RC_STATUS_SUCCESS; 422 } 423 424 mRadioAccessFamilyStatusCounter--; 425 if (mRadioAccessFamilyStatusCounter == 0) { 426 logd("onNotificationRadioCapabilityChanged: removing callback from handler"); 427 mHandler.removeCallbacks(mSetRadioCapabilityRunnable); 428 resetRadioAccessFamilyStatusCounter(); 429 boolean success = checkAllRadioCapabilitySuccess(); 430 logd("onNotificationRadioCapabilityChanged: APPLY URC success=" + success); 431 int status; 432 if (success) { 433 status = RadioCapability.RC_STATUS_SUCCESS; 434 } else { 435 status = RadioCapability.RC_STATUS_FAIL; 436 } 437 issueFinish(status, mRadioCapabilitySessionId); 438 } 439 } 440 } 441 442 /** 443 * Handle the FINISH Phase response 444 * @param msg obj field isa RadioCapability 445 */ 446 void onFinishRadioCapabilityResponse(Message msg) { 447 RadioCapability rc = (RadioCapability) ((AsyncResult) msg.obj).result; 448 if ((rc == null) || (rc.getSession() != mRadioCapabilitySessionId)) { 449 logd("onFinishRadioCapabilityResponse: Ignore session=" + mRadioCapabilitySessionId 450 + " rc=" + rc); 451 return; 452 } 453 synchronized (mSetRadioAccessFamilyStatus) { 454 logd(" onFinishRadioCapabilityResponse mRadioAccessFamilyStatusCounter=" 455 + mRadioAccessFamilyStatusCounter); 456 mRadioAccessFamilyStatusCounter--; 457 if (mRadioAccessFamilyStatusCounter == 0) { 458 completeRadioCapabilityTransaction(); 459 } 460 } 461 } 462 463 private void issueFinish(int status, int sessionId) { 464 // Issue FINISH 465 synchronized(mSetRadioAccessFamilyStatus) { 466 for (int i = 0; i < mProxyPhones.length; i++) { 467 if (mSetRadioAccessFamilyStatus[i] != SET_RC_STATUS_FAIL) { 468 logd("issueFinish: phoneId=" + i + " sessionId=" + sessionId 469 + " status=" + status); 470 sendRadioCapabilityRequest( 471 i, 472 sessionId, 473 RadioCapability.RC_PHASE_FINISH, 474 mOldRadioAccessFamily[i], 475 mLogicalModemIds[i], 476 status, 477 EVENT_FINISH_RC_RESPONSE); 478 if (status == RadioCapability.RC_STATUS_FAIL) { 479 logd("issueFinish: phoneId: " + i + " status: FAIL"); 480 // At least one failed, mark them all failed. 481 mSetRadioAccessFamilyStatus[i] = SET_RC_STATUS_FAIL; 482 } 483 } else { 484 logd("issueFinish: Ignore already FAIL, Phone" + i + " sessionId=" + sessionId 485 + " status=" + status); 486 } 487 } 488 } 489 } 490 491 private void completeRadioCapabilityTransaction() { 492 // Create the intent to broadcast 493 Intent intent; 494 boolean success = checkAllRadioCapabilitySuccess(); 495 logd("onFinishRadioCapabilityResponse: success=" + success); 496 if (success) { 497 ArrayList<RadioAccessFamily> phoneRAFList = new ArrayList<RadioAccessFamily>(); 498 for (int i = 0; i < mProxyPhones.length; i++) { 499 int raf = mProxyPhones[i].getRadioAccessFamily(); 500 logd("radioAccessFamily[" + i + "]=" + raf); 501 RadioAccessFamily phoneRC = new RadioAccessFamily(i, raf); 502 phoneRAFList.add(phoneRC); 503 } 504 intent = new Intent(TelephonyIntents.ACTION_SET_RADIO_CAPABILITY_DONE); 505 intent.putParcelableArrayListExtra(TelephonyIntents.EXTRA_RADIO_ACCESS_FAMILY, 506 phoneRAFList); 507 } else { 508 intent = new Intent(TelephonyIntents.ACTION_SET_RADIO_CAPABILITY_FAILED); 509 } 510 511 // Reinitialize 512 clearTransaction(); 513 514 // Broadcast that we're done 515 mContext.sendBroadcast(intent); 516 } 517 518 // Clear this transaction 519 private void clearTransaction() { 520 logd("clearTransaction"); 521 synchronized(mSetRadioAccessFamilyStatus) { 522 for (int i = 0; i < mProxyPhones.length; i++) { 523 logd("clearTransaction: phoneId=" + i + " status=IDLE"); 524 mSetRadioAccessFamilyStatus[i] = SET_RC_STATUS_IDLE; 525 mOldRadioAccessFamily[i] = 0; 526 mNewRadioAccessFamily[i] = 0; 527 } 528 529 if (mWakeLock.isHeld()) { 530 mWakeLock.release(); 531 } 532 } 533 } 534 535 private boolean checkAllRadioCapabilitySuccess() { 536 synchronized(mSetRadioAccessFamilyStatus) { 537 for (int i = 0; i < mProxyPhones.length; i++) { 538 if (mSetRadioAccessFamilyStatus[i] == SET_RC_STATUS_FAIL) { 539 return false; 540 } 541 } 542 return true; 543 } 544 } 545 546 private void resetRadioAccessFamilyStatusCounter() { 547 mRadioAccessFamilyStatusCounter = mProxyPhones.length; 548 } 549 550 private void sendRadioCapabilityRequest(int phoneId, int sessionId, int rcPhase, 551 int radioFamily, String logicalModemId, int status, int eventId) { 552 RadioCapability requestRC = new RadioCapability( 553 phoneId, sessionId, rcPhase, radioFamily, logicalModemId, status); 554 mProxyPhones[phoneId].setRadioCapability( 555 requestRC, mHandler.obtainMessage(eventId)); 556 } 557 558 /** 559 * RadioCapabilityRunnable is used to check 560 * if radio capability request's response is out of date. 561 * <p> 562 * Note that the setRadioCapability will be stopped directly and send FINISH 563 * with fail status to all logical modems. and send out fail intent 564 * 565 */ 566 private class RadioCapabilityRunnable implements Runnable { 567 private int mSessionId; 568 public RadioCapabilityRunnable() { 569 } 570 571 public void setTimeoutState(int sessionId) { 572 mSessionId = sessionId; 573 } 574 575 @Override 576 public void run() { 577 if (mSessionId != mRadioCapabilitySessionId) { 578 logd("RadioCapability timeout: Ignore mSessionId=" + mSessionId 579 + "!= mRadioCapabilitySessionId=" + mRadioCapabilitySessionId); 580 return; 581 } 582 583 synchronized(mSetRadioAccessFamilyStatus) { 584 for (int i = 0; i < mProxyPhones.length; i++) { 585 logd("RadioCapability timeout: mSetRadioAccessFamilyStatus[" + i + "]=" + 586 mSetRadioAccessFamilyStatus[i]); 587 } 588 589 // Increment the sessionId as we are completing the transaction below 590 // so we don't want it completed when the FINISH phase is done. 591 int uniqueDifferentId = mUniqueIdGenerator.getAndIncrement(); 592 593 // send FINISH request with fail status and then uniqueDifferentId 594 issueFinish(RadioCapability.RC_STATUS_FAIL, 595 uniqueDifferentId); 596 completeRadioCapabilityTransaction(); 597 } 598 } 599 } 600 601 private void logd(String string) { 602 Rlog.d(LOG_TAG, string); 603 } 604 605 private void loge(String string) { 606 Rlog.e(LOG_TAG, string); 607 } 608 609 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 610 try { 611 mDctController.dump(fd, pw, args); 612 } catch (Exception e) { 613 e.printStackTrace(); 614 } 615 } 616} 617