How to get configured APN types from the APN Type Bitmask?


OVERVIEW : 

An Access Point Name (APN) provides a gateway to connect different carrier mobile networks (GSM, GPRS, 3G, 4G) to another computer network, which mostly is the public internet. Carrier reads APN Settings to generate an IP Address, connect to the secure gateway, determine if the private network is required, and more. 

Most of the time, APN settings come already configured on the phone out of which one will work automatically for making phone calls and accessing data.

However, there could be some cases where we would want to change our already configured APN Settings – 

  1. If APN Settings are incorrect and give an error message that cellular network can’t be activated.
  2. To avoid Data Usage Overages.
  3. If we want to use an unlocked phone with a different carrier.
  4. To avoid Data Roaming Usage charges.

For such use cases, I was trying to develop an application where we can configure an APN, view the configured APN and can also edit the settings if required.

To Configure APN Settings, we need to enter many fields, out of which some are mandatory ones (Entry Name, APN Name, MCC, MNC, APN Type, APN Protocol, APN Roaming Protocol, Carrier Enabled) while others are optional.

While developing this application, one of the places where I was stuck was how to get the configured APN types so that the user can view and edit this particular mandatory field. 

APN TYPES :

APN types define the usage category for an APN entry. It is a mandatory field where one APN entry may take multiple APN types, eg, a single APN entry can service regular internet traffic (“default”) along with MMS-specific connections.

We can calculate bitmask of APN types defined in ApnSetting.

So, basically APN type is a bitmask describing the types of the APN Value. It is either 0 or a combination of TYPE_DEFAULT, TYPE_MMS, TYPE_SUPL, TYPE_DUN, TYPE_HIPRI, TYPE_FOTA, TYPE_IMS, TYPE_CBS, TYPE_IA, TYPE_EMERGENCY, TYPE_MCX, TYPE_XCAP, TYPE_BIP, TYPE_VSIM, and android.telephony.data.ApnSetting.TYPE_ENTERPRISE

We can do bitwise OR of all the APN types selected by the user and pass that bitmask to ApnSetting.Builder.setApnTypeBitmask(int)

HOW TO SEGREGATE DIFFERENT APN TYPES : 

To get the configured APN type bitmask, we can use getApnTypeBitmask ()

Now the problem arises where we want to segregate the different APN types present in the bitmask. If we carefully see all the integer values of different APN types, we can observe that apart from TYPE_DEFAULT (value : 17), all APN types have different integer values in the power of 2.

If we study this in bits, we can verify that any decimal having its value in the power of 2 (eg : 2, 4, 1024, 4096, etc..) will have only a single set bit.

For eg : 1024 can be represented as 10000000000

16 can be represented as 10000

Now, if we remember, while making bitmask we were doing bitwise OR of these APN types, i.e. if user selects, TYPE_DEFAULT, TYPE_MMS, TYPE_SUPL and TYPE_IMS, then the bitmask would be 

(0010001) | (0000010) | (0000100) | (1000000) = (1010111) 

So now to derive TYPE_DEFAULT, TYPE_MMS, TYPE_SUPL and TYPE_IMS from the above bitmask (1010111), we can reverse engineer this by doing bitwise AND with each APN type of this bitmask and comparing the result with that particular APN type.

For eg : (1010111) & (1000000) == (1000000), hence (1000000) i.e. TYPE_IMS is present in this bitmask.

(001010111) & (100000000) != (100000000), hence (100000000) i.e. TYPE_IA is not present in this bitmask.
Following code can be used to get the configured APN types from the bitmask

mIntAPNTypeBitmask :

int[] lIntArrApnTypes = new int[]{ApnSetting.TYPE_DEFAULT, ApnSetting.TYPE_MMS, ApnSetting.TYPE_SUPL, ApnSetting.TYPE_DUN,
       ApnSetting.TYPE_HIPRI, ApnSetting.TYPE_FOTA, ApnSetting.TYPE_IMS, ApnSetting.TYPE_CBS,
       ApnSetting.TYPE_IA, ApnSetting.TYPE_EMERGENCY, ApnSetting.TYPE_MCX, ApnSetting.TYPE_XCAP,
       ApnSetting.TYPE_BIP, ApnSetting.TYPE_VSIM};

for(int i = 0; i < lIntArrAPNTypes.length; i++)
{
   if((mIntAPNTypeBitmask & lIntArrAPNTypes[i]) == lIntArrAPNTypes[i])
   {
       //Your Code
   }
}

Note : If we see TYPE_DEFAULT (value : 17) and TYPE_HIPRI (value : 16), we can easily identify that TYPE_HIPRI will always be present in the bitmask if that bitmask contains TYPE_DEFAULT because

(10001) | (10000) == (10000), hence (10000) i.e. TYPE_HIPRI is present inside TYPE_DEFAULT but not vice versa.

REFERENCES : 

https://developer.android.com/reference/android/telephony/data/ApnSetting#getApnTypeBitmask()
https://developer.android.com/reference/android/telephony/data/ApnSetting.Builder#setApnTypeBitmask(int)
https://developer.android.com/reference/android/telephony/data/ApnSetting#TYPE_DEFAULT

Leave A Comment

Your email address will not be published. Required fields are marked *