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