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

Commit f131d5e5 authored by Pengquan Meng's avatar Pengquan Meng
Browse files

Add Carrier Display Name Resolver

Add CarrierDisplayNameResolver interface and its implementation.
CarrierDisplayNameResolver get the EF objects from various source
and use an unified rule to generate the service provider name & PLMN network name.

Bug: 122921456
Test: atest CarrierDisplayNameResolver.java
Merged-In: If46dc6c9c3172ff9e532a8b0e55dd941bca6857d
Change-Id: If46dc6c9c3172ff9e532a8b0e55dd941bca6857d
(cherry picked from commit c38b1903)
parent f6c61098
Loading
Loading
Loading
Loading
+174 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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 com.android.internal.telephony;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.telephony.ServiceState;

import com.android.internal.telephony.uicc.IccRecords.CarrierNameDisplayConditionBitmask;
import com.android.internal.telephony.uicc.IccRecords.OperatorPlmnInfo;
import com.android.internal.telephony.uicc.IccRecords.PlmnNetworkName;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;

/** Interface for carrier display name resolver. */
public interface CarrierDisplayNameResolver {
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = {"EF_SOURCE_"}, value = {
            EF_SOURCE_CARRIER_API,
            EF_SOURCE_CARRIER_CONFIG,
            EF_SOURCE_USIM,
            EF_SOURCE_SIM,
            EF_SOURCE_CSIM,
            EF_SOURCE_RUIM,
            EF_SOURCE_VOICE_OPERATOR_SIGNALLING,
            EF_SOURCE_DATA_OPERATOR_SIGNALLING,
            EF_SOURCE_MODEM_CONFIG})
    @interface EFSource {}

    int EF_SOURCE_DEFAULT = 0;
    int EF_SOURCE_CARRIER_CONFIG = 1;
    int EF_SOURCE_CARRIER_API = 2;
    int EF_SOURCE_USIM = 3;
    int EF_SOURCE_SIM = 4;
    int EF_SOURCE_CSIM = 5;
    int EF_SOURCE_RUIM = 6;
    int EF_SOURCE_VOICE_OPERATOR_SIGNALLING = 7;
    int EF_SOURCE_DATA_OPERATOR_SIGNALLING = 8;
    int EF_SOURCE_MODEM_CONFIG = 9;

    /**
     * Update the service provider name for the registered PLMN.
     *
     * Reference: 3GPP TS 131.102 Section 4.2.12 EF_SPN.
     *
     * @param source the source of where the service provider name come from.
     * @param spn the service provider name for the registered PLMN.
     */
    void updateServiceProviderName(@EFSource int source, @NonNull String spn);

    /**
     * Update the display condition of service provider name and PLMN network name. The display
     * condition has two bits(lsb). Service provider name display is required if the first bit
     * is set to 1. PLMN network name display is required if the second bit is set to 1.
     *
     * @see {@link IccRecords#CARRIER_NAME_DISPLAY_CONDITION_BITMASK_PLMN}
     * @see {@link IccRecords#CARRIER_NAME_DISPLAY_CONDITION_BITMASK_SPN}
     *
     * Reference: 3GPP TS 131.102 Section 4.2.12 EF_SPN
     *
     * @param source where the spn display condition come from.
     * @param spnDisplayCondition the spn display condition.
     */
    void updateServiceProviderNameDisplayCondition(
            @EFSource int source,
            @CarrierNameDisplayConditionBitmask int spnDisplayCondition);

    /**
     * Update the service provider display information. This is a list of PLMNs in which the
     * service provider name shall be displayed.
     *
     * Reference: 3GPP TS 131.102 Section 4.2.66 EF_SPDI
     *
     * @param source the source of where the service provider display information come from.
     * @param spdi a list of numeric version PLMNs.
     */
    void updateServiceProviderDisplayInformation(
            @EFSource int source, @NonNull List<String> spdi);

    /**
     * Update a list of full and short form versions of the network name for the registered
     * PLMN.
     *
     * Reference: 3GPP TS 131.102 Section 4.2.58 EF_PNN.
     *
     * @param source the source of where the PLMN network name come from.
     * @param pnnList a list of full name and short name of PLMN network name.
     */
    void updatePlmnNetworkNameList(
            @EFSource int source, @NonNull List<PlmnNetworkName> pnnList);

    /**
     * Update the equivalent HPLMN list.
     *
     * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.84 EF_EHPLMN
     * Reference: 3GPP TS 23.122 v15.6.0 Section 1.2 Equivalent HPLMN list
     *
     * @param source the source of where the ehplmn come from.
     * @param ehplmns a string list contains the equivalent HPLMN.
     */
    void updateEhplmnList(@EFSource int source, @NonNull List<String> ehplmns);

    /**
     * Update a list of operator PLMN information.
     *
     * Reference: 3GPP TS 131.102 Section 4.2.59 EF_OPL.
     *
     * @param source the source of where the OPL information come from.
     * @param oplList a list of operator PLMN information.
     */
    void updateOperatorPlmnList(
            @EFSource int source, @NonNull List<OperatorPlmnInfo> oplList);

    /**
     * Update service state.
     * @param serviceState service state.
     */
    void updateServiceState(@NonNull ServiceState serviceState);

    /**
     * Update the numeric version name of home PLMN.
     * @param homePlmnNumeric numeric version name of home PLMN.
     */
    void updateHomePlmnNumeric(@NonNull String homePlmnNumeric);

    /**
     * Check if display PLMN network name is required.
     *
     * @return {@code True} if display PLMN network name is required.
     */
    boolean shouldShowPlmnNetworkName();

    /**
     * Check if display service provider name is required.
     *
     * @return {@code True} if display service provider name is required.
     */
    boolean shouldShowServiceProviderName();

    /**
     * Get the plmn network name of the current registered PLMN.
     *
     * @return the full version name if is present, or return the short version name if it's
     * present and the full one is not present. If neither full name nor short name is present,
     * the numeric version name will be returned.
     */
    @NonNull
    String getPlmnNetworkName();

    /**
     * Get the service provider name of the current registered PLMN.
     *
     * @return the service provider name.
     */
    @NonNull
    String getServiceProviderName();
}
+273 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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 com.android.internal.telephony;

