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

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

Merge changes from topic "carrier-config-n1-mode" into main

* changes:
  Hook CarrierConfig 5G Capability to setN1ModeEnabled HAL
  Add FeatureFlags to the Phone Objects
  Add a Network flags file and flag for b/302033535
parents 85743552 3bcef4fe
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ aconfig_declarations {
      "ims.aconfig",
      "messaging.aconfig",
      "misc.aconfig",
      "network.aconfig",
      "subscription.aconfig",
      "uicc.aconfig",
      "satellite.aconfig",

flags/network.aconfig

0 → 100644
+8 −0
Original line number Diff line number Diff line
package: "com.android.internal.telephony.flags"

flag {
    name: "enable_carrier_config_n1_control"
    namespace: "telephony"
    description: "enabling this flag allows KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY to control N1 mode enablement"
    bug:"302033535"
}
+117 −1
Original line number Diff line number Diff line
@@ -297,6 +297,16 @@ public class GsmCdmaPhone extends Phone {
    private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener;
    private final CallWaitingController mCallWaitingController;

    // Set via Carrier Config
    private boolean mIsN1ModeAllowedByCarrier = true;
    // Set via a call to the method on Phone; the only caller is IMS, and all of this code will
    // need to be updated to a voting mechanism (...enabled for reason...) if additional callers
    // are desired.
    private boolean mIsN1ModeAllowedByIms = true;
    // If this value is null, then the modem value is unknown. If a caller explicitly sets the
    // N1 mode, this value will be initialized before any attempt to set the value in the modem.
    private Boolean mModemN1Mode = null;

    // Constructors

    public GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, int phoneId,
@@ -321,7 +331,8 @@ public class GsmCdmaPhone extends Phone {
            TelephonyComponentFactory telephonyComponentFactory,
            ImsManagerFactory imsManagerFactory, @NonNull FeatureFlags featureFlags) {
        super(precisePhoneType == PhoneConstants.PHONE_TYPE_GSM ? "GSM" : "CDMA",
                notifier, context, ci, unitTestMode, phoneId, telephonyComponentFactory);
                notifier, context, ci, unitTestMode, phoneId, telephonyComponentFactory,
                featureFlags);

        // phone type needs to be set before other initialization as other objects rely on it
        mPrecisePhoneType = precisePhoneType;
@@ -2355,6 +2366,75 @@ public class GsmCdmaPhone extends Phone {
        mSsOverCdmaSupported = b.getBoolean(CarrierConfigManager.KEY_SUPPORT_SS_OVER_CDMA_BOOL);
    }

    /**
     * Enables or disables N1 mode (access to 5G core network) in accordance with
     * 3GPP TS 24.501 4.9.
     *
     * <p> To prevent redundant calls down to the modem and to support a mechanism whereby
     * N1 mode is only on if both IMS and carrier config believe that it should be on, this
     * method will first sync the value from the modem prior to possibly setting it. In addition
     * N1 mode will not be set to enabled unless both IMS and Carrier want it, since the use
     * cases require all entities to agree lest it default to disabled.
     *
     * @param enable {@code true} to enable N1 mode, {@code false} to disable N1 mode.
     * @param result Callback message to receive the result or null.
     */
    @Override
    public void setN1ModeEnabled(boolean enable, @Nullable Message result) {
        if (mFeatureFlags.enableCarrierConfigN1Control()) {
            // This might be called by IMS on another thread, so to avoid the requirement to
            // lock, post it through the handler.
            post(() -> {
                mIsN1ModeAllowedByIms = enable;
                if (mModemN1Mode == null) {
                    mCi.isN1ModeEnabled(obtainMessage(EVENT_GET_N1_MODE_ENABLED_DONE, result));
                } else {
                    maybeUpdateModemN1Mode(result);
                }
            });
        } else {
            super.setN1ModeEnabled(enable, result);
        }
    }

    /** Only called on the handler thread. */
    private void maybeUpdateModemN1Mode(@Nullable Message result) {
        final boolean wantN1Enabled = mIsN1ModeAllowedByCarrier && mIsN1ModeAllowedByIms;

        logd("N1 Mode: isModemN1Enabled=" + mModemN1Mode + ", wantN1Enabled=" + wantN1Enabled);

        // mModemN1Mode is never null here
        if (mModemN1Mode != wantN1Enabled) {
            // Assume success pending a response, which avoids multiple concurrent requests
            // going down to the modem. If it fails, that is addressed in the response.
            mModemN1Mode = wantN1Enabled;
            super.setN1ModeEnabled(
                    wantN1Enabled, obtainMessage(EVENT_SET_N1_MODE_ENABLED_DONE, result));
        } else if (result != null) {
            AsyncResult.forMessage(result);
            result.sendToTarget();
        }
    }

    /** Only called on the handler thread. */
    private void updateCarrierN1ModeSupported(@Nullable PersistableBundle b) {
        if (!mFeatureFlags.enableCarrierConfigN1Control()) return;

        if (b == null) return;


        final int[] supportedNrModes = b.getIntArray(
                CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY);

        mIsN1ModeAllowedByCarrier = ArrayUtils.contains(
                supportedNrModes, CarrierConfigManager.CARRIER_NR_AVAILABILITY_SA);
        if (mModemN1Mode == null) {
            mCi.isN1ModeEnabled(obtainMessage(EVENT_GET_N1_MODE_ENABLED_DONE));
        } else {
            maybeUpdateModemN1Mode(null);
        }
    }

    @Override
    public boolean useSsOverIms(Message onComplete) {
        boolean isUtEnabled = isUtEnabled();
@@ -3227,6 +3307,7 @@ public class GsmCdmaPhone extends Phone {
                updateNrSettingsAfterCarrierConfigChanged(b);
                updateVoNrSettings(b);
                updateSsOverCdmaSupported(b);
                updateCarrierN1ModeSupported(b);
                loadAllowedNetworksFromSubscriptionDatabase();
                // Obtain new radio capabilities from the modem, since some are SIM-dependent
                mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY));
@@ -3553,6 +3634,41 @@ public class GsmCdmaPhone extends Phone {
                    }
                }
                break;

            case EVENT_GET_N1_MODE_ENABLED_DONE:
                logd("EVENT_GET_N1_MODE_ENABLED_DONE");
                ar = (AsyncResult) msg.obj;
                if (ar == null || ar.exception != null
                        || ar.result == null || !(ar.result instanceof Boolean)) {
                    Rlog.e(LOG_TAG, "Failed to Retrieve N1 Mode", ar.exception);
                    if (ar != null && ar.userObj instanceof Message) {
                        // original requester's message is stashed in the userObj
                        final Message rsp = (Message) ar.userObj;
                        AsyncResult.forMessage(rsp, null, ar.exception);
                        rsp.sendToTarget();
                    }
                    break;
                }

                mModemN1Mode = (Boolean) ar.result;
                maybeUpdateModemN1Mode((Message) ar.userObj);
                break;

            case EVENT_SET_N1_MODE_ENABLED_DONE:
                logd("EVENT_SET_N1_MODE_ENABLED_DONE");
                ar = (AsyncResult) msg.obj;
                if (ar == null || ar.exception != null) {
                    Rlog.e(LOG_TAG, "Failed to Set N1 Mode", ar.exception);
                    // Set failed, so we have no idea at this point.
                    mModemN1Mode = null;
                }
                if (ar != null && ar.userObj instanceof Message) {
                    // original requester's message is stashed in the userObj
                    final Message rsp = (Message) ar.userObj;
                    AsyncResult.forMessage(rsp, null, ar.exception);
                    rsp.sendToTarget();
                }
                break;
            default:
                super.handleMessage(msg);
        }
