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