• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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