+18 −5
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ import com.android.internal.telephony.domainselection.DomainSelectionResolver;
import com.android.internal.telephony.emergency.EmergencyConstants;
import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import com.android.internal.telephony.emergency.EmergencyStateTracker;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.imsphone.ImsCallInfo;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.imsphone.ImsPhoneCall;
@@ -251,8 +252,10 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    protected static final int EVENT_SET_NULL_CIPHER_AND_INTEGRITY_DONE = 66;
    protected static final int EVENT_GET_DEVICE_IMEI_DONE = 67;
    protected static final int EVENT_TRIGGER_NOTIFY_ANBR = 68;
    protected static final int EVENT_GET_N1_MODE_ENABLED_DONE = 69;
    protected static final int EVENT_SET_N1_MODE_ENABLED_DONE = 70;

    protected static final int EVENT_LAST = EVENT_TRIGGER_NOTIFY_ANBR;
    protected static final int EVENT_LAST = EVENT_SET_N1_MODE_ENABLED_DONE;

    // For shared prefs.
    private static final String GSM_ROAMING_LIST_OVERRIDE_PREFIX = "gsm_roaming_list_";
@@ -283,6 +286,8 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
            "pref_null_cipher_and_integrity_enabled";
    private final TelephonyAdminReceiver m2gAdminUpdater;

    protected final FeatureFlags mFeatureFlags;

    /**
     * This method is invoked when the Phone exits Emergency Callback Mode.
     */
