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.NonNull; 20 import android.annotation.SystemApi; 21 import android.app.Service; 22 import android.content.Intent; 23 import android.os.Handler; 24 import android.os.HandlerThread; 25 import android.os.IBinder; 26 import android.os.Looper; 27 import android.os.Message; 28 import android.os.RemoteException; 29 import android.telephony.AccessNetworkConstants.AccessNetworkType; 30 import android.telephony.Annotation.ApnType; 31 import android.util.Log; 32 import android.util.SparseArray; 33 34 import com.android.internal.annotations.VisibleForTesting; 35 import com.android.telephony.Rlog; 36 37 import java.util.List; 38 39 /** 40 * Base class of the qualified networks service, which is a vendor service providing up-to-date 41 * qualified network information to the frameworks for data handover control. A qualified network 42 * is defined as an access network that is ready for bringing up data connection for given APN 43 * types. 44 * 45 * Services that extend QualifiedNetworksService must register the service in their AndroidManifest 46 * to be detected by the framework. They must be protected by the permission 47 * "android.permission.BIND_TELEPHONY_DATA_SERVICE". The qualified networks service definition in 48 * the manifest must follow the following format: 49 * ... 50 * <service android:name=".xxxQualifiedNetworksService" 51 * android:permission="android.permission.BIND_TELEPHONY_DATA_SERVICE" > 52 * <intent-filter> 53 * <action android:name="android.telephony.data.QualifiedNetworksService" /> 54 * </intent-filter> 55 * </service> 56 * @hide 57 */ 58 @SystemApi 59 public abstract class QualifiedNetworksService extends Service { 60 private static final String TAG = QualifiedNetworksService.class.getSimpleName(); 61 62 public static final String QUALIFIED_NETWORKS_SERVICE_INTERFACE = 63 "android.telephony.data.QualifiedNetworksService"; 64 65 private static final int QNS_CREATE_NETWORK_AVAILABILITY_PROVIDER = 1; 66 private static final int QNS_REMOVE_NETWORK_AVAILABILITY_PROVIDER = 2; 67 private static final int QNS_REMOVE_ALL_NETWORK_AVAILABILITY_PROVIDERS = 3; 68 private static final int QNS_UPDATE_QUALIFIED_NETWORKS = 4; 69 private static final int QNS_APN_THROTTLE_STATUS_CHANGED = 5; 70 71 private final HandlerThread mHandlerThread; 72 73 private final QualifiedNetworksServiceHandler mHandler; 74 75 private final SparseArray<NetworkAvailabilityProvider> mProviders = new SparseArray<>(); 76 77 /** @hide */ 78 @VisibleForTesting 79 public final IQualifiedNetworksServiceWrapper mBinder = new IQualifiedNetworksServiceWrapper(); 80 81 /** 82 * The abstract class of the network availability provider implementation. The vendor qualified 83 * network service must extend this class to report the available networks for data 84 * connection setup. Note that each instance of network availability provider is associated with 85 * one physical SIM slot. 86 */ 87 public abstract class NetworkAvailabilityProvider implements AutoCloseable { 88 private final int mSlotIndex; 89 90 private IQualifiedNetworksServiceCallback mCallback; 91 92 /** 93 * Qualified networks for each APN type. Key is the {@link ApnType}, value is the array 94 * of available networks. 95 */ 96 private SparseArray<int[]> mQualifiedNetworkTypesList = new SparseArray<>(); 97 98 /** 99 * Constructor 100 * @param slotIndex SIM slot index the network availability provider associated with. 101 */ NetworkAvailabilityProvider(int slotIndex)102 public NetworkAvailabilityProvider(int slotIndex) { 103 mSlotIndex = slotIndex; 104 } 105 106 /** 107 * @return SIM slot index the network availability provider associated with. 108 */ getSlotIndex()109 public final int getSlotIndex() { 110 return mSlotIndex; 111 } 112 registerForQualifiedNetworkTypesChanged( IQualifiedNetworksServiceCallback callback)113 private void registerForQualifiedNetworkTypesChanged( 114 IQualifiedNetworksServiceCallback callback) { 115 mCallback = callback; 116 117 // Force sending the qualified networks upon registered. 118 if (mCallback != null) { 119 for (int i = 0; i < mQualifiedNetworkTypesList.size(); i++) { 120 try { 121 mCallback.onQualifiedNetworkTypesChanged( 122 mQualifiedNetworkTypesList.keyAt(i), 123 mQualifiedNetworkTypesList.valueAt(i)); 124 } catch (RemoteException e) { 125 loge("Failed to call onQualifiedNetworksChanged. " + e); 126 } 127 } 128 } 129 } 130 131 /** 132 * Update the qualified networks list. Network availability provider must invoke this method 133 * whenever the qualified networks changes. If this method is never invoked for certain 134 * APN types, then frameworks will always use the default (i.e. cellular) data and network 135 * service. 136 * 137 * @param apnTypes APN types of the qualified networks. This must be a bitmask combination 138 * of {@link ApnType}. 139 * @param qualifiedNetworkTypes List of network types which are qualified for data 140 * connection setup for {@link @apnType} in the preferred order. Each element in the list 141 * is a {@link AccessNetworkType}. An empty list indicates no networks are qualified 142 * for data setup. 143 */ updateQualifiedNetworkTypes( @pnType int apnTypes, @NonNull List<Integer> qualifiedNetworkTypes)144 public final void updateQualifiedNetworkTypes( 145 @ApnType int apnTypes, @NonNull List<Integer> qualifiedNetworkTypes) { 146 int[] qualifiedNetworkTypesArray = 147 qualifiedNetworkTypes.stream().mapToInt(i->i).toArray(); 148 mHandler.obtainMessage(QNS_UPDATE_QUALIFIED_NETWORKS, mSlotIndex, apnTypes, 149 qualifiedNetworkTypesArray).sendToTarget(); 150 } 151 onUpdateQualifiedNetworkTypes(@pnType int apnTypes, int[] qualifiedNetworkTypes)152 private void onUpdateQualifiedNetworkTypes(@ApnType int apnTypes, 153 int[] qualifiedNetworkTypes) { 154 mQualifiedNetworkTypesList.put(apnTypes, qualifiedNetworkTypes); 155 if (mCallback != null) { 156 try { 157 mCallback.onQualifiedNetworkTypesChanged(apnTypes, qualifiedNetworkTypes); 158 } catch (RemoteException e) { 159 loge("Failed to call onQualifiedNetworksChanged. " + e); 160 } 161 } 162 } 163 164 /** 165 * The framework calls this method when the throttle status of an APN changes. 166 * 167 * This method is meant to be overridden. 168 * 169 * @param statuses the statuses that have changed 170 */ reportThrottleStatusChanged(@onNull List<ThrottleStatus> statuses)171 public void reportThrottleStatusChanged(@NonNull List<ThrottleStatus> statuses) { 172 Log.d(TAG, "reportThrottleStatusChanged: statuses size=" + statuses.size()); 173 } 174 175 /** 176 * Called when the qualified networks provider is removed. The extended class should 177 * implement this method to perform cleanup works. 178 */ 179 @Override close()180 public abstract void close(); 181 } 182 183 private class QualifiedNetworksServiceHandler extends Handler { QualifiedNetworksServiceHandler(Looper looper)184 QualifiedNetworksServiceHandler(Looper looper) { 185 super(looper); 186 } 187 188 @Override handleMessage(Message message)189 public void handleMessage(Message message) { 190 IQualifiedNetworksServiceCallback callback; 191 final int slotIndex = message.arg1; 192 NetworkAvailabilityProvider provider = mProviders.get(slotIndex); 193 194 switch (message.what) { 195 case QNS_CREATE_NETWORK_AVAILABILITY_PROVIDER: 196 if (mProviders.get(slotIndex) != null) { 197 loge("Network availability provider for slot " + slotIndex 198 + " already existed."); 199 return; 200 } 201 202 provider = onCreateNetworkAvailabilityProvider(slotIndex); 203 if (provider != null) { 204 mProviders.put(slotIndex, provider); 205 206 callback = (IQualifiedNetworksServiceCallback) message.obj; 207 provider.registerForQualifiedNetworkTypesChanged(callback); 208 } else { 209 loge("Failed to create network availability provider. slot index = " 210 + slotIndex); 211 } 212 break; 213 case QNS_APN_THROTTLE_STATUS_CHANGED: 214 if (provider != null) { 215 List<ThrottleStatus> statuses = (List<ThrottleStatus>) message.obj; 216 provider.reportThrottleStatusChanged(statuses); 217 } 218 break; 219 220 case QNS_REMOVE_NETWORK_AVAILABILITY_PROVIDER: 221 if (provider != null) { 222 provider.close(); 223 mProviders.remove(slotIndex); 224 } 225 break; 226 227 case QNS_REMOVE_ALL_NETWORK_AVAILABILITY_PROVIDERS: 228 for (int i = 0; i < mProviders.size(); i++) { 229 provider = mProviders.get(i); 230 if (provider != null) { 231 provider.close(); 232 } 233 } 234 mProviders.clear(); 235 break; 236 237 case QNS_UPDATE_QUALIFIED_NETWORKS: 238 if (provider == null) break; 239 provider.onUpdateQualifiedNetworkTypes(message.arg2, (int[]) message.obj); 240 break; 241 } 242 } 243 } 244 245 /** 246 * Default constructor. 247 */ QualifiedNetworksService()248 public QualifiedNetworksService() { 249 mHandlerThread = new HandlerThread(TAG); 250 mHandlerThread.start(); 251 252 mHandler = new QualifiedNetworksServiceHandler(mHandlerThread.getLooper()); 253 log("Qualified networks service created"); 254 } 255 256 /** 257 * Create the instance of {@link NetworkAvailabilityProvider}. Vendor qualified network service 258 * must override this method to facilitate the creation of {@link NetworkAvailabilityProvider} 259 * instances. The system will call this method after binding the qualified networks service for 260 * each active SIM slot index. 261 * 262 * @param slotIndex SIM slot index the qualified networks service associated with. 263 * @return Qualified networks service instance 264 */ 265 @NonNull onCreateNetworkAvailabilityProvider(int slotIndex)266 public abstract NetworkAvailabilityProvider onCreateNetworkAvailabilityProvider(int slotIndex); 267 268 /** @hide */ 269 @Override onBind(Intent intent)270 public IBinder onBind(Intent intent) { 271 if (intent == null || !QUALIFIED_NETWORKS_SERVICE_INTERFACE.equals(intent.getAction())) { 272 loge("Unexpected intent " + intent); 273 return null; 274 } 275 return mBinder; 276 } 277 278 /** @hide */ 279 @Override onUnbind(Intent intent)280 public boolean onUnbind(Intent intent) { 281 mHandler.obtainMessage(QNS_REMOVE_ALL_NETWORK_AVAILABILITY_PROVIDERS).sendToTarget(); 282 return false; 283 } 284 285 /** @hide */ 286 @Override onDestroy()287 public void onDestroy() { 288 mHandlerThread.quit(); 289 } 290 291 /** 292 * A wrapper around IQualifiedNetworksService that forwards calls to implementations of 293 * {@link QualifiedNetworksService}. 294 */ 295 private class IQualifiedNetworksServiceWrapper extends IQualifiedNetworksService.Stub { 296 @Override createNetworkAvailabilityProvider(int slotIndex, IQualifiedNetworksServiceCallback callback)297 public void createNetworkAvailabilityProvider(int slotIndex, 298 IQualifiedNetworksServiceCallback callback) { 299 mHandler.obtainMessage(QNS_CREATE_NETWORK_AVAILABILITY_PROVIDER, slotIndex, 0, 300 callback).sendToTarget(); 301 } 302 303 @Override removeNetworkAvailabilityProvider(int slotIndex)304 public void removeNetworkAvailabilityProvider(int slotIndex) { 305 mHandler.obtainMessage(QNS_REMOVE_NETWORK_AVAILABILITY_PROVIDER, slotIndex, 0) 306 .sendToTarget(); 307 } 308 309 @Override reportThrottleStatusChanged(int slotIndex, List<ThrottleStatus> statuses)310 public void reportThrottleStatusChanged(int slotIndex, 311 List<ThrottleStatus> statuses) { 312 mHandler.obtainMessage(QNS_APN_THROTTLE_STATUS_CHANGED, slotIndex, 0, statuses) 313 .sendToTarget(); 314 } 315 } 316 log(String s)317 private void log(String s) { 318 Rlog.d(TAG, s); 319 } 320 loge(String s)321 private void loge(String s) { 322 Rlog.e(TAG, s); 323 } 324 } 325