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

Commit 55afb1d4 authored by Pengquan Meng's avatar Pengquan Meng Committed by Android (Google) Code Review
Browse files

Merge "Refactor CDNR" into qt-dev

parents f672b36e 87fabd67
Loading
Loading
Loading
Loading
+0 −323
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.LocalLog;
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 com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;

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 final LocalLog mLocalLog;

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

    /** {@code True} if any item is changed after the previous carrier name resolved. */
    private boolean mItemChanged;

    /**
     * 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_ERI,
                    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(LocalLog localLog) {
        mLocalLog = localLog;
        int key = getSourcePriority(EF_SOURCE_DEFAULT);
        mServiceProviderNames.put(key, "");
        mSpdi.put(key, Collections.EMPTY_LIST);
        mCarrierNameDisplayConditionRules.put(key,
                new CarrierDisplayNameConditionRule(
                        DEFAULT_CARRIER_NAME_DISPLAY_CONDITION_BITMASK));
        mPlmnNetworkNames.put(key, Collections.EMPTY_LIST);
        mOperatorPlmns.put(key, Collections.EMPTY_LIST);
        mEhplmns.put(key, Collections.EMPTY_LIST);
    }

    @Override
    public void updateServiceProviderName(@EFSource int source, String spn) {
        if (TextUtils.isEmpty(spn)) return;
        mServiceProviderNames.put(getSourcePriority(source), spn);
        mItemChanged = true;
    }

    @Override
    public void updateServiceProviderDisplayInformation(
            @EFSource int source, @NonNull List<String> spdi) {
        if (ArrayUtils.isEmpty(spdi)) return;
        mSpdi.put(getSourcePriority(source), spdi);
        mItemChanged = true;
    }

    @Override
    public void updateServiceProviderNameDisplayCondition(
            @EFSource int source, @CarrierNameDisplayConditionBitmask int condition) {
        if (condition == IccRecords.INVALID_CARRIER_NAME_DISPLAY_CONDITION_BITMASK) return;
        mCarrierNameDisplayConditionRules.put(getSourcePriority(source),
                new CarrierDisplayNameConditionRule(condition));
        mItemChanged = true;
    }

    @Override
    public void updatePlmnNetworkNameList(
            @EFSource int source, @NonNull List<PlmnNetworkName> pnnList) {
        if (ArrayUtils.isEmpty(pnnList)) return;
        mPlmnNetworkNames.put(getSourcePriority(source), pnnList);
        mItemChanged = true;
    }

    @Override
    public void updateEhplmnList(@EFSource int source, @NonNull List<String> ehplmns) {
        if (ArrayUtils.isEmpty(ehplmns)) return;
        mEhplmns.put(getSourcePriority(source), ehplmns);
        mItemChanged = true;
    }

    @Override
    public void updateServiceState(@NonNull ServiceState serviceState) {
        mServiceState = serviceState;
        mItemChanged = true;
    }

    @Override
    public void updateOperatorPlmnList(@EFSource int source, @NonNull List<OperatorPlmnInfo> opl) {
        if (ArrayUtils.isEmpty(opl)) return;
        mOperatorPlmns.put(getSourcePriority(source), opl);
        mItemChanged = true;
    }

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

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

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

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

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

    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.
        // All the PLMNs will be considered HOME PLMNs if there is a brand override.
        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;
        }

        String logInfo = "isRoaming = " + isRoaming
                + " ,registeredPLMN = " + registeredPlmnNumeric
                + " ,displayRule = " + displayRule
                + " ,shouldShowPlmn = " + mShouldShowPlmnNetworkName
                + " ,plmn = " + mPlmnNetworkName
                + " ,shouldShowSpn = " + mShouldShowServiceProviderName
                + " ,spn = " + mServiceProviderName;
        if (DBG) Rlog.d(TAG, logInfo);
        mLocalLog.log(logInfo);

        mItemChanged = false;
    }

    @Override
    public String toString() {
        Boolean roamingFromSS = mServiceState != null ? mServiceState.getRoaming() : null;
        String registeredPLMN = mServiceState != null ? mServiceState.getOperatorNumeric() : null;
        return " { spnDisplayCondition = " + mCarrierNameDisplayConditionRules
                + " ,roamingFromSS = " + roamingFromSS
                + " ,registeredPLMN = " + registeredPLMN
                + " ,homePLMN = " + mHomePlmn
                + " ,spnList = " + mServiceProviderNames
                + " ,spnCondition " + mCarrierNameDisplayConditionRules
                + " ,spdiList = " + mSpdi
                + " ,pnnList = " + mPlmnNetworkNames
                + " ,oplList = " + mOperatorPlmns
                + " ,ehplmn = " + mEhplmns
                + " }";
    }

    /**
     * Dumps information for carrier display name resolver.
     * @param pw information printer.
     */
    public void dump(IndentingPrintWriter pw) {
        pw.println("CDNRImpl");
        pw.increaseIndent();
        pw.println("fields = " + toString());
        pw.println("shouldShowPlmn = " + mShouldShowPlmnNetworkName);
        pw.println("plmn= " + mPlmnNetworkName);
        pw.println("showShowSpn = " + mShouldShowServiceProviderName);
        pw.println("spn = " + mServiceProviderName);
        pw.decreaseIndent();
    }

    /**
     * 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);
        }
    }
}
+85 −363

File changed.

Preview size limit exceeded, changes collapsed.

+48 −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.cdnr;

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

/** EF data from brand override. */
public final class BrandOverrideEfData implements EfData {
    private final String mSpn;
    private final String mRegisteredPlmn;

