All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.android.telephony.ims.stub.ImsConfigImplBase Maven / Gradle / Ivy

/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package android.telephony.ims.stub;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.telephony.ims.ProvisioningManager;
import android.telephony.ims.RcsClientConfiguration;
import android.telephony.ims.RcsConfig;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsConfigCallback;
import android.telephony.ims.aidl.IRcsConfigCallback;
import android.util.Log;

import com.android.ims.ImsConfig;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.util.RemoteCallbackListExt;
import com.android.internal.telephony.util.TelephonyUtils;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.HashMap;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;


/**
 * Controls the modification of IMS specific configurations. For more information on the supported
 * IMS configuration constants, see {@link ImsConfig}.
 *
 * The inner class {@link ImsConfigStub} implements methods of IImsConfig AIDL interface.
 * The IImsConfig AIDL interface is called by ImsConfig, which may exist in many other processes.
 * ImsConfigImpl access to the configuration parameters may be arbitrarily slow, especially in
 * during initialization, or times when a lot of configuration parameters are being set/get
 * (such as during boot up or SIM card change). By providing a cache in ImsConfigStub, we can speed
 * up access to these configuration parameters, so a query to the ImsConfigImpl does not have to be
 * performed every time.
 * @hide
 */
@SystemApi
public class ImsConfigImplBase {

    private static final String TAG = "ImsConfigImplBase";

    /**
     * Implements the IImsConfig AIDL interface, which is called by potentially many processes
     * in order to get/set configuration parameters.
     *
     * It holds an object of ImsConfigImplBase class which is usually extended by ImsConfigImpl
     * with actual implementations from vendors. This class caches provisioned values from
     * ImsConfigImpl layer because queries through ImsConfigImpl can be slow. When query goes in,
     * it first checks cache layer. If missed, it will call the vendor implementation of
     * ImsConfigImplBase API.
     * and cache the return value if the set succeeds.
     *
     * Provides APIs to get/set the IMS service feature/capability/parameters.
     * The config items include:
     * 1) Items provisioned by the operator.
     * 2) Items configured by user. Mainly service feature class.
     *
     * @hide
     */
    @VisibleForTesting
    static public class ImsConfigStub extends IImsConfig.Stub {
        WeakReference mImsConfigImplBaseWeakReference;
        private HashMap mProvisionedIntValue = new HashMap<>();
        private HashMap mProvisionedStringValue = new HashMap<>();
        private final Object mLock = new Object();
        private Executor mExecutor;

        @VisibleForTesting
        public ImsConfigStub(ImsConfigImplBase imsConfigImplBase, Executor executor) {
            mExecutor = executor;
            mImsConfigImplBaseWeakReference =
                    new WeakReference(imsConfigImplBase);
        }

        @Override
        public void addImsConfigCallback(IImsConfigCallback c) throws RemoteException {
            AtomicReference exceptionRef = new AtomicReference<>();
            executeMethodAsync(()-> {
                try {
                    getImsConfigImpl().addImsConfigCallback(c);
                } catch (RemoteException e) {
                    exceptionRef.set(e);
                }
            }, "addImsConfigCallback");

            if (exceptionRef.get() != null) {
                Log.d(TAG, "ImsConfigImplBase Exception addImsConfigCallback");
                throw exceptionRef.get();
            }
        }

        @Override
        public void removeImsConfigCallback(IImsConfigCallback c) throws RemoteException {
            AtomicReference exceptionRef = new AtomicReference<>();
            executeMethodAsync(()-> {
                try {
                    getImsConfigImpl().removeImsConfigCallback(c);
                } catch (RemoteException e) {
                    exceptionRef.set(e);
                }
            }, "removeImsConfigCallback");

            if (exceptionRef.get() != null) {
                Log.d(TAG, "ImsConfigImplBase Exception removeImsConfigCallback");
                throw exceptionRef.get();
            }
        }

