Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 45904b5d authored by Malcolm Chen's avatar Malcolm Chen Committed by Brad Ebinger
Browse files

IMS provisioned value refactor.

Instead of writing IMS provisioned values into system property,
now we always query it from ImsConfig, which keeps a cach version
of the values.

Bug: 66701374
Test: unittest
Merged-In: I4bf6880a500d7ccf1c2e149e86b803a7ae376ad9
Change-Id: I4bf6880a500d7ccf1c2e149e86b803a7ae376ad9
parent ed69077f
Loading
Loading
Loading
Loading
+55 −159
Original line number Diff line number Diff line
@@ -19,11 +19,8 @@ package com.android.ims;
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.os.PersistableBundle;
@@ -50,14 +47,13 @@ import com.android.ims.internal.IImsMultiEndpoint;
import com.android.ims.internal.IImsUt;
import android.telephony.ims.ImsCallSession;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.ExponentialBackoff;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.CopyOnWriteArraySet;

/**
@@ -165,6 +161,11 @@ public class ImsManager {
     */
    public static final String EXTRA_IS_UNKNOWN_CALL = "android:isUnknown";

    private static final int SYSTEM_PROPERTY_NOT_SET = -1;

    // -1 indicates a subscriptionProperty value that is never set.
    private static final int SUB_PROPERTY_NOT_INITIALIZED = -1;

    private static final String TAG = "ImsManager";
    private static final boolean DBG = true;

@@ -193,10 +194,6 @@ public class ImsManager {
    private Set<MmTelFeatureConnection.IFeatureUpdate> mStatusCallbacks =
            new CopyOnWriteArraySet<>();

    // SystemProperties used as cache
    private static final String VOLTE_PROVISIONED_PROP = "net.lte.ims.volte.provisioned";
    private static final String WFC_PROVISIONED_PROP = "net.lte.ims.wfc.provisioned";
    private static final String VT_PROVISIONED_PROP = "net.lte.ims.vt.provisioned";
    // Flag indicating data enabled or not. This flag should be in sync with
    // DcTracker.isDataEnabled(). The flag will be set later during boot up.
    private static final String DATA_ENABLED_PROP = "net.lte.ims.data.enabled";
@@ -209,19 +206,6 @@ public class ImsManager {
    private ConcurrentLinkedDeque<ImsReasonInfo> mRecentDisconnectReasons =
            new ConcurrentLinkedDeque<>();

    // Exponential backoff for provisioning cache update. May be null for instances of ImsManager
    // that are not on a thread supporting a looper.
    private ExponentialBackoff mProvisionBackoff;
    // Initial Provisioning check delay in ms
    private static final long BACKOFF_INITIAL_DELAY_MS = 500;
    // Max Provisioning check delay in ms (5 Minutes)
    private static final long BACKOFF_MAX_DELAY_MS = 300000;
    // Multiplier for exponential delay
    private static final int BACKOFF_MULTIPLIER = 2;
    // -1 indicates a subscriptionProperty value that is never set.
    private static final int SUB_PROPERTY_NOT_INITIALIZED = -1;


    /**
     * Gets a manager instance.
     *
@@ -387,8 +371,13 @@ public class ImsManager {
     * basis.
     */
    public boolean isVolteEnabledByPlatform() {
        if (SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
                PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE_DEFAULT) == 1) {
        // We first read the per slot value. If doesn't exist, we read the general value. If still
        // doesn't exist, we use the hardcoded default value.
        if (SystemProperties.getInt(
                PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE + Integer.toString(mPhoneId),
                SYSTEM_PROPERTY_NOT_SET) == 1 ||
                SystemProperties.getInt(PROPERTY_DBG_VOLTE_AVAIL_OVERRIDE,
                        SYSTEM_PROPERTY_NOT_SET) == 1) {
            return true;
        }

@@ -521,8 +510,12 @@ public class ImsManager {
     * which must be done correctly).
     */
    public boolean isVtEnabledByPlatform() {
        if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE,
                PROPERTY_DBG_VT_AVAIL_OVERRIDE_DEFAULT) == 1) {
        // We first read the per slot value. If doesn't exist, we read the general value. If still
        // doesn't exist, we use the hardcoded default value.
        if (SystemProperties.getInt(PROPERTY_DBG_VT_AVAIL_OVERRIDE +
                Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1  ||
                SystemProperties.getInt(
                        PROPERTY_DBG_VT_AVAIL_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
            return true;
        }

@@ -624,10 +617,15 @@ public class ImsManager {
     * The platform property may override the carrier config.
     */
    private boolean isTurnOffImsAllowedByPlatform() {
        if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE,
                PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE_DEFAULT) == 1) {
        // We first read the per slot value. If doesn't exist, we read the general value. If still
        // doesn't exist, we use the hardcoded default value.
        if (SystemProperties.getInt(PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE +
                Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1  ||
                SystemProperties.getInt(
                        PROPERTY_DBG_ALLOW_IMS_OFF_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
            return true;
        }

        return getBooleanCarrierConfig(
                CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL);
    }
@@ -1008,8 +1006,12 @@ public class ImsManager {
     * configuration settings which must be done correctly).
     */
    public boolean isWfcEnabledByPlatform() {
        if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE,
                PROPERTY_DBG_WFC_AVAIL_OVERRIDE_DEFAULT) == 1) {
        // We first read the per slot value. If doesn't exist, we read the general value. If still
        // doesn't exist, we use the hardcoded default value.
        if (SystemProperties.getInt(PROPERTY_DBG_WFC_AVAIL_OVERRIDE +
                Integer.toString(mPhoneId), SYSTEM_PROPERTY_NOT_SET) == 1  ||
                SystemProperties.getInt(
                        PROPERTY_DBG_WFC_AVAIL_OVERRIDE, SYSTEM_PROPERTY_NOT_SET) == 1) {
            return true;
        }

@@ -1043,117 +1045,29 @@ public class ImsManager {
        return true;
    }

    /**
     * This function should be called when ImsConfig.ACTION_IMS_CONFIG_CHANGED is received.
     *
     * We cannot register receiver in ImsManager because this would lead to resource leak.
     * ImsManager can be created in different processes and it is not notified when that process
     * is about to be terminated.
     *
     * @hide
     * */
    public static void onProvisionedValueChanged(Context context, int item, String value) {
        if (DBG) Rlog.d(TAG, "onProvisionedValueChanged: item=" + item + " val=" + value);
        ImsManager mgr = ImsManager.getInstance(context,
                SubscriptionManager.getDefaultVoicePhoneId());

        switch (item) {
            case ImsConfig.ConfigConstants.VLT_SETTING_ENABLED:
                mgr.setVolteProvisionedProperty(value.equals("1"));
                if (DBG) Rlog.d(TAG,"isVoLteProvisioned = " + mgr.isVolteProvisioned());
                break;

            case ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED:
                mgr.setWfcProvisionedProperty(value.equals("1"));
                if (DBG) Rlog.d(TAG,"isWfcProvisioned = " + mgr.isWfcProvisioned());
                break;

            case ImsConfig.ConfigConstants.LVC_SETTING_ENABLED:
                mgr.setVtProvisionedProperty(value.equals("1"));
                if (DBG) Rlog.d(TAG,"isVtProvisioned = " + mgr.isVtProvisioned());
                break;

        }
    }

    private class AsyncUpdateProvisionedValues extends AsyncTask<Void, Void, Boolean> {
        @Override
        protected Boolean doInBackground(Void... params) {
            // disable on any error
            setVolteProvisionedProperty(false);
            setWfcProvisionedProperty(false);
            setVtProvisionedProperty(false);

            try {
                ImsConfig config = getConfigInterface();
                if (config != null) {
                    setVolteProvisionedProperty(getProvisionedBool(config,
                            ImsConfig.ConfigConstants.VLT_SETTING_ENABLED));
                    if (DBG) Rlog.d(TAG, "isVoLteProvisioned = " + isVolteProvisioned());

                    setWfcProvisionedProperty(getProvisionedBool(config,
                            ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED));
                    if (DBG) Rlog.d(TAG, "isWfcProvisioned = " + isWfcProvisioned());

                    setVtProvisionedProperty(getProvisionedBool(config,
                            ImsConfig.ConfigConstants.LVC_SETTING_ENABLED));
                    if (DBG) Rlog.d(TAG, "isVtProvisioned = " + isVtProvisioned());

                }
            } catch (ImsException ie) {
                Rlog.e(TAG, "AsyncUpdateProvisionedValues error: ", ie);
                return false;
            }

            return true;
        }

        @Override
        protected void onPostExecute(Boolean completed) {
            if (mProvisionBackoff == null) {
                return;
            }
            if (!completed) {
                mProvisionBackoff.notifyFailed();
            } else {
                mProvisionBackoff.stop();
            }
        }

    /**
     * Will return with config value or throw an ImsException if we receive an error from
     * ImsConfig for that value.
     */
    private boolean getProvisionedBool(ImsConfig config, int item) throws ImsException {
        int value = config.getProvisionedValue(item);
            if (value == ImsConfig.FeatureValueConstants.ERROR) {
        if (value == ImsConfig.OperationStatusConstants.UNKNOWN) {
            throw new ImsException("getProvisionedBool failed with error for item: " + item,
                    ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
        }
        return config.getProvisionedValue(item) == ImsConfig.FeatureValueConstants.ON;
    }
    }

    // used internally only, use #updateProvisionedValues instead.
    private void handleUpdateProvisionedValues() {
        if (getBooleanCarrierConfig(
                CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL)) {

            new AsyncUpdateProvisionedValues().execute();
        }
    }

    /**
     * Asynchronously get VoLTE, WFC, VT provisioning statuses. If ImsConfig is not available, we
     * will retry with exponential backoff.
     * Will return with config value or return false if we receive an error from
     * ImsConfig for that value.
     */
    private void updateProvisionedValues() {
        // Start trying to receive provisioning status after BACKOFF_INITIAL_DELAY_MS.
        if (mProvisionBackoff != null) {
            mProvisionBackoff.start();
        } else {
            // bypass and launch async thread once without backoff.
            handleUpdateProvisionedValues();
    private boolean getProvisionedBoolNoException(int item) {
        try {
            ImsConfig config = getConfigInterface();
            return getProvisionedBool(config, item);
        } catch (ImsException ex) {
            return false;
        }
    }

@@ -1178,8 +1092,6 @@ public class ImsManager {
    /**
     * Sync carrier config and user settings with ImsConfig.
     *
     * @param context for the manager object
     * @param phoneId phone id
     * @param force update
     */
    public void updateImsServiceConfig(boolean force) {
@@ -1194,8 +1106,6 @@ public class ImsManager {

        if (!mConfigUpdated || force) {
            try {
                updateProvisionedValues();

                // TODO: Extend ImsConfig API and set all feature values in single function call.

                // Note: currently the order of updates is set to produce different order of
@@ -1318,11 +1228,6 @@ public class ImsManager {
                com.android.internal.R.bool.config_dynamic_bind_ims);
        mConfigManager = (CarrierConfigManager) context.getSystemService(
                Context.CARRIER_CONFIG_SERVICE);
        if (Looper.getMainLooper() != null) {
            mProvisionBackoff = new ExponentialBackoff(BACKOFF_INITIAL_DELAY_MS,
                    BACKOFF_MAX_DELAY_MS, BACKOFF_MULTIPLIER,
                    new Handler(Looper.getMainLooper()), this::handleUpdateProvisionedValues);
        }
        createImsService();
    }

@@ -2202,27 +2107,18 @@ public class ImsManager {
    }

    private boolean isVolteProvisioned() {
        return SystemProperties.getBoolean(VOLTE_PROVISIONED_PROP, true);
    }

    private void setVolteProvisionedProperty(boolean provisioned) {
        SystemProperties.set(VOLTE_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
        return getProvisionedBoolNoException(
                ImsConfig.ConfigConstants.VLT_SETTING_ENABLED);
    }

    private boolean isWfcProvisioned() {
        return SystemProperties.getBoolean(WFC_PROVISIONED_PROP, true);
    }

    private void setWfcProvisionedProperty(boolean provisioned) {
        SystemProperties.set(WFC_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
        return getProvisionedBoolNoException(
                ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED);
    }

    private boolean isVtProvisioned() {
        return SystemProperties.getBoolean(VT_PROVISIONED_PROP, true);
    }

    private void setVtProvisionedProperty(boolean provisioned) {
        SystemProperties.set(VT_PROVISIONED_PROP, provisioned ? TRUE : FALSE);
        return getProvisionedBoolNoException(
                ImsConfig.ConfigConstants.LVC_SETTING_ENABLED);
    }

    private static String booleanToPropertyString(boolean bool) {