Posted by on Feb 8, 2017 in Android, AOSP, development, RIL |

Recently I had the need to develop a custom behavior in AOSP for one of my modems: on the native side it was quite clear I had to use RIL_REQUEST_OEM_HOOK_RAW, but how to easily test this on the Java side?

RIL_REQUEST_OEM_HOOK_RAW

RIL_REQUEST_OEM_HOOK_RAW in ril.h

Taking a look at native RIL main include file

hardware/ril/include/telephony/ril.h 

we can find the description for the request:

/**
 * RIL_REQUEST_OEM_HOOK_RAW
 *
 * This request reserved for OEM-specific uses. It passes raw byte arrays
 * back and forth.
 *
 * It can be invoked on the Java side from
 * com.android.internal.telephony.Phone.invokeOemRilRequestRaw()
 ...
 */

So this give us an hint related to how should we use the request on the Java side, but the prefix com.android.internal means that we cannot create a simple application using the common SDK, so there are basically two choices:

  1. Find some kind of workaround (e.g. using reflection) to access not public telephony features (e.g. the ones defined in the ITelephony interface): there are a lot of good tutorials on the internet about this.
  2. If you have available a device supported in AOSP (or the sources to build the platform), you can create a platform application that is allowed to directly access the internal phone resources.

With the Minnowboard Max and Hikey 96 at my disposal my choice is #2, but how can I further reduce the development time for the testing application?

Since I’m lazy, I do not want to mess with UI, manifest, permissions, so the best option is to find something with all these pieces already in place for being quickly customized.

The Dialer

The Dialer application located in

packages/apps/Dialer

seems the perfect fit for this task: a quick check on the manifest confirms that all the needed permissions are set.

Being a platform application, the hidden methods in TelephonyManager can be called, so invokeOemRilRequestRaw can be used.

The last thing I would like to avoid is messing with the UI: as you probably know the Dialer is capable of managing special strings for implementing specific requests like, for example, IMEI displaying.

This feature can be easily extended: grepping for IMEI special code ‘*#06#’ in the dialer directory reveals that this kind of things are managed inside

src.com.android.dialer.SpecialCharSequenceMgr.java

Then I simply added another special string (e.g. *#09#) in SpecialCharSequenceMgr class, with the following related function:

static boolean handleOEMCustomRequest(Context context, String input) {
    <snip>

    TelephonyManager telephonyManager =
        (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

    if (telephonyManager != null && input.equals(MY_SPECIAL_CODE)) {
        telephonyManager.invokeOemRilRequestRaw(oemReq, oemResp);

        return true;
    }

    return false;
}

I had also to modify the function that handles the inserted characters, in order to consider also my new handleOEMCustomRequest:

public static boolean handleChars(Context context, String input, EditText textField) {
    //get rid of the separators so that the string gets parsed correctly
    String dialString = PhoneNumberUtils.stripSeparators(input);

    if (handleDeviceIdDisplay(context, dialString)
        || handleOEMCustomRequest(context, dialString)
        || handleRegulatoryInfoDisplay(context, dialString)
        || handlePinEntry(context, dialString)
        || handleAdnEntry(context, dialString, textField)
        || handleSecretCode(context, dialString)) {
        return true;
    }

    return false;
}

Done, my RIL_REQUEST_OEM_HOOK_RAW can now easily tested simply dialing the special code.