import android.annotation.NonNull;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.text.TextUtils;
import android.util.SparseArray;

import com.android.internal.telephony.uicc.IccRecords;
import com.android.internal.telephony.uicc.IccRecords.CarrierNameDisplayConditionBitmask;
import com.android.internal.telephony.uicc.IccRecords.OperatorPlmnInfo;
import com.android.internal.telephony.uicc.IccRecords.PlmnNetworkName;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Use EF filed from various source according to the priority to resolve the service provider name
 * and PLMN network name.
 */
public class CarrierDisplayNameResolverImpl implements CarrierDisplayNameResolver {
    private static final boolean DBG = true;
    private static final String TAG = "CDNRImpl";

    /**
     * Only display SPN in home network, and PLMN network name in roaming network.
     */
    @CarrierNameDisplayConditionBitmask
    private static final int DEFAULT_CARRIER_NAME_DISPLAY_CONDITION_BITMASK = 0;

    private final SparseArray<String> mServiceProviderNames = new SparseArray<>();
    private final SparseArray<List<String>> mSpdi = new SparseArray<>();
    private final SparseArray<CarrierDisplayNameConditionRule> mCarrierNameDisplayConditionRules =
            new SparseArray<>();
    private final SparseArray<List<PlmnNetworkName>> mPlmnNetworkNames = new SparseArray<>();
    private final SparseArray<List<OperatorPlmnInfo>> mOperatorPlmns = new SparseArray<>();
    private final SparseArray<List<String>> mEhplmns = new SparseArray<>();

    private ServiceState mServiceState;

    /**
     * The priority of ef source. Lower index means higher priority.
     *
     * {@link CarrierDisplayNameResolver#EF_SOURCE_DEFAULT} should always be the lowest priority
     * source.
     */
    private static final List<Integer> EF_SOURCE_PRIORITY =
            Arrays.asList(
                    EF_SOURCE_CARRIER_API,
                    EF_SOURCE_CARRIER_CONFIG,
                    EF_SOURCE_USIM,
                    EF_SOURCE_SIM,
                    EF_SOURCE_CSIM,
                    EF_SOURCE_RUIM,
                    EF_SOURCE_VOICE_OPERATOR_SIGNALLING,
                    EF_SOURCE_DATA_OPERATOR_SIGNALLING,
                    EF_SOURCE_MODEM_CONFIG,
                    EF_SOURCE_DEFAULT);

