CellularNetworkService.java revision 269ee0aa10b0cc586eef68d55f153b1bdbc2085c
1/* 2 * Copyright 2017 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 17package com.android.internal.telephony; 18 19import android.annotation.CallSuper; 20import android.hardware.radio.V1_0.CellInfoType; 21import android.hardware.radio.V1_0.DataRegStateResult; 22import android.hardware.radio.V1_0.RegState; 23import android.hardware.radio.V1_0.VoiceRegStateResult; 24import android.os.AsyncResult; 25import android.os.Handler; 26import android.os.HandlerThread; 27import android.os.Looper; 28import android.os.Message; 29import android.telephony.AccessNetworkConstants.TransportType; 30import android.telephony.CellIdentity; 31import android.telephony.CellIdentityCdma; 32import android.telephony.CellIdentityGsm; 33import android.telephony.CellIdentityLte; 34import android.telephony.CellIdentityTdscdma; 35import android.telephony.CellIdentityWcdma; 36import android.telephony.NetworkRegistrationState; 37import android.telephony.NetworkService; 38import android.telephony.NetworkServiceCallback; 39import android.telephony.Rlog; 40import android.telephony.ServiceState; 41import android.telephony.SubscriptionManager; 42 43import java.util.concurrent.ConcurrentHashMap; 44 45/** 46 * Implementation of network services for Cellular. It's a service that handles network requests 47 * for Cellular. It passes the requests to inner CellularNetworkServiceProvider which has a 48 * handler thread for each slot. 49 */ 50public class CellularNetworkService extends NetworkService { 51 private static final boolean DBG = false; 52 53 private static final String TAG = CellularNetworkService.class.getSimpleName(); 54 55 private static final int GET_CS_REGISTRATION_STATE_DONE = 1; 56 private static final int GET_PS_REGISTRATION_STATE_DONE = 2; 57 private static final int NETWORK_REGISTRATION_STATE_CHANGED = 3; 58 59 private class CellularNetworkServiceProvider extends NetworkServiceProvider { 60 61 private final ConcurrentHashMap<Message, NetworkServiceCallback> mCallbackMap = 62 new ConcurrentHashMap<>(); 63 64 private final Looper mLooper; 65 66 private final HandlerThread mHandlerThread; 67 68 private final Handler mHandler; 69 70 private final Phone mPhone; 71 72 CellularNetworkServiceProvider(int slotId) { 73 super(slotId); 74 75 mPhone = PhoneFactory.getPhone(getSlotId()); 76 77 mHandlerThread = new HandlerThread(CellularNetworkService.class.getSimpleName()); 78 mHandlerThread.start(); 79 mLooper = mHandlerThread.getLooper(); 80 mHandler = new Handler(mLooper) { 81 @Override 82 public void handleMessage(Message message) { 83 NetworkServiceCallback callback = mCallbackMap.remove(message); 84 85 AsyncResult ar; 86 switch (message.what) { 87 case GET_CS_REGISTRATION_STATE_DONE: 88 case GET_PS_REGISTRATION_STATE_DONE: 89 if (callback == null) return; 90 ar = (AsyncResult) message.obj; 91 int domain = (message.what == GET_CS_REGISTRATION_STATE_DONE) 92 ? NetworkRegistrationState.DOMAIN_CS 93 : NetworkRegistrationState.DOMAIN_PS; 94 NetworkRegistrationState netState = 95 getRegistrationStateFromResult(ar.result, domain); 96 97 int resultCode; 98 if (ar.exception != null || netState == null) { 99 resultCode = NetworkServiceCallback.RESULT_ERROR_FAILED; 100 } else { 101 resultCode = NetworkServiceCallback.RESULT_SUCCESS; 102 } 103 104 try { 105 if (DBG) { 106 log("Calling callback.onGetNetworkRegistrationStateComplete." 107 + "resultCode = " + resultCode 108 + ", netState = " + netState); 109 } 110 callback.onGetNetworkRegistrationStateComplete( 111 resultCode, netState); 112 } catch (Exception e) { 113 loge("Exception: " + e); 114 } 115 break; 116 case NETWORK_REGISTRATION_STATE_CHANGED: 117 notifyNetworkRegistrationStateChanged(); 118 break; 119 default: 120 return; 121 } 122 } 123 }; 124 125 mPhone.mCi.registerForNetworkStateChanged( 126 mHandler, NETWORK_REGISTRATION_STATE_CHANGED, null); 127 } 128 129 private int getRegStateFromHalRegState(int halRegState) { 130 switch (halRegState) { 131 case RegState.NOT_REG_MT_NOT_SEARCHING_OP: 132 case RegState.NOT_REG_MT_NOT_SEARCHING_OP_EM: 133 return NetworkRegistrationState.REG_STATE_NOT_REG_NOT_SEARCHING; 134 case RegState.REG_HOME: 135 return NetworkRegistrationState.REG_STATE_HOME; 136 case RegState.NOT_REG_MT_SEARCHING_OP: 137 case RegState.NOT_REG_MT_SEARCHING_OP_EM: 138 return NetworkRegistrationState.REG_STATE_NOT_REG_SEARCHING; 139 case RegState.REG_DENIED: 140 case RegState.REG_DENIED_EM: 141 return NetworkRegistrationState.REG_STATE_DENIED; 142 case RegState.UNKNOWN: 143 case RegState.UNKNOWN_EM: 144 return NetworkRegistrationState.REG_STATE_UNKNOWN; 145 case RegState.REG_ROAMING: 146 return NetworkRegistrationState.REG_STATE_ROAMING; 147 default: 148 return NetworkRegistrationState.REG_STATE_NOT_REG_NOT_SEARCHING; 149 } 150 } 151 152 private boolean isEmergencyOnly(int halRegState) { 153 switch (halRegState) { 154 case RegState.NOT_REG_MT_NOT_SEARCHING_OP_EM: 155 case RegState.NOT_REG_MT_SEARCHING_OP_EM: 156 case RegState.REG_DENIED_EM: 157 case RegState.UNKNOWN_EM: 158 return true; 159 case RegState.NOT_REG_MT_NOT_SEARCHING_OP: 160 case RegState.REG_HOME: 161 case RegState.NOT_REG_MT_SEARCHING_OP: 162 case RegState.REG_DENIED: 163 case RegState.UNKNOWN: 164 case RegState.REG_ROAMING: 165 default: 166 return false; 167 } 168 } 169 170 private int[] getAvailableServices(int regState, int domain, 171 boolean emergencyOnly) { 172 int[] availableServices = null; 173 174 // In emergency only states, only SERVICE_TYPE_EMERGENCY is available. 175 // Otherwise, certain services are available only if it's registered on home or roaming 176 // network. 177 if (emergencyOnly) { 178 availableServices = new int[] {NetworkRegistrationState.SERVICE_TYPE_EMERGENCY}; 179 } else if (regState == NetworkRegistrationState.REG_STATE_ROAMING 180 || regState != NetworkRegistrationState.REG_STATE_HOME) { 181 if (domain == NetworkRegistrationState.DOMAIN_PS) { 182 availableServices = new int[] {NetworkRegistrationState.SERVICE_TYPE_DATA}; 183 } else if (domain == NetworkRegistrationState.DOMAIN_CS) { 184 availableServices = new int[] { 185 NetworkRegistrationState.SERVICE_TYPE_VOICE, 186 NetworkRegistrationState.SERVICE_TYPE_SMS, 187 NetworkRegistrationState.SERVICE_TYPE_VIDEO 188 }; 189 } 190 } 191 192 return availableServices; 193 } 194 195 private int getAccessNetworkTechnologyFromRat(int rilRat) { 196 return ServiceState.rilRadioTechnologyToNetworkType(rilRat); 197 } 198 199 private NetworkRegistrationState getRegistrationStateFromResult(Object result, int domain) { 200 if (result == null) { 201 return null; 202 } 203 204 // TODO: unify when voiceRegStateResult and DataRegStateResult are unified. 205 if (domain == NetworkRegistrationState.DOMAIN_CS) { 206 VoiceRegStateResult voiceRegState = (VoiceRegStateResult) result; 207 int transportType = TransportType.WWAN; 208 int regState = getRegStateFromHalRegState(voiceRegState.regState); 209 int accessNetworkTechnology = getAccessNetworkTechnologyFromRat(voiceRegState.rat); 210 int reasonForDenial = voiceRegState.reasonForDenial; 211 boolean emergencyOnly = isEmergencyOnly(voiceRegState.regState); 212 boolean cssSupported = voiceRegState.cssSupported; 213 int roamingIndicator = voiceRegState.roamingIndicator; 214 int systemIsInPrl = voiceRegState.systemIsInPrl; 215 int defaultRoamingIndicator = voiceRegState.defaultRoamingIndicator; 216 int[] availableServices = getAvailableServices( 217 regState, domain, emergencyOnly); 218 CellIdentity cellIdentity = 219 convertHalCellIdentityToCellIdentity(voiceRegState.cellIdentity); 220 221 return new NetworkRegistrationState(transportType, domain, regState, 222 accessNetworkTechnology, reasonForDenial, emergencyOnly, availableServices, 223 cellIdentity, cssSupported, roamingIndicator, systemIsInPrl, 224 defaultRoamingIndicator); 225 } else if (domain == NetworkRegistrationState.DOMAIN_PS) { 226 DataRegStateResult dataRegState = (DataRegStateResult) result; 227 int transportType = TransportType.WWAN; 228 int regState = getRegStateFromHalRegState(dataRegState.regState); 229 int accessNetworkTechnology = getAccessNetworkTechnologyFromRat(dataRegState.rat); 230 int reasonForDenial = dataRegState.reasonDataDenied; 231 boolean emergencyOnly = isEmergencyOnly(dataRegState.regState); 232 int maxDataCalls = dataRegState.maxDataCalls; 233 int[] availableServices = getAvailableServices(regState, domain, emergencyOnly); 234 CellIdentity cellIdentity = 235 convertHalCellIdentityToCellIdentity(dataRegState.cellIdentity); 236 return new NetworkRegistrationState(transportType, domain, regState, 237 accessNetworkTechnology, reasonForDenial, emergencyOnly, availableServices, 238 cellIdentity, maxDataCalls); 239 } else { 240 return null; 241 } 242 } 243 244 private CellIdentity convertHalCellIdentityToCellIdentity( 245 android.hardware.radio.V1_0.CellIdentity cellIdentity) { 246 CellIdentity result = null; 247 switch(cellIdentity.cellInfoType) { 248 case CellInfoType.GSM: { 249 if (cellIdentity.cellIdentityGsm.size() == 1) { 250 android.hardware.radio.V1_0.CellIdentityGsm cellIdentityGsm = 251 cellIdentity.cellIdentityGsm.get(0); 252 result = new CellIdentityGsm(cellIdentityGsm.lac, cellIdentityGsm.cid, 253 cellIdentityGsm.arfcn, cellIdentityGsm.bsic, cellIdentityGsm.mcc, 254 cellIdentityGsm.mnc, null, null); 255 } 256 break; 257 } 258 case CellInfoType.WCDMA: { 259 if (cellIdentity.cellIdentityWcdma.size() == 1) { 260 android.hardware.radio.V1_0.CellIdentityWcdma cellIdentityWcdma = 261 cellIdentity.cellIdentityWcdma.get(0); 262 result = new CellIdentityWcdma(cellIdentityWcdma.lac, cellIdentityWcdma.cid, 263 cellIdentityWcdma.psc, cellIdentityWcdma.uarfcn, 264 cellIdentityWcdma.mcc, cellIdentityWcdma.mnc, null, null); 265 } 266 break; 267 } 268 case CellInfoType.TD_SCDMA: { 269 if (cellIdentity.cellIdentityTdscdma.size() == 1) { 270 android.hardware.radio.V1_0.CellIdentityTdscdma cellIdentityTdscdma = 271 cellIdentity.cellIdentityTdscdma.get(0); 272 result = new CellIdentityTdscdma(cellIdentityTdscdma.mcc, 273 cellIdentityTdscdma.mnc, cellIdentityTdscdma.lac, 274 cellIdentityTdscdma.cid, cellIdentityTdscdma.cpid); 275 } 276 break; 277 } 278 case CellInfoType.LTE: { 279 if (cellIdentity.cellIdentityLte.size() == 1) { 280 android.hardware.radio.V1_0.CellIdentityLte cellIdentityLte = 281 cellIdentity.cellIdentityLte.get(0); 282 283 result = new CellIdentityLte(cellIdentityLte.ci, cellIdentityLte.pci, 284 cellIdentityLte.tac, cellIdentityLte.earfcn, Integer.MAX_VALUE, 285 cellIdentityLte.mcc, cellIdentityLte.mnc, null, null); 286 } 287 break; 288 } 289 case CellInfoType.CDMA: { 290 if (cellIdentity.cellIdentityCdma.size() == 1) { 291 android.hardware.radio.V1_0.CellIdentityCdma cellIdentityCdma = 292 cellIdentity.cellIdentityCdma.get(0); 293 294 result = new CellIdentityCdma(cellIdentityCdma.networkId, 295 cellIdentityCdma.systemId, cellIdentityCdma.baseStationId, 296 cellIdentityCdma.longitude, cellIdentityCdma.latitude); 297 } 298 break; 299 } 300 case CellInfoType.NONE: 301 default: 302 break; 303 } 304 305 return result; 306 } 307 308 public void getNetworkRegistrationState(int domain, NetworkServiceCallback callback) { 309 if (DBG) log("getNetworkRegistrationState for domain " + domain); 310 Message message = null; 311 312 if (domain == NetworkRegistrationState.DOMAIN_CS) { 313 message = Message.obtain(mHandler, GET_CS_REGISTRATION_STATE_DONE); 314 mCallbackMap.put(message, callback); 315 mPhone.mCi.getVoiceRegistrationState(message); 316 } else if (domain == NetworkRegistrationState.DOMAIN_PS) { 317 message = Message.obtain(mHandler, GET_PS_REGISTRATION_STATE_DONE); 318 mCallbackMap.put(message, callback); 319 mPhone.mCi.getDataRegistrationState(message); 320 } else { 321 loge("getNetworkRegistrationState invalid domain " + domain); 322 callback.onGetNetworkRegistrationStateComplete( 323 NetworkServiceCallback.RESULT_ERROR_INVALID_ARG, null); 324 } 325 } 326 327 @CallSuper 328 protected void onDestroy() { 329 super.onDestroy(); 330 331 mCallbackMap.clear(); 332 mHandlerThread.quit(); 333 mPhone.mCi.unregisterForNetworkStateChanged(mHandler); 334 } 335 } 336 337 @Override 338 protected NetworkServiceProvider createNetworkServiceProvider(int slotId) { 339 if (DBG) log("Cellular network service created for slot " + slotId); 340 if (!SubscriptionManager.isValidSlotIndex(slotId)) { 341 loge("Tried to Cellular network service with invalid slotId " + slotId); 342 return null; 343 } 344 return new CellularNetworkServiceProvider(slotId); 345 } 346 347 private void log(String s) { 348 Rlog.d(TAG, s); 349 } 350 351 private void loge(String s) { 352 Rlog.e(TAG, s); 353 } 354} 355