        /**
         * Gets the value for ims service/capabilities parameters. It first checks its local cache,
         * if missed, it will call ImsConfigImplBase.getConfigInt.
         * Synchronous blocking call.
         *
         * @param item integer key
         * @return value in Integer format or {@link #CONFIG_RESULT_UNKNOWN} if
         * unavailable.
         */
        @Override
        public int getConfigInt(int item) throws RemoteException {
            AtomicReference exceptionRef = new AtomicReference<>();
            int retVal = executeMethodAsyncForResult(()-> {
                int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN;
                synchronized (mLock) {
                    if (mProvisionedIntValue.containsKey(item)) {
                        return mProvisionedIntValue.get(item);
                    } else {
                        try {
                            returnVal = getImsConfigImpl().getConfigInt(item);
                            if (returnVal != ImsConfig.OperationStatusConstants.UNKNOWN) {
                                mProvisionedIntValue.put(item, returnVal);
                            }
                        } catch (RemoteException e) {
                            exceptionRef.set(e);
                            return returnVal;
                        }
                    }
                }
                return returnVal;
            }, "getConfigInt");

            if (exceptionRef.get() != null) {
                Log.d(TAG, "ImsConfigImplBase Exception getConfigString");
                throw exceptionRef.get();
            }

            return retVal;
        }

        /**
         * Gets the value for ims service/capabilities parameters. It first checks its local cache,
         * if missed, it will call #ImsConfigImplBase.getConfigString.
         * Synchronous blocking call.
         *
         * @param item integer key
         * @return value in String format.
         */
        @Override
        public String getConfigString(int item) throws RemoteException {
            AtomicReference exceptionRef = new AtomicReference<>();
            String retVal = executeMethodAsyncForResult(()-> {
                String returnVal = null;
                synchronized (mLock) {
                    if (mProvisionedStringValue.containsKey(item)) {
                        returnVal = mProvisionedStringValue.get(item);
                    } else {
                        try {
                            returnVal = getImsConfigImpl().getConfigString(item);
                            if (returnVal != null) {
                                mProvisionedStringValue.put(item, returnVal);
                            }
                        } catch (RemoteException e) {
                            exceptionRef.set(e);
                            return returnVal;
                        }
                    }
                }
                return returnVal;
            }, "getConfigString");

            if (exceptionRef.get() != null) {
                Log.d(TAG, "ImsConfigImplBase Exception getConfigString");
                throw exceptionRef.get();
            }

            return retVal;
        }

        /**
         * Sets the value for IMS service/capabilities parameters by the operator device
         * management entity. It sets the config item value in the provisioned storage
         * from which the main value is derived, and write it into local cache.
         * Synchronous blocking call.
         *
         * @param item integer key
         * @param value in Integer format.
         * @return the result of setting the configuration value, defined as either
         * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
         */
        @Override
        public int setConfigInt(int item, int value) throws RemoteException {
            AtomicReference exceptionRef = new AtomicReference<>();
            int retVal = executeMethodAsyncForResult(()-> {
                int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN;
                try {
                    synchronized (mLock) {
                        mProvisionedIntValue.remove(item);
                        returnVal = getImsConfigImpl().setConfig(item, value);
                        if (returnVal == ImsConfig.OperationStatusConstants.SUCCESS) {
                            mProvisionedIntValue.put(item, value);
                        } else {
                            Log.d(TAG, "Set provision value of " + item
                                    + " to " + value + " failed with error code " + returnVal);
                        }
                    }
                    notifyImsConfigChanged(item, value);
                    return returnVal;
                } catch (RemoteException e) {
                    exceptionRef.set(e);
                    return returnVal;
                }
            }, "setConfigInt");

            if (exceptionRef.get() != null) {
                Log.d(TAG, "ImsConfigImplBase Exception setConfigInt");
                throw exceptionRef.get();
            }

            return retVal;
        }

        /**
         * Sets the value for IMS service/capabilities parameters by the operator device
         * management entity. It sets the config item value in the provisioned storage
         * from which the main value is derived, and write it into local cache.
         * Synchronous blocking call.
         *
         * @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
         * @param value in String format.
         * @return the result of setting the configuration value, defined as either
         * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
         */
        @Override
        public int setConfigString(int item, String value)
                throws RemoteException {
            AtomicReference exceptionRef = new AtomicReference<>();
            int retVal = executeMethodAsyncForResult(()-> {
                int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN;
                try {
                    synchronized (mLock) {
                        mProvisionedStringValue.remove(item);
                        returnVal = getImsConfigImpl().setConfig(item, value);
                        if (returnVal == ImsConfig.OperationStatusConstants.SUCCESS) {
                            mProvisionedStringValue.put(item, value);
                        }
                    }
                    notifyImsConfigChanged(item, value);
                    return returnVal;
                } catch (RemoteException e) {
                    exceptionRef.set(e);
                    return returnVal;
                }
            }, "setConfigString");

            if (exceptionRef.get() != null) {
                Log.d(TAG, "ImsConfigImplBase Exception setConfigInt");
                throw exceptionRef.get();
            }

            return retVal;
        }