    public BrandOverrideEfData(String operatorName, String registeredPlmn) {
        mSpn = operatorName;
        mRegisteredPlmn = registeredPlmn;
    }

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

    @Override
    public int getServiceProviderNameDisplayCondition() {
        // No SPN in roaming network, no PLMN in home network
        return 0;
    }

    @Override
    public List<String> getServiceProviderDisplayInformation() {
        // Registered PLMN should be regarded as HOME PLMN
        return Arrays.asList(mRegisteredPlmn);
    }
}
+115 −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.cdnr;

import android.annotation.NonNull;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.Rlog;
import android.text.TextUtils;

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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/** Ef data from carrier config. */
public final class CarrierConfigEfData implements EfData {
    private static final String TAG = "CarrierConfigEfData";
    private final PersistableBundle mConfig;

    public CarrierConfigEfData(@NonNull PersistableBundle config) {
        mConfig = config;
    }

    @Override
    public String getServiceProviderName() {
        String spn = mConfig.getString(CarrierConfigManager.KEY_CARRIER_NAME_STRING);
        if (TextUtils.isEmpty(spn)) return null;
        return spn;
    }

    @Override
    public int getServiceProviderNameDisplayCondition() {
        int condition = mConfig.getInt(
                CarrierConfigManager.KEY_SPN_DISPLAY_CONDITION_OVERRIDE_INT,
                IccRecords.INVALID_CARRIER_NAME_DISPLAY_CONDITION_BITMASK);
        return condition;
    }

    @Override
    public List<String> getServiceProviderDisplayInformation() {
        String[] spdi = mConfig.getStringArray(
                CarrierConfigManager.KEY_SPDI_OVERRIDE_STRING_ARRAY);
        return spdi != null ? Arrays.asList(spdi) : null;
    }

    @Override
    public List<String> getEhplmnList() {
        String[] ehplmn = mConfig.getStringArray(
                CarrierConfigManager.KEY_EHPLMN_OVERRIDE_STRING_ARRAY);
        return ehplmn != null ? Arrays.asList(ehplmn) : null;
    }

    @Override
    public List<PlmnNetworkName> getPlmnNetworkNameList() {
        String[] pnn = mConfig.getStringArray(
                CarrierConfigManager.KEY_PNN_OVERRIDE_STRING_ARRAY);
        List<PlmnNetworkName> pnnList = null;
        if (pnn != null) {
            pnnList = new ArrayList<>(pnn.length);
            for (String pnnStr : pnn) {
                try {
                    String[] names = pnnStr.split("\\s*,\\s*");
                    String alphal = names[0];
                    String alphas = names.length > 1 ? names[1] : "";
                    pnnList.add(new PlmnNetworkName(alphal, alphas));
                } catch (Exception ex) {
                    Rlog.e(TAG, "CarrierConfig wrong pnn format, pnnStr = " + pnnStr);
                }
            }
        }
        return pnnList;
    }

    @Override
    public List<OperatorPlmnInfo> getOperatorPlmnList() {
        // OPL
        String[] opl = mConfig.getStringArray(
                CarrierConfigManager.KEY_OPL_OVERRIDE_STRING_ARRAY);
        List<OperatorPlmnInfo> oplList = null;
        if (opl != null) {
            oplList = new ArrayList<>(opl.length);
            for (String oplStr : opl) {
                try {
                    String[] info = oplStr.split("\\s*,\\s*");
                    oplList.add(new OperatorPlmnInfo(
                            info[0] /* plmn */,
                            Integer.parseInt(info[1]) /* lactac_start */,
                            Integer.parseInt(info[2]) /* lactac_end */,
                            Integer.parseInt(info[3]) /* pnn index */));
                } catch (Exception ex) {
                    Rlog.e(TAG, "CarrierConfig wrong opl format, oplStr = " + oplStr);
                }
            }
        }
        return oplList;
    }
}
+201 −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.cdnr;

