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.TelephonyManager 20 .CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE; 21 import static android.telephony.TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED; 22 import static android.telephony.TelephonyManager.CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE; 23 import static android.telephony.TelephonyManager.CAPABILITY_SIM_PHONEBOOK_IN_MODEM; 24 import static android.telephony.TelephonyManager.CAPABILITY_SLICING_CONFIG_SUPPORTED; 25 import static android.telephony.TelephonyManager.CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING; 26 import static android.telephony.TelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK; 27 import static android.telephony.TelephonyManager.RadioInterfaceCapability; 28 29 import android.hardware.radio.V1_0.RadioError; 30 import android.hardware.radio.V1_0.RadioResponseInfo; 31 import android.hardware.radio.config.V1_1.ModemsConfig; 32 import android.hardware.radio.config.V1_3.IRadioConfigResponse; 33 import android.telephony.ModemInfo; 34 import android.telephony.PhoneCapability; 35 36 import com.android.internal.annotations.VisibleForTesting; 37 import com.android.internal.telephony.uicc.IccSlotStatus; 38 import com.android.telephony.Rlog; 39 40 import java.util.ArrayList; 41 import java.util.HashSet; 42 import java.util.List; 43 import java.util.Set; 44 45 /** 46 * This class is the implementation of IRadioConfigResponse interface. 47 */ 48 public class RadioConfigResponse extends IRadioConfigResponse.Stub { 49 private static final String TAG = "RadioConfigResponse"; 50 51 private final RadioConfig mRadioConfig; 52 private final HalVersion mRadioHalVersion; 53 RadioConfigResponse(RadioConfig radioConfig, HalVersion radioHalVersion)54 public RadioConfigResponse(RadioConfig radioConfig, HalVersion radioHalVersion) { 55 mRadioConfig = radioConfig; 56 mRadioHalVersion = radioHalVersion; 57 } 58 59 /** 60 * Response function for IRadioConfig.getSimSlotsStatus(). 61 */ getSimSlotsStatusResponse(RadioResponseInfo responseInfo, ArrayList<android.hardware.radio.config.V1_0.SimSlotStatus> slotStatus)62 public void getSimSlotsStatusResponse(RadioResponseInfo responseInfo, 63 ArrayList<android.hardware.radio.config.V1_0.SimSlotStatus> slotStatus) { 64 RILRequest rr = mRadioConfig.processResponse(responseInfo); 65 66 if (rr != null) { 67 ArrayList<IccSlotStatus> ret = RadioConfig.convertHalSlotStatus(slotStatus); 68 if (responseInfo.error == RadioError.NONE) { 69 // send response 70 RadioResponse.sendMessageResponse(rr.mResult, ret); 71 Rlog.d(TAG, rr.serialString() + "< " 72 + mRadioConfig.requestToString(rr.mRequest) + " " + ret.toString()); 73 } else { 74 rr.onError(responseInfo.error, ret); 75 Rlog.e(TAG, rr.serialString() + "< " 76 + mRadioConfig.requestToString(rr.mRequest) + " error " 77 + responseInfo.error); 78 } 79 80 } else { 81 Rlog.e(TAG, "getSimSlotsStatusResponse: Error " + responseInfo.toString()); 82 } 83 } 84 85 /** 86 * Response function for IRadioConfig.getSimSlotsStatus(). 87 */ getSimSlotsStatusResponse_1_2(RadioResponseInfo responseInfo, ArrayList<android.hardware.radio.config.V1_2.SimSlotStatus> slotStatus)88 public void getSimSlotsStatusResponse_1_2(RadioResponseInfo responseInfo, 89 ArrayList<android.hardware.radio.config.V1_2.SimSlotStatus> slotStatus) { 90 RILRequest rr = mRadioConfig.processResponse(responseInfo); 91 92 if (rr != null) { 93 ArrayList<IccSlotStatus> ret = RadioConfig.convertHalSlotStatus_1_2(slotStatus); 94 if (responseInfo.error == RadioError.NONE) { 95 // send response 96 RadioResponse.sendMessageResponse(rr.mResult, ret); 97 Rlog.d(TAG, rr.serialString() + "< " 98 + mRadioConfig.requestToString(rr.mRequest) + " " + ret.toString()); 99 } else { 100 rr.onError(responseInfo.error, ret); 101 Rlog.e(TAG, rr.serialString() + "< " 102 + mRadioConfig.requestToString(rr.mRequest) + " error " 103 + responseInfo.error); 104 } 105 } else { 106 Rlog.e(TAG, "getSimSlotsStatusResponse_1_2: Error " + responseInfo.toString()); 107 } 108 } 109 110 /** 111 * Response function for IRadioConfig.setSimSlotsMapping(). 112 */ setSimSlotsMappingResponse(RadioResponseInfo responseInfo)113 public void setSimSlotsMappingResponse(RadioResponseInfo responseInfo) { 114 RILRequest rr = mRadioConfig.processResponse(responseInfo); 115 116 if (rr != null) { 117 if (responseInfo.error == RadioError.NONE) { 118 // send response 119 RadioResponse.sendMessageResponse(rr.mResult, null); 120 Rlog.d(TAG, rr.serialString() + "< " 121 + mRadioConfig.requestToString(rr.mRequest)); 122 } else { 123 rr.onError(responseInfo.error, null); 124 Rlog.e(TAG, rr.serialString() + "< " 125 + mRadioConfig.requestToString(rr.mRequest) + " error " 126 + responseInfo.error); 127 } 128 } else { 129 Rlog.e(TAG, "setSimSlotsMappingResponse: Error " + responseInfo.toString()); 130 } 131 } 132 convertHalPhoneCapability( android.hardware.radio.config.V1_1.PhoneCapability phoneCapability)133 private PhoneCapability convertHalPhoneCapability( 134 android.hardware.radio.config.V1_1.PhoneCapability phoneCapability) { 135 // TODO b/121394331: clean up V1_1.PhoneCapability fields. 136 int maxActiveVoiceCalls = 0; 137 int maxActiveData = phoneCapability.maxActiveData; 138 boolean validationBeforeSwitchSupported = phoneCapability.isInternetLingeringSupported; 139 List<ModemInfo> logicalModemList = new ArrayList(); 140 141 for (android.hardware.radio.config.V1_1.ModemInfo 142 modemInfo : phoneCapability.logicalModemList) { 143 logicalModemList.add(new ModemInfo(modemInfo.modemId)); 144 } 145 146 return new PhoneCapability(maxActiveVoiceCalls, maxActiveData, logicalModemList, 147 validationBeforeSwitchSupported, mRadioConfig.getDeviceNrCapabilities()); 148 } 149 /** 150 * Response function for IRadioConfig.getPhoneCapability(). 151 */ getPhoneCapabilityResponse(RadioResponseInfo responseInfo, android.hardware.radio.config.V1_1.PhoneCapability phoneCapability)152 public void getPhoneCapabilityResponse(RadioResponseInfo responseInfo, 153 android.hardware.radio.config.V1_1.PhoneCapability phoneCapability) { 154 RILRequest rr = mRadioConfig.processResponse(responseInfo); 155 156 if (rr != null) { 157 PhoneCapability ret = convertHalPhoneCapability(phoneCapability); 158 if (responseInfo.error == RadioError.NONE) { 159 // send response 160 RadioResponse.sendMessageResponse(rr.mResult, ret); 161 Rlog.d(TAG, rr.serialString() + "< " 162 + mRadioConfig.requestToString(rr.mRequest) + " " + ret.toString()); 163 } else { 164 rr.onError(responseInfo.error, ret); 165 Rlog.e(TAG, rr.serialString() + "< " 166 + mRadioConfig.requestToString(rr.mRequest) + " error " 167 + responseInfo.error); 168 } 169 } else { 170 Rlog.e(TAG, "getPhoneCapabilityResponse: Error " + responseInfo.toString()); 171 } 172 } 173 174 /** 175 * Response function for IRadioConfig.setPreferredDataModem(). 176 */ setPreferredDataModemResponse(RadioResponseInfo responseInfo)177 public void setPreferredDataModemResponse(RadioResponseInfo responseInfo) { 178 RILRequest rr = mRadioConfig.processResponse(responseInfo); 179 180 if (rr != null) { 181 if (responseInfo.error == RadioError.NONE) { 182 // send response 183 RadioResponse.sendMessageResponse(rr.mResult, null); 184 Rlog.d(TAG, rr.serialString() + "< " 185 + mRadioConfig.requestToString(rr.mRequest)); 186 } else { 187 rr.onError(responseInfo.error, null); 188 Rlog.e(TAG, rr.serialString() + "< " 189 + mRadioConfig.requestToString(rr.mRequest) + " error " 190 + responseInfo.error); 191 } 192 } else { 193 Rlog.e(TAG, "setPreferredDataModemResponse: Error " + responseInfo.toString()); 194 } 195 } 196 197 /** 198 * Response function for IRadioConfig.setModemsConfigResponse() 199 * Currently this is being used as the callback for RadioConfig.setModemsConfig() method 200 */ setModemsConfigResponse(RadioResponseInfo responseInfo)201 public void setModemsConfigResponse(RadioResponseInfo responseInfo) { 202 RILRequest rr = mRadioConfig.processResponse(responseInfo); 203 204 if (rr != null) { 205 if (responseInfo.error == RadioError.NONE) { 206 // send response 207 RadioResponse.sendMessageResponse(rr.mResult, rr.mRequest); 208 Rlog.d(TAG, rr.serialString() + "< " 209 + mRadioConfig.requestToString(rr.mRequest)); 210 } else { 211 rr.onError(responseInfo.error, null); 212 Rlog.e(TAG, rr.serialString() + "< " 213 + mRadioConfig.requestToString(rr.mRequest) + " error " 214 + responseInfo.error); 215 } 216 } else { 217 Rlog.e(TAG, "setModemsConfigResponse: Error " + responseInfo.toString()); 218 } 219 } 220 221 /** 222 * Response function for IRadioConfig.getModemsConfigResponse() 223 */ getModemsConfigResponse(RadioResponseInfo responseInfo, ModemsConfig modemsConfig)224 public void getModemsConfigResponse(RadioResponseInfo responseInfo, ModemsConfig modemsConfig) { 225 RILRequest rr = mRadioConfig.processResponse(responseInfo); 226 227 if (rr != null) { 228 if (responseInfo.error == RadioError.NONE) { 229 // send response 230 RadioResponse.sendMessageResponse(rr.mResult, modemsConfig); 231 Rlog.d(TAG, rr.serialString() + "< " 232 + mRadioConfig.requestToString(rr.mRequest)); 233 } else { 234 rr.onError(responseInfo.error, modemsConfig); 235 Rlog.e(TAG, rr.serialString() + "< " 236 + mRadioConfig.requestToString(rr.mRequest) + " error " 237 + responseInfo.error); 238 } 239 } else { 240 Rlog.e(TAG, "getModemsConfigResponse: Error " + responseInfo.toString()); 241 } 242 } 243 244 /** 245 * Response function IRadioConfig.getHalDeviceCapabilities() 246 */ getHalDeviceCapabilitiesResponse( android.hardware.radio.V1_6.RadioResponseInfo responseInfo, boolean modemReducedFeatureSet1)247 public void getHalDeviceCapabilitiesResponse( 248 android.hardware.radio.V1_6.RadioResponseInfo responseInfo, 249 boolean modemReducedFeatureSet1) { 250 251 // convert hal device capabilities to RadioInterfaceCapabilities 252 253 RILRequest rr = mRadioConfig.processResponse_1_6(responseInfo); 254 if (rr != null) { 255 // The response is compatible with Radio 1.6, it means the modem 256 // supports setAllowedNetworkTypeBitmap. 257 258 final Set<String> ret = getCaps(mRadioHalVersion, modemReducedFeatureSet1); 259 260 if (responseInfo.error == RadioError.NONE) { 261 // send response 262 RadioResponse.sendMessageResponse(rr.mResult, ret); 263 Rlog.d(TAG, rr.serialString() + "< " 264 + mRadioConfig.requestToString(rr.mRequest)); 265 } else { 266 rr.onError(responseInfo.error, ret); 267 Rlog.e(TAG, rr.serialString() + "< " 268 + mRadioConfig.requestToString(rr.mRequest) + " error " 269 + responseInfo.error); 270 } 271 } else { 272 Rlog.e(TAG, "getHalDeviceCapabilities: Error " + responseInfo.toString()); 273 } 274 } 275 276 /** 277 * Returns all capabilities supported in the most recent radio hal version. 278 * <p/> 279 * Used in the {@link RILConstants.REQUEST_NOT_SUPPORTED} case. 280 * 281 * @return all capabilities 282 */ 283 @RadioInterfaceCapability getFullCapabilitySet()284 public Set<String> getFullCapabilitySet() { 285 return getCaps(mRadioHalVersion, false); 286 } 287 288 /** 289 * Create capabilities based off of the radio hal version and feature set configurations. 290 */ 291 @VisibleForTesting getCaps(HalVersion radioHalVersion, boolean modemReducedFeatureSet1)292 public static Set<String> getCaps(HalVersion radioHalVersion, 293 boolean modemReducedFeatureSet1) { 294 final Set<String> caps = new HashSet<>(); 295 296 if (radioHalVersion.equals(RIL.RADIO_HAL_VERSION_UNKNOWN)) { 297 // If the Radio HAL is UNKNOWN, no capabilities will present themselves. 298 Rlog.e(TAG, "Radio Hal Version is UNKNOWN!"); 299 } 300 301 Rlog.d(TAG, "Radio Hal Version = " + radioHalVersion.toString()); 302 if (radioHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_6)) { 303 caps.add(CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK); 304 Rlog.d(TAG, "CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK"); 305 306 if (!modemReducedFeatureSet1) { 307 caps.add(CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE); 308 Rlog.d(TAG, "CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE"); 309 caps.add(CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE); 310 Rlog.d(TAG, "CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE"); 311 caps.add(CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING); 312 Rlog.d(TAG, "CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING"); 313 caps.add(CAPABILITY_SLICING_CONFIG_SUPPORTED); 314 Rlog.d(TAG, "CAPABILITY_SLICING_CONFIG_SUPPORTED"); 315 caps.add(CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED); 316 Rlog.d(TAG, "CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED"); 317 } else { 318 caps.add(CAPABILITY_SIM_PHONEBOOK_IN_MODEM); 319 Rlog.d(TAG, "CAPABILITY_SIM_PHONEBOOK_IN_MODEM"); 320 } 321 } 322 return caps; 323 } 324 } 325