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