    public CarrierDisplayNameResolverImpl() {
        int defaultSourcePriority = getSourcePriority(EF_SOURCE_DEFAULT);
        mServiceProviderNames.put(defaultSourcePriority, "");
        mSpdi.put(defaultSourcePriority, Collections.EMPTY_LIST);
        mCarrierNameDisplayConditionRules.put(defaultSourcePriority,
                new CarrierDisplayNameConditionRule(
                        DEFAULT_CARRIER_NAME_DISPLAY_CONDITION_BITMASK));
        mPlmnNetworkNames.put(defaultSourcePriority, Collections.EMPTY_LIST);
        mOperatorPlmns.put(defaultSourcePriority, Collections.EMPTY_LIST);
        mEhplmns.put(defaultSourcePriority, Collections.EMPTY_LIST);
    }

    @Override
    public void updateServiceProviderName(@EFSource int source, @NonNull String spn) {
        mServiceProviderNames.put(getSourcePriority(source), spn);
        resolveCarrierDisplayName();
    }

    @Override
    public void updateServiceProviderDisplayInformation(
            @EFSource int source, @NonNull List<String> spdi) {
        mSpdi.put(getSourcePriority(source), spdi);
        resolveCarrierDisplayName();
    }

    @Override
    public void updateServiceProviderNameDisplayCondition(
            @EFSource int source, int condition) {
        mCarrierNameDisplayConditionRules.put(getSourcePriority(source),
                new CarrierDisplayNameConditionRule(condition));
        resolveCarrierDisplayName();
    }

    @Override
    public void updatePlmnNetworkNameList(
            @EFSource int source, @NonNull List<PlmnNetworkName> pnnList) {
        mPlmnNetworkNames.put(getSourcePriority(source), pnnList);
        resolveCarrierDisplayName();
    }

    @Override
    public void updateEhplmnList(@EFSource int source, List<String> ehplmns) {
        mEhplmns.put(getSourcePriority(source), ehplmns);
    }

    @Override
    public void updateServiceState(ServiceState serviceState) {
        mServiceState = serviceState;
        resolveCarrierDisplayName();
    }

    @Override
    public void updateOperatorPlmnList(
            @EFSource int source, @NonNull List<OperatorPlmnInfo> opl) {
        mOperatorPlmns.put(getSourcePriority(source), opl);
        resolveCarrierDisplayName();
    }

    @Override
    public void updateHomePlmnNumeric(@NonNull String homePlmnNumeric) {
        mHomePlmn = homePlmnNumeric;
        resolveCarrierDisplayName();
    }

    @Override
    public boolean shouldShowPlmnNetworkName() {
        return mShouldShowPlmnNetworkName;
    }

    @Override
    public boolean shouldShowServiceProviderName() {
        return mShouldShowServiceProviderName;
    }

    @Override
    public String getPlmnNetworkName() {
        return mPlmnNetworkName;
    }

    @Override
    public String getServiceProviderName() {
        return mServiceProviderName;
    }

    private boolean mShouldShowServiceProviderName;
    private boolean mShouldShowPlmnNetworkName;
    private String mServiceProviderName;
    private String mPlmnNetworkName;
    private String mHomePlmn;

