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

Commit deeff5ef authored by Jack Yu's avatar Jack Yu
Browse files

Added the prototype of DataConfigManager

Added the prototype of DataConfigManager. This
is not functional and not connected with other
telephony modules.

Bug: 196597630
Test: Build
Merged-In: I4950c6990f7c987d2665ba996e69242258bba20b
Change-Id: I4950c6990f7c987d2665ba996e69242258bba20b
parent 28f14d91
Loading
Loading
Loading
Loading
+222 −0
Original line number Diff line number Diff line
/*
 * Copyright 2021 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.data;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.RegistrantList;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.util.IndentingPrintWriter;

import com.android.internal.telephony.Phone;
import com.android.telephony.Rlog;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * DataConfigManager is the source of all data related configuration from carrier config and
 * resource overlay. DataConfigManager is created to reduce the excessive access to the
 * {@link CarrierConfigManager}. All the data config will be loaded once and store here.
 */
public class DataConfigManager extends Handler {
    private static final int EVENT_CARRIER_CONFIG_CHANGED = 1;

    private final Phone mPhone;
    private final String mLogTag;

    /** The registrants list for config update event. */
    private final RegistrantList mConfigUpdateRegistrants = new RegistrantList();

    private @NonNull final CarrierConfigManager mCarrierConfigManager;

    /** The network capability priority map */
    private final Map<Integer, Integer> mNetworkCapabilityPriorityMap = new ConcurrentHashMap<>();

    private @Nullable PersistableBundle mCarrierConfig = null;
    private @Nullable Resources mResources = null;

    /**
     * Constructor
     *
     * @param phone The phone instance.
     * @param looper The looper to be used by the handler. Currently the handler thread is the
     * phone process's main thread.
     */
    public DataConfigManager(@NonNull Phone phone, @NonNull Looper looper) {
        super(looper);
        mPhone = phone;
        mLogTag = "DCM-" + mPhone.getPhoneId();

        mCarrierConfigManager = mPhone.getContext().getSystemService(CarrierConfigManager.class);

        IntentFilter filter = new IntentFilter();
        filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        mPhone.getContext().registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
                    if (mPhone.getPhoneId() == intent.getIntExtra(
                            CarrierConfigManager.EXTRA_SLOT_INDEX,
                            SubscriptionManager.INVALID_SIM_SLOT_INDEX)) {
                        sendEmptyMessage(EVENT_CARRIER_CONFIG_CHANGED);
                    }
                }
            }
        }, filter, null, mPhone);

        if (mCarrierConfigManager != null) {
            mCarrierConfig = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId());
        }
        mResources = SubscriptionManager.getResourcesForSubId(mPhone.getContext(),
                mPhone.getSubId());
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case EVENT_CARRIER_CONFIG_CHANGED:
                updateConfig();
                break;
            default:
                loge("Unexpected message " + msg.what);
        }
    }

    /**
     * Update the configuration.
     */
    private void updateConfig() {
        if (mCarrierConfigManager != null) {
            mCarrierConfig = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId());
        }
        mResources = SubscriptionManager.getResourcesForSubId(mPhone.getContext(),
                mPhone.getSubId());
        updateNetworkCapabilityPriority();
        log("Data config updated.");

        mConfigUpdateRegistrants.notifyRegistrants();
    }

    /**
     * Update the network capability priority from carrier config.
     */
    private void updateNetworkCapabilityPriority() {
        String[] capabilityPriorityStrings = mCarrierConfig.getStringArray(
                // TODO: Add carrier config manager change
                ""/*CarrierConfigManager.KEY_NETWORK_CAPABILITY_PRIORITY_STRING_ARRAY*/);
        if (capabilityPriorityStrings != null) {
            for (String capabilityPriorityString : capabilityPriorityStrings) {
                capabilityPriorityString = capabilityPriorityString.trim().toUpperCase();
                String[] tokens = capabilityPriorityString.split(":");
                if (tokens.length != 2) {
                    loge("Invalid config \"" + capabilityPriorityString + "\"");
                    continue;
                }

                int netCap = DataUtils.getNetworkCapabilityFromString(tokens[0]);
                if (netCap < 0) {
                    loge("Invalid config \"" + capabilityPriorityString + "\"");
                    continue;
                }

                int priority = Integer.parseInt(tokens[1]);
                mNetworkCapabilityPriorityMap.put(netCap, priority);
            }
        }
    }

    /**
     * Get the priority of a network capability.
     *
     * @param capability The network capability
     * @return The priority range from 0 ~ 100. 100 is the highest priority.
     */
    public int getNetworkCapabilityPriority(int capability) {
        if (mNetworkCapabilityPriorityMap.containsKey(capability)) {
            return mNetworkCapabilityPriorityMap.get(capability);
        }
        return 0;
    }

    /**
     * Registration point for subscription info ready
     *
     * @param h handler to notify
     * @param what what code of message when delivered
     */
    public void registerForConfigUpdate(Handler h, int what) {
        mConfigUpdateRegistrants.addUnique(h, what, null);
    }

    /**
     *
     * @param h The original handler passed in {@link #registerForConfigUpdate(Handler, int)}.
     */
    public void unregisterForConfigUpdate(Handler h) {
        mConfigUpdateRegistrants.remove(h);
    }

    /**
     * Log debug messages.
     * @param s debug messages
     */
    private void log(@NonNull String s) {
        Rlog.d(mLogTag, s);
    }

    /**
     * Log error messages.
     * @param s error messages
     */
    private void loge(@NonNull String s) {
        Rlog.e(mLogTag, s);
    }

    /**
     * Dump the state of DataConfigManager
     *
     * @param fd File descriptor
     * @param printwriter Print writer
     * @param args Arguments
     */
    public void dump(FileDescriptor fd, PrintWriter printwriter, String[] args) {
        IndentingPrintWriter pw = new IndentingPrintWriter(printwriter, "  ");
        pw.println("DataConfigManager-" + mPhone.getPhoneId() + ":");
        pw.increaseIndent();
        pw.println("Network capability priority:");
        pw.increaseIndent();
        for (Map.Entry<Integer, Integer> entry : mNetworkCapabilityPriorityMap.entrySet()) {
            pw.println(DataUtils.networkCapabilityToString(entry.getKey()) + ": "
                    + entry.getValue());
        }
        pw.decreaseIndent();
        pw.decreaseIndent();
    }
}
+101 −0
Original line number Diff line number Diff line
/*
 * Copyright 2021 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.data;

import android.annotation.NonNull;
import android.net.NetworkCapabilities;

/**
 * This class contains all the utility methods used by telephony data stack.
 */
