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