1 /* 2 * Copyright (C) 2021 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 17 package com.android.internal.telephony; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.BroadcastReceiver; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.os.AsyncResult; 26 import android.os.Handler; 27 import android.os.IBinder; 28 import android.os.Message; 29 import android.os.PersistableBundle; 30 import android.os.RemoteException; 31 import android.telephony.AccessNetworkConstants; 32 import android.telephony.CarrierConfigManager; 33 import android.telephony.CellIdentity; 34 import android.telephony.CellIdentityLte; 35 import android.telephony.CellIdentityNr; 36 import android.telephony.CellInfo; 37 import android.telephony.CellSignalStrengthLte; 38 import android.telephony.CellSignalStrengthNr; 39 import android.telephony.ServiceState; 40 import android.telephony.SignalStrength; 41 import android.telephony.SignalStrengthUpdateRequest; 42 import android.telephony.SignalThresholdInfo; 43 import android.telephony.SubscriptionInfo; 44 import android.telephony.TelephonyManager; 45 import android.util.LocalLog; 46 import android.util.Pair; 47 48 import com.android.internal.annotations.VisibleForTesting; 49 import com.android.internal.telephony.util.ArrayUtils; 50 import com.android.internal.util.IndentingPrintWriter; 51 import com.android.telephony.Rlog; 52 53 import java.io.FileDescriptor; 54 import java.io.PrintWriter; 55 import java.util.ArrayList; 56 import java.util.Arrays; 57 import java.util.Iterator; 58 import java.util.List; 59 import java.util.NoSuchElementException; 60 import java.util.Set; 61 import java.util.TreeSet; 62 import java.util.concurrent.TimeUnit; 63 import java.util.regex.PatternSyntaxException; 64 65 /** 66 * SignalStrengthController handles signal polling request and unsolicited signal strength update. 67 */ 68 public class SignalStrengthController extends Handler { 69 private static final boolean DBG = false; /* STOPSHIP if true */ 70 private static final String TAG = "SSCtr"; 71 72 private static final long SIGNAL_STRENGTH_REFRESH_THRESHOLD_IN_MS = 73 TimeUnit.SECONDS.toMillis(10); 74 /** Signal strength poll rate. */ 75 private static final long POLL_PERIOD_MILLIS = TimeUnit.SECONDS.toMillis(20); 76 private static final int INVALID_ARFCN = -1; 77 78 /** Required magnitude change between unsolicited SignalStrength reports. */ 79 private static final int REPORTING_HYSTERESIS_DB = 2; 80 /** Minimum time between unsolicited SignalStrength reports. */ 81 private static final int REPORTING_HYSTERESIS_MILLIS = 3000; 82 /** 83 * A threshold within which (inclusive) the application requested signal strength 84 * thresholds will be aligned with threholds set in advance (by system or other apps). 85 * Since the alignment applies to both directions, the value is set to halt of 86 * REPORTING_HYSTERESIS_DB to respect it while without introducing additional gaps for 87 * thresholds set by apps. 88 */ 89 private static final int ALIGNMENT_HYSTERESIS_DB = 1; 90 91 private static final int EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST = 1; 92 private static final int EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST = 2; 93 private static final int EVENT_ON_DEVICE_IDLE_STATE_CHANGED = 3; 94 private static final int EVENT_RIL_CONNECTED = 4; 95 private static final int EVENT_RADIO_AVAILABLE = 5; 96 private static final int EVENT_GET_SIGNAL_STRENGTH = 6; 97 private static final int EVENT_POLL_SIGNAL_STRENGTH = 7; 98 private static final int EVENT_SIGNAL_STRENGTH_UPDATE = 8; 99 private static final int EVENT_POLL_SIGNAL_STRENGTH_DONE = 9; 100 private static final int EVENT_CARRIER_CONFIG_CHANGED = 10; 101 102 @NonNull 103 private final Phone mPhone; 104 @NonNull 105 private final CommandsInterface mCi; 106 107 @NonNull 108 private SignalStrength mSignalStrength; 109 private long mSignalStrengthUpdatedTime; 110 @Nullable 111 private SignalStrength mLastSignalStrength = null; 112 113 /** 114 * List of LTE EARFCNs (E-UTRAN Absolute Radio Frequency Channel Number, 115 * Reference: 3GPP TS 36.104 5.4.3) 116 * inclusive ranges for which the lte rsrp boost is applied 117 */ 118 @Nullable 119 private ArrayList<Pair<Integer, Integer>> mEarfcnPairListForRsrpBoost = null; 120 /** 121 * Offset which is reduced from the rsrp threshold while calculating signal strength level. 122 */ 123 private int mLteRsrpBoost = 0; 124 /** 125 * Ranges of NR ARFCNs (5G Absolute Radio Frequency Channel Number, 126 * Reference: 3GPP TS 38.104) 127 * inclusive ranges for which the corresponding nr rsrp boost is applied 128 */ 129 @Nullable 130 private ArrayList<Pair<Integer, Integer>> mNrarfcnRangeListForRsrpBoost = null; 131 @Nullable 132 private int[] mNrRsrpBoost = null; 133 @NonNull 134 private final Object mRsrpBoostLock = new Object(); 135 136 @NonNull 137 private final List<SignalRequestRecord> mSignalRequestRecords = new ArrayList<>(); 138 139 @NonNull 140 private PersistableBundle mCarrierConfig; 141 142 @NonNull 143 private final LocalLog mLocalLog = new LocalLog(64); 144 145 private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 146 @Override 147 public void onReceive(Context context, Intent intent) { 148 final String action = intent.getAction(); 149 if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action)) { 150 int phoneId = intent.getExtras().getInt(CarrierConfigManager.EXTRA_SLOT_INDEX); 151 // Ignore the carrier config changed if the phoneId is not matched. 152 if (phoneId == mPhone.getPhoneId()) { 153 sendEmptyMessage(EVENT_CARRIER_CONFIG_CHANGED); 154 } 155 } 156 } 157 }; 158 SignalStrengthController(@onNull Phone phone)159 public SignalStrengthController(@NonNull Phone phone) { 160 mPhone = phone; 161 mCi = mPhone.mCi; 162 163 mCi.registerForRilConnected(this, EVENT_RIL_CONNECTED, null); 164 mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); 165 mCi.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null); 166 setSignalStrengthDefaultValues(); 167 168 mCarrierConfig = getCarrierConfig(); 169 IntentFilter filter = new IntentFilter(); 170 filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 171 mPhone.getContext().registerReceiver(mBroadcastReceiver, filter); 172 } 173 174 @Override handleMessage(Message msg)175 public void handleMessage(Message msg) { 176 if (DBG) log("received event " + msg.what); 177 AsyncResult ar; 178 179 switch (msg.what) { 180 case EVENT_RIL_CONNECTED: // fall through 181 case EVENT_RADIO_AVAILABLE: 182 onReset(); 183 break; 184 case EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST: { 185 Pair<SignalRequestRecord, Message> pair = 186 (Pair<SignalRequestRecord, Message>) msg.obj; 187 SignalRequestRecord record = pair.first; 188 Message onCompleted = pair.second; 189 AsyncResult ret = AsyncResult.forMessage(onCompleted); 190 191 // TODO(b/177956310): Check subId to filter out old request until a better solution 192 boolean dupRequest = mSignalRequestRecords.stream().anyMatch( 193 srr -> srr.mCallingUid == record.mCallingUid 194 && srr.mSubId == record.mSubId); 195 if (dupRequest) { 196 ret.exception = new IllegalStateException( 197 "setSignalStrengthUpdateRequest called again with same subId"); 198 onCompleted.sendToTarget(); 199 break; 200 } 201 202 try { 203 record.mRequest.getLiveToken().linkToDeath(record, 0); 204 } catch (RemoteException | NullPointerException ex) { 205 ret.exception = new IllegalStateException( 206 "Signal request client is already dead."); 207 onCompleted.sendToTarget(); 208 break; 209 } 210 211 mSignalRequestRecords.add(record); 212 213 updateAlwaysReportSignalStrength(); 214 updateReportingCriteria(); 215 216 onCompleted.sendToTarget(); 217 break; 218 } 219 220 case EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST: { 221 Pair<SignalRequestRecord, Message> pair = 222 (Pair<SignalRequestRecord, Message>) msg.obj; 223 SignalRequestRecord record = pair.first; 224 Message onCompleted = pair.second; 225 226 // for loop with removal may cause ConcurrentModificationException 227 Iterator<SignalRequestRecord> it = mSignalRequestRecords.iterator(); 228 while (it.hasNext()) { 229 SignalRequestRecord srr = it.next(); 230 if (srr.mRequest.getLiveToken().equals(record.mRequest.getLiveToken())) { 231 try { 232 srr.mRequest.getLiveToken().unlinkToDeath(srr, 0); 233 } catch (NoSuchElementException ignored) { 234 // Either never linked or has already unlinked, ignore anyway 235 } 236 it.remove(); 237 } 238 } 239 240 updateAlwaysReportSignalStrength(); 241 updateReportingCriteria(); 242 243 if (onCompleted != null) { 244 AsyncResult ret = AsyncResult.forMessage(onCompleted); 245 onCompleted.sendToTarget(); 246 } 247 break; 248 } 249 250 case EVENT_ON_DEVICE_IDLE_STATE_CHANGED: { 251 updateReportingCriteria(); 252 break; 253 } 254 255 case EVENT_POLL_SIGNAL_STRENGTH_DONE: // fall through 256 case EVENT_GET_SIGNAL_STRENGTH: { 257 // This callback is called when signal strength is polled 258 // all by itself 259 260 if (!(mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON)) { 261 // Polling will continue when radio turns back on 262 return; 263 } 264 ar = (AsyncResult) msg.obj; 265 onSignalStrengthResult(ar); 266 break; 267 } 268 269 case EVENT_POLL_SIGNAL_STRENGTH: { 270 // Just poll signal strength...not part of pollState() 271 272 mCi.getSignalStrength(obtainMessage(EVENT_POLL_SIGNAL_STRENGTH_DONE)); 273 break; 274 } 275 276 case EVENT_SIGNAL_STRENGTH_UPDATE: { 277 // This is a notification from CommandsInterface.setOnSignalStrengthUpdate 278 279 ar = (AsyncResult) msg.obj; 280 onSignalStrengthResult(ar); 281 break; 282 } 283 284 case EVENT_CARRIER_CONFIG_CHANGED: { 285 onCarrierConfigChanged(); 286 break; 287 } 288 289 default: 290 log("Unhandled message with number: " + msg.what); 291 break; 292 } 293 } 294 dispose()295 void dispose() { 296 mCi.unSetOnSignalStrengthUpdate(this); 297 } 298 299 /** 300 * Called when RIL is connected during boot up or after modem restart. Set the default criteria 301 * so that modem can start with default state before updated criteria is ready. 302 */ onReset()303 private void onReset() { 304 setDefaultSignalStrengthReportingCriteria(); 305 } 306 getSignalStrengthFromCi()307 void getSignalStrengthFromCi() { 308 mCi.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH)); 309 } 310 311 /** 312 * send signal-strength-changed notification if changed Called both for 313 * solicited and unsolicited signal strength updates 314 * 315 * @return true if the signal strength changed and a notification was sent. 316 */ onSignalStrengthResult(@onNull AsyncResult ar)317 private boolean onSignalStrengthResult(@NonNull AsyncResult ar) { 318 319 // This signal is used for both voice and data radio signal so parse 320 // all fields 321 322 if ((ar.exception == null) && (ar.result != null)) { 323 mSignalStrength = (SignalStrength) ar.result; 324 325 if (mPhone.getServiceStateTracker() != null) { 326 mSignalStrength.updateLevel(mCarrierConfig, mPhone.getServiceStateTracker().mSS); 327 } 328 } else { 329 log("onSignalStrengthResult() Exception from RIL : " + ar.exception); 330 mSignalStrength = new SignalStrength(); 331 } 332 mSignalStrengthUpdatedTime = System.currentTimeMillis(); 333 334 boolean ssChanged = notifySignalStrength(); 335 336 return ssChanged; 337 } 338 339 /** 340 * @return signal strength 341 */ 342 @NonNull getSignalStrength()343 public SignalStrength getSignalStrength() { 344 if (shouldRefreshSignalStrength()) { 345 log("getSignalStrength() refreshing signal strength."); 346 obtainMessage(EVENT_POLL_SIGNAL_STRENGTH).sendToTarget(); 347 } 348 return mSignalStrength; 349 } 350 shouldRefreshSignalStrength()351 private boolean shouldRefreshSignalStrength() { 352 long curTime = System.currentTimeMillis(); 353 354 // If last signal strength is older than 10 seconds, or somehow if curTime is smaller 355 // than mSignalStrengthUpdatedTime (system time update), it's considered stale. 356 boolean isStale = (mSignalStrengthUpdatedTime > curTime) 357 || (curTime - mSignalStrengthUpdatedTime > SIGNAL_STRENGTH_REFRESH_THRESHOLD_IN_MS); 358 if (!isStale) return false; 359 360 List<SubscriptionInfo> subInfoList = SubscriptionController.getInstance() 361 .getActiveSubscriptionInfoList(mPhone.getContext().getOpPackageName(), 362 mPhone.getContext().getAttributionTag()); 363 364 if (!ArrayUtils.isEmpty(subInfoList)) { 365 for (SubscriptionInfo info : subInfoList) { 366 // If we have an active opportunistic subscription whose data is IN_SERVICE, 367 // we need to get signal strength to decide data switching threshold. In this case, 368 // we poll latest signal strength from modem. 369 if (info.isOpportunistic()) { 370 TelephonyManager tm = TelephonyManager.from(mPhone.getContext()) 371 .createForSubscriptionId(info.getSubscriptionId()); 372 ServiceState ss = tm.getServiceState(); 373 if (ss != null 374 && ss.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE) { 375 return true; 376 } 377 } 378 } 379 } 380 381 return false; 382 } 383 384 /** 385 * Update signal strength reporting criteria from the carrier config 386 */ 387 @VisibleForTesting updateReportingCriteria()388 public void updateReportingCriteria() { 389 List<SignalThresholdInfo> signalThresholdInfos = new ArrayList<>(); 390 391 int[] gsmRssiThresholds = mCarrierConfig.getIntArray( 392 CarrierConfigManager.KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY); 393 if (gsmRssiThresholds != null) { 394 signalThresholdInfos.add( 395 createSignalThresholdsInfo( 396 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI, 397 gsmRssiThresholds, 398 AccessNetworkConstants.AccessNetworkType.GERAN, 399 true)); 400 } 401 402 int[] wcdmaRscpThresholds = mCarrierConfig.getIntArray( 403 CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY); 404 if (wcdmaRscpThresholds != null) { 405 signalThresholdInfos.add( 406 createSignalThresholdsInfo( 407 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSCP, 408 wcdmaRscpThresholds, 409 AccessNetworkConstants.AccessNetworkType.UTRAN, 410 true)); 411 } 412 413 int lteMeasurementEnabled = mCarrierConfig.getInt(CarrierConfigManager 414 .KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT, CellSignalStrengthLte.USE_RSRP); 415 int[] lteRsrpThresholds = mCarrierConfig.getIntArray( 416 CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY); 417 if (lteRsrpThresholds != null) { 418 signalThresholdInfos.add( 419 createSignalThresholdsInfo( 420 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRP, 421 lteRsrpThresholds, 422 AccessNetworkConstants.AccessNetworkType.EUTRAN, 423 (lteMeasurementEnabled & CellSignalStrengthLte.USE_RSRP) != 0)); 424 } 425 426 if (mPhone.getHalVersion().greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) { 427 int[] lteRsrqThresholds = mCarrierConfig.getIntArray( 428 CarrierConfigManager.KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY); 429 if (lteRsrqThresholds != null) { 430 signalThresholdInfos.add( 431 createSignalThresholdsInfo( 432 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRQ, 433 lteRsrqThresholds, 434 AccessNetworkConstants.AccessNetworkType.EUTRAN, 435 (lteMeasurementEnabled & CellSignalStrengthLte.USE_RSRQ) != 0)); 436 } 437 438 int[] lteRssnrThresholds = mCarrierConfig.getIntArray( 439 CarrierConfigManager.KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY); 440 if (lteRssnrThresholds != null) { 441 signalThresholdInfos.add( 442 createSignalThresholdsInfo( 443 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSNR, 444 lteRssnrThresholds, 445 AccessNetworkConstants.AccessNetworkType.EUTRAN, 446 (lteMeasurementEnabled & CellSignalStrengthLte.USE_RSSNR) != 0)); 447 } 448 449 int nrMeasurementEnabled = mCarrierConfig.getInt(CarrierConfigManager 450 .KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT, CellSignalStrengthNr.USE_SSRSRP); 451 int[] nrSsrsrpThresholds = mCarrierConfig.getIntArray( 452 CarrierConfigManager.KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY); 453 if (nrSsrsrpThresholds != null) { 454 signalThresholdInfos.add( 455 createSignalThresholdsInfo( 456 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRP, 457 nrSsrsrpThresholds, 458 AccessNetworkConstants.AccessNetworkType.NGRAN, 459 (nrMeasurementEnabled & CellSignalStrengthNr.USE_SSRSRP) != 0)); 460 } 461 462 int[] nrSsrsrqThresholds = mCarrierConfig.getIntArray( 463 CarrierConfigManager.KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY); 464 if (nrSsrsrqThresholds != null) { 465 signalThresholdInfos.add( 466 createSignalThresholdsInfo( 467 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRQ, 468 nrSsrsrqThresholds, 469 AccessNetworkConstants.AccessNetworkType.NGRAN, 470 (nrMeasurementEnabled & CellSignalStrengthNr.USE_SSRSRQ) != 0)); 471 } 472 473 int[] nrSssinrThresholds = mCarrierConfig.getIntArray( 474 CarrierConfigManager.KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY); 475 if (nrSssinrThresholds != null) { 476 signalThresholdInfos.add( 477 createSignalThresholdsInfo( 478 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSSINR, 479 nrSssinrThresholds, 480 AccessNetworkConstants.AccessNetworkType.NGRAN, 481 (nrMeasurementEnabled & CellSignalStrengthNr.USE_SSSINR) != 0)); 482 } 483 } 484 485 consolidatedAndSetReportingCriteria(signalThresholdInfos); 486 } 487 setDefaultSignalStrengthReportingCriteria()488 private void setDefaultSignalStrengthReportingCriteria() { 489 List<SignalThresholdInfo> signalThresholdInfos = new ArrayList<>(); 490 491 signalThresholdInfos.add( 492 createSignalThresholdsInfo( 493 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI, 494 AccessNetworkThresholds.GERAN, 495 AccessNetworkConstants.AccessNetworkType.GERAN, 496 true)); 497 signalThresholdInfos.add( 498 createSignalThresholdsInfo( 499 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSCP, 500 AccessNetworkThresholds.UTRAN, 501 AccessNetworkConstants.AccessNetworkType.UTRAN, 502 true)); 503 signalThresholdInfos.add( 504 createSignalThresholdsInfo( 505 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRP, 506 AccessNetworkThresholds.EUTRAN_RSRP, 507 AccessNetworkConstants.AccessNetworkType.EUTRAN, 508 true)); 509 signalThresholdInfos.add( 510 createSignalThresholdsInfo( 511 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI, 512 AccessNetworkThresholds.CDMA2000, 513 AccessNetworkConstants.AccessNetworkType.CDMA2000, 514 true)); 515 516 if (mPhone.getHalVersion().greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) { 517 signalThresholdInfos.add( 518 createSignalThresholdsInfo( 519 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRQ, 520 AccessNetworkThresholds.EUTRAN_RSRQ, 521 AccessNetworkConstants.AccessNetworkType.EUTRAN, 522 false)); 523 signalThresholdInfos.add( 524 createSignalThresholdsInfo( 525 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSNR, 526 AccessNetworkThresholds.EUTRAN_RSSNR, 527 AccessNetworkConstants.AccessNetworkType.EUTRAN, 528 true)); 529 530 // Defaultly we only need SSRSRP for NGRAN signal criteria reporting 531 signalThresholdInfos.add( 532 createSignalThresholdsInfo( 533 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRP, 534 AccessNetworkThresholds.NGRAN_SSRSRP, 535 AccessNetworkConstants.AccessNetworkType.NGRAN, 536 true)); 537 signalThresholdInfos.add( 538 createSignalThresholdsInfo( 539 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRQ, 540 AccessNetworkThresholds.NGRAN_SSRSRQ, 541 AccessNetworkConstants.AccessNetworkType.NGRAN, 542 false)); 543 signalThresholdInfos.add( 544 createSignalThresholdsInfo( 545 SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSSINR, 546 AccessNetworkThresholds.NGRAN_SSSINR, 547 AccessNetworkConstants.AccessNetworkType.NGRAN, 548 false)); 549 } 550 551 consolidatedAndSetReportingCriteria(signalThresholdInfos); 552 } 553 consolidatedAndSetReportingCriteria( @onNull List<SignalThresholdInfo> signalThresholdInfos)554 private void consolidatedAndSetReportingCriteria( 555 @NonNull List<SignalThresholdInfo> signalThresholdInfos) { 556 List<SignalThresholdInfo> consolidatedSignalThresholdInfos = new ArrayList<>( 557 signalThresholdInfos.size()); 558 for (SignalThresholdInfo signalThresholdInfo : signalThresholdInfos) { 559 final int ran = signalThresholdInfo.getRadioAccessNetworkType(); 560 final int measurementType = signalThresholdInfo.getSignalMeasurementType(); 561 final boolean isEnabledForSystem = 562 signalThresholdInfo.isEnabled() && shouldHonorSystemThresholds(); 563 int[] consolidatedThresholds = 564 getConsolidatedSignalThresholds( 565 ran, 566 measurementType, 567 isEnabledForSystem 568 ? signalThresholdInfo.getThresholds() 569 : new int[]{}, 570 ALIGNMENT_HYSTERESIS_DB); 571 boolean isEnabledForAppRequest = 572 shouldEnableSignalThresholdForAppRequest( 573 ran, 574 measurementType, 575 mPhone.getSubId(), 576 mPhone.isDeviceIdle()); 577 consolidatedSignalThresholdInfos.add( 578 new SignalThresholdInfo.Builder() 579 .setRadioAccessNetworkType(ran) 580 .setSignalMeasurementType(measurementType) 581 .setHysteresisMs(REPORTING_HYSTERESIS_MILLIS) 582 .setHysteresisDb(REPORTING_HYSTERESIS_DB) 583 .setThresholds(consolidatedThresholds, true /*isSystem*/) 584 .setIsEnabled(isEnabledForSystem || isEnabledForAppRequest) 585 .build()); 586 } 587 mCi.setSignalStrengthReportingCriteria(consolidatedSignalThresholdInfos, null); 588 589 localLog("setSignalStrengthReportingCriteria consolidatedSignalThresholdInfos=" 590 + consolidatedSignalThresholdInfos); 591 } 592 setSignalStrengthDefaultValues()593 void setSignalStrengthDefaultValues() { 594 mSignalStrength = new SignalStrength(); 595 mSignalStrengthUpdatedTime = System.currentTimeMillis(); 596 } 597 notifySignalStrength()598 boolean notifySignalStrength() { 599 boolean notified = false; 600 if (!mSignalStrength.equals(mLastSignalStrength)) { 601 try { 602 mPhone.notifySignalStrength(); 603 notified = true; 604 mLastSignalStrength = mSignalStrength; 605 } catch (NullPointerException ex) { 606 log("updateSignalStrength() Phone already destroyed: " + ex 607 + "SignalStrength not notified"); 608 } 609 } 610 return notified; 611 } 612 613 /** 614 * Print the SignalStrengthController states into the given stream. 615 * 616 * @param fd The raw file descriptor that the dump is being sent to. 617 * @param pw A PrintWriter to which the dump is to be set. 618 * @param args Additional arguments to the dump request. 619 */ dump(FileDescriptor fd, PrintWriter pw, String[] args)620 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 621 pw.println("SignalStrengthController - phoneId: " + mPhone.getPhoneId()); 622 pw.println("SignalStrengthController - Log Begin ----"); 623 mLocalLog.dump(fd, pw, args); 624 pw.println("SignalStrengthController - Log End ----"); 625 626 final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 627 ipw.increaseIndent(); 628 pw.println("mSignalRequestRecords=" + mSignalRequestRecords); 629 pw.println(" mLastSignalStrength=" + mLastSignalStrength); 630 pw.println(" mSignalStrength=" + mSignalStrength); 631 pw.println(" mLteRsrpBoost=" + mLteRsrpBoost); 632 pw.println(" mNrRsrpBoost=" + Arrays.toString(mNrRsrpBoost)); 633 pw.println(" mEarfcnPairListForRsrpBoost=" + mEarfcnPairListForRsrpBoost); 634 pw.println(" mNrarfcnRangeListForRsrpBoost=" + mNrarfcnRangeListForRsrpBoost); 635 ipw.decreaseIndent(); 636 ipw.flush(); 637 } 638 639 /** 640 * Set a new request to update the signal strength thresholds. 641 */ setSignalStrengthUpdateRequest(int subId, int callingUid, @NonNull SignalStrengthUpdateRequest request, @NonNull Message onCompleted)642 public void setSignalStrengthUpdateRequest(int subId, int callingUid, 643 @NonNull SignalStrengthUpdateRequest request, @NonNull Message onCompleted) { 644 SignalRequestRecord record = new SignalRequestRecord(subId, callingUid, request); 645 sendMessage(obtainMessage(EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST, 646 new Pair<SignalRequestRecord, Message>(record, onCompleted))); 647 648 localLog("setSignalStrengthUpdateRequest" 649 + " subId=" + subId 650 + " callingUid=" + callingUid 651 + " request=" + request); 652 } 653 654 /** 655 * Clear the previously set request. 656 */ clearSignalStrengthUpdateRequest(int subId, int callingUid, @NonNull SignalStrengthUpdateRequest request, @Nullable Message onCompleted)657 public void clearSignalStrengthUpdateRequest(int subId, int callingUid, 658 @NonNull SignalStrengthUpdateRequest request, @Nullable Message onCompleted) { 659 SignalRequestRecord record = new SignalRequestRecord(subId, callingUid, request); 660 sendMessage(obtainMessage(EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST, 661 new Pair<SignalRequestRecord, Message>(record, onCompleted))); 662 663 localLog("clearSignalStrengthUpdateRequest" 664 + " subId=" + subId 665 + " callingUid=" + callingUid 666 + " request=" + request); 667 } 668 669 /** 670 * Align all the qualified thresholds set from applications to the {@code systemThresholds} 671 * and consolidate a new thresholds array, follow rules below: 672 * 1. All threshold values (whose interval is guaranteed to be larger than hysteresis) in 673 * {@code systemThresholds} will keep as it. 674 * 2. Any threshold from apps that has interval less than hysteresis from any threshold in 675 * {@code systemThresholds} will be removed. 676 * 3. The target thresholds will be {@code systemThresholds} + all qualified thresholds from 677 * apps, sorted in ascending order. 678 */ 679 @VisibleForTesting 680 @NonNull getConsolidatedSignalThresholds(int ran, int measurement, @Nullable int[] systemThresholds, int hysteresis)681 public int[] getConsolidatedSignalThresholds(int ran, int measurement, 682 @Nullable int[] systemThresholds, int hysteresis) { 683 684 // TreeSet with comparator that will filter element with interval less than hysteresis 685 // from any current element 686 Set<Integer> target = new TreeSet<>((x, y) -> { 687 if (y >= x - hysteresis && y <= x + hysteresis) { 688 return 0; 689 } 690 return Integer.compare(x, y); 691 }); 692 693 if (systemThresholds != null) { 694 for (int systemThreshold : systemThresholds) { 695 target.add(systemThreshold); 696 } 697 } 698 699 final boolean isDeviceIdle = mPhone.isDeviceIdle(); 700 final int curSubId = mPhone.getSubId(); 701 // The total number of record is small (10~15 tops). With each request has at most 5 702 // SignalThresholdInfo which has at most 8 thresholds arrays. So the nested loop should 703 // not be a concern here. 704 for (SignalRequestRecord record : mSignalRequestRecords) { 705 if (curSubId != record.mSubId 706 || (isDeviceIdle && !record.mRequest.isReportingRequestedWhileIdle())) { 707 continue; 708 } 709 for (SignalThresholdInfo info : record.mRequest.getSignalThresholdInfos()) { 710 if (isRanAndSignalMeasurementTypeMatch(ran, measurement, info)) { 711 for (int appThreshold : info.getThresholds()) { 712 target.add(appThreshold); 713 } 714 } 715 } 716 } 717 718 int[] targetArray = new int[target.size()]; 719 int i = 0; 720 for (int element : target) { 721 targetArray[i++] = element; 722 } 723 return targetArray; 724 } 725 726 /** 727 * Return true if system thresholds should be honored when consolidating. 728 */ 729 @VisibleForTesting shouldHonorSystemThresholds()730 public boolean shouldHonorSystemThresholds() { 731 if (!mPhone.isDeviceIdle()) { 732 return true; 733 } 734 735 final int curSubId = mPhone.getSubId(); 736 return mSignalRequestRecords.stream().anyMatch( 737 srr -> curSubId == srr.mSubId 738 && srr.mRequest.isSystemThresholdReportingRequestedWhileIdle()); 739 } 740 741 /** 742 * Get notified when device idle state changed 743 */ 744 @VisibleForTesting onDeviceIdleStateChanged(boolean isDeviceIdle)745 public void onDeviceIdleStateChanged(boolean isDeviceIdle) { 746 sendMessage(obtainMessage(EVENT_ON_DEVICE_IDLE_STATE_CHANGED, isDeviceIdle)); 747 748 localLog("onDeviceIdleStateChanged isDeviceIdle=" + isDeviceIdle); 749 } 750 751 /** 752 * Return true if signal threshold should be enabled due to the apps requests. 753 */ 754 @VisibleForTesting shouldEnableSignalThresholdForAppRequest( @ccessNetworkConstants.RadioAccessNetworkType int ran, @SignalThresholdInfo.SignalMeasurementType int measurement, int subId, boolean isDeviceIdle)755 public boolean shouldEnableSignalThresholdForAppRequest( 756 @AccessNetworkConstants.RadioAccessNetworkType int ran, 757 @SignalThresholdInfo.SignalMeasurementType int measurement, 758 int subId, 759 boolean isDeviceIdle) { 760 for (SignalRequestRecord record : mSignalRequestRecords) { 761 if (subId != record.mSubId) { 762 continue; 763 } 764 for (SignalThresholdInfo info : record.mRequest.getSignalThresholdInfos()) { 765 if (isRanAndSignalMeasurementTypeMatch(ran, measurement, info) 766 && (!isDeviceIdle || isSignalReportRequestedWhileIdle(record.mRequest))) { 767 return true; 768 } 769 } 770 } 771 return false; 772 } 773 isRanAndSignalMeasurementTypeMatch( @ccessNetworkConstants.RadioAccessNetworkType int ran, @SignalThresholdInfo.SignalMeasurementType int measurement, @NonNull SignalThresholdInfo info)774 private static boolean isRanAndSignalMeasurementTypeMatch( 775 @AccessNetworkConstants.RadioAccessNetworkType int ran, 776 @SignalThresholdInfo.SignalMeasurementType int measurement, 777 @NonNull SignalThresholdInfo info) { 778 return ran == info.getRadioAccessNetworkType() 779 && measurement == info.getSignalMeasurementType(); 780 } 781 isSignalReportRequestedWhileIdle( @onNull SignalStrengthUpdateRequest request)782 private static boolean isSignalReportRequestedWhileIdle( 783 @NonNull SignalStrengthUpdateRequest request) { 784 return request.isSystemThresholdReportingRequestedWhileIdle() 785 || request.isReportingRequestedWhileIdle(); 786 } 787 788 /** 789 * Gets the carrier configuration values for a particular subscription. 790 * 791 * @return A {@link PersistableBundle} containing the config for the given subId, 792 * or default values for an invalid subId. 793 */ 794 @NonNull getCarrierConfig()795 private PersistableBundle getCarrierConfig() { 796 CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext() 797 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 798 if (configManager != null) { 799 // If an invalid subId is used, this bundle will contain default values. 800 PersistableBundle config = configManager.getConfigForSubId(mPhone.getSubId()); 801 if (config != null) { 802 return config; 803 } 804 } 805 // Return static default defined in CarrierConfigManager. 806 return CarrierConfigManager.getDefaultConfig(); 807 } 808 809 private class SignalRequestRecord implements IBinder.DeathRecipient { 810 final int mSubId; // subId the request originally applied to 811 final int mCallingUid; 812 @NonNull 813 final SignalStrengthUpdateRequest mRequest; 814 SignalRequestRecord(int subId, int uid, @NonNull SignalStrengthUpdateRequest request)815 SignalRequestRecord(int subId, int uid, @NonNull SignalStrengthUpdateRequest request) { 816 this.mCallingUid = uid; 817 this.mSubId = subId; 818 this.mRequest = request; 819 } 820 821 @Override binderDied()822 public void binderDied() { 823 localLog("binderDied record=" + this); 824 clearSignalStrengthUpdateRequest(mSubId, mCallingUid, mRequest, null /*onCompleted*/); 825 } 826 827 @Override toString()828 public String toString() { 829 StringBuffer sb = new StringBuffer("SignalRequestRecord {"); 830 sb.append("mSubId=").append(mSubId); 831 sb.append(" mCallingUid=").append(mCallingUid); 832 sb.append(" mRequest=").append(mRequest).append("}"); 833 return sb.toString(); 834 } 835 } 836 updateAlwaysReportSignalStrength()837 private void updateAlwaysReportSignalStrength() { 838 final int curSubId = mPhone.getSubId(); 839 boolean alwaysReport = mSignalRequestRecords.stream().anyMatch( 840 srr -> srr.mSubId == curSubId && isSignalReportRequestedWhileIdle(srr.mRequest)); 841 842 // TODO(b/177924721): TM#setAlwaysReportSignalStrength will be removed and we will not 843 // worry about unset flag which was set by other client. 844 mPhone.setAlwaysReportSignalStrength(alwaysReport); 845 } 846 updateArfcnLists()847 void updateArfcnLists() { 848 synchronized (mRsrpBoostLock) { 849 mLteRsrpBoost = mCarrierConfig.getInt( 850 CarrierConfigManager.KEY_LTE_EARFCNS_RSRP_BOOST_INT, 0); 851 String[] earfcnsStringArrayForRsrpBoost = mCarrierConfig.getStringArray( 852 CarrierConfigManager.KEY_BOOSTED_LTE_EARFCNS_STRING_ARRAY); 853 mEarfcnPairListForRsrpBoost = convertEarfcnStringArrayToPairList( 854 earfcnsStringArrayForRsrpBoost); 855 856 mNrRsrpBoost = mCarrierConfig.getIntArray( 857 CarrierConfigManager.KEY_NRARFCNS_RSRP_BOOST_INT_ARRAY); 858 String[] nrarfcnsStringArrayForRsrpBoost = mCarrierConfig.getStringArray( 859 CarrierConfigManager.KEY_BOOSTED_NRARFCNS_STRING_ARRAY); 860 mNrarfcnRangeListForRsrpBoost = convertEarfcnStringArrayToPairList( 861 nrarfcnsStringArrayForRsrpBoost); 862 863 if ((mNrRsrpBoost == null && mNrarfcnRangeListForRsrpBoost != null) 864 || (mNrRsrpBoost != null && mNrarfcnRangeListForRsrpBoost == null) 865 || (mNrRsrpBoost != null && mNrarfcnRangeListForRsrpBoost != null 866 && mNrRsrpBoost.length != mNrarfcnRangeListForRsrpBoost.size())) { 867 loge("Invalid parameters for NR RSRP boost"); 868 mNrRsrpBoost = null; 869 mNrarfcnRangeListForRsrpBoost = null; 870 } 871 } 872 } 873 874 // package private access from ServiceStateTracker 875 // TODO(b/219572311): Maintains ArfcnRsrpBoost here only without forwarding by ServiceState updateServiceStateArfcnRsrpBoost(@onNull ServiceState serviceState, @Nullable CellIdentity cellIdentity)876 void updateServiceStateArfcnRsrpBoost(@NonNull ServiceState serviceState, 877 @Nullable CellIdentity cellIdentity) { 878 if (cellIdentity == null) return; 879 880 int rsrpBoost = 0; 881 int arfcn; 882 883 synchronized (mRsrpBoostLock) { 884 switch (cellIdentity.getType()) { 885 case CellInfo.TYPE_LTE: 886 arfcn = ((CellIdentityLte) cellIdentity).getEarfcn(); 887 if (arfcn != INVALID_ARFCN 888 && containsEarfcnInEarfcnRange(mEarfcnPairListForRsrpBoost, 889 arfcn) != -1) { 890 rsrpBoost = mLteRsrpBoost; 891 } 892 break; 893 case CellInfo.TYPE_NR: 894 arfcn = ((CellIdentityNr) cellIdentity).getNrarfcn(); 895 if (arfcn != INVALID_ARFCN) { 896 int index = containsEarfcnInEarfcnRange(mNrarfcnRangeListForRsrpBoost, 897 arfcn); 898 if (index != -1 && mNrRsrpBoost != null) { 899 rsrpBoost = mNrRsrpBoost[index]; 900 } 901 } 902 break; 903 default: 904 break; 905 } 906 } 907 serviceState.setArfcnRsrpBoost(rsrpBoost); 908 } 909 910 /** 911 * Checks if the provided earfcn falls within the range of earfcns. 912 * 913 * return int index in earfcnPairList if earfcn falls within the provided range; -1 otherwise. 914 */ containsEarfcnInEarfcnRange( @ullable ArrayList<Pair<Integer, Integer>> earfcnPairList, int earfcn)915 private static int containsEarfcnInEarfcnRange( 916 @Nullable ArrayList<Pair<Integer, Integer>> earfcnPairList, int earfcn) { 917 int index = 0; 918 if (earfcnPairList != null) { 919 for (Pair<Integer, Integer> earfcnPair : earfcnPairList) { 920 if ((earfcn >= earfcnPair.first) && (earfcn <= earfcnPair.second)) { 921 return index; 922 } 923 index++; 924 } 925 } 926 927 return -1; 928 } 929 930 /** 931 * Convert the earfcnStringArray to list of pairs. 932 * 933 * Format of the earfcnsList is expected to be {"erafcn1_start-earfcn1_end", 934 * "earfcn2_start-earfcn2_end" ... } 935 */ 936 @Nullable convertEarfcnStringArrayToPairList( @ullable String[] earfcnsList)937 private static ArrayList<Pair<Integer, Integer>> convertEarfcnStringArrayToPairList( 938 @Nullable String[] earfcnsList) { 939 ArrayList<Pair<Integer, Integer>> earfcnPairList = new ArrayList<Pair<Integer, Integer>>(); 940 941 if (earfcnsList != null) { 942 int earfcnStart; 943 int earfcnEnd; 944 for (int i = 0; i < earfcnsList.length; i++) { 945 try { 946 String[] earfcns = earfcnsList[i].split("-"); 947 if (earfcns.length != 2) { 948 if (DBG) { 949 log("Invalid earfcn range format"); 950 } 951 return null; 952 } 953 954 earfcnStart = Integer.parseInt(earfcns[0]); 955 earfcnEnd = Integer.parseInt(earfcns[1]); 956 957 if (earfcnStart > earfcnEnd) { 958 if (DBG) { 959 log("Invalid earfcn range format"); 960 } 961 return null; 962 } 963 964 earfcnPairList.add(new Pair<Integer, Integer>(earfcnStart, earfcnEnd)); 965 } catch (PatternSyntaxException pse) { 966 if (DBG) { 967 log("Invalid earfcn range format"); 968 } 969 return null; 970 } catch (NumberFormatException nfe) { 971 if (DBG) { 972 log("Invalid earfcn number format"); 973 } 974 return null; 975 } 976 } 977 } 978 979 return earfcnPairList; 980 } 981 onCarrierConfigChanged()982 private void onCarrierConfigChanged() { 983 mCarrierConfig = getCarrierConfig(); 984 log("Carrier Config changed."); 985 986 updateArfcnLists(); 987 updateReportingCriteria(); 988 } 989 createSignalThresholdsInfo( int measurementType, @NonNull int[] thresholds, int ran, boolean isEnabled)990 private static SignalThresholdInfo createSignalThresholdsInfo( 991 int measurementType, @NonNull int[] thresholds, int ran, boolean isEnabled) { 992 return new SignalThresholdInfo.Builder() 993 .setSignalMeasurementType(measurementType) 994 .setThresholds(thresholds) 995 .setRadioAccessNetworkType(ran) 996 .setIsEnabled(isEnabled) 997 .build(); 998 } 999 1000 /** 1001 * dBm thresholds that correspond to changes in signal strength indications. 1002 */ 1003 private static final class AccessNetworkThresholds { 1004 1005 /** 1006 * List of dBm thresholds for GERAN {@link AccessNetworkConstants.AccessNetworkType}. 1007 * 1008 * Calculated from GSM asu level thresholds - TS 27.007 Sec 8.5 1009 */ 1010 public static final int[] GERAN = new int[]{ 1011 -109, 1012 -103, 1013 -97, 1014 -89, 1015 }; 1016 1017 /** 1018 * List of default dBm thresholds for UTRAN 1019 * {@link AccessNetworkConstants.AccessNetworkType}. 1020 * 1021 * These thresholds are taken from the WCDMA RSCP defaults in {@link CarrierConfigManager}. 1022 * See TS 27.007 Sec 8.69. 1023 */ 1024 public static final int[] UTRAN = new int[]{ 1025 -114, /* SIGNAL_STRENGTH_POOR */ 1026 -104, /* SIGNAL_STRENGTH_MODERATE */ 1027 -94, /* SIGNAL_STRENGTH_GOOD */ 1028 -84 /* SIGNAL_STRENGTH_GREAT */ 1029 }; 1030 1031 /** 1032 * List of default dBm RSRP thresholds for EUTRAN 1033 * {@link AccessNetworkConstants.AccessNetworkType}. 1034 * 1035 * These thresholds are taken from the LTE RSRP defaults in {@link CarrierConfigManager}. 1036 */ 1037 public static final int[] EUTRAN_RSRP = new int[]{ 1038 -128, /* SIGNAL_STRENGTH_POOR */ 1039 -118, /* SIGNAL_STRENGTH_MODERATE */ 1040 -108, /* SIGNAL_STRENGTH_GOOD */ 1041 -98, /* SIGNAL_STRENGTH_GREAT */ 1042 }; 1043 1044 /** 1045 * List of default dB RSRQ thresholds for EUTRAN 1046 * {@link AccessNetworkConstants.AccessNetworkType}. 1047 * 1048 * These thresholds are taken from the LTE RSRQ defaults in {@link CarrierConfigManager}. 1049 */ 1050 public static final int[] EUTRAN_RSRQ = new int[]{ 1051 -20, /* SIGNAL_STRENGTH_POOR */ 1052 -17, /* SIGNAL_STRENGTH_MODERATE */ 1053 -14, /* SIGNAL_STRENGTH_GOOD */ 1054 -11 /* SIGNAL_STRENGTH_GREAT */ 1055 }; 1056 1057 /** 1058 * List of default dB RSSNR thresholds for EUTRAN 1059 * {@link AccessNetworkConstants.AccessNetworkType}. 1060 * 1061 * These thresholds are taken from the LTE RSSNR defaults in {@link CarrierConfigManager}. 1062 */ 1063 public static final int[] EUTRAN_RSSNR = new int[]{ 1064 -3, /* SIGNAL_STRENGTH_POOR */ 1065 1, /* SIGNAL_STRENGTH_MODERATE */ 1066 5, /* SIGNAL_STRENGTH_GOOD */ 1067 13 /* SIGNAL_STRENGTH_GREAT */ 1068 }; 1069 1070 /** 1071 * List of dBm thresholds for CDMA2000 {@link AccessNetworkConstants.AccessNetworkType}. 1072 * 1073 * These correspond to EVDO level thresholds. 1074 */ 1075 public static final int[] CDMA2000 = new int[]{ 1076 -105, 1077 -90, 1078 -75, 1079 -65 1080 }; 1081 1082 /** 1083 * List of dB thresholds for NGRAN {@link AccessNetworkConstants.AccessNetworkType} SSRSRP 1084 */ 1085 public static final int[] NGRAN_SSRSRP = new int[]{ 1086 -110, /* SIGNAL_STRENGTH_POOR */ 1087 -90, /* SIGNAL_STRENGTH_MODERATE */ 1088 -80, /* SIGNAL_STRENGTH_GOOD */ 1089 -65, /* SIGNAL_STRENGTH_GREAT */ 1090 }; 1091 1092 /** 1093 * List of dB thresholds for NGRAN {@link AccessNetworkConstants.AccessNetworkType} SSRSRQ 1094 */ 1095 public static final int[] NGRAN_SSRSRQ = new int[]{ 1096 -31, /* SIGNAL_STRENGTH_POOR */ 1097 -19, /* SIGNAL_STRENGTH_MODERATE */ 1098 -7, /* SIGNAL_STRENGTH_GOOD */ 1099 6 /* SIGNAL_STRENGTH_GREAT */ 1100 }; 1101 1102 /** 1103 * List of dB thresholds for NGRAN {@link AccessNetworkConstants.AccessNetworkType} SSSINR 1104 */ 1105 public static final int[] NGRAN_SSSINR = new int[]{ 1106 -5, /* SIGNAL_STRENGTH_POOR */ 1107 5, /* SIGNAL_STRENGTH_MODERATE */ 1108 15, /* SIGNAL_STRENGTH_GOOD */ 1109 30 /* SIGNAL_STRENGTH_GREAT */ 1110 }; 1111 } 1112 log(String msg)1113 private static void log(String msg) { 1114 if (DBG) Rlog.d(TAG, msg); 1115 } 1116 loge(String msg)1117 private static void loge(String msg) { 1118 Rlog.e(TAG, msg); 1119 } 1120 1121 /** Print to both Radio log and LocalLog, used only for critical but non-sensitive msg. */ localLog(String msg)1122 private void localLog(String msg) { 1123 Rlog.d(TAG, msg); 1124 mLocalLog.log(TAG + ": " + msg); 1125 } 1126 } 1127