    private void resolveCarrierDisplayName() {
        if (mServiceState == null) return;

        CarrierDisplayNameConditionRule displayRule =
                mCarrierNameDisplayConditionRules.valueAt(0);

        String registeredPlmnNumeric = mServiceState.getOperatorNumeric();
        List<String> efSpdi = mSpdi.valueAt(0);

        // Currently use the roaming state from ServiceState.
        // EF_SPDI is only used when determine the service provider name and PLMN network name
        // display condition rule.
        boolean isRoaming = mServiceState.getRoaming() && !efSpdi.contains(registeredPlmnNumeric);
        mShouldShowServiceProviderName = displayRule.shouldShowSpn(isRoaming);
        mShouldShowPlmnNetworkName = displayRule.shouldShowPnn(isRoaming);

        mServiceProviderName = mServiceProviderNames.valueAt(0);

        // Resolve the PLMN network name
        mPlmnNetworkName = "";
        List<OperatorPlmnInfo> efOpl = mOperatorPlmns.valueAt(0);
        List<PlmnNetworkName> efPnn = mPlmnNetworkNames.valueAt(0);

        if (efOpl.isEmpty()) {
            // If the EF_OPL is not present, then the first record in EF_PNN is used for the
            // default network name when registered in the HPLMN or an EHPLMN(if the EHPLMN list
            // is present).
            mPlmnNetworkName = efPnn.isEmpty() ? "" : getPlmnNetworkName(efPnn.get(0));
        } else {
            // TODO: Check the TAC/LAC & registered PLMN numeric in OPL list to determine which
            // PLMN name should be used to override the current one.
        }

        // If no PLMN override is present, then the PLMN should be displayed numerically.
        if (mPlmnNetworkName.isEmpty()) {
            mPlmnNetworkName = registeredPlmnNumeric;
        }

        if (DBG) {
            Rlog.d(TAG, "spnDisplayCondition = " + displayRule
                    + " ,isRoaming = " + isRoaming
                    + " ,registeredPLMN = " + registeredPlmnNumeric
                    + " ,homePLMN = " + mHomePlmn
                    + " ,spnList = " + mServiceProviderNames
                    + " ,spnCondition " + mCarrierNameDisplayConditionRules
                    + " ,spdiList = " + mSpdi
                    + " ,pnnList = " + mPlmnNetworkNames
                    + " ,oplList = " + mOperatorPlmns
                    + " ,ehplmn = " + mEhplmns);
        }
    }

    /**
     * Get the PLMN network name from the {@link PlmnNetworkName} object.
     * @param name the {@link PlmnNetworkName} object may contain the full and short version of PLMN
     * network name.
     * @return full/short version PLMN network name if one of those is existed, otherwise return an
     * empty string.
     */
    private static String getPlmnNetworkName(PlmnNetworkName name) {
        if (name == null) return "";
        if (!TextUtils.isEmpty(name.fullName)) return name.fullName;
        if (!TextUtils.isEmpty(name.shortName)) return name.shortName;
        return "";
    }

    /**
     * Get the priority of the source of ef object. If {@code source} is not in the priority list,
     * return {@link Integer#MAX_VALUE}.
     * @param source source of ef object.
     * @return the priority of the source of ef object.
     */
    private static int getSourcePriority(@EFSource int source) {
        int priority = EF_SOURCE_PRIORITY.indexOf(source);
        if (priority == -1) priority = Integer.MAX_VALUE;
        return priority;
    }

    private static final class CarrierDisplayNameConditionRule {
        private int mDisplayConditionBitmask;

        CarrierDisplayNameConditionRule(int carrierDisplayConditionBitmask) {
            mDisplayConditionBitmask = carrierDisplayConditionBitmask;
        }

        boolean shouldShowSpn(boolean isRoaming) {
            return !isRoaming || ((mDisplayConditionBitmask
                    & IccRecords.CARRIER_NAME_DISPLAY_CONDITION_BITMASK_SPN)
                    == IccRecords.CARRIER_NAME_DISPLAY_CONDITION_BITMASK_SPN);
        }

        boolean shouldShowPnn(boolean isRoaming) {
            return isRoaming || ((mDisplayConditionBitmask
                    & IccRecords.CARRIER_NAME_DISPLAY_CONDITION_BITMASK_PLMN)
                    == IccRecords.CARRIER_NAME_DISPLAY_CONDITION_BITMASK_PLMN);
        }

