Adding LTE in AOSP preferred network settings panel

Ever wondered why you do not find LTE in your AOSP preferred network settings panel even if you are using an LTE modem? Go ahead reading to find a possible solution…

AOSP preferred network

Native RIL library presents a way for telling the platform which capabilities are supported by the modem:

/**
 * RIL_REQUEST_GET_RADIO_CAPABILITY
 *
 * Used to get phone radio capablility.
 *
 * "data" is the RIL_RadioCapability structure
 *
 */

RIL_RadioCapability is a structure that amongs its field has

int rat; // RIL_RadioAccessFamily for the radio

rat should be set to a combination of the technologies supported by the radio among the following values:

typedef enum {
    RAF_UNKNOWN = (1 << RADIO_TECH_UNKNOWN),
    RAF_GPRS = (1 << RADIO_TECH_GPRS),
    RAF_EDGE = (1 << RADIO_TECH_EDGE),
    RAF_UMTS = (1 << RADIO_TECH_UMTS),
    RAF_IS95A = (1 << RADIO_TECH_IS95A),
    RAF_IS95B = (1 << RADIO_TECH_IS95B),
    RAF_1xRTT = (1 << RADIO_TECH_1xRTT),
    RAF_EVDO_0 = (1 << RADIO_TECH_EVDO_0),
    RAF_EVDO_A = (1 << RADIO_TECH_EVDO_A),
    RAF_HSDPA = (1 << RADIO_TECH_HSDPA),
    RAF_HSUPA = (1 << RADIO_TECH_HSUPA),
    RAF_HSPA = (1 << RADIO_TECH_HSPA),
    RAF_EVDO_B = (1 << RADIO_TECH_EVDO_B),
    RAF_EHRPD = (1 << RADIO_TECH_EHRPD),
    RAF_LTE = (1 << RADIO_TECH_LTE),
    RAF_HSPAP = (1 << RADIO_TECH_HSPAP),
    RAF_GSM = (1 << RADIO_TECH_GSM),
    RAF_TD_SCDMA = (1 << RADIO_TECH_TD_SCDMA),
    RAF_LTE_CA = (1 << RADIO_TECH_LTE_CA)
} RIL_RadioAccessFamily;

So one could expect that adding a 4G technology (like RAF_LTE) would do the trick. Unfortunately it does not happen in standard AOSP. Time to dig into the code…

AOSP preferred network settings panel

The first thing is to identify which is the part of code in charge of managing the preferred network setting. As an example I’m taking the code coming from latest nougat release in AOSP.

Grepping for PREFERED_NETWORK in the AOSP tree the most promising result looks like

packages/services/Telephony/src/com/android/phone/MobileNetworkSettings.java

and this is confirmed by the initial comment:

/**
 * "Mobile network settings" screen. This preference screen lets you
 * enable/disable mobile data, and control data roaming and other
 * network-specific mobile data features. It's used on non-voice-capable
 * tablets as well as regular phone devices.
 */

The building of the GUI is mainly done in the method updateBody and we are interested to the part in which the preferred network choices are created for a GSM phone.

Taking a look at the code it seems that the boolean R.bool.config_enabled_lte seems involved in our initial question: when true lte modes are shown, otherwise they are not.

Grepping for config_enabled_lte in the Telephony service directory returns, among the other items, an xml configuration file:

res/values/config.xml

that holds the following lines

<!-- Show enabled lte option for lte device -->
<bool name="config_enabled_lte" translatable="false">false</bool>

Ok, that’s probably what we were looking for. We’re almost done: instead of changing the value here, it is suggested to add an overlay file in your device directory (if missing), something like

device/<your device directory>/overlay/packages/services/Telephony/res/values/config.xml

e.g. for the hikey

device/linaro/hikey/overlay/packages/services/Telephony/res/values/config.xml

The file should the boolean found above, e.g.:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Show enabled lte option for lte device -->
<bool name="config_enabled_lte" translatable="false">true</bool>
</resources>

Rebuild the platform and you should be able to see the desired prefered network choice.

More AOSP preferred network choices

So it seems that the prefered network choices are not dinamically found according to the information sent by the modem and that’s weird, since it would be easy from a technichal point of view to add this kind of feature.

A possible explanation is that this is used by carriers as a “software block” when using the same hardware in different regions: the modem hardware and firmware stay untouched, but the Android device shows only part of its potential capabilities.

Taking a look again at the way in which the preferred network list is created we can find that there are used some predefined arrays defined in

packages/services/Telephony/res/values/strings.xml

like enabled_networks_4g_choices and enabled_networks_values

I did not try yet, but it should be possible to customize them in order to show all the needed AOSP preferred network values available in

hardware/ril/include/telephony/ril.h
typedef enum {
    PREF_NET_TYPE_GSM_WCDMA = 0, /* GSM/WCDMA (WCDMA preferred) */
    PREF_NET_TYPE_GSM_ONLY = 1, /* GSM only */
    PREF_NET_TYPE_WCDMA = 2, /* WCDMA */
    PREF_NET_TYPE_GSM_WCDMA_AUTO = 3, /* GSM/WCDMA (auto mode, according to PRL) */
    PREF_NET_TYPE_CDMA_EVDO_AUTO = 4, /* CDMA and EvDo (auto mode, according to PRL) */
    PREF_NET_TYPE_CDMA_ONLY = 5, /* CDMA only */
    PREF_NET_TYPE_EVDO_ONLY = 6, /* EvDo only */
    PREF_NET_TYPE_GSM_WCDMA_CDMA_EVDO_AUTO = 7, /* GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL) */
    PREF_NET_TYPE_LTE_CDMA_EVDO = 8, /* LTE, CDMA and EvDo */
    PREF_NET_TYPE_LTE_GSM_WCDMA = 9, /* LTE, GSM/WCDMA */
    PREF_NET_TYPE_LTE_CMDA_EVDO_GSM_WCDMA = 10, /* LTE, CDMA, EvDo, GSM/WCDMA */
    PREF_NET_TYPE_LTE_ONLY = 11, /* LTE only */
    PREF_NET_TYPE_LTE_WCDMA = 12 /* LTE/WCDMA */
} RIL_PreferredNetworkType;