1 /* 2 * Copyright (C) 2021 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.os.HwBinder; 20 import android.os.IBinder; 21 import android.os.RemoteException; 22 import android.telephony.UiccSlotMapping; 23 24 import com.android.telephony.Rlog; 25 26 import java.util.List; 27 import java.util.Set; 28 29 /** 30 * RadioConfig proxy class that abstracts the underlying RadioConfig service implementation to 31 * downstream users. 32 */ 33 public class RadioConfigProxy { 34 private final HalVersion mRadioHalVersion; 35 private final RadioConfigHidlServiceDeathRecipient mRadioConfigHidlServiceDeathRecipient; 36 private final RadioConfigAidlServiceDeathRecipient mRadioConfigAidlServiceDeathRecipient; 37 38 private volatile android.hardware.radio.config.V1_0.IRadioConfig mHidlRadioConfigProxy = null; 39 private volatile android.hardware.radio.config.IRadioConfig mAidlRadioConfigProxy = null; 40 41 private HalVersion mRadioConfigHalVersion = RadioConfig.RADIO_CONFIG_HAL_VERSION_UNKNOWN; 42 private boolean mIsAidl; 43 RadioConfigProxy(RadioConfig radioConfig, HalVersion radioHalVersion)44 public RadioConfigProxy(RadioConfig radioConfig, HalVersion radioHalVersion) { 45 mRadioHalVersion = radioHalVersion; 46 mRadioConfigAidlServiceDeathRecipient = 47 new RadioConfigAidlServiceDeathRecipient(radioConfig); 48 mRadioConfigHidlServiceDeathRecipient = 49 new RadioConfigHidlServiceDeathRecipient(radioConfig); 50 } 51 52 /** 53 * Set IRadioConfig as the HIDL implementation for RadioConfigProxy 54 * 55 * @param radioConfigHalVersion RadioConfig HAL version 56 * @param radioConfig IRadioConfig implementation 57 */ setHidl( HalVersion radioConfigHalVersion, android.hardware.radio.config.V1_0.IRadioConfig radioConfig)58 public void setHidl( 59 HalVersion radioConfigHalVersion, 60 android.hardware.radio.config.V1_0.IRadioConfig radioConfig) { 61 mRadioConfigHalVersion = radioConfigHalVersion; 62 mHidlRadioConfigProxy = radioConfig; 63 mIsAidl = false; 64 mRadioConfigHidlServiceDeathRecipient.setService(radioConfig); 65 } 66 67 /** 68 * Get HIDL IRadioConfig V1_0 69 * @return IRadioConfigV1_0 70 */ getHidl10()71 public android.hardware.radio.config.V1_0.IRadioConfig getHidl10() { 72 return mHidlRadioConfigProxy; 73 } 74 75 /** 76 * Get HIDL IRadioConfig V1_1 77 * @return IRadioConfigV1_1 78 */ getHidl11()79 public android.hardware.radio.config.V1_1.IRadioConfig getHidl11() { 80 return (android.hardware.radio.config.V1_1.IRadioConfig) mHidlRadioConfigProxy; 81 } 82 83 /** 84 * Get HIDL IRadioConfig V1_3 85 * @return IRadioConfigV1_3 86 */ getHidl13()87 public android.hardware.radio.config.V1_3.IRadioConfig getHidl13() { 88 return (android.hardware.radio.config.V1_3.IRadioConfig) mHidlRadioConfigProxy; 89 } 90 91 /** 92 * Set IRadioConfig as the AIDL implementation for RadioConfigProxy 93 * 94 * @param radioConfigHalVersion RadioConfig HAL version 95 * @param radioConfig IRadioConfig implementation 96 */ setAidl( HalVersion radioConfigHalVersion, android.hardware.radio.config.IRadioConfig radioConfig)97 public void setAidl( 98 HalVersion radioConfigHalVersion, 99 android.hardware.radio.config.IRadioConfig radioConfig) { 100 mRadioConfigHalVersion = radioConfigHalVersion; 101 mAidlRadioConfigProxy = radioConfig; 102 mIsAidl = true; 103 mRadioConfigAidlServiceDeathRecipient.setService(radioConfig.asBinder()); 104 } 105 106 /** 107 * Get the AIDL implementation of RadioConfigProxy 108 * 109 * @return IRadio implementation 110 */ getAidl()111 public android.hardware.radio.config.IRadioConfig getAidl() { 112 return mAidlRadioConfigProxy; 113 } 114 115 /** Reset RadioConfigProxy */ clear()116 public void clear() { 117 mRadioConfigHalVersion = RadioConfig.RADIO_CONFIG_HAL_VERSION_UNKNOWN; 118 mHidlRadioConfigProxy = null; 119 mAidlRadioConfigProxy = null; 120 mRadioConfigHidlServiceDeathRecipient.clear(); 121 mRadioConfigAidlServiceDeathRecipient.clear(); 122 } 123 124 /** 125 * Wrapper for service's linkToDeath() 126 */ linkToDeath(long cookie)127 public void linkToDeath(long cookie) throws RemoteException { 128 if (isAidl()) { 129 mRadioConfigAidlServiceDeathRecipient.linkToDeath((int) cookie); 130 } else { 131 mRadioConfigHidlServiceDeathRecipient.linkToDeath(cookie); 132 } 133 } 134 135 /** 136 * Check whether an implementation exists for this service 137 * 138 * @return false if there is neither a HIDL nor AIDL implementation 139 */ isEmpty()140 public boolean isEmpty() { 141 return mAidlRadioConfigProxy == null && mHidlRadioConfigProxy == null; 142 } 143 144 /** 145 * Whether RadioConfigProxy is an AIDL or HIDL implementation 146 * 147 * @return true if AIDL, false if HIDL 148 */ isAidl()149 public boolean isAidl() { 150 return mIsAidl; 151 } 152 153 /** 154 * Return RadioConfig HAL version used by this instance 155 * @return RadioConfig HAL Version 156 */ getVersion()157 public HalVersion getVersion() { 158 return mRadioConfigHalVersion; 159 } 160 161 /** 162 * Set the response functions for RadioConfig instance 163 * @param radioConfig main RadioConfig instance 164 * @throws RemoteException 165 */ setResponseFunctions(RadioConfig radioConfig)166 public void setResponseFunctions(RadioConfig radioConfig) throws RemoteException { 167 if (isEmpty()) return; 168 169 if (isAidl()) { 170 mAidlRadioConfigProxy.setResponseFunctions( 171 new RadioConfigResponseAidl(radioConfig, mRadioHalVersion), 172 new RadioConfigIndicationAidl(radioConfig)); 173 } else { 174 mHidlRadioConfigProxy.setResponseFunctions( 175 new RadioConfigResponseHidl(radioConfig, mRadioHalVersion), 176 new RadioConfigIndicationHidl(radioConfig)); 177 } 178 } 179 180 /** 181 * Get capabilities based off of the radio hal version and feature set configurations 182 * @return Set string capabilities 183 */ getFullCapabilitySet()184 public Set<String> getFullCapabilitySet() { 185 return RILUtils.getCaps(mRadioHalVersion, false); 186 } 187 188 /** 189 * Wrapper function for IRadioConfig.getSimSlotsStatus(). 190 */ getSimSlotStatus(int serial)191 public void getSimSlotStatus(int serial) throws RemoteException { 192 if (isAidl()) { 193 getAidl().getSimSlotsStatus(serial); 194 } else { 195 getHidl10().getSimSlotsStatus(serial); 196 } 197 } 198 199 /** 200 * Wrapper function for IRadioConfig.setPreferredDataModem(int modemId). 201 */ setPreferredDataModem(int serial, int modemId)202 public void setPreferredDataModem(int serial, int modemId) throws RemoteException { 203 if (isAidl()) { 204 getAidl().setPreferredDataModem(serial, (byte) modemId); 205 } else { 206 getHidl11().setPreferredDataModem(serial, (byte) modemId); 207 } 208 } 209 210 /** 211 * Wrapper function for IRadioConfig.getPhoneCapability(). 212 */ getPhoneCapability(int serial)213 public void getPhoneCapability(int serial) throws RemoteException { 214 if (isAidl()) { 215 getAidl().getPhoneCapability(serial); 216 } else { 217 getHidl11().getPhoneCapability(serial); 218 } 219 } 220 221 /** 222 * Wrapper function for IRadioConfig.setSimSlotsMapping(int32_t serial, 223 * vec<SlotPortMapping> portMap). 224 */ setSimSlotsMapping(int serial, List<UiccSlotMapping> slotMapping)225 public void setSimSlotsMapping(int serial, List<UiccSlotMapping> slotMapping) 226 throws RemoteException { 227 if (isAidl()) { 228 getAidl().setSimSlotsMapping(serial, RILUtils.convertSimSlotsMapping(slotMapping)); 229 } else { 230 getHidl10().setSimSlotsMapping(serial, 231 RILUtils.convertSlotMappingToList(slotMapping)); 232 } 233 } 234 235 /** 236 * Wrapper function for using IRadioConfig.setNumOfLiveModems(int32_t serial, 237 * byte numOfLiveModems) to switch between single-sim and multi-sim. 238 */ setNumOfLiveModems(int serial, int numOfLiveModems)239 public void setNumOfLiveModems(int serial, int numOfLiveModems) throws RemoteException { 240 if (isAidl()) { 241 getAidl().setNumOfLiveModems(serial, (byte) numOfLiveModems); 242 } else { 243 android.hardware.radio.config.V1_1.ModemsConfig modemsConfig = 244 new android.hardware.radio.config.V1_1.ModemsConfig(); 245 modemsConfig.numOfLiveModems = (byte) numOfLiveModems; 246 getHidl11().setModemsConfig(serial, modemsConfig); 247 } 248 } 249 250 /** 251 * Gets the hal capabilities from the device. 252 */ getHalDeviceCapabilities(int serial)253 public void getHalDeviceCapabilities(int serial) throws RemoteException { 254 if (isAidl()) { 255 getAidl().getHalDeviceCapabilities(serial); 256 } else { 257 getHidl13().getHalDeviceCapabilities(serial); 258 } 259 } 260 261 /** 262 * Death Recipient for HIDL binder (if any) of RadioConfig. 263 */ 264 private static class RadioConfigHidlServiceDeathRecipient implements HwBinder.DeathRecipient { 265 private static final String TAG = "RadioConfigHidlSDR"; 266 267 private final RadioConfig mRadioConfig; 268 private android.hardware.radio.config.V1_0.IRadioConfig mService; 269 RadioConfigHidlServiceDeathRecipient(RadioConfig radioConfig)270 RadioConfigHidlServiceDeathRecipient(RadioConfig radioConfig) { 271 mRadioConfig = radioConfig; 272 } 273 setService(android.hardware.radio.config.V1_0.IRadioConfig service)274 public void setService(android.hardware.radio.config.V1_0.IRadioConfig service) { 275 mService = service; 276 } 277 linkToDeath(long cookie)278 public void linkToDeath(long cookie) throws RemoteException { 279 mService.linkToDeath(this, cookie); 280 } 281 clear()282 public void clear() { 283 mService = null; 284 } 285 286 @Override serviceDied(long cookie)287 public void serviceDied(long cookie) { 288 // Deal with service going away 289 Rlog.e(TAG, "serviceDied"); 290 mRadioConfig.sendMessage( 291 mRadioConfig.obtainMessage(RadioConfig.EVENT_HIDL_SERVICE_DEAD, cookie)); 292 } 293 } 294 295 /** 296 * DeathRecipient for AIDL binder service (if any) of RadioConfig 297 */ 298 private static class RadioConfigAidlServiceDeathRecipient implements IBinder.DeathRecipient { 299 private static final String TAG = "RadioConfigAidlSDR"; 300 301 private final RadioConfig mRadioConfig; 302 303 private IBinder mService; 304 RadioConfigAidlServiceDeathRecipient(RadioConfig radioConfig)305 RadioConfigAidlServiceDeathRecipient(RadioConfig radioConfig) { 306 mRadioConfig = radioConfig; 307 } 308 setService(IBinder service)309 public void setService(IBinder service) { 310 mService = service; 311 } 312 linkToDeath(int cookie)313 public void linkToDeath(int cookie) throws RemoteException { 314 mService.linkToDeath(this, cookie); 315 } 316 clear()317 public void clear() { 318 mService = null; 319 } 320 321 /** 322 * Unlink from RadioConfig if any. 323 */ unlinkToDeath()324 public synchronized void unlinkToDeath() { 325 if (mService != null) { 326 mService.unlinkToDeath(this, 0); 327 mService = null; 328 } 329 } 330 331 @Override binderDied()332 public void binderDied() { 333 Rlog.e(TAG, "service died."); 334 unlinkToDeath(); 335 mRadioConfig.sendMessage( 336 mRadioConfig.obtainMessage(RadioConfig.EVENT_AIDL_SERVICE_DEAD)); 337 } 338 } 339 } 340