        @Override
        public void updateImsCarrierConfigs(PersistableBundle bundle) throws RemoteException {
            AtomicReference exceptionRef = new AtomicReference<>();
            executeMethodAsync(()-> {
                try {
                    getImsConfigImpl().updateImsCarrierConfigs(bundle);
                } catch (RemoteException e) {
                    exceptionRef.set(e);
                }
            }, "updateImsCarrierConfigs");

            if (exceptionRef.get() != null) {
                Log.d(TAG, "ImsConfigImplBase Exception updateImsCarrierConfigs");
                throw exceptionRef.get();
            }
        }

        private ImsConfigImplBase getImsConfigImpl() throws RemoteException {
            ImsConfigImplBase ref = mImsConfigImplBaseWeakReference.get();
            if (ref == null) {
                throw new RemoteException("Fail to get ImsConfigImpl");
            } else {
                return ref;
            }
        }

        @Override
        public void notifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed)
                throws RemoteException {
            AtomicReference exceptionRef = new AtomicReference<>();
            executeMethodAsync(()-> {
                try {
                    getImsConfigImpl().onNotifyRcsAutoConfigurationReceived(config, isCompressed);
                } catch (RemoteException e) {
                    exceptionRef.set(e);
                }
            }, "notifyRcsAutoConfigurationReceived");

            if (exceptionRef.get() != null) {
                Log.d(TAG, "ImsConfigImplBase Exception notifyRcsAutoConfigurationReceived");
                throw exceptionRef.get();
            }
        }

        @Override
        public void notifyRcsAutoConfigurationRemoved()
                throws RemoteException {
            AtomicReference exceptionRef = new AtomicReference<>();
            executeMethodAsync(()-> {
                try {
                    getImsConfigImpl().onNotifyRcsAutoConfigurationRemoved();
                } catch (RemoteException e) {
                    exceptionRef.set(e);
                }
            }, "notifyRcsAutoConfigurationRemoved");

            if (exceptionRef.get() != null) {
                Log.d(TAG, "ImsConfigImplBase Exception notifyRcsAutoConfigurationRemoved");
                throw exceptionRef.get();
            }
        }

        private void notifyImsConfigChanged(int item, int value) throws RemoteException {
            getImsConfigImpl().notifyConfigChanged(item, value);
        }

        private void notifyImsConfigChanged(int item, String value) throws RemoteException {
            getImsConfigImpl().notifyConfigChanged(item, value);
        }

        protected void updateCachedValue(int item, int value) {
            synchronized (mLock) {
                mProvisionedIntValue.put(item, value);
            }
        }

        protected void updateCachedValue(int item, String value) {
            synchronized (mLock) {
                mProvisionedStringValue.put(item, value);
            }
        }

        @Override
        public void addRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
            AtomicReference exceptionRef = new AtomicReference<>();
            executeMethodAsync(()-> {
                try {
                    getImsConfigImpl().addRcsConfigCallback(c);
                } catch (RemoteException e) {
                    exceptionRef.set(e);
                }
            }, "addRcsConfigCallback");