public class DataUtils {
    /**
     * Get the network capability from the string.
     *
     * @param capabilityString The capability in string format
     * @return The network capability.
     */
    public static int getNetworkCapabilityFromString(@NonNull String capabilityString) {
        switch (capabilityString) {
            case "MMS": return NetworkCapabilities.NET_CAPABILITY_MMS;
            case "SUPL": return NetworkCapabilities.NET_CAPABILITY_SUPL;
            case "DUN": return NetworkCapabilities.NET_CAPABILITY_DUN;
            case "FOTA": return NetworkCapabilities.NET_CAPABILITY_FOTA;
            case "IMS": return NetworkCapabilities.NET_CAPABILITY_IMS;
            case "CBS": return NetworkCapabilities.NET_CAPABILITY_CBS;
            case "XCAP": return NetworkCapabilities.NET_CAPABILITY_XCAP;
            case "EIMS": return NetworkCapabilities.NET_CAPABILITY_EIMS;
            case "INTERNET": return NetworkCapabilities.NET_CAPABILITY_INTERNET;
            case "MCX": return NetworkCapabilities.NET_CAPABILITY_MCX;
            case "ENTERPRISE": return NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
            // Only add APN type capabilities here. This should be only used by the priority
            // configuration.
            default:
                return -1;
        }
    }

    /**
     * Convert capabilities to string.
     *
     * This is for debugging and logging purposes only.
     *
     * @param netCap Network capability
     * @return Network capability in string format
     */
    public static String networkCapabilityToString(int netCap) {
        switch (netCap) {
            case NetworkCapabilities.NET_CAPABILITY_MMS:                  return "MMS";
            case NetworkCapabilities.NET_CAPABILITY_SUPL:                 return "SUPL";
            case NetworkCapabilities.NET_CAPABILITY_DUN:                  return "DUN";
            case NetworkCapabilities.NET_CAPABILITY_FOTA:                 return "FOTA";
            case NetworkCapabilities.NET_CAPABILITY_IMS:                  return "IMS";
            case NetworkCapabilities.NET_CAPABILITY_CBS:                  return "CBS";
            case NetworkCapabilities.NET_CAPABILITY_WIFI_P2P:             return "WIFI_P2P";
            case NetworkCapabilities.NET_CAPABILITY_IA:                   return "IA";
            case NetworkCapabilities.NET_CAPABILITY_RCS:                  return "RCS";
            case NetworkCapabilities.NET_CAPABILITY_XCAP:                 return "XCAP";
            case NetworkCapabilities.NET_CAPABILITY_EIMS:                 return "EIMS";
            case NetworkCapabilities.NET_CAPABILITY_NOT_METERED:          return "NOT_METERED";
            case NetworkCapabilities.NET_CAPABILITY_INTERNET:             return "INTERNET";
            case NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED:       return "NOT_RESTRICTED";
            case NetworkCapabilities.NET_CAPABILITY_TRUSTED:              return "TRUSTED";
            case NetworkCapabilities.NET_CAPABILITY_NOT_VPN:              return "NOT_VPN";
            case NetworkCapabilities.NET_CAPABILITY_VALIDATED:            return "VALIDATED";
            case NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL:       return "CAPTIVE_PORTAL";
            case NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING:          return "NOT_ROAMING";
            case NetworkCapabilities.NET_CAPABILITY_FOREGROUND:           return "FOREGROUND";
            case NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED:        return "NOT_CONGESTED";
            case NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED:        return "NOT_SUSPENDED";
            case NetworkCapabilities.NET_CAPABILITY_OEM_PAID:             return "OEM_PAID";
            case NetworkCapabilities.NET_CAPABILITY_MCX:                  return "MCX";
            case NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY:
                return "PARTIAL_CONNECTIVITY";
            case NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED:
                return "TEMPORARILY_NOT_METERED";
            case NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE:          return "OEM_PRIVATE";
            case NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL:     return "VEHICLE_INTERNAL";
            case NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED:      return "NOT_VCN_MANAGED";
            case NetworkCapabilities.NET_CAPABILITY_ENTERPRISE:           return "ENTERPRISE";
            case NetworkCapabilities.NET_CAPABILITY_VSIM:                 return "VSIM";
            case NetworkCapabilities.NET_CAPABILITY_BIP:                  return "BIP";
            case NetworkCapabilities.NET_CAPABILITY_HEAD_UNIT:            return "HEAD_UNIT";
            default:
                return "Unknown(" + Integer.toString(netCap) + ")";
        }
    }
}