1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.telephony.qns;
17 
18 import android.content.Context;
19 import android.util.Log;
20 
21 import java.io.PrintWriter;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.concurrent.ConcurrentHashMap;
26 
27 /**
28  * This class manages threshold information registered from AccessNetworkEvaluator It monitors
29  * Cellular or WiFi qualities(WiFi RSSI, 4g/5g RSRP , 3G RSCP , 2G RSSI etc..) and report event if
30  * the network quality changes over the threshold value.
31  */
32 abstract class QualityMonitor {
33     private static final int BASE = 1000;
34     protected static final int EVENT_CELLULAR_QNS_TELEPHONY_INFO_CHANGED = BASE + 1;
35     protected static final int EVENT_WIFI_RSSI_CHANGED = BASE + 2;
36     protected static final int EVENT_WIFI_STATE_CHANGED = BASE + 3;
37     protected static final int EVENT_WIFI_NOTIFY_TIMER_EXPIRED = BASE + 4;
38     protected static final int EVENT_SUBSCRIPTION_ID_CHANGED = BASE + 5;
39     private final String mTag;
40     protected Context mContext;
41     protected final HashMap<String, IThresholdListener> mThresholdCallbackMap = new HashMap<>();
42     protected final ConcurrentHashMap<String, List<Threshold>> mThresholdsList =
43             new ConcurrentHashMap<>();
44     protected final HashMap<String, Boolean> mWaitingThresholds = new HashMap<>();
45 
46     /** To-Do: For future use. */
QualityMonitor(String tag)47     protected QualityMonitor(String tag) {
48         mTag = tag;
49     }
50 
51     /** Get current Quality based on access network & measurement type */
getCurrentQuality(int accessNetwork, int measurementType)52     abstract int getCurrentQuality(int accessNetwork, int measurementType);
53 
54     /** This method registers the thresholds to monitor the signal strengths */
registerThresholdChange( ThresholdCallback thresholdCallback, int netCapability, Threshold[] ths, int slotIndex)55     void registerThresholdChange(
56             ThresholdCallback thresholdCallback,
57             int netCapability,
58             Threshold[] ths,
59             int slotIndex) {
60         String key = getKey(netCapability, slotIndex);
61         Log.d(mTag, "Registering for slotIndex=[" + slotIndex + "], key=[" + key + "]");
62         mThresholdCallbackMap.put(key, thresholdCallback.mCallback);
63     }
64 
65     /** Unregister the Cellular & Wifi Quality threshold */
unregisterThresholdChange(int netCapability, int slotIndex)66     void unregisterThresholdChange(int netCapability, int slotIndex) {
67         String key = getKey(netCapability, slotIndex);
68         Log.d(mTag, "Unregister threshold change for key=[" + key + "]");
69         mThresholdCallbackMap.remove(key);
70         mThresholdsList.remove(key);
71         mWaitingThresholds.remove(key);
72     }
73 
74     /**
75      * It replace/set the new threshold values to listen for the given netCapability.
76      *
77      * @param netCapability Network Capability for which new thresholds are updated
78      * @param slotIndex slot id
79      * @param ths updated thresholds array. If ths is empty; if thresholds are registered for given
80      *     netCapability, it will be cleared and removed from registered list.
81      */
updateThresholdsForNetCapability(int netCapability, int slotIndex, Threshold[] ths)82     void updateThresholdsForNetCapability(int netCapability, int slotIndex, Threshold[] ths) {
83         String key = getKey(netCapability, slotIndex);
84         if (mThresholdCallbackMap.get(key) == null) {
85             throw new IllegalStateException(
86                     "For the netCapability = "
87                             + netCapability
88                             + "["
89                             + slotIndex
90                             + "], no callback is registered");
91         }
92         if (ths == null || ths.length == 0) {
93             mThresholdsList.remove(key);
94             mWaitingThresholds.remove(key);
95         } else {
96             mThresholdsList.put(key, new ArrayList<>(List.of(ths)));
97         }
98         Log.d(mTag, "Thresholds stored: " + mThresholdsList);
99     }
100 
notifyThresholdChange(String key, Threshold[] ths)101     protected abstract void notifyThresholdChange(String key, Threshold[] ths);
102 
103     /**
104      * This method provides unique key to store the hashmap values and need to optimize in future.
105      */
getKey(int netCapability, int slotIndex)106     protected String getKey(int netCapability, int slotIndex) {
107         return netCapability + "_" + slotIndex;
108     }
109 
close()110     public void close() {
111         mThresholdsList.clear();
112         mWaitingThresholds.clear();
113         mThresholdCallbackMap.clear();
114     }
115 
116     /**
117      * Dumps the state of {@link QualityMonitor}
118      *
119      * @param pw {@link PrintWriter} to write the state of the object.
120      * @param prefix String to append at start of dumped log.
121      */
dump(PrintWriter pw, String prefix)122     void dump(PrintWriter pw, String prefix) {
123         pw.println(prefix + "mThresholdCallbackMap=" + mThresholdCallbackMap);
124         pw.println(prefix + "mThresholdsList=" + mThresholdsList);
125         pw.println(prefix + "mWaitingThresholds=" + mWaitingThresholds);
126     }
127 }
128