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.telephony.qns; 18 19 import static android.telephony.data.ThrottleStatus.THROTTLE_TYPE_ELAPSED_TIME; 20 21 import android.annotation.NonNull; 22 import android.content.Context; 23 import android.net.NetworkCapabilities; 24 import android.os.Handler; 25 import android.os.HandlerThread; 26 import android.os.Looper; 27 import android.os.Message; 28 import android.telephony.AccessNetworkConstants; 29 import android.telephony.data.QualifiedNetworksService; 30 import android.telephony.data.ThrottleStatus; 31 import android.util.Log; 32 33 import com.android.internal.annotations.VisibleForTesting; 34 35 import java.io.FileDescriptor; 36 import java.io.PrintWriter; 37 import java.util.HashMap; 38 import java.util.List; 39 import java.util.Map; 40 41 /** 42 * Implementation of the qualified networks service, which is a service providing up-to-date 43 * qualified network information to the frameworks for data handover control. A qualified network is 44 * defined as an access network that is ready for bringing up data connection for given APN types. 45 */ 46 public class QualifiedNetworksServiceImpl extends QualifiedNetworksService { 47 48 static final String LOG_TAG = QualifiedNetworksServiceImpl.class.getSimpleName(); 49 private static final boolean DBG = true; 50 private static final int QNS_CONFIGURATION_LOADED = 1; 51 private static final int QUALIFIED_NETWORKS_CHANGED = 2; 52 private static final int QNS_CONFIGURATION_CHANGED = 3; 53 HashMap<Integer, NetworkAvailabilityProviderImpl> mProviderMap = new HashMap<>(); 54 HashMap<Integer, HandlerThread> mHandlerThreadMap = new HashMap<>(); 55 Context mContext; 56 HandlerThread mHandlerThread; 57 @VisibleForTesting QnsComponents mQnsComponents; 58 59 /** Default constructor. */ QualifiedNetworksServiceImpl()60 public QualifiedNetworksServiceImpl() { 61 super(); 62 log("created QualifiedNetworksServiceImpl."); 63 } 64 65 /** 66 * Create the instance of {@link NetworkAvailabilityProvider}. Vendor qualified network service 67 * must override this method to facilitate the creation of {@link NetworkAvailabilityProvider} 68 * instances. The system will call this method after binding the qualified networks service for 69 * each active SIM slot index. 70 * 71 * @param slotIndex SIM slot index the qualified networks service associated with. 72 * @return Qualified networks service instance 73 */ 74 @Override onCreateNetworkAvailabilityProvider(int slotIndex)75 public NetworkAvailabilityProvider onCreateNetworkAvailabilityProvider(int slotIndex) { 76 log("Qualified Networks Service created for slot " + slotIndex); 77 if (!QnsUtils.isValidSlotIndex(mContext, slotIndex)) { 78 log("Invalid slotIndex " + slotIndex + ". fail to create NetworkAvailabilityProvider"); 79 return null; 80 } 81 if (!mHandlerThreadMap.containsKey(slotIndex)) { 82 HandlerThread ht = new HandlerThread("NapConfigHandler-" + slotIndex); 83 ht.start(); 84 mHandlerThreadMap.put(slotIndex, ht); 85 } 86 NetworkAvailabilityProviderImpl provider = new NetworkAvailabilityProviderImpl(slotIndex); 87 mProviderMap.put(slotIndex, provider); 88 return provider; 89 } 90 91 @Override onCreate()92 public void onCreate() { 93 log("onCreate"); 94 mContext = getApplicationContext(); 95 mQnsComponents = new QnsComponents(mContext); 96 mHandlerThread = new HandlerThread(LOG_TAG); 97 mHandlerThread.start(); 98 } 99 100 @Override onDestroy()101 public void onDestroy() { 102 log("onDestroy"); 103 for (NetworkAvailabilityProviderImpl provider : mProviderMap.values()) { 104 provider.close(); 105 } 106 for (HandlerThread ht : mHandlerThreadMap.values()) { 107 ht.quitSafely(); 108 } 109 mHandlerThreadMap.clear(); 110 mProviderMap.clear(); 111 mHandlerThread.quitSafely(); 112 super.onDestroy(); 113 } 114 log(String s)115 protected void log(String s) { 116 if (DBG) Log.d(LOG_TAG, s); 117 } 118 119 static class QualifiedNetworksInfo { 120 int mNetCapability; 121 List<Integer> mAccessNetworkTypes; 122 QualifiedNetworksInfo(int netCapability, List<Integer> accessNetworkTypes)123 QualifiedNetworksInfo(int netCapability, List<Integer> accessNetworkTypes) { 124 mNetCapability = netCapability; 125 mAccessNetworkTypes = accessNetworkTypes; 126 } 127 getNetCapability()128 int getNetCapability() { 129 return mNetCapability; 130 } 131 setNetCapability(int netCapability)132 void setNetCapability(int netCapability) { 133 mNetCapability = netCapability; 134 } 135 getAccessNetworkTypes()136 List<Integer> getAccessNetworkTypes() { 137 return mAccessNetworkTypes; 138 } 139 setAccessNetworkTypes(List<Integer> accessNetworkTypes)140 void setAccessNetworkTypes(List<Integer> accessNetworkTypes) { 141 mAccessNetworkTypes = accessNetworkTypes; 142 } 143 } 144 145 /** 146 * The network availability provider implementation class. The qualified network service must 147 * extend this class to report the available networks for data connection setup. Note that each 148 * instance of network availability provider is associated with slot. 149 */ 150 public class NetworkAvailabilityProviderImpl extends NetworkAvailabilityProvider { 151 private final String mLogTag; 152 private final int mSlotIndex; 153 @VisibleForTesting Handler mHandler; 154 @VisibleForTesting Handler mConfigHandler; 155 private boolean mIsQnsConfigChangeRegistered = false; 156 157 protected QnsCarrierConfigManager mConfigManager; 158 protected HashMap<Integer, AccessNetworkEvaluator> mEvaluators = new HashMap<>(); 159 private boolean mIsClosed; 160 161 /** 162 * Constructor 163 * 164 * @param slotIndex SIM slot index the network availability provider associated with. 165 */ NetworkAvailabilityProviderImpl(int slotIndex)166 public NetworkAvailabilityProviderImpl(int slotIndex) { 167 super(slotIndex); 168 mLogTag = NetworkAvailabilityProviderImpl.class.getSimpleName() + "_" + slotIndex; 169 170 mIsClosed = false; 171 mSlotIndex = slotIndex; 172 mConfigHandler = new NapHandler(mHandlerThreadMap.get(mSlotIndex).getLooper()); 173 mConfigHandler.post(this::initNetworkAvailabilityProvider); 174 mHandler = new NapHandler(mHandlerThread.getLooper()); 175 } 176 177 private class NapHandler extends Handler { NapHandler(Looper looper)178 NapHandler(Looper looper) { 179 super(looper); 180 } 181 182 @Override handleMessage(Message msg)183 public void handleMessage(Message msg) { 184 super.handleMessage(msg); 185 switch (msg.what) { 186 case QNS_CONFIGURATION_LOADED: 187 onConfigurationLoaded(); 188 break; 189 case QNS_CONFIGURATION_CHANGED: 190 log("Qns Configuration changed received"); 191 onConfigurationChanged(); 192 break; 193 case QUALIFIED_NETWORKS_CHANGED: 194 QnsAsyncResult ar = (QnsAsyncResult) msg.obj; 195 onQualifiedNetworksChanged((QualifiedNetworksInfo) ar.mResult); 196 break; 197 default: 198 log("got event " + msg.what + " never reached here."); 199 break; 200 } 201 } 202 } 203 initNetworkAvailabilityProvider()204 private void initNetworkAvailabilityProvider() { 205 mQnsComponents.createQnsComponents(mSlotIndex); 206 mConfigManager = mQnsComponents.getQnsCarrierConfigManager(mSlotIndex); 207 mConfigManager.registerForConfigurationLoaded(mConfigHandler, QNS_CONFIGURATION_LOADED); 208 } 209 onConfigurationLoaded()210 protected void onConfigurationLoaded() { 211 log("onConfigurationLoaded"); 212 // Register for Upgradable Config items load case 213 if (!mIsQnsConfigChangeRegistered) { 214 mConfigManager.registerForConfigurationChanged( 215 mConfigHandler, QNS_CONFIGURATION_CHANGED); 216 mIsQnsConfigChangeRegistered = true; 217 } 218 219 HashMap<Integer, AccessNetworkEvaluator> evaluators = new HashMap<>(); 220 List<Integer> netCapabilities = mConfigManager.getQnsSupportedNetCapabilities(); 221 222 for (int netCapability : netCapabilities) { 223 int transportType = mConfigManager.getQnsSupportedTransportType(netCapability); 224 if (transportType < 0 225 || transportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_WWAN) { 226 continue; 227 } 228 if (mEvaluators.get(netCapability) != null) { 229 AccessNetworkEvaluator evaluator = mEvaluators.remove(netCapability); 230 evaluators.put(netCapability, evaluator); 231 // reuse evaluator 232 evaluator.rebuild(); 233 } else { 234 AccessNetworkEvaluator evaluator = 235 new AccessNetworkEvaluator(mQnsComponents, netCapability, mSlotIndex); 236 evaluator.registerForQualifiedNetworksChanged( 237 mHandler, QUALIFIED_NETWORKS_CHANGED); 238 evaluators.put(netCapability, evaluator); 239 } 240 } 241 for (Integer capability : mEvaluators.keySet()) { 242 AccessNetworkEvaluator evaluator = mEvaluators.get(capability); 243 evaluator.unregisterForQualifiedNetworksChanged(mHandler); 244 evaluator.close(); 245 } 246 mEvaluators.clear(); 247 mEvaluators = evaluators; 248 } 249 onConfigurationChanged()250 protected void onConfigurationChanged() {} 251 onQualifiedNetworksChanged(QualifiedNetworksInfo info)252 private void onQualifiedNetworksChanged(QualifiedNetworksInfo info) { 253 log( 254 "Calling updateQualifiedNetworkTypes for mNetCapability[" 255 + QnsUtils.getNameOfNetCapability(info.getNetCapability()) 256 + "], preferred networks " 257 + QnsUtils.getStringAccessNetworkTypes(info.getAccessNetworkTypes())); 258 259 int apnType = QnsUtils.getApnTypeFromNetCapability(info.getNetCapability()); 260 updateQualifiedNetworkTypes(apnType, info.getAccessNetworkTypes()); 261 } 262 263 @Override reportThrottleStatusChanged(@onNull List<ThrottleStatus> statuses)264 public void reportThrottleStatusChanged(@NonNull List<ThrottleStatus> statuses) { 265 log("reportThrottleStatusChanged: statuses size=" + statuses.size()); 266 for (ThrottleStatus ts : statuses) { 267 int netCapability; 268 try { 269 netCapability = QnsUtils.getNetCapabilityFromApnType(ts.getApnType()); 270 } catch (IllegalArgumentException e) { 271 continue; 272 } 273 log("ThrottleStatus:" + ts + ", netCapability" + netCapability); 274 if (ts.getSlotIndex() != getSlotIndex()) { 275 continue; 276 } 277 AccessNetworkEvaluator evaluator = mEvaluators.get(netCapability); 278 if (evaluator == null) { 279 continue; 280 } 281 boolean isThrottle = ts.getThrottleType() == THROTTLE_TYPE_ELAPSED_TIME; 282 evaluator.updateThrottleStatus( 283 isThrottle, ts.getThrottleExpiryTimeMillis(), ts.getTransportType()); 284 } 285 } 286 287 @Override reportEmergencyDataNetworkPreferredTransportChanged( @ccessNetworkConstants.TransportType int transportType)288 public void reportEmergencyDataNetworkPreferredTransportChanged( 289 @AccessNetworkConstants.TransportType int transportType) { 290 log("reportEmergencyDataNetworkPreferredTransportChanged: " 291 + QnsConstants.transportTypeToString(transportType)); 292 AccessNetworkEvaluator evaluator = 293 mEvaluators.get(NetworkCapabilities.NET_CAPABILITY_EIMS); 294 if (evaluator != null) { 295 evaluator.onEmergencyPreferredTransportTypeChanged(transportType); 296 } else { 297 log("There is no Emergency ANE"); 298 } 299 } 300 301 @Override close()302 public synchronized void close() { 303 mConfigHandler.post(this::onClose); 304 } 305 onClose()306 private synchronized void onClose() { 307 if (!mIsClosed) { 308 mIsClosed = true; 309 log("closing NetworkAvailabilityProviderImpl"); 310 mConfigManager.unregisterForConfigurationLoaded(mConfigHandler); 311 mConfigManager.unregisterForConfigurationChanged(mConfigHandler); 312 mIsQnsConfigChangeRegistered = false; 313 for (Integer netCapability : mEvaluators.keySet()) { 314 AccessNetworkEvaluator evaluator = mEvaluators.get(netCapability); 315 evaluator.unregisterForQualifiedNetworksChanged(mHandler); 316 evaluator.close(); 317 } 318 mQnsComponents.closeComponents(mSlotIndex); 319 mEvaluators.clear(); 320 } 321 } 322 log(String s)323 protected void log(String s) { 324 if (DBG) Log.d(mLogTag, s); 325 } 326 327 /** 328 * Dumps the state of {@link QualityMonitor} 329 * 330 * @param pw {@link PrintWriter} to write the state of the object. 331 * @param prefix String to append at start of dumped log. 332 */ dump(PrintWriter pw, String prefix)333 void dump(PrintWriter pw, String prefix) { 334 pw.println(prefix + "------------------------------"); 335 pw.println(prefix + "NetworkAvailabilityProviderImpl[" + mSlotIndex + "]:"); 336 for (Map.Entry<Integer, AccessNetworkEvaluator> aneMap : mEvaluators.entrySet()) { 337 AccessNetworkEvaluator ane = aneMap.getValue(); 338 ane.dump(pw, prefix + " "); 339 } 340 QnsTelephonyListener tl = mQnsComponents.getQnsTelephonyListener(mSlotIndex); 341 if (tl != null) { 342 tl.dump(pw, prefix + " "); 343 } 344 CellularQualityMonitor cQM = mQnsComponents.getCellularQualityMonitor(mSlotIndex); 345 if (cQM != null) { 346 cQM.dump(pw, prefix + " "); 347 } 348 } 349 } 350 351 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)352 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 353 super.dump(fd, pw, args); 354 pw.println("QualifiedNetworksServiceImpl:"); 355 pw.println("=============================="); 356 for (Map.Entry<Integer, NetworkAvailabilityProviderImpl> providerMap : 357 mProviderMap.entrySet()) { 358 NetworkAvailabilityProviderImpl provider = providerMap.getValue(); 359 provider.dump(pw, " "); 360 } 361 mQnsComponents.dump(pw); 362 pw.println("=============================="); 363 } 364 } 365