        @Override
        public String toString() {
            return String.format("{ SPN_bit = %d, PLMN_bit = %d }",
                    mDisplayConditionBitmask
                            & IccRecords.CARRIER_NAME_DISPLAY_CONDITION_BITMASK_SPN,
                    mDisplayConditionBitmask
                            & IccRecords.CARRIER_NAME_DISPLAY_CONDITION_BITMASK_PLMN);
        }
    }
}
+62 −5
Original line number Diff line number Diff line
@@ -162,6 +162,11 @@ public abstract class IccRecords extends Handler implements IccConstants {
    // Reference: 3GPP TS 31.102 Section 4.2.66
    protected String[] mSpdi;


    // Carrier name display condition bitmask
    // Reference: 3GPP TS 131.102 section 4.2.12 EF_SPN Display Condition
    protected int mCarrierNameDisplayCondition;

    protected String[] mEhplmns;
    protected String[] mFplmns;

@@ -193,10 +198,9 @@ public abstract class IccRecords extends Handler implements IccConstants {
    public static final int CARRIER_NAME_DISPLAY_CONDITION_BITMASK_PLMN = 1;
    public static final int CARRIER_NAME_DISPLAY_CONDITION_BITMASK_SPN = 2;

    // Display both SPN & PLMN regardless the roaming state.
    public static final int DEFAULT_CARRIER_NAME_DISPLAY_CONDITION =
            CARRIER_NAME_DISPLAY_CONDITION_BITMASK_PLMN
                    | CARRIER_NAME_DISPLAY_CONDITION_BITMASK_SPN;
    // Display SPN only and only if registered to Home PLMNs.
    // Display PLMN only and only if registered to Non-Home PLMNs.
    public static final int DEFAULT_CARRIER_NAME_DISPLAY_CONDITION = 0;

    // ***** Event Constants
    public static final int EVENT_MWI = 0; // Message Waiting indication
@@ -909,7 +913,9 @@ public abstract class IccRecords extends Handler implements IccConstants {
     * @return a bitmask represent the carrier name display condition.
     */
    @CarrierNameDisplayConditionBitmask
    public abstract int getCarrierNameDisplayCondition();
    public int getCarrierNameDisplayCondition() {
        return mCarrierNameDisplayCondition;
    }

    /**
     * Retrieves the service provider display information. This is a list of PLMNs in which the
@@ -1186,4 +1192,55 @@ public abstract class IccRecords extends Handler implements IccConstants {
        }
        pw.flush();
    }

    /**
     * Operator PLMN information. This contains the location area information or tracking area
     * that are used to associate a specific name contained in EF_PNN.
     *
     * Reference: 3GPP TS 31.102 section 4.2.59 EF_OPL
     */
    public static final class OperatorPlmnInfo {
        // PLMN numeric that may contains wildcard character ".".
        // For example, the pattern "123..." could match all PLMN which mcc is 123.
        public final String plmnNumericPattern;

        public final int lacTacStart;
        public final int lacTacEnd;

        public final int plmnNetworkNameIndex;
        public OperatorPlmnInfo(String plmnNumericPattern, int lacTacStart, int lacTacEnd,
                                int plmnNetworkNameIndex) {
            this.plmnNumericPattern = plmnNumericPattern;
            this.lacTacStart = lacTacStart;
            this.lacTacEnd = lacTacEnd;
            this.plmnNetworkNameIndex = plmnNetworkNameIndex;
        }

        @Override
        public String toString() {
            return "{ plmnNumericPattern = " + plmnNumericPattern
                    + "lacTacStart = " + lacTacStart
                    + "lacTacEnd = " + lacTacEnd
                    + "plmnNetworkNameIndex = " + plmnNetworkNameIndex
                    + " }";
        }
    }

    /**
     * Full and short version of PLMN network name.
     */
    public static final class PlmnNetworkName {
        public final String fullName;
        public final String shortName;

        public PlmnNetworkName(String fullName, String shortName) {
            this.fullName = fullName;
            this.shortName = shortName;
        }

        @Override
        public String toString() {
            return "{ fullName = " + fullName + " shortName = " + shortName + " }";
        }
    }
}
+0 −6
Original line number Diff line number Diff line
@@ -412,12 +412,6 @@ public class IsimUiccRecords extends IccRecords implements IsimRecords {
        return (mIsimPcscf != null) ? mIsimPcscf.clone() : null;
    }

    @Override
    public int getCarrierNameDisplayCondition() {
        // No display rule in Isim, return 0.
        return 0;
    }

    @Override
    public void onReady() {
        fetchIsimRecords();
+0 −6
Original line number Diff line number Diff line
@@ -897,12 +897,6 @@ public class RuimRecords extends IccRecords {
        // Further records that can be inserted are Operator/OEM dependent
    }

    @Override
    public int getCarrierNameDisplayCondition() {
        // No display rule in Ruim, return 0.
        return 0;
    }

    @Override
    public boolean isProvisioned() {
        // If UICC card has CSIM app, look for MDN and MIN field
Loading