@@ -548,22 +553,25 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    /**
     * Constructs a Phone in normal (non-unit test) mode.
     *
     * @param name a name for this phone object
     * @param notifier An instance of DefaultPhoneNotifier,
     * @param context Context object from hosting application
     * unless unit testing.
     * @param ci is CommandsInterface
     * @param unitTestMode when true, prevents notifications
     * of state change events
     * @param featureFlags an instance of the FeatureFlags set
     */
    protected Phone(String name, PhoneNotifier notifier, Context context, CommandsInterface ci,
                    boolean unitTestMode) {
                    boolean unitTestMode, FeatureFlags featureFlags) {
        this(name, notifier, context, ci, unitTestMode, SubscriptionManager.DEFAULT_PHONE_INDEX,
                TelephonyComponentFactory.getInstance());
                TelephonyComponentFactory.getInstance(), featureFlags);
    }

    /**
     * Constructs a Phone in normal (non-unit test) mode.
     *
     * @param name a name for this phone object
     * @param notifier An instance of DefaultPhoneNotifier,
     * @param context Context object from hosting application
     * unless unit testing.
@@ -571,10 +579,13 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
     * @param unitTestMode when true, prevents notifications
     * of state change events
     * @param phoneId the phone-id of this phone.
     * @param telephonyComponentFactory a factory for injecting telephony components
     * @param featureFlags an instance of the FeatureFlags set
     */
    protected Phone(String name, PhoneNotifier notifier, Context context, CommandsInterface ci,
                    boolean unitTestMode, int phoneId,
                    TelephonyComponentFactory telephonyComponentFactory) {
                    TelephonyComponentFactory telephonyComponentFactory,
                    FeatureFlags featureFlags) {
        mPhoneId = phoneId;
        mName = name;
        mNotifier = notifier;
@@ -587,6 +598,8 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
                .makeAppSmsManager(context);
        mLocalLog = new LocalLog(64);

        mFeatureFlags = featureFlags;

        setUnitTestMode(unitTestMode);

        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
@@ -857,7 +870,7 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
                }
                break;
            default:
                throw new RuntimeException("unexpected event not handled");
                throw new RuntimeException("unexpected event not handled, msgId=" + msg.what);
        }
    }

+1 −1
Original line number Diff line number Diff line
@@ -455,7 +455,7 @@ public class PhoneFactory {
     * @return the {@code ImsPhone} object or null if the exception occured
     */
    public static Phone makeImsPhone(PhoneNotifier phoneNotifier, Phone defaultPhone) {
        return ImsPhoneFactory.makePhone(sContext, phoneNotifier, defaultPhone);
        return ImsPhoneFactory.makePhone(sContext, phoneNotifier, defaultPhone, sFeatureFlags);
    }

    /**
Loading