CellularNetworkService.java revision 2c7b51528995b3774488343d83b26114fa283d10
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.RegState; 22import android.os.AsyncResult; 23import android.os.Handler; 24import android.os.HandlerThread; 25import android.os.Looper; 26import android.os.Message; 27import android.telephony.AccessNetworkConstants.TransportType; 28import android.telephony.CellIdentity; 29import android.telephony.CellIdentityCdma; 30import android.telephony.CellIdentityGsm; 31import android.telephony.CellIdentityLte; 32import android.telephony.CellIdentityTdscdma; 33import android.telephony.CellIdentityWcdma; 34import android.telephony.NetworkRegistrationState; 35import android.telephony.NetworkService; 36import android.telephony.NetworkServiceCallback; 37import android.telephony.Rlog; 38import android.telephony.ServiceState; 39import android.telephony.SubscriptionManager; 40 41import java.util.concurrent.ConcurrentHashMap; 42 43/** 44 * Implementation of network services for Cellular. It's a service that handles network requests 45 * for Cellular. It passes the requests to inner CellularNetworkServiceProvider which has a 46 * handler thread for each slot. 47 */ 48public class CellularNetworkService extends NetworkService { 49 private static final boolean DBG = false; 50 51 private static final String TAG = CellularNetworkService.class.getSimpleName(); 52 53 private static final int GET_CS_REGISTRATION_STATE_DONE = 1; 54 private static final int GET_PS_REGISTRATION_STATE_DONE = 2; 55 private static final int NETWORK_REGISTRATION_STATE_CHANGED = 3; 56 57 private class CellularNetworkServiceProvider extends NetworkServiceProvider { 58 59 private final ConcurrentHashMap<Message, NetworkServiceCallback> mCallbackMap = 60 new ConcurrentHashMap<>(); 61 62 private final Looper mLooper; 63 64 private final HandlerThread mHandlerThread; 65 66 private final Handler mHandler; 67 68 private final Phone mPhone; 69 70 CellularNetworkServiceProvider(int slotId) { 71 super(slotId); 72 73 mPhone = PhoneFactory.getPhone(getSlotId()); 74 75 mHandlerThread = new HandlerThread(CellularNetworkService.class.getSimpleName()); 76 mHandlerThread.start(); 77 mLooper = mHandlerThread.getLooper(); 78 mHandler = new Handler(mLooper) { 79 @Override 80 public void handleMessage(Message message) { 81 NetworkServiceCallback callback = mCallbackMap.remove(message); 82 83 AsyncResult ar; 84 switch (message.what) { 85 case GET_CS_REGISTRATION_STATE_DONE: 86 case GET_PS_REGISTRATION_STATE_DONE: 87 if (callback == null) return; 88 ar = (AsyncResult) message.obj; 89 int domain = (message.what == GET_CS_REGISTRATION_STATE_DONE) 90 ? NetworkRegistrationState.DOMAIN_CS 91 : NetworkRegistrationState.DOMAIN_PS; 92 NetworkRegistrationState netState = 93 getRegistrationStateFromResult(ar.result, domain); 94 95 int resultCode; 96 if (ar.exception != null || netState == null) { 97 resultCode = NetworkServiceCallback.RESULT_ERROR_FAILED; 98 } else { 99 resultCode = NetworkServiceCallback.RESULT_SUCCESS; 100 } 101 102 try { 103 if (DBG) { 104 log("Calling callback.onGetNetworkRegistrationStateComplete." 105 + "resultCode = " + resultCode 106 + ", netState = " + netState); 107 } 108 callback.onGetNetworkRegistrationStateComplete( 109 resultCode, netState); 110 } catch (Exception e) { 111 loge("Exception: " + e); 112 } 113 break; 114 case NETWORK_REGISTRATION_STATE_CHANGED: 115 notifyNetworkRegistrationStateChanged(); 116 break; 117 default: 118 return; 119 } 120 } 121 }; 122 123 mPhone.mCi.registerForNetworkStateChanged( 124 mHandler, NETWORK_REGISTRATION_STATE_CHANGED, null); 125 } 126 127 private int getRegStateFromHalRegState(int halRegState) { 128 switch (halRegState) { 129 case RegState.NOT_REG_MT_NOT_SEARCHING_OP: 130 case RegState.NOT_REG_MT_NOT_SEARCHING_OP_EM: 131 return NetworkRegistrationState.REG_STATE_NOT_REG_NOT_SEARCHING; 132 case RegState.REG_HOME: 133 return NetworkRegistrationState.REG_STATE_HOME; 134 case RegState.NOT_REG_MT_SEARCHING_OP: 135 case RegState.NOT_REG_MT_SEARCHING_OP_EM: 136 return NetworkRegistrationState.REG_STATE_NOT_REG_SEARCHING; 137 case RegState.REG_DENIED: 138 case RegState.REG_DENIED_EM: 139 return NetworkRegistrationState.REG_STATE_DENIED; 140 case RegState.UNKNOWN: 141 case RegState.UNKNOWN_EM: 142 return NetworkRegistrationState.REG_STATE_UNKNOWN; 143 case RegState.REG_ROAMING: 144 return NetworkRegistrationState.REG_STATE_ROAMING; 145 default: 146 return NetworkRegistrationState.REG_STATE_NOT_REG_NOT_SEARCHING; 147 } 148 } 149 150 private boolean isEmergencyOnly(int halRegState) { 151 switch (halRegState) { 152 case RegState.NOT_REG_MT_NOT_SEARCHING_OP_EM: 153 case RegState.NOT_REG_MT_SEARCHING_OP_EM: 154 case RegState.REG_DENIED_EM: 155 case RegState.UNKNOWN_EM: 156 return true; 157 case RegState.NOT_REG_MT_NOT_SEARCHING_OP: 158 case RegState.REG_HOME: 159 case RegState.NOT_REG_MT_SEARCHING_OP: 160 case RegState.REG_DENIED: 161 case RegState.UNKNOWN: 162 case RegState.REG_ROAMING: 163 default: 164 return false; 165 } 166 } 167 168 private int[] getAvailableServices(int regState, int domain, boolean emergencyOnly) { 169 int[] availableServices = null; 170 171 // In emergency only states, only SERVICE_TYPE_EMERGENCY is available. 172 // Otherwise, certain services are available only if it's registered on home or roaming 173 // network. 174 if (emergencyOnly) { 175 availableServices = new int[] {NetworkRegistrationState.SERVICE_TYPE_EMERGENCY}; 176 } else if (regState == NetworkRegistrationState.REG_STATE_ROAMING 177 || regState == NetworkRegistrationState.REG_STATE_HOME) { 178 if (domain == NetworkRegistrationState.DOMAIN_PS) { 179 availableServices = new int[] {NetworkRegistrationState.SERVICE_TYPE_DATA}; 180 } else if (domain == NetworkRegistrationState.DOMAIN_CS) { 181 availableServices = new int[] { 182 NetworkRegistrationState.SERVICE_TYPE_VOICE, 183 NetworkRegistrationState.SERVICE_TYPE_SMS, 184 NetworkRegistrationState.SERVICE_TYPE_VIDEO 185 }; 186 } 187 } 188 189 return availableServices; 190 } 191 192 private int getAccessNetworkTechnologyFromRat(int rilRat) { 193 return ServiceState.rilRadioTechnologyToNetworkType(rilRat); 194 } 195 196 private NetworkRegistrationState getRegistrationStateFromResult(Object result, int domain) { 197 if (result == null) { 198 return null; 199 } 200 201 // TODO: unify when voiceRegStateResult and DataRegStateResult are unified. 202 if (domain == NetworkRegistrationState.DOMAIN_CS) { 203 return createRegistrationStateFromVoiceRegState(result); 204 } else if (domain == NetworkRegistrationState.DOMAIN_PS) { 205 return createRegistrationStateFromDataRegState(result); 206 } else { 207 return null; 208 } 209 } 210 211 private NetworkRegistrationState createRegistrationStateFromVoiceRegState(Object result) { 212 int transportType = TransportType.WWAN; 213 int domain = NetworkRegistrationState.DOMAIN_CS; 214 215 if (result instanceof android.hardware.radio.V1_0.VoiceRegStateResult) { 216 android.hardware.radio.V1_0.VoiceRegStateResult voiceRegState = 217 (android.hardware.radio.V1_0.VoiceRegStateResult) result; 218 int regState = getRegStateFromHalRegState(voiceRegState.regState); 219 int accessNetworkTechnology = getAccessNetworkTechnologyFromRat(voiceRegState.rat); 220 int reasonForDenial = voiceRegState.reasonForDenial; 221 boolean emergencyOnly = isEmergencyOnly(voiceRegState.regState); 222 boolean cssSupported = voiceRegState.cssSupported; 223 int roamingIndicator = voiceRegState.roamingIndicator; 224 int systemIsInPrl = voiceRegState.systemIsInPrl; 225 int defaultRoamingIndicator = voiceRegState.defaultRoamingIndicator; 226 int[] availableServices = getAvailableServices( 227 regState, domain, emergencyOnly); 228 CellIdentity cellIdentity = 229 convertHalCellIdentityToCellIdentity(voiceRegState.cellIdentity); 230 231 return new NetworkRegistrationState(transportType, domain, regState, 232 accessNetworkTechnology, reasonForDenial, emergencyOnly, availableServices, 233 cellIdentity, cssSupported, roamingIndicator, systemIsInPrl, 234 defaultRoamingIndicator); 235 } else if (result instanceof android.hardware.radio.V1_2.VoiceRegStateResult) { 236 android.hardware.radio.V1_2.VoiceRegStateResult voiceRegState = 237 (android.hardware.radio.V1_2.VoiceRegStateResult) result; 238 int regState = getRegStateFromHalRegState(voiceRegState.regState); 239 int accessNetworkTechnology = getAccessNetworkTechnologyFromRat(voiceRegState.rat); 240 int reasonForDenial = voiceRegState.reasonForDenial; 241 boolean emergencyOnly = isEmergencyOnly(voiceRegState.regState); 242 boolean cssSupported = voiceRegState.cssSupported; 243 int roamingIndicator = voiceRegState.roamingIndicator; 244 int systemIsInPrl = voiceRegState.systemIsInPrl; 245 int defaultRoamingIndicator = voiceRegState.defaultRoamingIndicator; 246 int[] availableServices = getAvailableServices( 247 regState, domain, emergencyOnly); 248 CellIdentity cellIdentity = 249 convertHalCellIdentityToCellIdentity(voiceRegState.cellIdentity); 250 251 return new NetworkRegistrationState(transportType, domain, regState, 252 accessNetworkTechnology, reasonForDenial, emergencyOnly, availableServices, 253 cellIdentity, cssSupported, roamingIndicator, systemIsInPrl, 254 defaultRoamingIndicator); 255 } 256 257 return null; 258 } 259 260 private NetworkRegistrationState createRegistrationStateFromDataRegState(Object result) { 261 int transportType = TransportType.WWAN; 262 int domain = NetworkRegistrationState.DOMAIN_PS; 263 264 if (result instanceof android.hardware.radio.V1_0.DataRegStateResult) { 265 android.hardware.radio.V1_0.DataRegStateResult dataRegState = 266 (android.hardware.radio.V1_0.DataRegStateResult) result; 267 int regState = getRegStateFromHalRegState(dataRegState.regState); 268 int accessNetworkTechnology = getAccessNetworkTechnologyFromRat(dataRegState.rat); 269 int reasonForDenial = dataRegState.reasonDataDenied; 270 boolean emergencyOnly = isEmergencyOnly(dataRegState.regState); 271 int maxDataCalls = dataRegState.maxDataCalls; 272 int[] availableServices = getAvailableServices(regState, domain, emergencyOnly); 273 CellIdentity cellIdentity = 274 convertHalCellIdentityToCellIdentity(dataRegState.cellIdentity); 275 276 return new NetworkRegistrationState(transportType, domain, regState, 277 accessNetworkTechnology, reasonForDenial, emergencyOnly, availableServices, 278 cellIdentity, maxDataCalls); 279 } else if (result instanceof android.hardware.radio.V1_2.DataRegStateResult) { 280 android.hardware.radio.V1_2.DataRegStateResult dataRegState = 281 (android.hardware.radio.V1_2.DataRegStateResult) result; 282 int regState = getRegStateFromHalRegState(dataRegState.regState); 283 int accessNetworkTechnology = getAccessNetworkTechnologyFromRat(dataRegState.rat); 284 int reasonForDenial = dataRegState.reasonDataDenied; 285 boolean emergencyOnly = isEmergencyOnly(dataRegState.regState); 286 int maxDataCalls = dataRegState.maxDataCalls; 287 int[] availableServices = getAvailableServices(regState, domain, emergencyOnly); 288 CellIdentity cellIdentity = 289 convertHalCellIdentityToCellIdentity(dataRegState.cellIdentity); 290 291 return new NetworkRegistrationState(transportType, domain, regState, 292 accessNetworkTechnology, reasonForDenial, emergencyOnly, availableServices, 293 cellIdentity, maxDataCalls); 294 } 295 296 return null; 297 } 298 299 private CellIdentity convertHalCellIdentityToCellIdentity( 300 android.hardware.radio.V1_0.CellIdentity cellIdentity) { 301 if (cellIdentity == null) { 302 return null; 303 } 304 305 CellIdentity result = null; 306 switch(cellIdentity.cellInfoType) { 307 case CellInfoType.GSM: { 308 if (cellIdentity.cellIdentityGsm.size() == 1) { 309 android.hardware.radio.V1_0.CellIdentityGsm cellIdentityGsm = 310 cellIdentity.cellIdentityGsm.get(0); 311 result = new CellIdentityGsm(cellIdentityGsm.lac, cellIdentityGsm.cid, 312 cellIdentityGsm.arfcn, cellIdentityGsm.bsic, cellIdentityGsm.mcc, 313 cellIdentityGsm.mnc, null, null); 314 } 315 break; 316 } 317 case CellInfoType.WCDMA: { 318 if (cellIdentity.cellIdentityWcdma.size() == 1) { 319 android.hardware.radio.V1_0.CellIdentityWcdma cellIdentityWcdma = 320 cellIdentity.cellIdentityWcdma.get(0); 321 result = new CellIdentityWcdma(cellIdentityWcdma.lac, cellIdentityWcdma.cid, 322 cellIdentityWcdma.psc, cellIdentityWcdma.uarfcn, 323 cellIdentityWcdma.mcc, cellIdentityWcdma.mnc, null, null); 324 } 325 break; 326 } 327 case CellInfoType.TD_SCDMA: { 328 if (cellIdentity.cellIdentityTdscdma.size() == 1) { 329 android.hardware.radio.V1_0.CellIdentityTdscdma cellIdentityTdscdma = 330 cellIdentity.cellIdentityTdscdma.get(0); 331 result = new CellIdentityTdscdma(cellIdentityTdscdma.mcc, 332 cellIdentityTdscdma.mnc, cellIdentityTdscdma.lac, 333 cellIdentityTdscdma.cid, cellIdentityTdscdma.cpid); 334 } 335 break; 336 } 337 case CellInfoType.LTE: { 338 if (cellIdentity.cellIdentityLte.size() == 1) { 339 android.hardware.radio.V1_0.CellIdentityLte cellIdentityLte = 340 cellIdentity.cellIdentityLte.get(0); 341 342 result = new CellIdentityLte(cellIdentityLte.ci, cellIdentityLte.pci, 343 cellIdentityLte.tac, cellIdentityLte.earfcn, Integer.MAX_VALUE, 344 cellIdentityLte.mcc, cellIdentityLte.mnc, null, null); 345 } 346 break; 347 } 348 case CellInfoType.CDMA: { 349 if (cellIdentity.cellIdentityCdma.size() == 1) { 350 android.hardware.radio.V1_0.CellIdentityCdma cellIdentityCdma = 351 cellIdentity.cellIdentityCdma.get(0); 352 353 result = new CellIdentityCdma(cellIdentityCdma.networkId, 354 cellIdentityCdma.systemId, cellIdentityCdma.baseStationId, 355 cellIdentityCdma.longitude, cellIdentityCdma.latitude); 356 } 357 break; 358 } 359 case CellInfoType.NONE: 360 default: 361 break; 362 } 363 364 return result; 365 } 366 367 private CellIdentity convertHalCellIdentityToCellIdentity( 368 android.hardware.radio.V1_2.CellIdentity cellIdentity) { 369 if (cellIdentity == null) { 370 return null; 371 } 372 373 CellIdentity result = null; 374 switch(cellIdentity.cellInfoType) { 375 case CellInfoType.GSM: { 376 if (cellIdentity.cellIdentityGsm.size() == 1) { 377 android.hardware.radio.V1_2.CellIdentityGsm cellIdentityGsm = 378 cellIdentity.cellIdentityGsm.get(0); 379 380 result = new CellIdentityGsm( 381 cellIdentityGsm.base.lac, 382 cellIdentityGsm.base.cid, 383 cellIdentityGsm.base.arfcn, 384 cellIdentityGsm.base.bsic, 385 cellIdentityGsm.base.mcc, 386 cellIdentityGsm.base.mnc, 387 cellIdentityGsm.operatorNames.alphaLong, 388 cellIdentityGsm.operatorNames.alphaShort); 389 } 390 break; 391 } 392 case CellInfoType.WCDMA: { 393 if (cellIdentity.cellIdentityWcdma.size() == 1) { 394 android.hardware.radio.V1_2.CellIdentityWcdma cellIdentityWcdma = 395 cellIdentity.cellIdentityWcdma.get(0); 396 397 result = new CellIdentityWcdma( 398 cellIdentityWcdma.base.lac, 399 cellIdentityWcdma.base.cid, 400 cellIdentityWcdma.base.psc, 401 cellIdentityWcdma.base.uarfcn, 402 cellIdentityWcdma.base.mcc, 403 cellIdentityWcdma.base.mnc, 404 cellIdentityWcdma.operatorNames.alphaLong, 405 cellIdentityWcdma.operatorNames.alphaShort); 406 } 407 break; 408 } 409 case CellInfoType.TD_SCDMA: { 410 if (cellIdentity.cellIdentityTdscdma.size() == 1) { 411 android.hardware.radio.V1_2.CellIdentityTdscdma cellIdentityTdscdma = 412 cellIdentity.cellIdentityTdscdma.get(0); 413 414 result = new CellIdentityTdscdma( 415 cellIdentityTdscdma.base.mcc, 416 cellIdentityTdscdma.base.mnc, 417 cellIdentityTdscdma.base.lac, 418 cellIdentityTdscdma.base.cid, 419 cellIdentityTdscdma.base.cpid, 420 cellIdentityTdscdma.operatorNames.alphaLong, 421 cellIdentityTdscdma.operatorNames.alphaShort); 422 } 423 break; 424 } 425 case CellInfoType.LTE: { 426 if (cellIdentity.cellIdentityLte.size() == 1) { 427 android.hardware.radio.V1_2.CellIdentityLte cellIdentityLte = 428 cellIdentity.cellIdentityLte.get(0); 429 430 result = new CellIdentityLte( 431 cellIdentityLte.base.ci, 432 cellIdentityLte.base.pci, 433 cellIdentityLte.base.tac, 434 cellIdentityLte.base.earfcn, 435 cellIdentityLte.bandwidth, 436 cellIdentityLte.base.mcc, 437 cellIdentityLte.base.mnc, 438 cellIdentityLte.operatorNames.alphaLong, 439 cellIdentityLte.operatorNames.alphaShort); 440 } 441 break; 442 } 443 case CellInfoType.CDMA: { 444 if (cellIdentity.cellIdentityCdma.size() == 1) { 445 android.hardware.radio.V1_2.CellIdentityCdma cellIdentityCdma = 446 cellIdentity.cellIdentityCdma.get(0); 447 448 result = new CellIdentityCdma( 449 cellIdentityCdma.base.networkId, 450 cellIdentityCdma.base.systemId, 451 cellIdentityCdma.base.baseStationId, 452 cellIdentityCdma.base.longitude, 453 cellIdentityCdma.base.latitude, 454 cellIdentityCdma.operatorNames.alphaLong, 455 cellIdentityCdma.operatorNames.alphaShort); 456 } 457 break; 458 } 459 case CellInfoType.NONE: 460 default: 461 break; 462 } 463 464 return result; 465 } 466 467 @Override 468 public void getNetworkRegistrationState(int domain, NetworkServiceCallback callback) { 469 if (DBG) log("getNetworkRegistrationState for domain " + domain); 470 Message message = null; 471 472 if (domain == NetworkRegistrationState.DOMAIN_CS) { 473 message = Message.obtain(mHandler, GET_CS_REGISTRATION_STATE_DONE); 474 mCallbackMap.put(message, callback); 475 mPhone.mCi.getVoiceRegistrationState(message); 476 } else if (domain == NetworkRegistrationState.DOMAIN_PS) { 477 message = Message.obtain(mHandler, GET_PS_REGISTRATION_STATE_DONE); 478 mCallbackMap.put(message, callback); 479 mPhone.mCi.getDataRegistrationState(message); 480 } else { 481 loge("getNetworkRegistrationState invalid domain " + domain); 482 callback.onGetNetworkRegistrationStateComplete( 483 NetworkServiceCallback.RESULT_ERROR_INVALID_ARG, null); 484 } 485 } 486 487 @CallSuper 488 protected void onDestroy() { 489 super.onDestroy(); 490 491 mCallbackMap.clear(); 492 mHandlerThread.quit(); 493 mPhone.mCi.unregisterForNetworkStateChanged(mHandler); 494 } 495 } 496 497 @Override 498 protected NetworkServiceProvider createNetworkServiceProvider(int slotId) { 499 if (DBG) log("Cellular network service created for slot " + slotId); 500 if (!SubscriptionManager.isValidSlotIndex(slotId)) { 501 loge("Tried to Cellular network service with invalid slotId " + slotId); 502 return null; 503 } 504 return new CellularNetworkServiceProvider(slotId); 505 } 506 507 private void log(String s) { 508 Rlog.d(TAG, s); 509 } 510 511 private void loge(String s) { 512 Rlog.e(TAG, s); 513 } 514} 515