import android.os.Parcel;
import android.os.Parcelable;

import java.util.Objects;

/**
 * A container of carrier display name.
 */
public class CarrierDisplayNameData implements Parcelable {
    /** Service provider name. */
    private final String mSpn;

    /** Data service provider name. */
    private final String mDataSpn;

    /** PLMN network name */
    private final String mPlmn;

    /** {@code True} if display service provider name is required. */
    private final boolean mShowSpn;

    /** {@code True} if display PLMN network name is required. */
    private final boolean mShowPlmn;

    private CarrierDisplayNameData(String spn, String dataSpn, boolean showSpn, String plmn,
            boolean showPlmn) {
        this.mSpn = spn;
        this.mDataSpn = dataSpn;
        this.mShowSpn = showSpn;
        this.mPlmn = plmn;
        this.mShowPlmn = showPlmn;
    }

    /**
     * Get the service provider name.
     * @return service provider name.
     */
    public String getSpn() {
        return mSpn;
    }

    /**
     * Get the service provider name of data provider.
     * @return service provider name of data provider.
     */
    public String getDataSpn() {
        return mDataSpn;
    }

    /**
     * Get the PLMN network name.
     * @return PLMN network name.
     */
    public String getPlmn() {
        return mPlmn;
    }

    /**
     * Whether the spn should be displayed.
     * @return
     */
    public boolean shouldShowSpn() {
        return mShowSpn;
    }

    /**
     * Whether the PLMN should be displayed.
     * @return
     */
    public boolean shouldShowPlmn() {
        return mShowPlmn;
    }

    @Override
    public String toString() {
        return String.format("{ spn = %s, dataSpn = %s, showSpn = %b, plmn = %s, showPlmn = %b",
                mSpn, mDataSpn, mShowSpn, mPlmn, mShowPlmn);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mSpn);
        dest.writeString(mDataSpn);
        dest.writeString(mPlmn);
        dest.writeBoolean(mShowSpn);
        dest.writeBoolean(mShowPlmn);
    }

    private CarrierDisplayNameData(Parcel source) {
        mSpn = source.readString();
        mDataSpn = source.readString();
        mPlmn = source.readString();
        mShowSpn = source.readBoolean();
        mShowPlmn = source.readBoolean();
    }

    public static final Parcelable.Creator<CarrierDisplayNameData> CREATOR =
            new Creator<CarrierDisplayNameData>() {
                @Override
                public CarrierDisplayNameData createFromParcel(Parcel source) {
                    return new CarrierDisplayNameData(source);
                }

                @Override
                public CarrierDisplayNameData[] newArray(int size) {
                    return new CarrierDisplayNameData[size];
                }
            };

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CarrierDisplayNameData that = (CarrierDisplayNameData) o;
        return mShowSpn == that.mShowSpn
                && mShowPlmn == that.mShowPlmn
                && Objects.equals(mSpn, that.mSpn)
                && Objects.equals(mDataSpn, that.mDataSpn)
                && Objects.equals(mPlmn, that.mPlmn);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mSpn, mDataSpn, mPlmn, mShowSpn, mShowPlmn);
    }

    /** Builder class for {@link com.android.internal.telephony.cdnr.CarrierDisplayNameData}. */
    public static final class Builder {
        private String mSpn;
        private String mDataSpn;
        private String mPlmn;
        private boolean mShowSpn;
        private boolean mShowPlmn;

        public Builder() {
            mSpn = null;
            mDataSpn = null;
            mPlmn = null;
            mShowPlmn = false;
            mShowSpn = false;
        }

        /** Create a {@link com.android.internal.telephony.cdnr.CarrierDisplayNameData} instance. */
        public CarrierDisplayNameData build() {
            return new CarrierDisplayNameData(mSpn, mDataSpn, mShowSpn, mPlmn, mShowPlmn);
        }

        /** Set service provider name. */
        public Builder setSpn(String spn) {
            mSpn = spn;
            return this;
        }

        /** Set data service provider name. */
        public Builder setDataSpn(String dataSpn) {
            mDataSpn = dataSpn;
            return this;
        }

        /** Set PLMN network name. */
        public Builder setPlmn(String plmn) {
            mPlmn = plmn;
            return this;
        }

        /** Set whether the service provider name should be displayed. */
        public Builder setShowSpn(boolean showSpn) {
            mShowSpn = showSpn;
            return this;
        }

        /** Set whether the PLMN network name should be displayed. */
        public Builder setShowPlmn(boolean showPlmn) {
            mShowPlmn = showPlmn;
            return this;
        }
    }
}
Loading