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