            if (exceptionRef.get() != null) {
                Log.d(TAG, "ImsConfigImplBase Exception addRcsConfigCallback");
                throw exceptionRef.get();
            }
        }

        @Override
        public void removeRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
            AtomicReference exceptionRef = new AtomicReference<>();
            executeMethodAsync(()-> {
                try {
                    getImsConfigImpl().removeRcsConfigCallback(c);
                } catch (RemoteException e) {
                    exceptionRef.set(e);
                }
            }, "removeRcsConfigCallback");

            if (exceptionRef.get() != null) {
                Log.d(TAG, "ImsConfigImplBase Exception removeRcsConfigCallback");
                throw exceptionRef.get();
            }
        }

        @Override
        public void triggerRcsReconfiguration() throws RemoteException {
            AtomicReference exceptionRef = new AtomicReference<>();
            executeMethodAsync(()-> {
                try {
                    getImsConfigImpl().triggerAutoConfiguration();
                } catch (RemoteException e) {
                    exceptionRef.set(e);
                }
            }, "triggerRcsReconfiguration");

            if (exceptionRef.get() != null) {
                Log.d(TAG, "ImsConfigImplBase Exception triggerRcsReconfiguration");
                throw exceptionRef.get();
            }
        }

        @Override
        public void setRcsClientConfiguration(RcsClientConfiguration rcc) throws RemoteException {
            AtomicReference exceptionRef = new AtomicReference<>();
            executeMethodAsync(()-> {
                try {
                    getImsConfigImpl().setRcsClientConfiguration(rcc);
                } catch (RemoteException e) {
                    exceptionRef.set(e);
                }
            }, "setRcsClientConfiguration");

            if (exceptionRef.get() != null) {
                Log.d(TAG, "ImsConfigImplBase Exception setRcsClientConfiguration");
                throw exceptionRef.get();
            }
        }

        @Override
        public void notifyIntImsConfigChanged(int item, int value) throws RemoteException {
            AtomicReference exceptionRef = new AtomicReference<>();
            executeMethodAsync(()-> {
                try {
                    notifyImsConfigChanged(item, value);
                } catch (RemoteException e) {
                    exceptionRef.set(e);
                }
            }, "notifyIntImsConfigChanged");

            if (exceptionRef.get() != null) {
                Log.d(TAG, "ImsConfigImplBase Exception notifyIntImsConfigChanged");
                throw exceptionRef.get();
            }
        }

        @Override
        public void notifyStringImsConfigChanged(int item, String value) throws RemoteException {
            AtomicReference exceptionRef = new AtomicReference<>();
            executeMethodAsync(()-> {
                try {
                    notifyImsConfigChanged(item, value);
                } catch (RemoteException e) {
                    exceptionRef.set(e);
                }
            }, "notifyStringImsConfigChanged");

            if (exceptionRef.get() != null) {
                Log.d(TAG, "ImsConfigImplBase Exception notifyStringImsConfigChanged");
                throw exceptionRef.get();
            }
        }

        // Call the methods with a clean calling identity on the executor and wait indefinitely for
        // the future to return.
        private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
            try {
                CompletableFuture.runAsync(
                        () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
            } catch (CancellationException | CompletionException e) {
                Log.w(TAG, "ImsConfigImplBase Binder - " + errorLogName + " exception: "
                        + e.getMessage());
                throw new RemoteException(e.getMessage());
            }
        }

        private  T executeMethodAsyncForResult(Supplier r,
                String errorLogName) throws RemoteException {
            CompletableFuture future = CompletableFuture.supplyAsync(
                    () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
            try {
                return future.get();
            } catch (ExecutionException | InterruptedException e) {
                Log.w(TAG, "ImsConfigImplBase Binder - " + errorLogName + " exception: "
                        + e.getMessage());
                throw new RemoteException(e.getMessage());
            }
        }
    }

    /**
     * The configuration requested resulted in an unknown result. This may happen if the
     * IMS configurations are unavailable.
     */
    public static final int CONFIG_RESULT_UNKNOWN = ProvisioningManager.PROVISIONING_RESULT_UNKNOWN;

    /**
     * Setting the configuration value completed.
     */
    public static final int CONFIG_RESULT_SUCCESS = 0;
    /**
     * Setting the configuration value failed.
     */
    public static final int CONFIG_RESULT_FAILED =  1;

    /**
     * @hide
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = "CONFIG_RESULT_", value = {
            CONFIG_RESULT_SUCCESS,
            CONFIG_RESULT_FAILED
    })
    public @interface SetConfigResult {}

    private final RemoteCallbackListExt mCallbacks =
            new RemoteCallbackListExt<>();
    private final RemoteCallbackListExt mRcsCallbacks =
            new RemoteCallbackListExt<>();
    private byte[] mRcsConfigData;
    ImsConfigStub mImsConfigStub;

    /**
     * Create a ImsConfig using the Executor specified for methods being called by the
     * framework.
     * @param executor The executor for the framework to use when executing the methods overridden
     * by the implementation of ImsConfig.
     */
    public ImsConfigImplBase(@NonNull Executor executor) {
        mImsConfigStub = new ImsConfigStub(this, executor);
    }

    /**
     * @hide
     */
    public ImsConfigImplBase(@NonNull Context context) {
        mImsConfigStub = new ImsConfigStub(this, null);
    }

    public ImsConfigImplBase() {
        mImsConfigStub = new ImsConfigStub(this, null);
    }

    /**
     * Adds a {@link android.telephony.ims.ProvisioningManager.Callback} to the list of callbacks
     * notified when a value in the configuration changes.
     * @param c callback to add.
     */
    private void addImsConfigCallback(IImsConfigCallback c) {
        mCallbacks.register(c);
    }
    /**
     * Removes a {@link android.telephony.ims.ProvisioningManager.Callback} to the list of callbacks
     * notified when a value in the configuration changes.
     * @param c callback to remove.
     */
    private void removeImsConfigCallback(IImsConfigCallback c) {
        mCallbacks.unregister(c);
    }

    /**
     * @param item
     * @param value
     */
    private final void notifyConfigChanged(int item, int value) {
        // can be null in testing
        if (mCallbacks == null) {
            return;
        }
        synchronized (mCallbacks) {
            mCallbacks.broadcastAction(c -> {
                try {
                    c.onIntConfigChanged(item, value);
                } catch (RemoteException e) {
                    Log.w(TAG, "notifyConfigChanged(int): dead binder in notify, skipping.");
                }
            });
        }
    }

    private void notifyConfigChanged(int item, String value) {
        // can be null in testing
        if (mCallbacks == null) {
            return;
        }
        synchronized (mCallbacks) {
            mCallbacks.broadcastAction(c -> {
                try {
                    c.onStringConfigChanged(item, value);
                } catch (RemoteException e) {
                    Log.w(TAG, "notifyConfigChanged(string): dead binder in notify, skipping.");
                }
            });
        }
    }

    private void addRcsConfigCallback(IRcsConfigCallback c) {
        mRcsCallbacks.register(c);
        if (mRcsConfigData != null) {
            try {
                c.onConfigurationChanged(mRcsConfigData);
            } catch (RemoteException e) {
                Log.w(TAG, "dead binder to call onConfigurationChanged, skipping.");
            }
        }
    }

    private void removeRcsConfigCallback(IRcsConfigCallback c) {
        mRcsCallbacks.unregister(c);
    }

    private void onNotifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed) {
        // cache uncompressed config
        config = isCompressed ? RcsConfig.decompressGzip(config) : config;
        if (Arrays.equals(mRcsConfigData, config)) {
            return;
        }
        mRcsConfigData = config;

        // can be null in testing
        if (mRcsCallbacks != null) {
            synchronized (mRcsCallbacks) {
                mRcsCallbacks.broadcastAction(c -> {
                    try {
                        c.onConfigurationChanged(mRcsConfigData);
                    } catch (RemoteException e) {
                        Log.w(TAG, "dead binder in notifyRcsAutoConfigurationReceived, skipping.");
                    }
                });
            }
        }
        notifyRcsAutoConfigurationReceived(config, isCompressed);
    }

    private void onNotifyRcsAutoConfigurationRemoved() {
        mRcsConfigData = null;
        if (mRcsCallbacks != null) {
            synchronized (mRcsCallbacks) {
                mRcsCallbacks.broadcastAction(c -> {
                    try {
                        c.onConfigurationReset();
                    } catch (RemoteException e) {
                        Log.w(TAG, "dead binder in notifyRcsAutoConfigurationRemoved, skipping.");
                    }
                });
            }
        }
        notifyRcsAutoConfigurationRemoved();
    }

    /**
     * @hide
     */
    public IImsConfig getIImsConfig() { return mImsConfigStub; }

    /**
     * Updates provisioning value and notifies the framework of the change.
     * Doesn't call {@link #setConfig(int,int)} and assumes the result succeeded.
     * This should only be used when the IMS implementer implicitly changed provisioned values.
     *
     * @param item an integer key.
     * @param value in Integer format.
     */
    public final void notifyProvisionedValueChanged(int item, int value) {
        mImsConfigStub.updateCachedValue(item, value);

        try {
            mImsConfigStub.notifyImsConfigChanged(item, value);
        } catch (RemoteException e) {
            Log.w(TAG, "notifyProvisionedValueChanged(int): Framework connection is dead.");
        }
    }

    /**
     * Updates provisioning value and notifies the framework of the change.
     * Doesn't call {@link #setConfig(int,String)} and assumes the result succeeded.
     * This should only be used when the IMS implementer implicitly changed provisioned values.
     *
     * @param item an integer key.
     * @param value in String format.
     */
    public final void notifyProvisionedValueChanged(int item, String value) {
        mImsConfigStub.updateCachedValue(item, value);

        try {
            mImsConfigStub.notifyImsConfigChanged(item, value);
        } catch (RemoteException e) {
            Log.w(TAG, "notifyProvisionedValueChanged(string): Framework connection is dead.");
        }
    }

    /**
     * The framework has received an RCS autoconfiguration XML file for provisioning.
     *
     * @param config The XML file to be read, if not compressed, it should be in ASCII/UTF8 format.
     * @param isCompressed The XML file is compressed in gzip format and must be decompressed
     *         before being read.
     *
     */
    public void notifyRcsAutoConfigurationReceived(@NonNull byte[] config, boolean isCompressed) {
    }

    /**
     * The RCS autoconfiguration XML file is removed or invalid.
     */
    public void notifyRcsAutoConfigurationRemoved() {
    }

    /**
     * Sets the configuration value for this ImsService.
     *
     * @param item an integer key.
     * @param value an integer containing the configuration value.
     * @return the result of setting the configuration value.
     */
    public @SetConfigResult int setConfig(int item, int value) {
        // Base Implementation - To be overridden.
        return CONFIG_RESULT_FAILED;
    }

    /**
     * Sets the configuration value for this ImsService.
     *
     * @param item an integer key.
     * @param value a String containing the new configuration value.
     * @return Result of setting the configuration value.
     */
    public @SetConfigResult int setConfig(int item, String value) {
        // Base Implementation - To be overridden.
        return CONFIG_RESULT_FAILED;
    }

    /**
     * Gets the currently stored value configuration value from the ImsService for {@code item}.
     *
     * @param item an integer key.
     * @return configuration value, stored in integer format or {@link #CONFIG_RESULT_UNKNOWN} if
     * unavailable.
     */
    public int getConfigInt(int item) {
        // Base Implementation - To be overridden.
        return CONFIG_RESULT_UNKNOWN;
    }

    /**
     * Gets the currently stored value configuration value from the ImsService for {@code item}.
     *
     * @param item an integer key.
     * @return configuration value, stored in String format or {@code null} if unavailable.
     */
    public String getConfigString(int item) {
        // Base Implementation - To be overridden.
        return null;
    }

    /**
     * @hide
     */
    public void updateImsCarrierConfigs(PersistableBundle bundle) {
        // Base Implementation - Should be overridden
    }

    /**
     * Default messaging application parameters are sent to the ACS client
     * using this interface.
     * @param rcc RCS client configuration {@link RcsClientConfiguration}
     */
    public void setRcsClientConfiguration(@NonNull RcsClientConfiguration rcc) {
        // Base Implementation - Should be overridden
    }

    /**
     * Reconfiguration triggered by the RCS application. Most likely cause
     * is the 403 forbidden to a SIP/HTTP request
     */
    public void triggerAutoConfiguration() {
        // Base Implementation - Should be overridden
    }

    /**
     * Errors during autoconfiguration connection setup are notified by the
     * ACS client using this interface.
     * @param errorCode HTTP error received during connection setup.
     * @param errorString reason phrase received with the error
     */
    public final void notifyAutoConfigurationErrorReceived(int errorCode,
            @NonNull String errorString) {
        // can be null in testing
        if (mRcsCallbacks == null) {
            return;
        }
        synchronized (mRcsCallbacks) {
            mRcsCallbacks.broadcastAction(c -> {
                try {
                    c.onAutoConfigurationErrorReceived(errorCode, errorString);
                } catch (RemoteException e) {
                    Log.w(TAG, "dead binder in notifyAutoConfigurationErrorReceived, skipping.");
                }
            });
        }
    }

    /**
     * Notifies application that pre-provisioning config is received.
     *
     * 

Some carriers using ACS (auto configuration server) may send a carrier-specific * pre-provisioning configuration XML if the user has not been provisioned for RCS * services yet. When such provisioning XML is received, ACS client must call this * method to notify the application with the XML. * * @param configXml the pre-provisioning config in carrier specified format. */ public final void notifyPreProvisioningReceived(@NonNull byte[] configXml) { // can be null in testing if (mRcsCallbacks == null) { return; } synchronized (mRcsCallbacks) { mRcsCallbacks.broadcastAction(c -> { try { c.onPreProvisioningReceived(configXml); } catch (RemoteException e) { Log.w(TAG, "dead binder in notifyPreProvisioningReceived, skipping."); } }); } } /** * Set default Executor from ImsService. * @param executor The default executor for the framework to use when executing the methods * overridden by the implementation of ImsConfig. * @hide */ public final void setDefaultExecutor(@NonNull Executor executor) { if (mImsConfigStub.mExecutor == null) { mImsConfigStub.mExecutor = executor; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy