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

Commit 6e2553ae authored by Nathan Harold's avatar Nathan Harold Committed by Android (Google) Code Review
Browse files

Merge changes from topic "usage-setting"

* changes:
  Update Usage Setting From SubInfo to Modem
  Update the usage setting in SubInfoUpdater
  Add setter and getter for UsageSetting
  Add Usage Setting to SIMINFO
parents 19760912 458a1b29
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import android.os.AsyncResult;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
@@ -274,6 +275,8 @@ public class GsmCdmaPhone extends Phone {
    private final ImsManagerFactory mImsManagerFactory;
    private final CarrierPrivilegesTracker mCarrierPrivilegesTracker;

    private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener;

    // Constructors

    public GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, int phoneId,
@@ -376,6 +379,19 @@ public class GsmCdmaPhone extends Phone {
        loadTtyMode();

        CallManager.getInstance().registerPhone(this);

        mSubscriptionsChangedListener =
                new SubscriptionManager.OnSubscriptionsChangedListener() {
            @Override
            public void onSubscriptionsChanged() {
                sendEmptyMessage(EVENT_SUBSCRIPTIONS_CHANGED);
            }
        };

        SubscriptionManager subMan = context.getSystemService(SubscriptionManager.class);
        subMan.addOnSubscriptionsChangedListener(
                new HandlerExecutor(this), mSubscriptionsChangedListener);

        logd("GsmCdmaPhone: constructor: sub = " + mPhoneId);
    }

@@ -3307,6 +3323,10 @@ public class GsmCdmaPhone extends Phone {
            case EVENT_SET_VONR_ENABLED_DONE:
                logd("EVENT_SET_VONR_ENABLED_DONE is done");
                break;
            case EVENT_SUBSCRIPTIONS_CHANGED:
                logd("EVENT_SUBSCRIPTIONS_CHANGED");
                updateUsageSetting();
                break;

            default:
                super.handleMessage(msg);
+102 −1
Original line number Diff line number Diff line
@@ -236,8 +236,11 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    protected static final int EVENT_LINK_CAPACITY_CHANGED = 59;
    protected static final int EVENT_RESET_CARRIER_KEY_IMSI_ENCRYPTION = 60;
    protected static final int EVENT_SET_VONR_ENABLED_DONE = 61;
    protected static final int EVENT_SUBSCRIPTIONS_CHANGED = 62;
    protected static final int EVENT_GET_USAGE_SETTING_DONE = 63;
    protected static final int EVENT_SET_USAGE_SETTING_DONE = 64;

    protected static final int EVENT_LAST = EVENT_SET_VONR_ENABLED_DONE;
    protected static final int EVENT_LAST = EVENT_SET_USAGE_SETTING_DONE;

    // For shared prefs.
    private static final String GSM_ROAMING_LIST_OVERRIDE_PREFIX = "gsm_roaming_list_";
@@ -364,6 +367,10 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    private int mLceStatus = RILConstants.LCE_NOT_AVAILABLE;
    protected TelephonyComponentFactory mTelephonyComponentFactory;

    private int mPreferredUsageSetting = SubscriptionManager.USAGE_SETTING_UNKNOWN;
    private int mUsageSettingFromModem = SubscriptionManager.USAGE_SETTING_UNKNOWN;
    private boolean mIsUsageSettingSupported = true;

    //IMS
    /**
     * {@link CallStateException} message text used to indicate that an IMS call has failed because
@@ -812,6 +819,48 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
                    mAllDataDisconnectedRegistrants.notifyRegistrants();
                }
                break;
            case EVENT_GET_USAGE_SETTING_DONE:
                ar = (AsyncResult) msg.obj;
                if (ar.exception == null) {
                    try {
                        int mUsageSettingFromModem = ((int[]) ar.result)[0];
                    } catch (NullPointerException | ClassCastException e) {
                        Rlog.e(LOG_TAG, "Invalid response for usage setting " + ar.result);
                        break;
                    }

                    if (mUsageSettingFromModem != mPreferredUsageSetting) {
                        mCi.setUsageSetting(obtainMessage(EVENT_SET_USAGE_SETTING_DONE),
                                mPreferredUsageSetting);
                    }
                } else {
                    try {
                        CommandException ce = (CommandException) ar.exception;
                        if (ce.getCommandError() == CommandException.Error.REQUEST_NOT_SUPPORTED) {
                            mIsUsageSettingSupported = false;
                        }
                        Rlog.w(LOG_TAG, "Unexpected failure to retrieve usage setting " + ce);
                    } catch (ClassCastException unused) {
                        Rlog.e(LOG_TAG, "Invalid Exception for usage setting " + ar.exception);
                        break; // technically extraneous, but good hygiene
                    }
                }
                break;
            case EVENT_SET_USAGE_SETTING_DONE:
                ar = (AsyncResult) msg.obj;
                if (ar.exception != null) {
                    try {
                        CommandException ce = (CommandException) ar.exception;
                        if (ce.getCommandError() == CommandException.Error.REQUEST_NOT_SUPPORTED) {
                            mIsUsageSettingSupported = false;
                        }
                        Rlog.w(LOG_TAG, "Unexpected failure to set usage setting " + ce);
                    } catch (ClassCastException unused) {
                        Rlog.e(LOG_TAG, "Invalid Exception for usage setting " + ar.exception);
                        break; // technically extraneous, but good hygiene
                    }
                }
                break;
            default:
                throw new RuntimeException("unexpected event not handled");
        }
@@ -4435,8 +4484,60 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        if (restoreNetworkSelection) {
            restoreSavedNetworkSelection(null);
        }

        updateUsageSetting();
    }

    // Need a magic little helper function to avoid a static call via SubscriptionManager
    private int getPreferredUsageSetting() {
        String result = SubscriptionController.getInstance().getSubscriptionProperty(
                getSubId(), SubscriptionManager.USAGE_SETTING);
        try {
            return Integer.parseInt(result);
        } catch (NumberFormatException nfe) {
        }
        return SubscriptionManager.USAGE_SETTING_UNKNOWN;
    }

    /**
     * Attempt to update the usage setting.
     *
     * @return whether the usage setting will be updated (used for test)
     */
    public boolean updateUsageSetting() {
        if (!mIsUsageSettingSupported) return false;

        final int subId = getSubId();
        if (!SubscriptionManager.isValidSubscriptionId(subId)) return false;

        int lastPreferredUsageSetting = mPreferredUsageSetting;

        int mPreferredUsageSetting = getPreferredUsageSetting();

        // We might get a lot of requests to update, so definitely we don't want to hammer
        // the modem with multiple duplicate requests for usage setting updates
        if (mPreferredUsageSetting == lastPreferredUsageSetting) return false;

        // If the user prefers the default setting, we now need to resolve that into a concrete
        // value, since the modem will have a "concrete" value.
        if (mPreferredUsageSetting == SubscriptionManager.USAGE_SETTING_DEFAULT) {
            mPreferredUsageSetting = mContext.getResources().getInteger(
                    com.android.internal.R.integer.config_default_cellular_usage_setting);
        }

        // If the modem value hasn't been updated, request it.
        if (mUsageSettingFromModem == SubscriptionManager.USAGE_SETTING_UNKNOWN) {
            mCi.getUsageSetting(obtainMessage(EVENT_GET_USAGE_SETTING_DONE));
            // If the modem value is already known, and the value has changed, proceed to update.
        } else if (mPreferredUsageSetting != mUsageSettingFromModem) {
            mCi.setUsageSetting(obtainMessage(EVENT_SET_USAGE_SETTING_DONE),
                    mPreferredUsageSetting);
        }
        return true;
    }



    /**
     * Registers the handler when phone radio  capability is changed.
     *
+6 −0
Original line number Diff line number Diff line
@@ -1096,4 +1096,10 @@ public interface PhoneInternalInterface {
     *  their mobile plan.
     */
    String getMobileProvisioningUrl();

    /**
     * Update the cellular usage setting if applicable.
     */
    boolean updateUsageSetting();

}
+59 −4
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import android.telephony.RadioAccessFamily;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.SimDisplayNameSource;
import android.telephony.SubscriptionManager.UsageSetting;
import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyRegistryManager;
@@ -597,6 +598,9 @@ public class SubscriptionController extends ISub.Stub {
        boolean areUiccApplicationsEnabled = cursor.getInt(cursor.getColumnIndexOrThrow(
                SubscriptionManager.UICC_APPLICATIONS_ENABLED)) == 1;

        int usageSetting = cursor.getInt(cursor.getColumnIndexOrThrow(
                SubscriptionManager.USAGE_SETTING));

        if (VDBG) {
            String iccIdToPrint = SubscriptionInfo.givePrintableIccid(iccId);
            String cardIdToPrint = SubscriptionInfo.givePrintableIccid(cardId);
@@ -612,7 +616,8 @@ public class SubscriptionController extends ISub.Stub {
                    + " isOpportunistic:" + isOpportunistic + " groupUUID:" + groupUUID
                    + " profileClass:" + profileClass + " subscriptionType: " + subType
                    + " carrierConfigAccessRules:" + carrierConfigAccessRules
                    + " areUiccApplicationsEnabled: " + areUiccApplicationsEnabled);
                    + " areUiccApplicationsEnabled: " + areUiccApplicationsEnabled
                    + " usageSetting: " + usageSetting);
        }

        // If line1number has been set to a different number, use it instead.
@@ -620,12 +625,14 @@ public class SubscriptionController extends ISub.Stub {
        if (!TextUtils.isEmpty(line1Number) && !line1Number.equals(number)) {
            number = line1Number;
        }
        // FIXME(b/210771052): constructing a complete SubscriptionInfo requires a port index,
        // but the port index isn't available here. Should it actually be part of SubscriptionInfo?
        SubscriptionInfo info = new SubscriptionInfo(id, iccId, simSlotIndex, displayName,
                carrierName, nameSource, iconTint, number, dataRoaming, /* icon= */ null,
                mcc, mnc, countryIso, isEmbedded, accessRules, cardId, publicCardId,
                isOpportunistic, groupUUID, /* isGroupDisabled= */ false , carrierId, profileClass,
                subType, groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled,
                portIndex);
                portIndex, usageSetting);
        info.setAssociatedPlmns(ehplmns, hplmns);
        return info;
    }
@@ -1753,6 +1760,9 @@ public class SubscriptionController extends ISub.Stub {
                "user=" + RadioAccessFamily.getRafFromNetworkType(
                        RILConstants.PREFERRED_NETWORK_MODE));

        value.put(SubscriptionManager.USAGE_SETTING,
                SubscriptionManager.USAGE_SETTING_UNKNOWN);

        Uri uri = resolver.insert(SubscriptionManager.CONTENT_URI, value);

        // Refresh the Cache of Active Subscription Info List
@@ -3053,9 +3063,9 @@ public class SubscriptionController extends ISub.Stub {
    private void validateSubId(int subId) {
        if (DBG) logd("validateSubId subId: " + subId);
        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
            throw new RuntimeException("Invalid sub id passed as parameter");
            throw new IllegalArgumentException("Invalid sub id passed as parameter");
        } else if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
            throw new RuntimeException("Default sub id passed as parameter");
            throw new IllegalArgumentException("Default sub id passed as parameter");
        }
    }

@@ -3243,6 +3253,7 @@ public class SubscriptionController extends ISub.Stub {
            case SubscriptionManager.CROSS_SIM_CALLING_ENABLED:
            case SubscriptionManager.VOIMS_OPT_IN_STATUS:
            case SubscriptionManager.NR_ADVANCED_CALLING_ENABLED:
            case SubscriptionManager.USAGE_SETTING:
                value.put(propKey, Integer.parseInt(propValue));
                break;
            case SubscriptionManager.ALLOWED_NETWORK_TYPES:
@@ -3328,6 +3339,7 @@ public class SubscriptionController extends ISub.Stub {
                        case SubscriptionManager.NR_ADVANCED_CALLING_ENABLED:
                        case SimInfo.COLUMN_PHONE_NUMBER_SOURCE_CARRIER:
                        case SimInfo.COLUMN_PHONE_NUMBER_SOURCE_IMS:
                        case SubscriptionManager.USAGE_SETTING:
                            resultValue = cursor.getString(0);
                            break;
                        default:
@@ -4666,6 +4678,49 @@ public class SubscriptionController extends ISub.Stub {
        }
    }

    /**
     * Set the Usage Setting for this subscription.
     *
     * @param usageSetting the cellular usage setting
     * @param subId the unique SubscriptionInfo index in database
     * @param callingPackage the package making the IPC
     * @return the number of records updated
     *
     * @throws SecurityException if doesn't have required permission.
     */
    @Override
    public int setUsageSetting(@UsageSetting int usageSetting, int subId, String callingPackage) {
        try {
            TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
                    mContext, subId, callingPackage);
        } catch (SecurityException e) {
            enforceCarrierPrivilegeOnInactiveSub(subId, callingPackage,
                    "Caller requires permission on sub " + subId);
        }

        if (usageSetting < SubscriptionManager.USAGE_SETTING_DEFAULT
                || usageSetting > SubscriptionManager.USAGE_SETTING_DATA_CENTRIC) {
            throw new IllegalArgumentException("setUsageSetting: Invalid usage setting: "
                    + usageSetting);
        }

        final long token = Binder.clearCallingIdentity();
        int ret;
        try {
            ret = setSubscriptionProperty(subId, SubscriptionManager.USAGE_SETTING,
                    String.valueOf(usageSetting));

            // ret is the number of records updated in the DB, which should always be 1.
            // TODO(b/205027930): move this check prior to the database mutation request
            if (ret != 1) throw new IllegalArgumentException(
                    "Invalid SubscriptionId for setUsageSetting");
        } finally {
            Binder.restoreCallingIdentity(token);
            // FIXME(b/205726099) return void
        }
        return ret;
    }

    /**
     * @hide
     */
+85 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.AsyncResult;
import android.os.Build;
import android.os.Handler;
@@ -44,6 +45,7 @@ import android.service.euicc.GetEuiccProfileInfoListResult;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.UsageSetting;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager.SimState;
import android.telephony.UiccAccessRule;
@@ -629,6 +631,62 @@ public class SubscriptionInfoUpdater extends Handler {
        updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOADED);
    }

    /**
     * Calculate the usage setting based on the carrier request.
     *
     * @param currentUsageSetting the current setting in the subscription DB
     * @param preferredUsageSetting provided by the carrier config
     * @return the calculated usage setting.
     */
    @VisibleForTesting
    @UsageSetting public int calculateUsageSetting(
            @UsageSetting int currentUsageSetting, @UsageSetting int preferredUsageSetting) {
        int defaultUsageSetting;
        int[] supportedUsageSettings;

        //  Load the resources to provide the device capability
        try {
            defaultUsageSetting = sContext.getResources().getInteger(
                com.android.internal.R.integer.config_default_cellular_usage_setting);
            supportedUsageSettings = sContext.getResources().getIntArray(
                com.android.internal.R.array.config_supported_cellular_usage_settings);
            // If usage settings are not supported, return the default setting, which is UNKNOWN.
            if (supportedUsageSettings == null
                    || supportedUsageSettings.length < 1) return currentUsageSetting;
        } catch (Resources.NotFoundException nfe) {
            loge("Failed to load usage setting resources!");
            return currentUsageSetting;
        }

        // If the current setting is invalid, including the first time the value is set,
        // update it to default (this will trigger a change in the DB).
        if (currentUsageSetting < SubscriptionManager.USAGE_SETTING_DEFAULT
                || currentUsageSetting > SubscriptionManager.USAGE_SETTING_DATA_CENTRIC) {
            logd("Updating usage setting for current subscription");
            currentUsageSetting = SubscriptionManager.USAGE_SETTING_DEFAULT;
        }

        // Range check the inputs, and on failure, make no changes
        if (preferredUsageSetting < SubscriptionManager.USAGE_SETTING_DEFAULT
                || preferredUsageSetting > SubscriptionManager.USAGE_SETTING_DATA_CENTRIC) {
            loge("Invalid usage setting!" + preferredUsageSetting);
            return currentUsageSetting;
        }

        // Default is always allowed
        if (preferredUsageSetting == SubscriptionManager.USAGE_SETTING_DEFAULT) {
            return preferredUsageSetting;
        }

        // Forced setting must be explicitly supported
        for (int i = 0; i < supportedUsageSettings.length; i++) {
            if (preferredUsageSetting == supportedUsageSettings[i]) return preferredUsageSetting;
        }

        // If the preferred setting is not possible, just keep the current setting.
        return currentUsageSetting;
    }

    private void restoreSimSpecificSettingsForPhone(int phoneId) {
        SubscriptionManager subManager = SubscriptionManager.from(sContext);
        subManager.restoreSimSpecificSettingsForIccIdFromBackup(sIccId[phoneId]);
@@ -1166,6 +1224,33 @@ public class SubscriptionInfoUpdater extends Handler {
                }
            }
        }

        final int preferredUsageSetting =
                config.getInt(
                        CarrierConfigManager.KEY_CELLULAR_USAGE_SETTING_INT,
                        SubscriptionManager.USAGE_SETTING_UNKNOWN);

        @UsageSetting int newUsageSetting = calculateUsageSetting(
                currentSubInfo.getUsageSetting(),
                preferredUsageSetting);

        if (newUsageSetting != currentSubInfo.getUsageSetting()) {
            cv.put(SubscriptionManager.USAGE_SETTING, newUsageSetting);
            if (DBG) {
                logd("UsageSetting changed,"
                        + " oldSetting=" + currentSubInfo.getUsageSetting()
                        + " preferredSetting=" + preferredUsageSetting
                        + " newSetting=" + newUsageSetting);
            }
        } else {
            if (DBG) {
                logd("UsageSetting unchanged,"
                        + " oldSetting=" + currentSubInfo.getUsageSetting()
                        + " preferredSetting=" + preferredUsageSetting
                        + " newSetting=" + newUsageSetting);
            }
        }

        if (cv.size() > 0 && sContext.getContentResolver().update(SubscriptionManager
                    .getUriForSubscriptionId(currentSubId), cv, null, null) > 0) {
            mSubscriptionController.refreshCachedActiveSubscriptionInfoList();
Loading