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 package com.android.telephony.qns; 17 18 import static android.telephony.CellInfo.UNAVAILABLE; 19 20 import android.annotation.NonNull; 21 import android.content.Context; 22 import android.net.NetworkCapabilities; 23 import android.os.Binder; 24 import android.os.Handler; 25 import android.os.HandlerThread; 26 import android.os.Looper; 27 import android.os.Message; 28 import android.telephony.AccessNetworkConstants.AccessNetworkType; 29 import android.telephony.CellSignalStrength; 30 import android.telephony.CellSignalStrengthGsm; 31 import android.telephony.CellSignalStrengthLte; 32 import android.telephony.CellSignalStrengthNr; 33 import android.telephony.CellSignalStrengthWcdma; 34 import android.telephony.SignalStrength; 35 import android.telephony.SignalStrengthUpdateRequest; 36 import android.telephony.SignalThresholdInfo; 37 import android.telephony.TelephonyCallback; 38 import android.telephony.TelephonyManager; 39 import android.util.Log; 40 import android.util.SparseArray; 41 42 import com.android.internal.annotations.VisibleForTesting; 43 44 import java.io.PrintWriter; 45 import java.util.ArrayList; 46 import java.util.Arrays; 47 import java.util.HashMap; 48 import java.util.HashSet; 49 import java.util.List; 50 import java.util.Map; 51 import java.util.Set; 52 import java.util.concurrent.ConcurrentHashMap; 53 import java.util.concurrent.Executor; 54 55 /** 56 * This class manages cellular threshold information registered from AccessNetworkEvaluator. It 57 * extends QualityMonitor class to implement and notify the signal changes in Cellular RAT. 58 */ 59 class CellularQualityMonitor extends QualityMonitor { 60 61 private static final int MAX_THRESHOLD_COUNT = 62 SignalThresholdInfo.MAXIMUM_NUMBER_OF_THRESHOLDS_ALLOWED; 63 private final String mTag; 64 private TelephonyManager mTelephonyManager; 65 private QnsCarrierConfigManager mConfigManager; 66 private int mSubId; 67 private final int mSlotIndex; 68 private boolean mIsQnsListenerRegistered; 69 private final List<SignalThresholdInfo> mSignalThresholdInfoList; 70 private final HandlerThread mHandlerThread; 71 72 /** 73 * thresholdMatrix stores the thresholds according to measurement type and netCapability. For 74 * ex: LTE_RSRP: {TYPE_IMS: [-112, -110, -90], TYPE_XCAP: [-100, -99]} LTE_RSSNR:{TYPE_IMS: 75 * [-10, -15], TYPE_EMERGENCY: [-15]} 76 */ 77 private final ConcurrentHashMap<String, SparseArray<List<Integer>>> mThresholdMatrix = 78 new ConcurrentHashMap<>(); 79 80 private final HashMap<String, int[]> mThresholdsRegistered = new HashMap<>(); 81 private HashMap<String, Integer> mThresholdWaitTimer = new HashMap<>(); 82 private SignalStrengthUpdateRequest mSSUpdateRequest; 83 private final CellularSignalStrengthListener mSignalStrengthListener; 84 private final QnsTelephonyListener mQnsTelephonyListener; 85 @VisibleForTesting final Handler mHandler; 86 /** 87 * Constructor to instantiate CellularQualityMonitor 88 * 89 * @param context application context 90 * @param listener QnsTelephonyListener instance 91 * @param slotIndex slot index 92 */ CellularQualityMonitor(Context context, QnsCarrierConfigManager configMgr, QnsTelephonyListener listener, int slotIndex)93 CellularQualityMonitor(Context context, 94 QnsCarrierConfigManager configMgr, 95 QnsTelephonyListener listener, 96 int slotIndex) { 97 super(QualityMonitor.class.getSimpleName() + "-C-" + slotIndex); 98 mContext = context; 99 mSlotIndex = slotIndex; 100 mQnsTelephonyListener = listener; 101 102 mTag = CellularQualityMonitor.class.getSimpleName() + "-" + mSlotIndex; 103 mSubId = QnsUtils.getSubId(mContext, mSlotIndex); 104 mIsQnsListenerRegistered = false; 105 mSignalThresholdInfoList = new ArrayList<>(); 106 mHandlerThread = new HandlerThread(mTag); 107 mHandlerThread.start(); 108 mHandler = new CellularEventsHandler(mHandlerThread.getLooper()); 109 mTelephonyManager = mContext.getSystemService(TelephonyManager.class); 110 mQnsTelephonyListener.registerSubscriptionIdListener( 111 mHandler, EVENT_SUBSCRIPTION_ID_CHANGED, null); 112 if (mTelephonyManager != null) { 113 mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId); 114 } else { 115 Log.e(mTag, "Failed to get Telephony Service"); 116 } 117 mConfigManager = configMgr; 118 mSignalStrengthListener = new CellularSignalStrengthListener(mContext.getMainExecutor()); 119 mSignalStrengthListener.setSignalStrengthListener(this::onSignalStrengthsChanged); 120 } 121 122 /** Listener for change of signal strength. */ 123 private interface OnSignalStrengthListener { 124 /** Notify the cellular signal strength changed. */ onSignalStrengthsChanged(SignalStrength signalStrength)125 void onSignalStrengthsChanged(SignalStrength signalStrength); 126 } 127 128 /** {@link TelephonyCallback} to listen to Cellular Service State Changed. */ 129 private class CellularSignalStrengthListener extends TelephonyCallback 130 implements TelephonyCallback.SignalStrengthsListener { 131 private OnSignalStrengthListener mSignalStrengthListener; 132 private Executor mExecutor; 133 CellularSignalStrengthListener(Executor executor)134 CellularSignalStrengthListener(Executor executor) { 135 super(); 136 mExecutor = executor; 137 } 138 setSignalStrengthListener(OnSignalStrengthListener listener)139 void setSignalStrengthListener(OnSignalStrengthListener listener) { 140 mSignalStrengthListener = listener; 141 } 142 143 /** Register a TelephonyCallback for this listener. */ register()144 void register() { 145 long identity = Binder.clearCallingIdentity(); 146 try { 147 mTelephonyManager.registerTelephonyCallback(mExecutor, this); 148 } finally { 149 Binder.restoreCallingIdentity(identity); 150 } 151 } 152 153 /** Unregister a TelephonyCallback for this listener. */ unregister()154 void unregister() { 155 mTelephonyManager.unregisterTelephonyCallback(this); 156 } 157 158 @Override onSignalStrengthsChanged(@onNull SignalStrength signalStrength)159 public void onSignalStrengthsChanged(@NonNull SignalStrength signalStrength) { 160 if (mSignalStrengthListener != null) { 161 Log.d(mTag, "Signal Strength Changed : " + signalStrength); 162 mSignalStrengthListener.onSignalStrengthsChanged(signalStrength); 163 } 164 } 165 } 166 onSignalStrengthsChanged(SignalStrength signalStrength)167 private void onSignalStrengthsChanged(SignalStrength signalStrength) { 168 List<CellSignalStrength> ss = signalStrength.getCellSignalStrengths(); 169 if (!ss.isEmpty()) { 170 for (CellSignalStrength cs : ss) { 171 checkAndNotifySignalStrength(cs); 172 } 173 } 174 } 175 checkAndNotifySignalStrength(CellSignalStrength cellSignalStrength)176 private void checkAndNotifySignalStrength(CellSignalStrength cellSignalStrength) { 177 Log.d(mTag, "CellSignalStrength Changed: " + cellSignalStrength); 178 179 int signalStrength; 180 for (Map.Entry<String, List<Threshold>> entry : mThresholdsList.entrySet()) { 181 // check if key is in waiting list of backhaul 182 if (mWaitingThresholds.getOrDefault(entry.getKey(), false)) { 183 Log.d(mTag, "Backhaul timer already running for the threshold"); 184 continue; 185 } 186 List<Threshold> matchedThresholds = new ArrayList<>(); 187 Threshold threshold; 188 for (Threshold th : entry.getValue()) { 189 signalStrength = 190 getSignalStrength( 191 th.getAccessNetwork(), th.getMeasurementType(), cellSignalStrength); 192 if (signalStrength != UNAVAILABLE && th.isMatching(signalStrength)) { 193 threshold = th.copy(); 194 threshold.setThreshold(signalStrength); 195 matchedThresholds.add(threshold); 196 } 197 } 198 if (matchedThresholds.size() > 0) { 199 notifyThresholdChange(entry.getKey(), matchedThresholds.toArray(new Threshold[0])); 200 } 201 } 202 } 203 204 @Override getCurrentQuality(int accessNetwork, int measurementType)205 synchronized int getCurrentQuality(int accessNetwork, int measurementType) { 206 SignalStrength ss = mTelephonyManager.getSignalStrength(); 207 int quality = SignalStrength.INVALID; // Int Max Value 208 if (ss != null) { 209 List<CellSignalStrength> cellSignalStrengthList = ss.getCellSignalStrengths(); 210 for (CellSignalStrength cs : cellSignalStrengthList) { 211 quality = getSignalStrength(accessNetwork, measurementType, cs); 212 if (quality != UNAVAILABLE) { 213 return quality; 214 } 215 } 216 } 217 return quality; 218 } 219 220 @Override registerThresholdChange( ThresholdCallback thresholdCallback, int netCapability, Threshold[] ths, int slotIndex)221 synchronized void registerThresholdChange( 222 ThresholdCallback thresholdCallback, 223 int netCapability, 224 Threshold[] ths, 225 int slotIndex) { 226 Log.d(mTag, "registerThresholdChange for netCapability= " + netCapability); 227 super.registerThresholdChange(thresholdCallback, netCapability, ths, slotIndex); 228 updateThresholdsForNetCapability(netCapability, slotIndex, ths); 229 } 230 231 @Override unregisterThresholdChange(int netCapability, int slotIndex)232 synchronized void unregisterThresholdChange(int netCapability, int slotIndex) { 233 Log.d(mTag, "unregisterThresholdChange for netCapability= " + netCapability); 234 super.unregisterThresholdChange(netCapability, slotIndex); 235 updateThresholdsMatrix(netCapability, null); 236 if (updateRegisteredThresholdsArray()) { 237 createSignalThresholdsInfoList(); 238 listenRequests(); 239 } 240 } 241 242 @Override updateThresholdsForNetCapability( int netCapability, int slotIndex, Threshold[] ths)243 synchronized void updateThresholdsForNetCapability( 244 int netCapability, int slotIndex, Threshold[] ths) { 245 Log.d(mTag, "updateThresholdsForNetCapability for netCapability= " + netCapability); 246 super.updateThresholdsForNetCapability(netCapability, slotIndex, ths); 247 if (ths != null && ths.length > 0 && !validateThresholdList(ths)) { 248 throw new IllegalStateException("Thresholds are not in valid range."); 249 } 250 updateThresholdsMatrix(netCapability, ths); 251 if (updateRegisteredThresholdsArray()) { 252 createSignalThresholdsInfoList(); 253 listenRequests(); 254 } 255 } 256 257 @Override notifyThresholdChange(String key, Threshold[] ths)258 protected void notifyThresholdChange(String key, Threshold[] ths) { 259 IThresholdListener listener = mThresholdCallbackMap.get(key); 260 Log.d(mTag, "Notify Threshold Change to listener = " + listener); 261 if (listener != null) { 262 listener.onCellularThresholdChanged(ths); 263 } 264 } 265 createSignalThresholdsInfoList()266 private void createSignalThresholdsInfoList() { 267 mSignalThresholdInfoList.clear(); 268 for (Map.Entry<String, int[]> entry : mThresholdsRegistered.entrySet()) { 269 if (entry.getValue().length == 0) continue; 270 int networkType = Integer.parseInt(entry.getKey().split("_")[0]); 271 int measurementType = Integer.parseInt(entry.getKey().split("_")[1]); 272 SignalThresholdInfo.Builder builder = 273 new SignalThresholdInfo.Builder() 274 .setRadioAccessNetworkType(networkType) 275 .setSignalMeasurementType(measurementType) 276 .setThresholds(entry.getValue()); 277 int backhaulTime = mThresholdWaitTimer.getOrDefault(entry.getKey(), -1); 278 if (backhaulTime > 0) { 279 builder.setHysteresisMs(backhaulTime); 280 } 281 int hysteresisDb = mConfigManager.getWwanHysteresisDbLevel(networkType, 282 measurementType); 283 builder.setHysteresisDb(hysteresisDb); 284 mSignalThresholdInfoList.add(builder.build()); 285 Log.d(mTag, "Updated SignalThresholdInfo List: " + mSignalThresholdInfoList); 286 } 287 } 288 updateRegisteredThresholdsArray()289 private boolean updateRegisteredThresholdsArray() { 290 boolean isUpdated = false; 291 for (Map.Entry<String, SparseArray<List<Integer>>> entry : mThresholdMatrix.entrySet()) { 292 SparseArray<List<Integer>> netCapabilityThresholds = 293 mThresholdMatrix.getOrDefault(entry.getKey(), new SparseArray<>()); 294 Set<Integer> thresholdsSet = new HashSet<>(); // to store unique thresholds 295 int count = 0; 296 for (int i = 0; 297 (i < netCapabilityThresholds.size() && count <= MAX_THRESHOLD_COUNT); 298 i++) { 299 List<Integer> thresholdsList = 300 netCapabilityThresholds.get( 301 netCapabilityThresholds.keyAt(i), new ArrayList<>()); 302 for (int t : thresholdsList) { 303 if (thresholdsSet.add(t)) { 304 count++; 305 } 306 if (count >= MAX_THRESHOLD_COUNT) { 307 break; 308 } 309 } 310 } 311 int[] newThresholds = new int[thresholdsSet.size()]; 312 count = 0; 313 for (int i : thresholdsSet) { 314 newThresholds[count++] = i; 315 } 316 Arrays.sort(newThresholds); 317 int[] oldThresholds = mThresholdsRegistered.get(entry.getKey()); 318 Log.d( 319 mTag, 320 "For measurement type= " 321 + entry.getKey() 322 + " old Threshold= " 323 + Arrays.toString(oldThresholds) 324 + " new Threshold= " 325 + Arrays.toString(newThresholds)); 326 if (!Arrays.equals(newThresholds, oldThresholds)) { 327 mThresholdsRegistered.put(entry.getKey(), newThresholds); 328 isUpdated = true; 329 } 330 } 331 return isUpdated; 332 } 333 updateThresholdsMatrix(int netCapability, Threshold[] ths)334 private void updateThresholdsMatrix(int netCapability, Threshold[] ths) { 335 336 Log.d(mTag, "Current threshold matrix: " + mThresholdMatrix); 337 // clear old threshold for the netCapability in given netCapability from threshold matrix. 338 for (Map.Entry<String, SparseArray<List<Integer>>> entry : mThresholdMatrix.entrySet()) { 339 SparseArray<List<Integer>> netCapabilityThresholds = 340 mThresholdMatrix.get(entry.getKey()); 341 if (netCapabilityThresholds != null) { 342 netCapabilityThresholds.remove(netCapability); 343 } 344 } 345 if (ths == null || ths.length == 0) { 346 return; 347 } 348 349 // store new thresholds in threshold matrix 350 for (Threshold th : ths) { 351 String key = th.getAccessNetwork() + "_" + th.getMeasurementType(); 352 SparseArray<List<Integer>> netCapabilityThresholds = 353 mThresholdMatrix.getOrDefault(key, new SparseArray<>()); 354 List<Integer> thresholdsList = 355 netCapabilityThresholds.get(netCapability, new ArrayList<>()); 356 thresholdsList.add(th.getThreshold()); 357 netCapabilityThresholds.put(netCapability, thresholdsList); 358 mThresholdMatrix.put(key, netCapabilityThresholds); 359 mThresholdWaitTimer.put(key, th.getWaitTime()); 360 } 361 Log.d(mTag, "updated thresholds matrix: " + mThresholdMatrix); 362 } 363 364 /** This methods stops listening for the thresholds. */ clearOldRequests()365 private synchronized void clearOldRequests() { 366 if (mSSUpdateRequest != null) { 367 Log.d(mTag, "Clearing request: " + mSSUpdateRequest); 368 mTelephonyManager.clearSignalStrengthUpdateRequest(mSSUpdateRequest); 369 mSSUpdateRequest = null; 370 } 371 mSignalStrengthListener.unregister(); 372 } 373 374 /** This methods starts listening for the thresholds. */ listenRequests()375 private void listenRequests() { 376 clearOldRequests(); 377 if (mSignalThresholdInfoList.size() > 0) { 378 mSSUpdateRequest = 379 new SignalStrengthUpdateRequest.Builder() 380 .setSignalThresholdInfos(mSignalThresholdInfoList) 381 .setReportingRequestedWhileIdle(true) 382 .build(); 383 mTelephonyManager.setSignalStrengthUpdateRequest(mSSUpdateRequest); 384 Log.d(mTag, "Listening to request: " + mSSUpdateRequest); 385 mSignalStrengthListener.register(); 386 if (!mIsQnsListenerRegistered) { 387 mQnsTelephonyListener.registerQnsTelephonyInfoChanged( 388 NetworkCapabilities.NET_CAPABILITY_IMS, 389 mHandler, 390 EVENT_CELLULAR_QNS_TELEPHONY_INFO_CHANGED, 391 null, 392 false); 393 mIsQnsListenerRegistered = true; 394 } 395 } else { 396 Log.d(mTag, "No requests are pending to listen"); 397 mQnsTelephonyListener.unregisterQnsTelephonyInfoChanged( 398 NetworkCapabilities.NET_CAPABILITY_IMS, mHandler); 399 mIsQnsListenerRegistered = false; 400 } 401 } 402 getSignalStrength(int accessNetwork, int measurementType, CellSignalStrength css)403 private int getSignalStrength(int accessNetwork, int measurementType, CellSignalStrength css) { 404 int signalStrength = UNAVAILABLE; 405 switch (measurementType) { 406 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI: 407 if (accessNetwork == AccessNetworkType.GERAN 408 && css instanceof CellSignalStrengthGsm) { 409 signalStrength = ((CellSignalStrengthGsm) css).getRssi(); 410 } 411 break; 412 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSCP: 413 if (accessNetwork == AccessNetworkType.UTRAN 414 && css instanceof CellSignalStrengthWcdma) { 415 signalStrength = ((CellSignalStrengthWcdma) css).getDbm(); 416 } 417 break; 418 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRP: 419 if (accessNetwork == AccessNetworkType.EUTRAN 420 && css instanceof CellSignalStrengthLte) { 421 signalStrength = ((CellSignalStrengthLte) css).getRsrp(); 422 } 423 break; 424 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRQ: 425 if (accessNetwork == AccessNetworkType.EUTRAN 426 && css instanceof CellSignalStrengthLte) { 427 signalStrength = ((CellSignalStrengthLte) css).getRsrq(); 428 } 429 break; 430 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSNR: 431 if (accessNetwork == AccessNetworkType.EUTRAN 432 && css instanceof CellSignalStrengthLte) { 433 signalStrength = ((CellSignalStrengthLte) css).getRssnr(); 434 } 435 break; 436 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRP: 437 if (accessNetwork == AccessNetworkType.NGRAN 438 && css instanceof CellSignalStrengthNr) { 439 signalStrength = ((CellSignalStrengthNr) css).getSsRsrp(); 440 } 441 break; 442 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRQ: 443 if (accessNetwork == AccessNetworkType.NGRAN 444 && css instanceof CellSignalStrengthNr) { 445 signalStrength = ((CellSignalStrengthNr) css).getSsRsrq(); 446 } 447 break; 448 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSSINR: 449 if (accessNetwork == AccessNetworkType.NGRAN 450 && css instanceof CellSignalStrengthNr) { 451 signalStrength = ((CellSignalStrengthNr) css).getSsSinr(); 452 } 453 break; 454 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_ECNO: 455 if (accessNetwork == AccessNetworkType.UTRAN 456 && css instanceof CellSignalStrengthWcdma) { 457 signalStrength = ((CellSignalStrengthWcdma) css).getEcNo(); 458 } 459 break; 460 default: 461 Log.d(mTag, "measurement type = " + measurementType + " not handled."); 462 break; 463 } 464 return signalStrength; 465 } 466 validateThresholdList(Threshold[] ths)467 private boolean validateThresholdList(Threshold[] ths) { 468 for (Threshold threshold : ths) { 469 if (!isValidThreshold(threshold.getMeasurementType(), threshold.getThreshold())) { 470 return false; 471 } 472 } 473 return true; 474 } 475 476 /** Return true if signal measurement type is valid and the threshold value is in range. */ isValidThreshold(int type, int threshold)477 private static boolean isValidThreshold(int type, int threshold) { 478 switch (type) { 479 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI: 480 return threshold >= SignalThresholdInfo.SIGNAL_RSSI_MIN_VALUE 481 && threshold <= SignalThresholdInfo.SIGNAL_RSSI_MAX_VALUE; 482 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSCP: 483 return threshold >= SignalThresholdInfo.SIGNAL_RSCP_MIN_VALUE 484 && threshold <= SignalThresholdInfo.SIGNAL_RSCP_MAX_VALUE; 485 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRP: 486 return threshold >= SignalThresholdInfo.SIGNAL_RSRP_MIN_VALUE 487 && threshold <= SignalThresholdInfo.SIGNAL_RSRP_MAX_VALUE; 488 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRQ: 489 return threshold >= SignalThresholdInfo.SIGNAL_RSRQ_MIN_VALUE 490 && threshold <= SignalThresholdInfo.SIGNAL_RSRQ_MAX_VALUE; 491 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSNR: 492 return threshold >= SignalThresholdInfo.SIGNAL_RSSNR_MIN_VALUE 493 && threshold <= SignalThresholdInfo.SIGNAL_RSSNR_MAX_VALUE; 494 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRP: 495 return threshold >= SignalThresholdInfo.SIGNAL_SSRSRP_MIN_VALUE 496 && threshold <= SignalThresholdInfo.SIGNAL_SSRSRP_MAX_VALUE; 497 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRQ: 498 return threshold >= SignalThresholdInfo.SIGNAL_SSRSRQ_MIN_VALUE 499 && threshold <= SignalThresholdInfo.SIGNAL_SSRSRQ_MAX_VALUE; 500 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSSINR: 501 return threshold >= SignalThresholdInfo.SIGNAL_SSSINR_MIN_VALUE 502 && threshold <= SignalThresholdInfo.SIGNAL_SSSINR_MAX_VALUE; 503 case SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_ECNO: 504 return threshold >= SignalThresholdInfo.SIGNAL_ECNO_MIN_VALUE 505 && threshold <= SignalThresholdInfo.SIGNAL_ECNO_MAX_VALUE; 506 507 default: 508 return false; 509 } 510 } 511 512 @VisibleForTesting getSignalThresholdInfo()513 List<SignalThresholdInfo> getSignalThresholdInfo() { 514 return mSignalThresholdInfoList; 515 } 516 517 private class CellularEventsHandler extends Handler { CellularEventsHandler(Looper looper)518 CellularEventsHandler(Looper looper) { 519 super(looper); 520 } 521 522 @Override handleMessage(@onNull Message msg)523 public void handleMessage(@NonNull Message msg) { 524 Log.d(mTag, "handleMessage what = " + msg.what); 525 QnsAsyncResult ar; 526 switch (msg.what) { 527 case EVENT_CELLULAR_QNS_TELEPHONY_INFO_CHANGED: 528 ar = (QnsAsyncResult) msg.obj; 529 if (ar.mException == null 530 && ar.mResult instanceof QnsTelephonyListener.QnsTelephonyInfo) { 531 QnsTelephonyListener.QnsTelephonyInfo info = 532 (QnsTelephonyListener.QnsTelephonyInfo) ar.mResult; 533 onQnsTelephonyInfoChanged(info); 534 } 535 break; 536 case EVENT_SUBSCRIPTION_ID_CHANGED: 537 ar = (QnsAsyncResult) msg.obj; 538 int newSubId = (int) ar.mResult; 539 clearOldRequests(); 540 mSubId = newSubId; 541 mTelephonyManager = 542 mContext.getSystemService(TelephonyManager.class) 543 .createForSubscriptionId(mSubId); 544 break; 545 default: 546 Log.d(mTag, "Not Handled !"); 547 } 548 } 549 550 QnsTelephonyListener.QnsTelephonyInfo mLastQnsTelephonyInfo = null; 551 onQnsTelephonyInfoChanged(QnsTelephonyListener.QnsTelephonyInfo info)552 private void onQnsTelephonyInfoChanged(QnsTelephonyListener.QnsTelephonyInfo info) { 553 if (mLastQnsTelephonyInfo == null 554 || mLastQnsTelephonyInfo.getDataNetworkType() != info.getDataNetworkType() 555 || mLastQnsTelephonyInfo.getDataRegState() != info.getDataRegState() 556 || mLastQnsTelephonyInfo.isCellularAvailable() != info.isCellularAvailable()) { 557 if (!info.isCellularAvailable()) { 558 clearOldRequests(); 559 } 560 mLastQnsTelephonyInfo = info; 561 } 562 } 563 } 564 565 @VisibleForTesting 566 @Override close()567 public void close() { 568 mQnsTelephonyListener.unregisterSubscriptionIdChanged(mHandler); 569 clearOldRequests(); 570 mSignalThresholdInfoList.clear(); 571 mIsQnsListenerRegistered = false; 572 if (mHandlerThread != null) { 573 mHandlerThread.quit(); 574 } 575 } 576 577 @Override dump(PrintWriter pw, String prefix)578 void dump(PrintWriter pw, String prefix) { 579 pw.println(prefix + "------------------------------"); 580 pw.println(prefix + "CellularQualityMonitor[" + mSlotIndex + "]:"); 581 pw.println(prefix + "mSubId=" + mSubId); 582 super.dump(pw, prefix); 583 pw.println(prefix + "mIsQnsListenerRegistered=" + mIsQnsListenerRegistered); 584 pw.println(prefix + "mSignalThresholdInfoList=" + mSignalThresholdInfoList); 585 pw.println(prefix + "mSSUpdateRequest=" + mSSUpdateRequest); 586 pw.println(prefix + "mThresholdMatrix=" + mThresholdMatrix); 587 pw.println(prefix + "mThresholdsRegistered=" + mThresholdsRegistered); 588 pw.println(prefix + "mThresholdWaitTimer=" + mThresholdWaitTimer); 589 } 590 } 591