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