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