1 /* 2 * Copyright 2018 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 android.telephony.data; 18 19 import android.annotation.CallbackExecutor; 20 import android.annotation.NonNull; 21 import android.annotation.SystemApi; 22 import android.app.Service; 23 import android.content.Intent; 24 import android.os.Handler; 25 import android.os.HandlerThread; 26 import android.os.IBinder; 27 import android.os.Looper; 28 import android.os.Message; 29 import android.os.RemoteException; 30 import android.telephony.AccessNetworkConstants; 31 import android.telephony.AccessNetworkConstants.AccessNetworkType; 32 import android.telephony.Annotation.ApnType; 33 import android.telephony.Annotation.NetCapability; 34 import android.telephony.PreciseDataConnectionState; 35 import android.telephony.TelephonyManager; 36 import android.util.Log; 37 import android.util.SparseArray; 38 39 import com.android.internal.annotations.VisibleForTesting; 40 import com.android.internal.telephony.IIntegerConsumer; 41 import com.android.internal.telephony.flags.FeatureFlags; 42 import com.android.internal.telephony.flags.FeatureFlagsImpl; 43 import com.android.internal.util.FunctionalUtils; 44 import com.android.telephony.Rlog; 45 46 import java.util.List; 47 import java.util.Objects; 48 import java.util.concurrent.Executor; 49 import java.util.function.Consumer; 50 51 /** 52 * Base class of the qualified networks service, which is a vendor service providing up-to-date 53 * qualified network information to the frameworks for data handover control. A qualified network 54 * is defined as an access network that is ready for bringing up data connection for given APN 55 * types. 56 * 57 * Services that extend QualifiedNetworksService must register the service in their AndroidManifest 58 * to be detected by the framework. They must be protected by the permission 59 * "android.permission.BIND_TELEPHONY_DATA_SERVICE". The qualified networks service definition in 60 * the manifest must follow the following format: 61 * ... 62 * <service android:name=".xxxQualifiedNetworksService" 63 * android:permission="android.permission.BIND_TELEPHONY_DATA_SERVICE" > 64 * <intent-filter> 65 * <action android:name="android.telephony.data.QualifiedNetworksService" /> 66 * </intent-filter> 67 * </service> 68 * @hide 69 */ 70 @SystemApi 71 public abstract class QualifiedNetworksService extends Service { 72 private static final String TAG = QualifiedNetworksService.class.getSimpleName(); 73 74 public static final String QUALIFIED_NETWORKS_SERVICE_INTERFACE = 75 "android.telephony.data.QualifiedNetworksService"; 76 77 private static final int QNS_CREATE_NETWORK_AVAILABILITY_PROVIDER = 1; 78 private static final int QNS_REMOVE_NETWORK_AVAILABILITY_PROVIDER = 2; 79 private static final int QNS_REMOVE_ALL_NETWORK_AVAILABILITY_PROVIDERS = 3; 80 private static final int QNS_UPDATE_QUALIFIED_NETWORKS = 4; 81 private static final int QNS_APN_THROTTLE_STATUS_CHANGED = 5; 82 private static final int QNS_EMERGENCY_DATA_NETWORK_PREFERRED_TRANSPORT_CHANGED = 6; 83 private static final int QNS_REQUEST_NETWORK_VALIDATION = 7; 84 private static final int QNS_RECONNECT_QUALIFIED_NETWORK = 8; 85 86 /** Feature flags */ 87 private static final FeatureFlags sFeatureFlag = new FeatureFlagsImpl(); 88 89 private final HandlerThread mHandlerThread; 90 91 private final QualifiedNetworksServiceHandler mHandler; 92 93 private final SparseArray<NetworkAvailabilityProvider> mProviders = new SparseArray<>(); 94 95 /** @hide */ 96 @VisibleForTesting 97 public final IQualifiedNetworksServiceWrapper mBinder = new IQualifiedNetworksServiceWrapper(); 98 99 /** 100 * The abstract class of the network availability provider implementation. The vendor qualified 101 * network service must extend this class to report the available networks for data 102 * connection setup. Note that each instance of network availability provider is associated with 103 * one physical SIM slot. 104 */ 105 public abstract class NetworkAvailabilityProvider implements AutoCloseable { 106 private final int mSlotIndex; 107 108 private IQualifiedNetworksServiceCallback mCallback; 109 110 /** 111 * Qualified networks for each APN type. Key is the {@link ApnType}, value is the array 112 * of available networks. 113 */ 114 private SparseArray<int[]> mQualifiedNetworkTypesList = new SparseArray<>(); 115 116 /** 117 * Constructor 118 * @param slotIndex SIM slot index the network availability provider associated with. 119 */ NetworkAvailabilityProvider(int slotIndex)120 public NetworkAvailabilityProvider(int slotIndex) { 121 mSlotIndex = slotIndex; 122 } 123 124 /** 125 * @return SIM slot index the network availability provider associated with. 126 */ getSlotIndex()127 public final int getSlotIndex() { 128 return mSlotIndex; 129 } 130 registerForQualifiedNetworkTypesChanged( IQualifiedNetworksServiceCallback callback)131 private void registerForQualifiedNetworkTypesChanged( 132 IQualifiedNetworksServiceCallback callback) { 133 mCallback = callback; 134 135 // Force sending the qualified networks upon registered. 136 if (mCallback != null) { 137 for (int i = 0; i < mQualifiedNetworkTypesList.size(); i++) { 138 try { 139 mCallback.onQualifiedNetworkTypesChanged( 140 mQualifiedNetworkTypesList.keyAt(i), 141 mQualifiedNetworkTypesList.valueAt(i)); 142 } catch (RemoteException e) { 143 loge("Failed to call onQualifiedNetworksChanged. " + e); 144 } 145 } 146 } 147 } 148 149 /** 150 * Update the suggested qualified networks list. Network availability provider must invoke 151 * this method whenever the suggested qualified networks changes. If this method is never 152 * invoked for certain APN types, then frameworks uses its own logic to determine the 153 * transport to setup the data network. 154 * 155 * For example, QNS can suggest frameworks setting up IMS data network on IWLAN by 156 * specifying {@link ApnSetting#TYPE_IMS} with a list containing 157 * {@link AccessNetworkType#IWLAN}. 158 * 159 * If QNS considers multiple access networks qualified for certain APN type, it can 160 * suggest frameworks by specifying the APN type with multiple access networks in the list, 161 * for example {{@link AccessNetworkType#EUTRAN}, {@link AccessNetworkType#IWLAN}}. 162 * Frameworks will then first attempt to setup data on LTE network, and If the device moves 163 * from LTE to UMTS, then frameworks will perform handover the data network to the second 164 * preferred access network if available. 165 * 166 * If the {@code qualifiedNetworkTypes} list is empty, it means QNS has no suggestion to the 167 * frameworks, and for that APN type frameworks will route the corresponding network 168 * requests to {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN}. 169 * 170 * @param apnTypes APN type(s) of the qualified networks. This must be a bitmask combination 171 * of {@link ApnType}. The same qualified networks will be applicable to all APN types 172 * specified here. 173 * @param qualifiedNetworkTypes List of access network types which are qualified for data 174 * connection setup for {@code apnTypes} in the preferred order. Empty list means QNS has no 175 * suggestion to the frameworks, and for that APN type frameworks will route the 176 * corresponding network requests to {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN}. 177 * 178 * If one of the element is invalid, for example, {@link AccessNetworkType#UNKNOWN}, then 179 * this operation becomes a no-op. 180 */ updateQualifiedNetworkTypes( @pnType int apnTypes, @NonNull List<Integer> qualifiedNetworkTypes)181 public final void updateQualifiedNetworkTypes( 182 @ApnType int apnTypes, @NonNull List<Integer> qualifiedNetworkTypes) { 183 int[] qualifiedNetworkTypesArray = 184 qualifiedNetworkTypes.stream().mapToInt(i->i).toArray(); 185 mHandler.obtainMessage(QNS_UPDATE_QUALIFIED_NETWORKS, mSlotIndex, apnTypes, 186 qualifiedNetworkTypesArray).sendToTarget(); 187 } 188 189 /** 190 * Request to make a clean initial connection instead of handover to a transport type mapped 191 * to the {@code qualifiedNetworkType} for the {@code apnTypes}. This will update the 192 * preferred network type like {@link #updateQualifiedNetworkTypes(int, List)}, however if 193 * the data network for the {@code apnTypes} is not in the state {@link TelephonyManager 194 * #DATA_CONNECTED} or it's already connected on the transport type mapped to the 195 * qualified network type, forced reconnection will be ignored. 196 * 197 * <p>This will tear down current data network even though target transport type mapped to 198 * the {@code qualifiedNetworkType} is not available, and the data network will be connected 199 * to the transport type when it becomes available. 200 * 201 * <p>This is one shot request and does not mean further handover is not allowed to the 202 * qualified network type for this APN type. 203 * 204 * @param apnTypes APN type(s) of the qualified networks. This must be a bitmask combination 205 * of {@link ApnType}. The same qualified networks will be applicable to all APN types 206 * specified here. 207 * @param qualifiedNetworkType Access network types which are qualified for data connection 208 * setup for {@link ApnType}. Empty list means QNS has no suggestion to the frameworks, and 209 * for that APN type frameworks will route the corresponding network requests to 210 * {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN}. 211 * 212 * <p> If one of the element is invalid, for example, {@link AccessNetworkType#UNKNOWN}, 213 * then this operation becomes a no-op. 214 * 215 * @hide 216 */ reconnectQualifiedNetworkType(@pnType int apnTypes, @AccessNetworkConstants.RadioAccessNetworkType int qualifiedNetworkType)217 public final void reconnectQualifiedNetworkType(@ApnType int apnTypes, 218 @AccessNetworkConstants.RadioAccessNetworkType int qualifiedNetworkType) { 219 mHandler.obtainMessage(QNS_RECONNECT_QUALIFIED_NETWORK, mSlotIndex, apnTypes, 220 new Integer(qualifiedNetworkType)).sendToTarget(); 221 } 222 onUpdateQualifiedNetworkTypes( @pnType int apnTypes, int[] qualifiedNetworkTypes)223 private void onUpdateQualifiedNetworkTypes( 224 @ApnType int apnTypes, int[] qualifiedNetworkTypes) { 225 mQualifiedNetworkTypesList.put(apnTypes, qualifiedNetworkTypes); 226 if (mCallback != null) { 227 try { 228 mCallback.onQualifiedNetworkTypesChanged(apnTypes, qualifiedNetworkTypes); 229 } catch (RemoteException e) { 230 loge("Failed to call onQualifiedNetworksChanged. " + e); 231 } 232 } 233 } 234 onReconnectQualifiedNetworkType(@pnType int apnTypes, @AccessNetworkConstants.RadioAccessNetworkType int qualifiedNetworkType)235 private void onReconnectQualifiedNetworkType(@ApnType int apnTypes, 236 @AccessNetworkConstants.RadioAccessNetworkType int qualifiedNetworkType) { 237 if (mCallback != null) { 238 try { 239 mCallback.onReconnectQualifiedNetworkType(apnTypes, qualifiedNetworkType); 240 } catch (RemoteException e) { 241 loge("Failed to call onReconnectQualifiedNetworkType. " + e); 242 } 243 } 244 } 245 246 /** 247 * The framework calls this method when the throttle status of an APN changes. 248 * 249 * This method is meant to be overridden. 250 * 251 * @param statuses the statuses that have changed 252 */ reportThrottleStatusChanged(@onNull List<ThrottleStatus> statuses)253 public void reportThrottleStatusChanged(@NonNull List<ThrottleStatus> statuses) { 254 Log.d(TAG, "reportThrottleStatusChanged: statuses size=" + statuses.size()); 255 } 256 257 /** 258 * The framework calls this method when the preferred transport type used to set up 259 * emergency data network is changed. 260 * 261 * This method is meant to be overridden. 262 * 263 * @param transportType transport type changed to be preferred 264 */ reportEmergencyDataNetworkPreferredTransportChanged( @ccessNetworkConstants.TransportType int transportType)265 public void reportEmergencyDataNetworkPreferredTransportChanged( 266 @AccessNetworkConstants.TransportType int transportType) { 267 Log.d(TAG, "reportEmergencyDataNetworkPreferredTransportChanged: " 268 + AccessNetworkConstants.transportTypeToString(transportType)); 269 } 270 271 /** 272 * Request network validation to the connected data network for given a network capability. 273 * 274 * <p>This network validation can only be performed when a data network is in connected 275 * state, and will not be triggered if the data network does not support network validation 276 * feature or network validation is not in connected state. 277 * 278 * <p>See {@link DataServiceCallback.ResultCode} for the type of response that indicates 279 * whether the request was successfully submitted or had an error. 280 * 281 * <p>If network validation is requested, monitor network validation status in {@link 282 * PreciseDataConnectionState#getNetworkValidationStatus()}. 283 * 284 * @param networkCapability A network capability. (Note that only APN-type capabilities are 285 * supported. 286 * @param executor executor The callback executor that responds whether the request has been 287 * successfully submitted or not. 288 * @param resultCodeCallback A callback to determine whether the request was successfully 289 * submitted or not. 290 */ requestNetworkValidation( @etCapability int networkCapability, @NonNull @CallbackExecutor Executor executor, @NonNull @DataServiceCallback.ResultCode Consumer<Integer> resultCodeCallback)291 public void requestNetworkValidation( 292 @NetCapability int networkCapability, 293 @NonNull @CallbackExecutor Executor executor, 294 @NonNull @DataServiceCallback.ResultCode Consumer<Integer> resultCodeCallback) { 295 Objects.requireNonNull(executor, "executor cannot be null"); 296 Objects.requireNonNull(resultCodeCallback, "resultCodeCallback cannot be null"); 297 298 IIntegerConsumer callback = new IIntegerConsumer.Stub() { 299 @Override 300 public void accept(int result) { 301 executor.execute(() -> resultCodeCallback.accept(result)); 302 } 303 }; 304 305 // Move to the internal handler and process it. 306 mHandler.obtainMessage( 307 QNS_REQUEST_NETWORK_VALIDATION, 308 mSlotIndex, 309 0, 310 new NetworkValidationRequestData(networkCapability, callback)) 311 .sendToTarget(); 312 } 313 314 /** Process a network validation request on the internal handler. */ onRequestNetworkValidation(NetworkValidationRequestData data)315 private void onRequestNetworkValidation(NetworkValidationRequestData data) { 316 try { 317 log("onRequestNetworkValidation"); 318 // Callback to request a network validation. 319 mCallback.onNetworkValidationRequested(data.mNetworkCapability, data.mCallback); 320 } catch (RemoteException | NullPointerException e) { 321 loge("Failed to call onRequestNetworkValidation. " + e); 322 FunctionalUtils.ignoreRemoteException(data.mCallback::accept) 323 .accept(DataServiceCallback.RESULT_ERROR_UNSUPPORTED); 324 } 325 } 326 327 /** 328 * Called when the qualified networks provider is removed. The extended class should 329 * implement this method to perform cleanup works. 330 */ 331 @Override close()332 public abstract void close(); 333 } 334 335 private class QualifiedNetworksServiceHandler extends Handler { QualifiedNetworksServiceHandler(Looper looper)336 QualifiedNetworksServiceHandler(Looper looper) { 337 super(looper); 338 } 339 340 @Override handleMessage(Message message)341 public void handleMessage(Message message) { 342 IQualifiedNetworksServiceCallback callback; 343 final int slotIndex = message.arg1; 344 NetworkAvailabilityProvider provider = mProviders.get(slotIndex); 345 346 switch (message.what) { 347 case QNS_CREATE_NETWORK_AVAILABILITY_PROVIDER: 348 if (mProviders.get(slotIndex) != null) { 349 loge("Network availability provider for slot " + slotIndex 350 + " already existed."); 351 return; 352 } 353 354 provider = onCreateNetworkAvailabilityProvider(slotIndex); 355 if (provider != null) { 356 mProviders.put(slotIndex, provider); 357 358 callback = (IQualifiedNetworksServiceCallback) message.obj; 359 provider.registerForQualifiedNetworkTypesChanged(callback); 360 } else { 361 loge("Failed to create network availability provider. slot index = " 362 + slotIndex); 363 } 364 break; 365 case QNS_APN_THROTTLE_STATUS_CHANGED: 366 if (provider != null) { 367 List<ThrottleStatus> statuses = (List<ThrottleStatus>) message.obj; 368 provider.reportThrottleStatusChanged(statuses); 369 } 370 break; 371 372 case QNS_EMERGENCY_DATA_NETWORK_PREFERRED_TRANSPORT_CHANGED: 373 if (provider != null) { 374 int transportType = (int) message.arg2; 375 provider.reportEmergencyDataNetworkPreferredTransportChanged(transportType); 376 } 377 break; 378 379 case QNS_REMOVE_NETWORK_AVAILABILITY_PROVIDER: 380 if (provider != null) { 381 provider.close(); 382 mProviders.remove(slotIndex); 383 } 384 break; 385 386 case QNS_REMOVE_ALL_NETWORK_AVAILABILITY_PROVIDERS: 387 for (int i = 0; i < mProviders.size(); i++) { 388 provider = mProviders.get(i); 389 if (provider != null) { 390 provider.close(); 391 } 392 } 393 mProviders.clear(); 394 break; 395 396 case QNS_UPDATE_QUALIFIED_NETWORKS: 397 if (provider == null) break; 398 provider.onUpdateQualifiedNetworkTypes(message.arg2, (int[]) message.obj); 399 break; 400 401 case QNS_REQUEST_NETWORK_VALIDATION: 402 if (provider == null) break; 403 provider.onRequestNetworkValidation((NetworkValidationRequestData) message.obj); 404 break; 405 406 case QNS_RECONNECT_QUALIFIED_NETWORK: 407 if (provider == null) break; 408 provider.onReconnectQualifiedNetworkType(message.arg2, (Integer) message.obj); 409 break; 410 } 411 } 412 } 413 414 /** 415 * Default constructor. 416 */ QualifiedNetworksService()417 public QualifiedNetworksService() { 418 mHandlerThread = new HandlerThread(TAG); 419 mHandlerThread.start(); 420 421 mHandler = new QualifiedNetworksServiceHandler(mHandlerThread.getLooper()); 422 log("Qualified networks service created"); 423 } 424 425 /** 426 * Create the instance of {@link NetworkAvailabilityProvider}. Vendor qualified network service 427 * must override this method to facilitate the creation of {@link NetworkAvailabilityProvider} 428 * instances. The system will call this method after binding the qualified networks service for 429 * each active SIM slot index. 430 * 431 * @param slotIndex SIM slot index the qualified networks service associated with. 432 * @return Qualified networks service instance 433 */ 434 @NonNull onCreateNetworkAvailabilityProvider(int slotIndex)435 public abstract NetworkAvailabilityProvider onCreateNetworkAvailabilityProvider(int slotIndex); 436 437 /** @hide */ 438 @Override onBind(Intent intent)439 public IBinder onBind(Intent intent) { 440 if (intent == null || !QUALIFIED_NETWORKS_SERVICE_INTERFACE.equals(intent.getAction())) { 441 loge("Unexpected intent " + intent); 442 return null; 443 } 444 return mBinder; 445 } 446 447 /** @hide */ 448 @Override onUnbind(Intent intent)449 public boolean onUnbind(Intent intent) { 450 mHandler.obtainMessage(QNS_REMOVE_ALL_NETWORK_AVAILABILITY_PROVIDERS).sendToTarget(); 451 return false; 452 } 453 454 /** @hide */ 455 @Override onDestroy()456 public void onDestroy() { 457 mHandlerThread.quit(); 458 } 459 460 /** 461 * A wrapper around IQualifiedNetworksService that forwards calls to implementations of 462 * {@link QualifiedNetworksService}. 463 */ 464 private class IQualifiedNetworksServiceWrapper extends IQualifiedNetworksService.Stub { 465 @Override createNetworkAvailabilityProvider(int slotIndex, IQualifiedNetworksServiceCallback callback)466 public void createNetworkAvailabilityProvider(int slotIndex, 467 IQualifiedNetworksServiceCallback callback) { 468 mHandler.obtainMessage(QNS_CREATE_NETWORK_AVAILABILITY_PROVIDER, slotIndex, 0, 469 callback).sendToTarget(); 470 } 471 472 @Override removeNetworkAvailabilityProvider(int slotIndex)473 public void removeNetworkAvailabilityProvider(int slotIndex) { 474 mHandler.obtainMessage(QNS_REMOVE_NETWORK_AVAILABILITY_PROVIDER, slotIndex, 0) 475 .sendToTarget(); 476 } 477 478 @Override reportThrottleStatusChanged(int slotIndex, List<ThrottleStatus> statuses)479 public void reportThrottleStatusChanged(int slotIndex, 480 List<ThrottleStatus> statuses) { 481 mHandler.obtainMessage(QNS_APN_THROTTLE_STATUS_CHANGED, slotIndex, 0, statuses) 482 .sendToTarget(); 483 } 484 485 @Override reportEmergencyDataNetworkPreferredTransportChanged(int slotIndex, @AccessNetworkConstants.TransportType int transportType)486 public void reportEmergencyDataNetworkPreferredTransportChanged(int slotIndex, 487 @AccessNetworkConstants.TransportType int transportType) { 488 mHandler.obtainMessage( 489 QNS_EMERGENCY_DATA_NETWORK_PREFERRED_TRANSPORT_CHANGED, 490 slotIndex, transportType).sendToTarget(); 491 } 492 } 493 494 private static final class NetworkValidationRequestData { 495 final @NetCapability int mNetworkCapability; 496 final IIntegerConsumer mCallback; 497 NetworkValidationRequestData(@etCapability int networkCapability, @NonNull IIntegerConsumer callback)498 private NetworkValidationRequestData(@NetCapability int networkCapability, 499 @NonNull IIntegerConsumer callback) { 500 mNetworkCapability = networkCapability; 501 mCallback = callback; 502 } 503 } 504 log(String s)505 private void log(String s) { 506 Rlog.d(TAG, s); 507 } 508 loge(String s)509 private void loge(String s) { 510 Rlog.e(TAG, s); 511 } 512 } 513