How to manage properly the Pin Lock State in AOSP RIL

I’m currently developing the native AOSP RIL library (Android 5 and 6) for a modem of mine. While adding the code to manage the Pin Lock State I faced a puzzling problem: no matter what I wrote in the native RIL library, the Pin Service State in the Settings GUI was always wrong.

AOSP RIL wrong Pin Lock State
Time to go through the Java code…

AOSP RIL and the wrong Pin Lock State…

Taking a look at the native RIL calls (found in hardware/ril/include/telephony/ril.h), the one dedicated to the Sim state is identified by the value RIL_REQUEST_GET_SIM_STATUS.

According to the modem technology in use this can be mapped into an AT command, or a QMI request, or an MBIM request or whatever… This does not matter: the important part is the structure returned by the native ril daemon to the upper layer of the RIL:

RIL_CardStatus_vX

where X depends on the Android version in use (and on what is implemented in the native RIL library).

Two fields seem to be relevant for this feature:

RIL_PinState universal_pin_state;
RIL_AppStatus applications[RIL_CARD_MAX_APPS];

RIL_AppStatus is a structure with another interesting field:

RIL_PinState     pin1;

When dealing with the native RIL there is no much documentation to rely on, so looking only at the native code the difference between universal_pin_state and pin1 of the Sim Application is not very clear.

An honest first try consists in updating both the fields with the relevant pin state, to see what happens. The values are taken from the following enum found in ril.h, that are quite descriptive:

typedef enum {
    RIL_PINSTATE_UNKNOWN = 0,
    RIL_PINSTATE_ENABLED_NOT_VERIFIED = 1,
    RIL_PINSTATE_ENABLED_VERIFIED = 2,
    RIL_PINSTATE_DISABLED = 3,
    RIL_PINSTATE_ENABLED_BLOCKED = 4,
    RIL_PINSTATE_ENABLED_PERM_BLOCKED = 5
} RIL_PinState;

Making short a long story, no matter which value and in which field it is returned by the native RIL: the GUI won’t ever be updated with the correct setting.

Debugging the Java RIL

The first friend for debugging AOSP RIL issues is:

adb logcat -b radio

Looking for the calls identified by RIL_REQUEST_GET_SIM_STATUS we can understand if there are problems in the result returned by the native RIL.

Once verified that there are no errors in the native part, unfortunately the radio log is no more helpful, but we can take a look at the main log:

adb logcat -b main

We are looking for some clue that can help us in finding which is the piece of code in charge of showing the Pin Status Lock setting.

When clicking on the Sim Lock Setting element on the Security panel I can see the following line:

T/ActivityManager( 2113): Displayed com.android.settings/.IccLockSettings: +342 ms

Good, an hint!

The Settings application is found in the package/ directory: we can grep looking for the word IccLockSettings. The most promising result is the file

apps/Settings/src/com/android/settings/IccLockSettings.java

Looking for some sensitive word (pin, lock…), bring us to the function isIccLockEnabled() with the following line:

return PhoneFactory.getDefaultPhone().getIccCard().getIccLockEnabled();

Ah… Another hint!

In recent Android versions, part of Java telephony code is inside frameworks/opt/telephony. Grepping again for getIccLockEnabled returns a few results: the method implementation can be found in UiccCardApplication.java and, surprise surprise, we got the following:

public boolean getIccLockEnabled() {
    return mIccLockEnabled;
    /* STOPSHIP: Remove line above and all code associated with setting
        mIccLockEanbled once all RIL correctly sends the pin1 state.
    // Use getPin1State to take into account pin1Replaced flag
    PinState pinState = getPin1State();
    return pinState == PinState.PINSTATE_ENABLED_NOT_VERIFIED ||
        pinState == PinState.PINSTATE_ENABLED_VERIFIED ||
        pinState == PinState.PINSTATE_ENABLED_BLOCKED ||
        pinState == PinState.PINSTATE_ENABLED_PERM_BLOCKED;*/
}

So, whatever was done in the native AOSP RIL layer is not enough since this code is commented. Comment the return statement, uncomment the other part and you’re done!

Why?

Well… This sentence is quite eye opening:

Remove line above and all code associated with setting mIccLockEanbled once all RIL correctly sends the pin1 state

Probably most of the native AOSP RIL libraries released by the modem vendors do not properly implement RIL_REQUEST_GET_SIM_STATUS, so they wrote that workaround in order to make things work.

To me, it is not the best solution to rely on a cached value that has many pieces of information at the same time: asking the modem just for the pin lock status when the setting is shown, would have been better in my opinion.

However, once modified the getIccLockEnabled function, things just work!

AOSP RIL correct pin lock state