1 /* 2 * Copyright (C) 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 android.telephony.ims.compat.stub; 18 19 import android.compat.annotation.UnsupportedAppUsage; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.os.Build; 23 import android.os.RemoteException; 24 import android.util.Log; 25 26 import com.android.ims.ImsConfig; 27 import com.android.ims.ImsConfigListener; 28 import com.android.ims.internal.IImsConfig; 29 import com.android.internal.annotations.VisibleForTesting; 30 31 import java.lang.ref.WeakReference; 32 import java.util.HashMap; 33 34 35 /** 36 * Base implementation of ImsConfig. 37 * Override the methods that your implementation of ImsConfig supports. 38 * 39 * DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you 40 * will break other implementations of ImsConfig maintained by other ImsServices. 41 * 42 * Provides APIs to get/set the IMS service feature/capability/parameters. 43 * The config items include: 44 * 1) Items provisioned by the operator. 45 * 2) Items configured by user. Mainly service feature class. 46 * 47 * The inner class {@link ImsConfigStub} implements methods of IImsConfig AIDL interface. 48 * The IImsConfig AIDL interface is called by ImsConfig, which may exist in many other processes. 49 * ImsConfigImpl access to the configuration parameters may be arbitrarily slow, especially in 50 * during initialization, or times when a lot of configuration parameters are being set/get 51 * (such as during boot up or SIM card change). By providing a cache in ImsConfigStub, we can speed 52 * up access to these configuration parameters, so a query to the ImsConfigImpl does not have to be 53 * performed every time. 54 * @hide 55 */ 56 57 public class ImsConfigImplBase { 58 59 static final private String TAG = "ImsConfigImplBase"; 60 61 ImsConfigStub mImsConfigStub; 62 63 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) ImsConfigImplBase(Context context)64 public ImsConfigImplBase(Context context) { 65 mImsConfigStub = new ImsConfigStub(this, context); 66 } 67 68 /** 69 * Gets the value for ims service/capabilities parameters from the provisioned 70 * value storage. Synchronous blocking call. 71 * 72 * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. 73 * @return value in Integer format. 74 */ getProvisionedValue(int item)75 public int getProvisionedValue(int item) throws RemoteException { 76 return -1; 77 } 78 79 /** 80 * Gets the value for ims service/capabilities parameters from the provisioned 81 * value storage. Synchronous blocking call. 82 * 83 * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. 84 * @return value in String format. 85 */ getProvisionedStringValue(int item)86 public String getProvisionedStringValue(int item) throws RemoteException { 87 return null; 88 } 89 90 /** 91 * Sets the value for IMS service/capabilities parameters by the operator device 92 * management entity. It sets the config item value in the provisioned storage 93 * from which the main value is derived. Synchronous blocking call. 94 * 95 * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. 96 * @param value in Integer format. 97 * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. 98 */ setProvisionedValue(int item, int value)99 public int setProvisionedValue(int item, int value) throws RemoteException { 100 return ImsConfig.OperationStatusConstants.FAILED; 101 } 102 103 /** 104 * Sets the value for IMS service/capabilities parameters by the operator device 105 * management entity. It sets the config item value in the provisioned storage 106 * from which the main value is derived. Synchronous blocking call. 107 * 108 * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. 109 * @param value in String format. 110 * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. 111 */ setProvisionedStringValue(int item, String value)112 public int setProvisionedStringValue(int item, String value) throws RemoteException { 113 return ImsConfig.OperationStatusConstants.FAILED; 114 } 115 116 /** 117 * Gets the value of the specified IMS feature item for specified network type. 118 * This operation gets the feature config value from the main storage (i.e. final 119 * value). Asynchronous non-blocking call. 120 * 121 * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants. 122 * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX. 123 * @param listener feature value returned asynchronously through listener. 124 */ getFeatureValue(int feature, int network, ImsConfigListener listener)125 public void getFeatureValue(int feature, int network, ImsConfigListener listener) 126 throws RemoteException { 127 } 128 129 /** 130 * Sets the value for IMS feature item for specified network type. 131 * This operation stores the user setting in setting db from which main db 132 * is derived. 133 * 134 * @param feature as defined in com.android.ims.ImsConfig#FeatureConstants. 135 * @param network as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX. 136 * @param value as defined in com.android.ims.ImsConfig#FeatureValueConstants. 137 * @param listener, provided if caller needs to be notified for set result. 138 */ setFeatureValue(int feature, int network, int value, ImsConfigListener listener)139 public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener) 140 throws RemoteException { 141 } 142 143 /** 144 * Gets the value for IMS VoLTE provisioned. 145 * This should be the same as the operator provisioned value if applies. 146 */ getVolteProvisioned()147 public boolean getVolteProvisioned() throws RemoteException { 148 return false; 149 } 150 151 /** 152 * Gets the value for IMS feature item video quality. 153 * 154 * @param listener Video quality value returned asynchronously through listener. 155 */ getVideoQuality(ImsConfigListener listener)156 public void getVideoQuality(ImsConfigListener listener) throws RemoteException { 157 } 158 159 /** 160 * Sets the value for IMS feature item video quality. 161 * 162 * @param quality, defines the value of video quality. 163 * @param listener, provided if caller needs to be notified for set result. 164 */ setVideoQuality(int quality, ImsConfigListener listener)165 public void setVideoQuality(int quality, ImsConfigListener listener) throws RemoteException { 166 } 167 168 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getIImsConfig()169 public IImsConfig getIImsConfig() { return mImsConfigStub; } 170 171 /** 172 * Updates provisioning value and notifies the framework of the change. 173 * Doesn't call #setProvisionedValue and assumes the result succeeded. 174 * This should only be used by modem when they implicitly changed provisioned values. 175 * 176 * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. 177 * @param value in Integer format. 178 */ notifyProvisionedValueChanged(int item, int value)179 public final void notifyProvisionedValueChanged(int item, int value) { 180 mImsConfigStub.updateCachedValue(item, value, true); 181 } 182 183 /** 184 * Updates provisioning value and notifies the framework of the change. 185 * Doesn't call #setProvisionedValue and assumes the result succeeded. 186 * This should only be used by modem when they implicitly changed provisioned values. 187 * 188 * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. 189 * @param value in String format. 190 */ notifyProvisionedValueChanged(int item, String value)191 public final void notifyProvisionedValueChanged(int item, String value) { 192 mImsConfigStub.updateCachedValue(item, value, true); 193 } 194 195 /** 196 * Implements the IImsConfig AIDL interface, which is called by potentially many processes 197 * in order to get/set configuration parameters. 198 * 199 * It holds an object of ImsConfigImplBase class which is usually extended by ImsConfigImpl 200 * with actual implementations from vendors. This class caches provisioned values from 201 * ImsConfigImpl layer because queries through ImsConfigImpl can be slow. When query goes in, 202 * it first checks cache layer. If missed, it will call the vendor implementation of 203 * ImsConfigImplBase API. 204 * and cache the return value if the set succeeds. 205 * 206 * Provides APIs to get/set the IMS service feature/capability/parameters. 207 * The config items include: 208 * 1) Items provisioned by the operator. 209 * 2) Items configured by user. Mainly service feature class. 210 * 211 * @hide 212 */ 213 @VisibleForTesting 214 static public class ImsConfigStub extends IImsConfig.Stub { 215 Context mContext; 216 WeakReference<ImsConfigImplBase> mImsConfigImplBaseWeakReference; 217 private HashMap<Integer, Integer> mProvisionedIntValue = new HashMap<>(); 218 private HashMap<Integer, String> mProvisionedStringValue = new HashMap<>(); 219 220 @VisibleForTesting ImsConfigStub(ImsConfigImplBase imsConfigImplBase, Context context)221 public ImsConfigStub(ImsConfigImplBase imsConfigImplBase, Context context) { 222 mContext = context; 223 mImsConfigImplBaseWeakReference = 224 new WeakReference<ImsConfigImplBase>(imsConfigImplBase); 225 } 226 227 /** 228 * Gets the value for ims service/capabilities parameters. It first checks its local cache, 229 * if missed, it will call ImsConfigImplBase.getProvisionedValue. 230 * Synchronous blocking call. 231 * 232 * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. 233 * @return value in Integer format. 234 */ 235 @Override getProvisionedValue(int item)236 public synchronized int getProvisionedValue(int item) throws RemoteException { 237 if (mProvisionedIntValue.containsKey(item)) { 238 return mProvisionedIntValue.get(item); 239 } else { 240 int retVal = getImsConfigImpl().getProvisionedValue(item); 241 if (retVal != ImsConfig.OperationStatusConstants.UNKNOWN) { 242 updateCachedValue(item, retVal, false); 243 } 244 return retVal; 245 } 246 } 247 248 /** 249 * Gets the value for ims service/capabilities parameters. It first checks its local cache, 250 * if missed, it will call #ImsConfigImplBase.getProvisionedValue. 251 * Synchronous blocking call. 252 * 253 * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. 254 * @return value in String format. 255 */ 256 @Override getProvisionedStringValue(int item)257 public synchronized String getProvisionedStringValue(int item) throws RemoteException { 258 if (mProvisionedIntValue.containsKey(item)) { 259 return mProvisionedStringValue.get(item); 260 } else { 261 String retVal = getImsConfigImpl().getProvisionedStringValue(item); 262 if (retVal != null) { 263 updateCachedValue(item, retVal, false); 264 } 265 return retVal; 266 } 267 } 268 269 /** 270 * Sets the value for IMS service/capabilities parameters by the operator device 271 * management entity. It sets the config item value in the provisioned storage 272 * from which the main value is derived, and write it into local cache. 273 * Synchronous blocking call. 274 * 275 * @param item, as defined in com.android.ims.ImsConfig#ConfigConstants. 276 * @param value in Integer format. 277 * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. 278 */ 279 @Override setProvisionedValue(int item, int value)280 public synchronized int setProvisionedValue(int item, int value) throws RemoteException { 281 mProvisionedIntValue.remove(item); 282 int retVal = getImsConfigImpl().setProvisionedValue(item, value); 283 if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) { 284 updateCachedValue(item, value, true); 285 } else { 286 Log.d(TAG, "Set provision value of " + item + 287 " to " + value + " failed with error code " + retVal); 288 } 289 290 return retVal; 291 } 292 293 /** 294 * Sets the value for IMS service/capabilities parameters by the operator device 295 * management entity. It sets the config item value in the provisioned storage 296 * from which the main value is derived, and write it into local cache. 297 * Synchronous blocking call. 298 * 299 * @param item as defined in com.android.ims.ImsConfig#ConfigConstants. 300 * @param value in String format. 301 * @return as defined in com.android.ims.ImsConfig#OperationStatusConstants. 302 */ 303 @Override setProvisionedStringValue(int item, String value)304 public synchronized int setProvisionedStringValue(int item, String value) 305 throws RemoteException { 306 mProvisionedStringValue.remove(item); 307 int retVal = getImsConfigImpl().setProvisionedStringValue(item, value); 308 if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) { 309 updateCachedValue(item, value, true); 310 } 311 312 return retVal; 313 } 314 315 /** 316 * Wrapper function to call ImsConfigImplBase.getFeatureValue. 317 */ 318 @Override getFeatureValue(int feature, int network, ImsConfigListener listener)319 public void getFeatureValue(int feature, int network, ImsConfigListener listener) 320 throws RemoteException { 321 getImsConfigImpl().getFeatureValue(feature, network, listener); 322 } 323 324 /** 325 * Wrapper function to call ImsConfigImplBase.setFeatureValue. 326 */ 327 @Override setFeatureValue(int feature, int network, int value, ImsConfigListener listener)328 public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener) 329 throws RemoteException { 330 getImsConfigImpl().setFeatureValue(feature, network, value, listener); 331 } 332 333 /** 334 * Wrapper function to call ImsConfigImplBase.getVolteProvisioned. 335 */ 336 @Override getVolteProvisioned()337 public boolean getVolteProvisioned() throws RemoteException { 338 return getImsConfigImpl().getVolteProvisioned(); 339 } 340 341 /** 342 * Wrapper function to call ImsConfigImplBase.getVideoQuality. 343 */ 344 @Override getVideoQuality(ImsConfigListener listener)345 public void getVideoQuality(ImsConfigListener listener) throws RemoteException { 346 getImsConfigImpl().getVideoQuality(listener); 347 } 348 349 /** 350 * Wrapper function to call ImsConfigImplBase.setVideoQuality. 351 */ 352 @Override setVideoQuality(int quality, ImsConfigListener listener)353 public void setVideoQuality(int quality, ImsConfigListener listener) 354 throws RemoteException { 355 getImsConfigImpl().setVideoQuality(quality, listener); 356 } 357 getImsConfigImpl()358 private ImsConfigImplBase getImsConfigImpl() throws RemoteException { 359 ImsConfigImplBase ref = mImsConfigImplBaseWeakReference.get(); 360 if (ref == null) { 361 throw new RemoteException("Fail to get ImsConfigImpl"); 362 } else { 363 return ref; 364 } 365 } 366 sendImsConfigChangedIntent(int item, int value)367 private void sendImsConfigChangedIntent(int item, int value) { 368 sendImsConfigChangedIntent(item, Integer.toString(value)); 369 } 370 sendImsConfigChangedIntent(int item, String value)371 private void sendImsConfigChangedIntent(int item, String value) { 372 Intent configChangedIntent = new Intent(ImsConfig.ACTION_IMS_CONFIG_CHANGED); 373 configChangedIntent.putExtra(ImsConfig.EXTRA_CHANGED_ITEM, item); 374 configChangedIntent.putExtra(ImsConfig.EXTRA_NEW_VALUE, value); 375 if (mContext != null) { 376 mContext.sendBroadcast(configChangedIntent); 377 } 378 } 379 updateCachedValue(int item, int value, boolean notifyChange)380 protected synchronized void updateCachedValue(int item, int value, boolean notifyChange) { 381 mProvisionedIntValue.put(item, value); 382 if (notifyChange) { 383 sendImsConfigChangedIntent(item, value); 384 } 385 } 386 updateCachedValue( int item, String value, boolean notifyChange)387 protected synchronized void updateCachedValue( 388 int item, String value, boolean notifyChange) { 389 mProvisionedStringValue.put(item, value); 390 if (notifyChange) { 391 sendImsConfigChangedIntent(item, value); 392 } 393 } 394 } 395 }