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