• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 com.android.internal.telephony;
18 
19 import static android.telephony.PhoneCapability.DEVICE_NR_CAPABILITY_NSA;
20 import static android.telephony.PhoneCapability.DEVICE_NR_CAPABILITY_SA;
21 
22 import static com.android.internal.telephony.RILConstants.RADIO_NOT_AVAILABLE;
23 import static com.android.internal.telephony.RILConstants.REQUEST_NOT_SUPPORTED;
24 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_HAL_DEVICE_CAPABILITIES;
25 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_PHONE_CAPABILITY;
26 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_SLOT_STATUS;
27 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING;
28 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_PREFERRED_DATA_MODEM;
29 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG;
30 
31 import android.content.Context;
32 import android.hardware.radio.V1_0.RadioResponseInfo;
33 import android.hardware.radio.V1_0.RadioResponseType;
34 import android.hardware.radio.config.V1_0.IRadioConfig;
35 import android.hardware.radio.config.V1_1.ModemsConfig;
36 import android.os.AsyncResult;
37 import android.os.Handler;
38 import android.os.HwBinder;
39 import android.os.Message;
40 import android.os.Registrant;
41 import android.os.RemoteException;
42 import android.os.WorkSource;
43 import android.telephony.TelephonyManager;
44 import android.util.SparseArray;
45 
46 import com.android.internal.telephony.uicc.IccSlotStatus;
47 import com.android.telephony.Rlog;
48 
49 import java.util.ArrayList;
50 import java.util.Arrays;
51 import java.util.List;
52 import java.util.NoSuchElementException;
53 import java.util.concurrent.atomic.AtomicLong;
54 
55 /**
56  * This class provides wrapper APIs for IRadioConfig interface.
57  */
58 public class RadioConfig extends Handler {
59     private static final String TAG = "RadioConfig";
60     private static final boolean DBG = true;
61     private static final boolean VDBG = false;   //STOPSHIP if true
62 
63     private static final int EVENT_SERVICE_DEAD = 1;
64 
65     private static final HalVersion RADIO_CONFIG_HAL_VERSION_UNKNOWN = new HalVersion(-1, -1);
66 
67     private static final HalVersion RADIO_CONFIG_HAL_VERSION_1_0 = new HalVersion(1, 0);
68 
69     private static final HalVersion RADIO_CONFIG_HAL_VERSION_1_1 = new HalVersion(1, 1);
70 
71     private static final HalVersion RADIO_CONFIG_HAL_VERSION_1_3 = new HalVersion(1, 3);
72 
73     private final boolean mIsMobileNetworkSupported;
74     private volatile IRadioConfig mRadioConfigProxy = null;
75     // IRadioConfig version
76     private HalVersion mRadioConfigVersion = RADIO_CONFIG_HAL_VERSION_UNKNOWN;
77     private final ServiceDeathRecipient mServiceDeathRecipient;
78     private final AtomicLong mRadioConfigProxyCookie = new AtomicLong(0);
79     private final RadioConfigResponse mRadioConfigResponse;
80     private final RadioConfigIndication mRadioConfigIndication;
81     private final SparseArray<RILRequest> mRequestList = new SparseArray<RILRequest>();
82     /* default work source which will blame phone process */
83     private final WorkSource mDefaultWorkSource;
84     private final int[] mDeviceNrCapabilities;
85     private static RadioConfig sRadioConfig;
86     private static final Object sLock = new Object();
87 
88     protected Registrant mSimSlotStatusRegistrant;
89 
90     final class ServiceDeathRecipient implements HwBinder.DeathRecipient {
91         @Override
serviceDied(long cookie)92         public void serviceDied(long cookie) {
93             // Deal with service going away
94             logd("serviceDied");
95             sendMessage(obtainMessage(EVENT_SERVICE_DEAD, cookie));
96         }
97     }
98 
isMobileDataCapable(Context context)99     private boolean isMobileDataCapable(Context context) {
100         final TelephonyManager tm = context.getSystemService(TelephonyManager.class);
101         if (tm == null) {
102             return false;
103         }
104         return tm.isDataCapable();
105     }
106 
RadioConfig(Context context, HalVersion radioHalVersion)107     private RadioConfig(Context context, HalVersion radioHalVersion) {
108         mIsMobileNetworkSupported = isMobileDataCapable(context);
109 
110         mRadioConfigResponse = new RadioConfigResponse(this, radioHalVersion);
111         mRadioConfigIndication = new RadioConfigIndication(this);
112         mServiceDeathRecipient = new ServiceDeathRecipient();
113 
114         mDefaultWorkSource = new WorkSource(context.getApplicationInfo().uid,
115                 context.getPackageName());
116 
117         boolean is5gStandalone = context.getResources().getBoolean(
118                 com.android.internal.R.bool.config_telephony5gStandalone);
119         boolean is5gNonStandalone = context.getResources().getBoolean(
120                 com.android.internal.R.bool.config_telephony5gNonStandalone);
121 
122         if (!is5gStandalone && !is5gNonStandalone) {
123             mDeviceNrCapabilities = new int[0];
124         } else {
125             List<Integer> list = new ArrayList<>();
126             if (is5gNonStandalone) {
127                 list.add(DEVICE_NR_CAPABILITY_NSA);
128             }
129             if (is5gStandalone) {
130                 list.add(DEVICE_NR_CAPABILITY_SA);
131             }
132             mDeviceNrCapabilities = list.stream().mapToInt(Integer::valueOf).toArray();
133         }
134     }
135 
136     /**
137      * Returns the singleton static instance of RadioConfig
138      */
getInstance()139     public static RadioConfig getInstance() {
140         synchronized (sLock) {
141             if (sRadioConfig == null) {
142                 throw new RuntimeException(
143                         "RadioConfig.getInstance can't be called before make()");
144             }
145             return sRadioConfig;
146         }
147     }
148 
149     /**
150      * Makes the radio config based on the context and the radio hal version passed in
151      */
make(Context c, HalVersion radioHalVersion)152     public static RadioConfig make(Context c, HalVersion radioHalVersion) {
153         synchronized (sLock) {
154             if (sRadioConfig != null) {
155                 throw new RuntimeException("RadioConfig.make() should only be called once");
156             }
157             sRadioConfig = new RadioConfig(c, radioHalVersion);
158             return sRadioConfig;
159         }
160     }
161 
162     @Override
handleMessage(Message message)163     public void handleMessage(Message message) {
164         switch (message.what) {
165             case EVENT_SERVICE_DEAD:
166                 logd("handleMessage: EVENT_SERVICE_DEAD cookie = " + message.obj
167                         + " mRadioConfigProxyCookie = " + mRadioConfigProxyCookie.get());
168                 if ((long) message.obj == mRadioConfigProxyCookie.get()) {
169                     resetProxyAndRequestList("EVENT_SERVICE_DEAD", null);
170                 }
171                 break;
172         }
173     }
174 
175     /**
176      * Release each request in mRequestList then clear the list
177      * @param error is the RIL_Errno sent back
178      * @param loggable true means to print all requests in mRequestList
179      */
clearRequestList(int error, boolean loggable)180     private void clearRequestList(int error, boolean loggable) {
181         RILRequest rr;
182         synchronized (mRequestList) {
183             int count = mRequestList.size();
184             if (DBG && loggable) {
185                 logd("clearRequestList: mRequestList=" + count);
186             }
187 
188             for (int i = 0; i < count; i++) {
189                 rr = mRequestList.valueAt(i);
190                 if (DBG && loggable) {
191                     logd(i + ": [" + rr.mSerial + "] " + requestToString(rr.mRequest));
192                 }
193                 rr.onError(error, null);
194                 rr.release();
195             }
196             mRequestList.clear();
197         }
198     }
199 
resetProxyAndRequestList(String caller, Exception e)200     private void resetProxyAndRequestList(String caller, Exception e) {
201         loge(caller + ": " + e);
202         mRadioConfigProxy = null;
203 
204         // increment the cookie so that death notification can be ignored
205         mRadioConfigProxyCookie.incrementAndGet();
206 
207         RILRequest.resetSerial();
208         // Clear request list on close
209         clearRequestList(RADIO_NOT_AVAILABLE, false);
210 
211         getRadioConfigProxy(null);
212     }
213 
214     /** Returns a {@link IRadioConfig} instance or null if the service is not available. */
getRadioConfigProxy(Message result)215     public IRadioConfig getRadioConfigProxy(Message result) {
216         if (!mIsMobileNetworkSupported) {
217             if (VDBG) logd("getRadioConfigProxy: Not calling getService(): wifi-only");
218             if (result != null) {
219                 AsyncResult.forMessage(result, null,
220                         CommandException.fromRilErrno(RADIO_NOT_AVAILABLE));
221                 result.sendToTarget();
222             }
223             return null;
224         }
225 
226         if (mRadioConfigProxy != null) {
227             return mRadioConfigProxy;
228         }
229 
230         updateRadioConfigProxy();
231 
232         if (mRadioConfigProxy == null) {
233             if (result != null) {
234                 AsyncResult.forMessage(result, null,
235                         CommandException.fromRilErrno(RADIO_NOT_AVAILABLE));
236                 result.sendToTarget();
237             }
238         }
239 
240         return mRadioConfigProxy;
241     }
242 
updateRadioConfigProxy()243     private void updateRadioConfigProxy() {
244         try {
245 
246             // Try to get service from different versions.
247             try {
248                 mRadioConfigProxy = android.hardware.radio.config.V1_3.IRadioConfig.getService(
249                         true);
250                 mRadioConfigVersion = RADIO_CONFIG_HAL_VERSION_1_3;
251             } catch (NoSuchElementException e) {
252             }
253 
254 
255             if (mRadioConfigProxy == null) {
256                 // Try to get service from different versions.
257                 try {
258                     mRadioConfigProxy = android.hardware.radio.config.V1_1.IRadioConfig.getService(
259                             true);
260                     mRadioConfigVersion = RADIO_CONFIG_HAL_VERSION_1_1;
261                 } catch (NoSuchElementException e) {
262                 }
263             }
264 
265             if (mRadioConfigProxy == null) {
266                 try {
267                     mRadioConfigProxy = android.hardware.radio.config.V1_0
268                             .IRadioConfig.getService(true);
269                     mRadioConfigVersion = RADIO_CONFIG_HAL_VERSION_1_0;
270                 } catch (NoSuchElementException e) {
271                 }
272             }
273 
274             if (mRadioConfigProxy == null) {
275                 loge("getRadioConfigProxy: mRadioConfigProxy == null");
276                 return;
277             }
278 
279             // Link to death recipient and set response. If fails, set proxy to null and return.
280             mRadioConfigProxy.linkToDeath(mServiceDeathRecipient,
281                     mRadioConfigProxyCookie.incrementAndGet());
282             mRadioConfigProxy.setResponseFunctions(mRadioConfigResponse,
283                     mRadioConfigIndication);
284         } catch (RemoteException | RuntimeException e) {
285             mRadioConfigProxy = null;
286             loge("getRadioConfigProxy: RadioConfigProxy setResponseFunctions: " + e);
287             return;
288         }
289     }
290 
obtainRequest(int request, Message result, WorkSource workSource)291     private RILRequest obtainRequest(int request, Message result, WorkSource workSource) {
292         RILRequest rr = RILRequest.obtain(request, result, workSource);
293         synchronized (mRequestList) {
294             mRequestList.append(rr.mSerial, rr);
295         }
296         return rr;
297     }
298 
findAndRemoveRequestFromList(int serial)299     private RILRequest findAndRemoveRequestFromList(int serial) {
300         RILRequest rr;
301         synchronized (mRequestList) {
302             rr = mRequestList.get(serial);
303             if (rr != null) {
304                 mRequestList.remove(serial);
305             }
306         }
307 
308         return rr;
309     }
310 
311     /**
312      * This is a helper function to be called when a RadioConfigResponse callback is called.
313      * It finds and returns RILRequest corresponding to the response if one is found.
314      * @param responseInfo RadioResponseInfo received in response callback
315      * @return RILRequest corresponding to the response
316      */
processResponse(RadioResponseInfo responseInfo)317     public RILRequest processResponse(RadioResponseInfo responseInfo) {
318         int serial = responseInfo.serial;
319         int error = responseInfo.error;
320         int type = responseInfo.type;
321 
322         if (type != RadioResponseType.SOLICITED) {
323             loge("processResponse: Unexpected response type " + type);
324         }
325 
326         RILRequest rr = findAndRemoveRequestFromList(serial);
327         if (rr == null) {
328             loge("processResponse: Unexpected response! serial: " + serial + " error: " + error);
329             return null;
330         }
331 
332         return rr;
333     }
334 
335     /**
336      * This is a helper function to be called when a RadioConfigResponse callback is called.
337      * It finds and returns RILRequest corresponding to the response if one is found.
338      * @param responseInfo RadioResponseInfo received in response callback
339      * @return RILRequest corresponding to the response
340      */
processResponse_1_6( android.hardware.radio.V1_6.RadioResponseInfo responseInfo)341     public RILRequest processResponse_1_6(
342             android.hardware.radio.V1_6.RadioResponseInfo responseInfo) {
343         int serial = responseInfo.serial;
344         int error = responseInfo.error;
345         int type = responseInfo.type;
346 
347         if (type != RadioResponseType.SOLICITED) {
348             loge("processResponse: Unexpected response type " + type);
349         }
350 
351         RILRequest rr = findAndRemoveRequestFromList(serial);
352         if (rr == null) {
353             loge("processResponse: Unexpected response! serial: " + serial + " error: " + error);
354             return null;
355         }
356 
357         return rr;
358     }
359 
360     /**
361      * Wrapper function for IRadioConfig.getSimSlotsStatus().
362      */
getSimSlotsStatus(Message result)363     public void getSimSlotsStatus(Message result) {
364         IRadioConfig radioConfigProxy = getRadioConfigProxy(result);
365         if (radioConfigProxy != null) {
366             RILRequest rr = obtainRequest(RIL_REQUEST_GET_SLOT_STATUS, result, mDefaultWorkSource);
367 
368             if (DBG) {
369                 logd(rr.serialString() + "> " + requestToString(rr.mRequest));
370             }
371 
372             try {
373                 radioConfigProxy.getSimSlotsStatus(rr.mSerial);
374             } catch (RemoteException | RuntimeException e) {
375                 resetProxyAndRequestList("getSimSlotsStatus", e);
376             }
377         }
378     }
379 
380     /**
381      * Wrapper function for IRadioConfig.setPreferredDataModem(int modemId).
382      */
setPreferredDataModem(int modemId, Message result)383     public void setPreferredDataModem(int modemId, Message result) {
384         if (!isSetPreferredDataCommandSupported()) {
385             if (result != null) {
386                 AsyncResult.forMessage(result, null,
387                         CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
388                 result.sendToTarget();
389             }
390             return;
391         }
392 
393         RILRequest rr = obtainRequest(RIL_REQUEST_SET_PREFERRED_DATA_MODEM,
394                 result, mDefaultWorkSource);
395 
396         if (DBG) {
397             logd(rr.serialString() + "> " + requestToString(rr.mRequest));
398         }
399 
400         try {
401             ((android.hardware.radio.config.V1_1.IRadioConfig) mRadioConfigProxy)
402                     .setPreferredDataModem(rr.mSerial, (byte) modemId);
403         } catch (RemoteException | RuntimeException e) {
404             resetProxyAndRequestList("setPreferredDataModem", e);
405         }
406     }
407 
408     /**
409      * Wrapper function for IRadioConfig.getPhoneCapability().
410      */
getPhoneCapability(Message result)411     public void getPhoneCapability(Message result) {
412         IRadioConfig radioConfigProxy = getRadioConfigProxy(null);
413         if (radioConfigProxy == null || mRadioConfigVersion.less(RADIO_CONFIG_HAL_VERSION_1_1)) {
414             if (result != null) {
415                 AsyncResult.forMessage(result, null,
416                         CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
417                 result.sendToTarget();
418             }
419             return;
420         }
421 
422         RILRequest rr = obtainRequest(RIL_REQUEST_GET_PHONE_CAPABILITY, result, mDefaultWorkSource);
423 
424         if (DBG) {
425             logd(rr.serialString() + "> " + requestToString(rr.mRequest));
426         }
427 
428         try {
429             ((android.hardware.radio.config.V1_1.IRadioConfig) mRadioConfigProxy)
430                     .getPhoneCapability(rr.mSerial);
431         } catch (RemoteException | RuntimeException e) {
432             resetProxyAndRequestList("getPhoneCapability", e);
433         }
434     }
435 
436     /**
437      * @return whether current radio config version supports SET_PREFERRED_DATA_MODEM command.
438      * If yes, we'll use RIL_REQUEST_SET_PREFERRED_DATA_MODEM to indicate which modem is preferred.
439      * If not, we shall use RIL_REQUEST_ALLOW_DATA for on-demand PS attach / detach.
440      * See PhoneSwitcher for more details.
441      */
isSetPreferredDataCommandSupported()442     public boolean isSetPreferredDataCommandSupported() {
443         IRadioConfig radioConfigProxy = getRadioConfigProxy(null);
444         return radioConfigProxy != null && mRadioConfigVersion
445                 .greaterOrEqual(RADIO_CONFIG_HAL_VERSION_1_1);
446     }
447 
448     /**
449      * Wrapper function for IRadioConfig.setSimSlotsMapping(int32_t serial, vec<uint32_t> slotMap).
450      */
setSimSlotsMapping(int[] physicalSlots, Message result)451     public void setSimSlotsMapping(int[] physicalSlots, Message result) {
452         IRadioConfig radioConfigProxy = getRadioConfigProxy(result);
453         if (radioConfigProxy != null) {
454             RILRequest rr = obtainRequest(RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING, result,
455                     mDefaultWorkSource);
456 
457             if (DBG) {
458                 logd(rr.serialString() + "> " + requestToString(rr.mRequest)
459                         + " " + Arrays.toString(physicalSlots));
460             }
461 
462             try {
463                 radioConfigProxy.setSimSlotsMapping(rr.mSerial,
464                         primitiveArrayToArrayList(physicalSlots));
465             } catch (RemoteException | RuntimeException e) {
466                 resetProxyAndRequestList("setSimSlotsMapping", e);
467             }
468         }
469     }
470 
primitiveArrayToArrayList(int[] arr)471     private static ArrayList<Integer> primitiveArrayToArrayList(int[] arr) {
472         ArrayList<Integer> arrayList = new ArrayList<>(arr.length);
473         for (int i : arr) {
474             arrayList.add(i);
475         }
476         return arrayList;
477     }
478 
requestToString(int request)479     static String requestToString(int request) {
480         switch (request) {
481             case RIL_REQUEST_GET_PHONE_CAPABILITY:
482                 return "GET_PHONE_CAPABILITY";
483             case RIL_REQUEST_GET_SLOT_STATUS:
484                 return "GET_SLOT_STATUS";
485             case RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING:
486                 return "SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING";
487             case RIL_REQUEST_SET_PREFERRED_DATA_MODEM:
488                 return "SET_PREFERRED_DATA_MODEM";
489             case RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG:
490                 return "SWITCH_DUAL_SIM_CONFIG";
491             case RIL_REQUEST_GET_HAL_DEVICE_CAPABILITIES:
492                 return "GET_HAL_DEVICE_CAPABILITIES";
493             default:
494                 return "<unknown request " + request + ">";
495         }
496     }
497 
498     /**
499      * Wrapper function for using IRadioConfig.setModemsConfig(int32_t serial,
500      * ModemsConfig modemsConfig) to switch between single-sim and multi-sim.
501      */
setModemsConfig(int numOfLiveModems, Message result)502     public void setModemsConfig(int numOfLiveModems, Message result) {
503         IRadioConfig radioConfigProxy = getRadioConfigProxy(result);
504         if (radioConfigProxy != null
505                 && mRadioConfigVersion.greaterOrEqual(RADIO_CONFIG_HAL_VERSION_1_1)) {
506             android.hardware.radio.config.V1_1.IRadioConfig radioConfigProxy11 =
507                     (android.hardware.radio.config.V1_1.IRadioConfig) radioConfigProxy;
508             RILRequest rr = obtainRequest(RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG,
509                     result, mDefaultWorkSource);
510 
511             if (DBG) {
512                 logd(rr.serialString() + "> " + requestToString(rr.mRequest)
513                         + ", numOfLiveModems = " + numOfLiveModems);
514             }
515 
516             try {
517                 ModemsConfig modemsConfig = new ModemsConfig();
518                 modemsConfig.numOfLiveModems = (byte) numOfLiveModems;
519                 radioConfigProxy11.setModemsConfig(rr.mSerial, modemsConfig);
520             } catch (RemoteException | RuntimeException e) {
521                 resetProxyAndRequestList("setModemsConfig", e);
522             }
523         }
524     }
525 
526     // TODO: not needed for now, but if we don't want to use System Properties any more,
527     // we need to implement a wrapper function for getModemsConfig as well
528 
529     /**
530      * Register a handler to get SIM slot status changed notifications.
531      */
registerForSimSlotStatusChanged(Handler h, int what, Object obj)532     public void registerForSimSlotStatusChanged(Handler h, int what, Object obj) {
533         mSimSlotStatusRegistrant = new Registrant(h, what, obj);
534     }
535 
536     /**
537      * Unregister corresponding to registerForSimSlotStatusChanged().
538      */
unregisterForSimSlotStatusChanged(Handler h)539     public void unregisterForSimSlotStatusChanged(Handler h) {
540         if (mSimSlotStatusRegistrant != null && mSimSlotStatusRegistrant.getHandler() == h) {
541             mSimSlotStatusRegistrant.clear();
542             mSimSlotStatusRegistrant = null;
543         }
544     }
545 
546     /**
547      * Gets the hal capabilities from the device.
548      */
getHalDeviceCapabilities(Message result)549     public void getHalDeviceCapabilities(Message result) {
550         IRadioConfig radioConfigProxy = getRadioConfigProxy(Message.obtain(result));
551         if (radioConfigProxy != null
552                 && mRadioConfigVersion.greaterOrEqual(RADIO_CONFIG_HAL_VERSION_1_3)) {
553             android.hardware.radio.config.V1_3.IRadioConfig radioConfigProxy13 =
554                     (android.hardware.radio.config.V1_3.IRadioConfig) radioConfigProxy;
555             RILRequest rr = obtainRequest(RIL_REQUEST_GET_HAL_DEVICE_CAPABILITIES,
556                     result, mDefaultWorkSource);
557 
558             if (DBG) {
559                 logd(rr.serialString() + "> " + requestToString(rr.mRequest));
560             }
561 
562             try {
563                 mRadioConfigVersion = RADIO_CONFIG_HAL_VERSION_1_3;
564                 radioConfigProxy13.getHalDeviceCapabilities(rr.mSerial);
565 
566             } catch (RemoteException | RuntimeException e) {
567                 resetProxyAndRequestList("getHalDeviceCapabilities", e);
568             }
569         } else {
570             if (result != null) {
571                 if (DBG) {
572                     logd("RIL_REQUEST_GET_HAL_DEVICE_CAPABILITIES > REQUEST_NOT_SUPPORTED");
573                 }
574                 AsyncResult.forMessage(result,
575                         /* Send response such that all capabilities are supported (depending on
576                            the hal version of course.) */
577                         mRadioConfigResponse.getFullCapabilitySet(),
578                         CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
579                 result.sendToTarget();
580             } else {
581                 if (DBG) {
582                     logd("RIL_REQUEST_GET_HAL_DEVICE_CAPABILITIES > REQUEST_NOT_SUPPORTED "
583                             + "on complete message not set.");
584                 }
585             }
586         }
587     }
588 
589     /**
590      * Returns the device's nr capability.
591      */
getDeviceNrCapabilities()592     public int[] getDeviceNrCapabilities() {
593         return mDeviceNrCapabilities;
594     }
595 
convertHalSlotStatus( ArrayList<android.hardware.radio.config.V1_0.SimSlotStatus> halSlotStatusList)596     static ArrayList<IccSlotStatus> convertHalSlotStatus(
597             ArrayList<android.hardware.radio.config.V1_0.SimSlotStatus> halSlotStatusList) {
598         ArrayList<IccSlotStatus> response = new ArrayList<IccSlotStatus>(halSlotStatusList.size());
599         for (android.hardware.radio.config.V1_0.SimSlotStatus slotStatus : halSlotStatusList) {
600             IccSlotStatus iccSlotStatus = new IccSlotStatus();
601             iccSlotStatus.setCardState(slotStatus.cardState);
602             iccSlotStatus.setSlotState(slotStatus.slotState);
603             iccSlotStatus.logicalSlotIndex = slotStatus.logicalSlotId;
604             iccSlotStatus.atr = slotStatus.atr;
605             iccSlotStatus.iccid = slotStatus.iccid;
606             response.add(iccSlotStatus);
607         }
608         return response;
609     }
610 
convertHalSlotStatus_1_2( ArrayList<android.hardware.radio.config.V1_2.SimSlotStatus> halSlotStatusList)611     static ArrayList<IccSlotStatus> convertHalSlotStatus_1_2(
612             ArrayList<android.hardware.radio.config.V1_2.SimSlotStatus> halSlotStatusList) {
613         ArrayList<IccSlotStatus> response = new ArrayList<IccSlotStatus>(halSlotStatusList.size());
614         for (android.hardware.radio.config.V1_2.SimSlotStatus slotStatus : halSlotStatusList) {
615             IccSlotStatus iccSlotStatus = new IccSlotStatus();
616             iccSlotStatus.setCardState(slotStatus.base.cardState);
617             iccSlotStatus.setSlotState(slotStatus.base.slotState);
618             iccSlotStatus.logicalSlotIndex = slotStatus.base.logicalSlotId;
619             iccSlotStatus.atr = slotStatus.base.atr;
620             iccSlotStatus.iccid = slotStatus.base.iccid;
621             iccSlotStatus.eid = slotStatus.eid;
622             response.add(iccSlotStatus);
623         }
624         return response;
625     }
626 
logd(String log)627     private static void logd(String log) {
628         Rlog.d(TAG, log);
629     }
630 
loge(String log)631     private static void loge(String log) {
632         Rlog.e(TAG, log);
633     }
634 }
635