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 
17 package com.android.internal.telephony;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.hardware.radio.V1_0.RegState;
22 import android.hardware.radio.V1_4.DataRegStateResult.VopsInfo.hidl_discriminator;
23 import android.hardware.radio.V1_6.RegStateResult.AccessTechnologySpecificInfo;
24 import android.os.AsyncResult;
25 import android.os.Handler;
26 import android.os.Looper;
27 import android.os.Message;
28 import android.telephony.AccessNetworkConstants;
29 import android.telephony.AccessNetworkConstants.AccessNetworkType;
30 import android.telephony.CellIdentity;
31 import android.telephony.CellIdentityCdma;
32 import android.telephony.LteVopsSupportInfo;
33 import android.telephony.NetworkRegistrationInfo;
34 import android.telephony.NetworkService;
35 import android.telephony.NetworkServiceCallback;
36 import android.telephony.NrVopsSupportInfo;
37 import android.telephony.ServiceState;
38 import android.telephony.SubscriptionManager;
39 import android.telephony.TelephonyManager;
40 import android.telephony.VopsSupportInfo;
41 import android.text.TextUtils;
42 
43 import com.android.telephony.Rlog;
44 
45 import java.util.ArrayList;
46 import java.util.HashMap;
47 import java.util.List;
48 import java.util.Map;
49 
50 /**
51  * Implementation of network services for Cellular. It's a service that handles network requests
52  * for Cellular. It passes the requests to inner CellularNetworkServiceProvider which has a
53  * handler thread for each slot.
54  */
55 public class CellularNetworkService extends NetworkService {
56     private static final boolean DBG = false;
57 
58     private static final String TAG = CellularNetworkService.class.getSimpleName();
59 
60     private static final int GET_CS_REGISTRATION_STATE_DONE = 1;
61     private static final int GET_PS_REGISTRATION_STATE_DONE = 2;
62     private static final int NETWORK_REGISTRATION_STATE_CHANGED = 3;
63 
64     // From 24.008 6.1.3.0 and 10.5.6.2 the maximum number of PDP Contexts is 16.
65     private static final int MAX_DATA_CALLS = 16;
66 
67     private class CellularNetworkServiceProvider extends NetworkServiceProvider {
68 
69         private final Map<Message, NetworkServiceCallback> mCallbackMap = new HashMap<>();
70 
71         private final Handler mHandler;
72 
73         private final Phone mPhone;
74 
CellularNetworkServiceProvider(int slotId)75         CellularNetworkServiceProvider(int slotId) {
76             super(slotId);
77 
78             mPhone = PhoneFactory.getPhone(getSlotIndex());
79 
80             mHandler = new Handler(Looper.myLooper()) {
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                                     ? NetworkRegistrationInfo.DOMAIN_CS
93                                     : NetworkRegistrationInfo.DOMAIN_PS;
94                             NetworkRegistrationInfo 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 onRequestNetworkRegistrationInfoComplete."
107                                             + "resultCode = " + resultCode
108                                             + ", netState = " + netState);
109                                 }
110                                 callback.onRequestNetworkRegistrationInfoComplete(
111                                          resultCode, netState);
112                             } catch (Exception e) {
113                                 loge("Exception: " + e);
114                             }
115                             break;
116                         case NETWORK_REGISTRATION_STATE_CHANGED:
117                             notifyNetworkRegistrationInfoChanged();
118                             break;
119                         default:
120                             return;
121                     }
122                 }
123             };
124 
125             mPhone.mCi.registerForNetworkStateChanged(
126                     mHandler, NETWORK_REGISTRATION_STATE_CHANGED, null);
127         }
128 
getRegStateFromHalRegState(int halRegState)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 NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING;
134                 case RegState.REG_HOME:
135                     return NetworkRegistrationInfo.REGISTRATION_STATE_HOME;
136                 case RegState.NOT_REG_MT_SEARCHING_OP:
137                 case RegState.NOT_REG_MT_SEARCHING_OP_EM:
138                     return NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING;
139                 case RegState.REG_DENIED:
140                 case RegState.REG_DENIED_EM:
141                     return NetworkRegistrationInfo.REGISTRATION_STATE_DENIED;
142                 case RegState.UNKNOWN:
143                 case RegState.UNKNOWN_EM:
144                     return NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN;
145                 case RegState.REG_ROAMING:
146                     return NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING;
147                 default:
148                     return NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING;
149             }
150         }
151 
isEmergencyOnly(int halRegState)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 
getAvailableServices(int regState, int domain, boolean emergencyOnly)170         private List<Integer> getAvailableServices(int regState, int domain,
171                                                    boolean emergencyOnly) {
172             List<Integer> availableServices = new ArrayList<>();
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.add(NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY);
179             } else if (regState == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING
180                     || regState == NetworkRegistrationInfo.REGISTRATION_STATE_HOME) {
181                 if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
182                     availableServices.add(NetworkRegistrationInfo.SERVICE_TYPE_DATA);
183                 } else if (domain == NetworkRegistrationInfo.DOMAIN_CS) {
184                     availableServices.add(NetworkRegistrationInfo.SERVICE_TYPE_VOICE);
185                     availableServices.add(NetworkRegistrationInfo.SERVICE_TYPE_SMS);
186                     availableServices.add(NetworkRegistrationInfo.SERVICE_TYPE_VIDEO);
187                 }
188             }
189 
190             return availableServices;
191         }
192 
getRegistrationStateFromResult(Object result, int domain)193         private NetworkRegistrationInfo getRegistrationStateFromResult(Object result, int domain) {
194             if (result == null) {
195                 return null;
196             }
197 
198             // TODO: unify when voiceRegStateResult and DataRegStateResult are unified.
199             if (domain == NetworkRegistrationInfo.DOMAIN_CS) {
200                 return createRegistrationStateFromVoiceRegState(result);
201             } else if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
202                 return createRegistrationStateFromDataRegState(result);
203             } else {
204                 return null;
205             }
206         }
207 
getPlmnFromCellIdentity(@ullable final CellIdentity ci)208         private @NonNull String getPlmnFromCellIdentity(@Nullable final CellIdentity ci) {
209             if (ci == null || ci instanceof CellIdentityCdma) return "";
210 
211             final String mcc = ci.getMccString();
212             final String mnc = ci.getMncString();
213 
214             if (TextUtils.isEmpty(mcc) || TextUtils.isEmpty(mnc)) return "";
215 
216             return mcc + mnc;
217         }
218 
createRegistrationStateFromVoiceRegState(Object result)219         private NetworkRegistrationInfo createRegistrationStateFromVoiceRegState(Object result) {
220             final int transportType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
221             final int domain = NetworkRegistrationInfo.DOMAIN_CS;
222 
223             if (result instanceof android.hardware.radio.V1_6.RegStateResult) {
224                 return getNetworkRegistrationInfo1_6(
225                         domain,
226                         transportType,
227                         (android.hardware.radio.V1_6.RegStateResult) result);
228             }
229             // 1.5 at the top so that we can do an "early exit" from the method
230             else if (result instanceof android.hardware.radio.V1_5.RegStateResult) {
231                 return getNetworkRegistrationInfo(
232                         domain,
233                         transportType,
234                         (android.hardware.radio.V1_5.RegStateResult) result);
235             } else if (result instanceof android.hardware.radio.V1_0.VoiceRegStateResult) {
236                 android.hardware.radio.V1_0.VoiceRegStateResult voiceRegState =
237                         (android.hardware.radio.V1_0.VoiceRegStateResult) result;
238                 int regState = getRegStateFromHalRegState(voiceRegState.regState);
239                 int networkType = ServiceState.rilRadioTechnologyToNetworkType(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                 List<Integer> availableServices = getAvailableServices(
247                         regState, domain, emergencyOnly);
248                 CellIdentity cellIdentity = CellIdentity.create(voiceRegState.cellIdentity);
249                 final String rplmn = getPlmnFromCellIdentity(cellIdentity);
250 
251                 return new NetworkRegistrationInfo(domain, transportType, regState,
252                         networkType, reasonForDenial, emergencyOnly, availableServices,
253                         cellIdentity, rplmn, cssSupported, roamingIndicator, systemIsInPrl,
254                         defaultRoamingIndicator);
255             } else if (result instanceof android.hardware.radio.V1_2.VoiceRegStateResult) {
256                 android.hardware.radio.V1_2.VoiceRegStateResult voiceRegState =
257                         (android.hardware.radio.V1_2.VoiceRegStateResult) result;
258                 int regState = getRegStateFromHalRegState(voiceRegState.regState);
259                 int networkType = ServiceState.rilRadioTechnologyToNetworkType(voiceRegState.rat);
260                 int reasonForDenial = voiceRegState.reasonForDenial;
261                 boolean emergencyOnly = isEmergencyOnly(voiceRegState.regState);
262                 boolean cssSupported = voiceRegState.cssSupported;
263                 int roamingIndicator = voiceRegState.roamingIndicator;
264                 int systemIsInPrl = voiceRegState.systemIsInPrl;
265                 int defaultRoamingIndicator = voiceRegState.defaultRoamingIndicator;
266                 List<Integer> availableServices = getAvailableServices(
267                         regState, domain, emergencyOnly);
268                 CellIdentity cellIdentity = CellIdentity.create(voiceRegState.cellIdentity);
269                 final String rplmn = getPlmnFromCellIdentity(cellIdentity);
270 
271                 return new NetworkRegistrationInfo(domain, transportType, regState,
272                         networkType, reasonForDenial, emergencyOnly, availableServices,
273                         cellIdentity, rplmn, cssSupported, roamingIndicator, systemIsInPrl,
274                         defaultRoamingIndicator);
275             }
276 
277             return null;
278         }
279 
createRegistrationStateFromDataRegState(Object result)280         private NetworkRegistrationInfo createRegistrationStateFromDataRegState(Object result) {
281             final int domain = NetworkRegistrationInfo.DOMAIN_PS;
282             final int transportType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
283 
284             int regState = NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN;
285             int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
286             int reasonForDenial = 0;
287             boolean emergencyOnly = false;
288             int maxDataCalls = 0;
289             CellIdentity cellIdentity;
290             boolean isEndcAvailable = false;
291             boolean isNrAvailable = false;
292             boolean isDcNrRestricted = false;
293 
294             LteVopsSupportInfo lteVopsSupportInfo =
295                     new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE,
296                             LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE);
297 
298             if (result instanceof android.hardware.radio.V1_6.RegStateResult) {
299                 return getNetworkRegistrationInfo1_6(
300                         domain,
301                         transportType,
302                         (android.hardware.radio.V1_6.RegStateResult) result);
303             }
304             // 1.5 at the top so that we can do an "early exit" from the method
305             else if (result instanceof android.hardware.radio.V1_5.RegStateResult) {
306                 return getNetworkRegistrationInfo(
307                         domain,
308                         transportType,
309                         (android.hardware.radio.V1_5.RegStateResult) result);
310             } else if (result instanceof android.hardware.radio.V1_0.DataRegStateResult) {
311                 android.hardware.radio.V1_0.DataRegStateResult dataRegState =
312                         (android.hardware.radio.V1_0.DataRegStateResult) result;
313                 regState = getRegStateFromHalRegState(dataRegState.regState);
314                 networkType = ServiceState.rilRadioTechnologyToNetworkType(dataRegState.rat);
315                 reasonForDenial = dataRegState.reasonDataDenied;
316                 emergencyOnly = isEmergencyOnly(dataRegState.regState);
317                 maxDataCalls = dataRegState.maxDataCalls;
318                 cellIdentity = CellIdentity.create(dataRegState.cellIdentity);
319             } else if (result instanceof android.hardware.radio.V1_2.DataRegStateResult) {
320                 android.hardware.radio.V1_2.DataRegStateResult dataRegState =
321                         (android.hardware.radio.V1_2.DataRegStateResult) result;
322                 regState = getRegStateFromHalRegState(dataRegState.regState);
323                 networkType = ServiceState.rilRadioTechnologyToNetworkType(dataRegState.rat);
324                 reasonForDenial = dataRegState.reasonDataDenied;
325                 emergencyOnly = isEmergencyOnly(dataRegState.regState);
326                 maxDataCalls = dataRegState.maxDataCalls;
327                 cellIdentity = CellIdentity.create(dataRegState.cellIdentity);
328             } else if (result instanceof android.hardware.radio.V1_4.DataRegStateResult) {
329                 android.hardware.radio.V1_4.DataRegStateResult dataRegState =
330                         (android.hardware.radio.V1_4.DataRegStateResult) result;
331                 regState = getRegStateFromHalRegState(dataRegState.base.regState);
332                 networkType = ServiceState.rilRadioTechnologyToNetworkType(dataRegState.base.rat);
333 
334                 reasonForDenial = dataRegState.base.reasonDataDenied;
335                 emergencyOnly = isEmergencyOnly(dataRegState.base.regState);
336                 maxDataCalls = dataRegState.base.maxDataCalls;
337                 cellIdentity = CellIdentity.create(dataRegState.base.cellIdentity);
338                 android.hardware.radio.V1_4.NrIndicators nrIndicators = dataRegState.nrIndicators;
339 
340                 // Check for lteVopsInfo only if its initialized and RAT is EUTRAN
341                 if (dataRegState.vopsInfo.getDiscriminator() == hidl_discriminator.lteVopsInfo
342                         && ServiceState.rilRadioTechnologyToAccessNetworkType(dataRegState.base.rat)
343                             == AccessNetworkType.EUTRAN) {
344                     android.hardware.radio.V1_4.LteVopsInfo vopsSupport =
345                             dataRegState.vopsInfo.lteVopsInfo();
346                     lteVopsSupportInfo = convertHalLteVopsSupportInfo(vopsSupport.isVopsSupported,
347                         vopsSupport.isEmcBearerSupported);
348                 } else {
349                     lteVopsSupportInfo =
350                         new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE,
351                         LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE);
352                 }
353 
354                 isEndcAvailable = nrIndicators.isEndcAvailable;
355                 isNrAvailable = nrIndicators.isNrAvailable;
356                 isDcNrRestricted = nrIndicators.isDcNrRestricted;
357             } else {
358                 loge("Unknown type of DataRegStateResult " + result);
359                 return null;
360             }
361 
362             String rplmn = getPlmnFromCellIdentity(cellIdentity);
363             List<Integer> availableServices = getAvailableServices(
364                     regState, domain, emergencyOnly);
365 
366             return new NetworkRegistrationInfo(domain, transportType, regState, networkType,
367                     reasonForDenial, emergencyOnly, availableServices, cellIdentity, rplmn,
368                     maxDataCalls, isDcNrRestricted, isNrAvailable, isEndcAvailable,
369                     lteVopsSupportInfo);
370         }
371 
getNetworkRegistrationInfo( int domain, int transportType, android.hardware.radio.V1_5.RegStateResult regResult)372         private @NonNull NetworkRegistrationInfo getNetworkRegistrationInfo(
373                 int domain, int transportType,
374                 android.hardware.radio.V1_5.RegStateResult regResult) {
375 
376             // Perform common conversions that aren't domain specific
377             final int regState = getRegStateFromHalRegState(regResult.regState);
378             final boolean isEmergencyOnly = isEmergencyOnly(regResult.regState);
379             final List<Integer> availableServices = getAvailableServices(
380                     regState, domain, isEmergencyOnly);
381             final int rejectCause = regResult.reasonForDenial;
382             final CellIdentity cellIdentity = CellIdentity.create(regResult.cellIdentity);
383             final String rplmn = regResult.registeredPlmn;
384             final int reasonForDenial = regResult.reasonForDenial;
385 
386             int networkType = ServiceState.rilRadioTechnologyToNetworkType(regResult.rat);
387             if (networkType == TelephonyManager.NETWORK_TYPE_LTE_CA) {
388                 // In Radio HAL v1.5, NETWORK_TYPE_LTE_CA is ignored. Callers should use
389                 // PhysicalChannelConfig.
390                 networkType = TelephonyManager.NETWORK_TYPE_LTE;
391             }
392 
393             // Conditional parameters for specific RANs
394             boolean cssSupported = false;
395             int roamingIndicator = 0;
396             int systemIsInPrl = 0;
397             int defaultRoamingIndicator = 0;
398             boolean isEndcAvailable = false;
399             boolean isNrAvailable = false;
400             boolean isDcNrRestricted = false;
401             LteVopsSupportInfo vopsInfo = new LteVopsSupportInfo(
402                     LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE,
403                     LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE);
404 
405             switch (regResult.accessTechnologySpecificInfo.getDiscriminator()) {
406                 case android.hardware.radio.V1_5.RegStateResult
407                         .AccessTechnologySpecificInfo.hidl_discriminator.cdmaInfo:
408                     android.hardware.radio.V1_5.RegStateResult
409                             .AccessTechnologySpecificInfo.Cdma2000RegistrationInfo cdmaInfo =
410                                     regResult.accessTechnologySpecificInfo.cdmaInfo();
411                     cssSupported = cdmaInfo.cssSupported;
412                     roamingIndicator = cdmaInfo.roamingIndicator;
413                     systemIsInPrl = cdmaInfo.systemIsInPrl;
414                     defaultRoamingIndicator = cdmaInfo.defaultRoamingIndicator;
415                     break;
416                 case android.hardware.radio.V1_5.RegStateResult
417                         .AccessTechnologySpecificInfo.hidl_discriminator.eutranInfo:
418                     android.hardware.radio.V1_5.RegStateResult
419                             .AccessTechnologySpecificInfo.EutranRegistrationInfo eutranInfo =
420                                     regResult.accessTechnologySpecificInfo.eutranInfo();
421 
422                     isDcNrRestricted = eutranInfo.nrIndicators.isDcNrRestricted;
423                     isNrAvailable = eutranInfo.nrIndicators.isNrAvailable;
424                     isEndcAvailable = eutranInfo.nrIndicators.isEndcAvailable;
425                     vopsInfo = convertHalLteVopsSupportInfo(
426                             eutranInfo.lteVopsInfo.isVopsSupported,
427                             eutranInfo.lteVopsInfo.isEmcBearerSupported);
428                     break;
429                 default:
430                     log("No access tech specific info passes for RegStateResult");
431                     break;
432             }
433 
434             // build the result based on the domain for the request
435             switch(domain) {
436                 case NetworkRegistrationInfo.DOMAIN_CS:
437                     return new NetworkRegistrationInfo(domain, transportType, regState,
438                             networkType, reasonForDenial, isEmergencyOnly, availableServices,
439                             cellIdentity, rplmn, cssSupported, roamingIndicator, systemIsInPrl,
440                             defaultRoamingIndicator);
441                 default:
442                     loge("Unknown domain passed to CellularNetworkService= " + domain);
443                     // fall through
444                 case NetworkRegistrationInfo.DOMAIN_PS:
445                     return new NetworkRegistrationInfo(domain, transportType, regState, networkType,
446                             reasonForDenial, isEmergencyOnly, availableServices, cellIdentity,
447                             rplmn, MAX_DATA_CALLS, isDcNrRestricted, isNrAvailable, isEndcAvailable,
448                             vopsInfo);
449             }
450         }
451 
getNetworkRegistrationInfo1_6( int domain, int transportType, android.hardware.radio.V1_6.RegStateResult regResult)452         private @NonNull NetworkRegistrationInfo getNetworkRegistrationInfo1_6(
453                 int domain, int transportType,
454                 android.hardware.radio.V1_6.RegStateResult regResult) {
455 
456             // Perform common conversions that aren't domain specific
457             final int regState = getRegStateFromHalRegState(regResult.regState);
458             final boolean isEmergencyOnly = isEmergencyOnly(regResult.regState);
459             final List<Integer> availableServices = getAvailableServices(
460                     regState, domain, isEmergencyOnly);
461             final int rejectCause = regResult.reasonForDenial;
462             final CellIdentity cellIdentity = CellIdentity.create(regResult.cellIdentity);
463             final String rplmn = regResult.registeredPlmn;
464             final int reasonForDenial = regResult.reasonForDenial;
465 
466             int networkType = ServiceState.rilRadioTechnologyToNetworkType(regResult.rat);
467             if (networkType == TelephonyManager.NETWORK_TYPE_LTE_CA) {
468                 // In Radio HAL v1.5, NETWORK_TYPE_LTE_CA is ignored. Callers should use
469                 // PhysicalChannelConfig.
470                 networkType = TelephonyManager.NETWORK_TYPE_LTE;
471             }
472 
473             // Conditional parameters for specific RANs
474             boolean cssSupported = false;
475             int roamingIndicator = 0;
476             int systemIsInPrl = 0;
477             int defaultRoamingIndicator = 0;
478             boolean isEndcAvailable = false;
479             boolean isNrAvailable = false;
480             boolean isDcNrRestricted = false;
481             VopsSupportInfo vopsInfo = null;
482 
483             android.hardware.radio.V1_6.RegStateResult.AccessTechnologySpecificInfo info =
484                     regResult.accessTechnologySpecificInfo;
485 
486             switch (info.getDiscriminator()) {
487                 case AccessTechnologySpecificInfo.hidl_discriminator.cdmaInfo:
488                     cssSupported = info.cdmaInfo().cssSupported;
489                     roamingIndicator = info.cdmaInfo().roamingIndicator;
490                     systemIsInPrl = info.cdmaInfo().systemIsInPrl;
491                     defaultRoamingIndicator = info.cdmaInfo().defaultRoamingIndicator;
492                     break;
493                 case AccessTechnologySpecificInfo.hidl_discriminator.eutranInfo:
494                     isDcNrRestricted = info.eutranInfo().nrIndicators.isDcNrRestricted;
495                     isNrAvailable = info.eutranInfo().nrIndicators.isNrAvailable;
496                     isEndcAvailable = info.eutranInfo().nrIndicators.isEndcAvailable;
497                     vopsInfo = convertHalLteVopsSupportInfo(
498                             info.eutranInfo().lteVopsInfo.isVopsSupported,
499                             info.eutranInfo().lteVopsInfo.isEmcBearerSupported);
500                     break;
501                 case AccessTechnologySpecificInfo.hidl_discriminator.ngranNrVopsInfo:
502                     vopsInfo = new NrVopsSupportInfo(info.ngranNrVopsInfo().vopsSupported,
503                             info.ngranNrVopsInfo().emcSupported,
504                             info.ngranNrVopsInfo().emfSupported);
505                     break;
506                 case AccessTechnologySpecificInfo.hidl_discriminator.geranDtmSupported:
507                     cssSupported = info.geranDtmSupported();
508                     break;
509                 default:
510                     log("No access tech specific info passes for RegStateResult");
511                     break;
512             }
513 
514             // build the result based on the domain for the request
515             switch(domain) {
516                 case NetworkRegistrationInfo.DOMAIN_CS:
517                     return new NetworkRegistrationInfo(domain, transportType, regState,
518                             networkType, reasonForDenial, isEmergencyOnly, availableServices,
519                             cellIdentity, rplmn, cssSupported, roamingIndicator, systemIsInPrl,
520                             defaultRoamingIndicator);
521                 default:
522                     loge("Unknown domain passed to CellularNetworkService= " + domain);
523                     // fall through
524                 case NetworkRegistrationInfo.DOMAIN_PS:
525                     return new NetworkRegistrationInfo(domain, transportType, regState, networkType,
526                             reasonForDenial, isEmergencyOnly, availableServices, cellIdentity,
527                             rplmn, MAX_DATA_CALLS, isDcNrRestricted, isNrAvailable, isEndcAvailable,
528                             vopsInfo);
529             }
530         }
531 
convertHalLteVopsSupportInfo( boolean vopsSupport, boolean emcBearerSupport)532         private LteVopsSupportInfo convertHalLteVopsSupportInfo(
533                 boolean vopsSupport, boolean emcBearerSupport) {
534             int vops = LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED;
535             int emergency = LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED;
536 
537             if (vopsSupport) {
538                 vops = LteVopsSupportInfo.LTE_STATUS_SUPPORTED;
539             }
540             if (emcBearerSupport) {
541                 emergency = LteVopsSupportInfo.LTE_STATUS_SUPPORTED;
542             }
543             return new LteVopsSupportInfo(vops, emergency);
544         }
545 
546         @Override
requestNetworkRegistrationInfo(int domain, NetworkServiceCallback callback)547         public void requestNetworkRegistrationInfo(int domain, NetworkServiceCallback callback) {
548             if (DBG) log("requestNetworkRegistrationInfo for domain " + domain);
549             Message message = null;
550 
551             if (domain == NetworkRegistrationInfo.DOMAIN_CS) {
552                 message = Message.obtain(mHandler, GET_CS_REGISTRATION_STATE_DONE);
553                 mCallbackMap.put(message, callback);
554                 mPhone.mCi.getVoiceRegistrationState(message);
555             } else if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
556                 message = Message.obtain(mHandler, GET_PS_REGISTRATION_STATE_DONE);
557                 mCallbackMap.put(message, callback);
558                 mPhone.mCi.getDataRegistrationState(message);
559             } else {
560                 loge("requestNetworkRegistrationInfo invalid domain " + domain);
561                 callback.onRequestNetworkRegistrationInfoComplete(
562                         NetworkServiceCallback.RESULT_ERROR_INVALID_ARG, null);
563             }
564         }
565 
566         @Override
close()567         public void close() {
568             mCallbackMap.clear();
569             mPhone.mCi.unregisterForNetworkStateChanged(mHandler);
570         }
571     }
572 
573     @Override
onCreateNetworkServiceProvider(int slotIndex)574     public NetworkServiceProvider onCreateNetworkServiceProvider(int slotIndex) {
575         if (DBG) log("Cellular network service created for slot " + slotIndex);
576         if (!SubscriptionManager.isValidSlotIndex(slotIndex)) {
577             loge("Tried to Cellular network service with invalid slotId " + slotIndex);
578             return null;
579         }
580         return new CellularNetworkServiceProvider(slotIndex);
581     }
582 
log(String s)583     private void log(String s) {
584         Rlog.d(TAG, s);
585     }
586 
loge(String s)587     private void loge(String s) {
588         Rlog.e(TAG, s);
589     }
590 }
591