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