[TOOL][APP][WIP] Native AT Command Injector

E:V:A

Inactive Recognized Developer
Dec 6, 2011
1,449
2,212
0
-∇ϕ
I trying to develop an application that can send AT commands directly to modem, from a native application interface (or possibly via terminal).

There are many obstacles here, but the main one is that the modem AT interface is rarely available through a simple serial device, which is why all other AT command apps always fail for the Samsung Galaxy class devices, which use a modified IPC protocol over sockets. However, by using the built-in RIL_OEM_HOOK_RAW and RIL_OEM_HOOK_STR we should be able to do this.

I then found this document for the Ublox LISA-U2 UMTS/HSPA voice and data modules, which show an example Android App, including most of the code used in that App. However, I cannot get this to compile in Eclipse. I think the reason is that there are many cosmetic changes in the AOS, while there are many typos in the code in that document.

I would very much like to get this or something very similar to work. I'm mainly developing on the Samsung Galaxy S2 (GB).

Here is a picture (from that document).


Any help with this would be very very much appreciated!

It will also benefit the rest of the community as it will provide a foundation
for my future development of many other things to come, for free!

BTW. The BP used in that device is the very popular Intel/Infineon XGOLD-626...
 

Attachments

Last edited:
  • Like
Reactions: dexter35803

E:V:A

Inactive Recognized Developer
Dec 6, 2011
1,449
2,212
0
-∇ϕ
When trying to run the code shown below in Eclipse (using GB 2.3.3+),
it fails with the following errors:
The import com.android.internal.telephony cannot be resolved
The import android.os.AsyncResult cannot be resolved
It seem like it doesn't recognize these imports:

Code:
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import android.os.AsyncResult;
The java code is:
Code:
[SIZE=2]
/*=========================================================
Demo App Code by Ublox, modified copy and paste from:
http://www.u-blox.com/images/downloads/Product_Docs/AndroidRIL_Source_Code_ApplicationNote_%283G.G2-CS-11003%29.pdf

=========================================================== */

package com.testapp.sat;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import android.view.View.OnKeyListener;
import android.view.KeyEvent;
import android.os.Message;
import android.os.Handler;
import android.os.AsyncResult;
import android.util.Log;
import android.app.AlertDialog;


public class RilOemHookTest extends Activity
{
        private static final String LOG_TAG = "RILOemHookTestApp";
        private RadioButton mRadioButtonAPI1 = null;
        private RadioGroup mRadioGroupAPI = null;
        private Phone mPhone = null;
        private EditText CmdRespText = null;
        
        private static final int EVENT_RIL_OEM_HOOK_CMDRAW_COMPLETE = 1300;
        private static final int EVENT_RIL_OEM_HOOK_CMDSTR_COMPLETE = 1400;
        private static final int EVENT_UNSOL_RIL_OEM_HOOK_RAW = 500;
        private static final int EVENT_UNSOL_RIL_OEM_HOOK_STR = 600;

@Override 
public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.riloemhook_layout);
        mRadioButtonAPI1 = (RadioButton) findViewById(R.id.radio_api1);
        mRadioGroupAPI = (RadioGroup) findViewById(R.id.radio_group_api);
        
        // Initially turn on first button.
        mRadioButtonAPI1.toggle();
        
        //Get our main phone object.
//      mPhone = PhoneFactory.getDefaultPhone();
        
        //Register for OEM raw notification.
//      mPhone.mCM.setOnUnsolOemHookRaw(mHandler, EVENT_UNSOL_RIL_OEM_HOOK_RAW, null);
        
        //Capture text edit key press
        CmdRespText = (EditText) findViewById(R.id.edit_cmdstr);
        CmdRespText.setOnKeyListener(new OnKeyListener() {
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                        //If the event is a key-down event on the "enter" button
                        if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
                                //Perform action on key press
                                Toast.makeText(RilOemHookTest.this,
                                CmdRespText.getText(), Toast.LENGTH_SHORT).show();
                                return true;
                        }
                        return false;
                }
        });
}

@Override
public void onPause() 
{
        super.onPause();
        log("onPause()");
        //Unregister for OEM raw notification.
//      mPhone.mCM.unSetOnUnsolOemHookRaw(mHandler);
}

@Override
public void onResume()
{
        super.onResume();
        log("onResume()");
        //Register for OEM raw notification.
//      mPhone.mCM.setOnUnsolOemHookRaw(mHandler, EVENT_UNSOL_RIL_OEM_HOOK_RAW, null);
}

public void onRun(View view)
{
        //Get the checked button
        int idButtonChecked = mRadioGroupAPI.getCheckedRadioButtonId();

        //Get the response field
        CmdRespText = (EditText) findViewById(R.id.edit_response);
        byte[] oemhook = null;
        switch(idButtonChecked)
        {
                case R.id.radio_api1:
                        oemhook = new byte[1];
                        oemhook[0] = (byte)0xAA;
                        break;
                case R.id.radio_api2:
                        oemhook = new byte[2];
                        oemhook[0] = (byte)0xBB;
                        oemhook[1] = (byte)0x55;
                        break;
                case R.id.radio_api3:
                        //Send OEM notification (just echo the data bytes)
                        oemhook = new byte[7];
                        oemhook[0] = (byte)0xCC;
                        oemhook[1] = (byte)0x12;
                        oemhook[2] = (byte)0x34;
                        oemhook[3] = (byte)0x56;
                        oemhook[4] = (byte)0x78;
                        oemhook[5] = (byte)0x9A;
                        oemhook[6] = (byte)0xBC;
                        break;
                case R.id.radio_api4:
                        //Send OEM command string
                        break;
                default:
                        log("unknown button selected");
                        break;
        }
        
        if (idButtonChecked!=R.id.radio_api4) {
                Message msg =
                mHandler.obtainMessage(EVENT_RIL_OEM_HOOK_CMDRAW_COMPLETE);
                mPhone.invokeOemRilRequestRaw(oemhook, msg);
                CmdRespText.setText("");
        } else {
                //Copy string from EditText and add carriage return
                String[] oemhookstring = { ((EditText)
                findViewById(R.id.edit_cmdstr)).getText().toString()+'\r' } ;

                //Create message
                Message msg =
                mHandler.obtainMessage(EVENT_RIL_OEM_HOOK_CMDSTR_COMPLETE);
                //Send request
                mPhone.invokeOemRilRequestStrings(oemhookstring, msg);
                CmdRespText = (EditText) findViewById(R.id.edit_response);
                CmdRespText.setText("---Wait response---");
        }
}

private void logRilOemHookResponse(AsyncResult ar) {
        log("received oem hook response");
        String str = new String("");

        if (ar.exception != null) {
                log("Exception:" + ar.exception);
                str += "Exception:" + ar.exception + "\n\n";
        }

        if (ar.result != null) 
        {
                byte[] oemResponse = (byte[])ar.result;
                int size = oemResponse.length;
                log("oemResponse length=[" + Integer.toString(size) + "]");
                str += "oemResponse length=[" + Integer.toString(size) + "]" + "\n";
                
                if (size > 0) {
                        for (int i=0; i<size; i++) {
                                byte myByte = oemResponse[i];
                                int myInt = (int)(myByte & 0xFF);
                                log("oemResponse[" + Integer.toString(i) + "]=[0x" +
                                Integer.toString(myInt,16) + "]");
                                str += "oemResponse[" + Integer.toString(i) + "]=[0x" +
                                Integer.toString(myInt,16) + "]" + "\n";
                        }
                }
        } else {
                log("received NULL oem hook response");
                str += "received NULL oem hook response";
        }
        
        // Display message box
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(str);
        builder.setPositiveButton("OK", null);
        AlertDialog alert = builder.create();
        alert.show();
}

private void logRilOemHookResponseString(AsyncResult ar) {
                log("received oem hook string response");
                String str = new String("");
                CmdRespText = (EditText) findViewById(R.id.edit_response);
                
                if (ar.exception != null) {
                        log("Exception:" + ar.exception);
                        str += "Exception:" + ar.exception + "\n\n";
                }
                
                if (ar.result != null) {
                        String[] oemStrResponse = (String[])ar.result;
                        int sizeStr = oemStrResponse.length;
                        log("oemResponseString[0] [" + oemStrResponse[0] + "]");
                        CmdRespText.setText( "" + oemStrResponse[0] );
                } else {
                        log("received NULL oem hook response");
                        CmdRespText.setText( "No response or error received" );
                }
}

private void log(String msg) {
        Log.d(LOG_TAG, "[RIL_HOOK_OEM_TESTAPP] " + msg);
}

private Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {        
                AsyncResult ar;
                switch (msg.what) {
                        case EVENT_RIL_OEM_HOOK_CMDRAW_COMPLETE:
                                log("EVENT_RIL_OEM_HOOK_CMDRAW_COMPLETE");
                                ar = (AsyncResult) msg.obj;
                                logRilOemHookResponse(ar);
                                break;
                        case EVENT_RIL_OEM_HOOK_CMDSTR_COMPLETE:
                                log("EVENT_RIL_OEM_HOOK_CMDSTR_COMPLETE");
                                ar = (AsyncResult) msg.obj;
                                logRilOemHookResponseString(ar);
                                break;
                        case EVENT_UNSOL_RIL_OEM_HOOK_RAW:
                                break;
                        case EVENT_UNSOL_RIL_OEM_HOOK_STR:
                                break;
                }
        }
};

}

[/SIZE]
:(

------------------ EDIT ---------------------

Of course they aren't recognized! They are internal packages not available outside the standard AOS API's. But I'm very stubborn and have now spent 2 days trying to use those damn packages anyway! I managed! I will post an update here and a whole new thread on how that is done, once I can get some other bugs out of the way...
 
Last edited:

E:V:A

Inactive Recognized Developer
Dec 6, 2011
1,449
2,212
0
-∇ϕ
Here is my new thread on how to use and import internal packages into your project,
including instructions for hacking Eclipse ADT plugin, in order to allow for using
the com.android.internal classes.

"[APP][DEV][GUIDE] Using the Android Java Internal/Hidden API classes"

It is work in progress (WIP), and include a lot of manual file manipulations.
As such it is closely related to this thread. So keep an eye open for updates.

EDIT: 2014-01-06

That thread still work for API-17 JAR's!!
 
Last edited:

E:V:A

Inactive Recognized Developer
Dec 6, 2011
1,449
2,212
0
-∇ϕ
So, I managed to get it to compile but not without two main issues.

0) I got it to run on an SGS2 running GB2.3.4, but it FC's after being run.

1) I kept on getting AlertDialog builder complaints like:
"the constructor AlertDialog.Builder is undefined" so I had to comment out all code related to that. I searched for fixes, but since I'm not a Java programmer, I could not resolve this in the proper way...

2) Then I ran into some other undocumented errors from my own built (according to instructions) android.jar, so I just used the inazaruk's pre-made one, and it compiled. Here are his files:
https://github.com/inazaruk/android-sdk/tree/master/platforms

The main point is that we should not expect to blindly use the Ublox code and think it will work. Instead we need to understand the following:

a) How to properly use the RIL constants
Code:
[SIZE=2]RILConstants.java:
int RIL_REQUEST_OEM_HOOK_RAW = 59;
int RIL_REQUEST_OEM_HOOK_STRINGS = 60;
int RIL_UNSOL_OEM_HOOK_RAW = 1028;

my code:
EVENT_RIL_OEM_HOOK_CMDRAW_COMPLETE
EVENT_RIL_OEM_HOOK_CMDSTR_COMPLETE
EVENT_UNSOL_RIL_OEM_HOOK_RAW
EVENT_UNSOL_RIL_OEM_HOOK_STR
[/SIZE]
b) What the various bytecodes sent, are actually doing, and how to make them do what we want.
Code:
[SIZE=2]    case R.id.radio_api1:
    oemhook = new byte[1];
    oemhook[0] = (byte)0xAA;
    break;
    case R.id.radio_api2:
    oemhook = new byte[2];
    oemhook[0] = (byte)0xBB;
    oemhook[1] = (byte)0x55;
    break;
    case R.id.radio_api3:
    //Send OEM notification (just echo the data bytes)
    oemhook = new byte[7];
    oemhook[0] = (byte)0xCC;
    oemhook[1] = (byte)0x12;
    oemhook[2] = (byte)0x34;
    oemhook[3] = (byte)0x56;
    oemhook[4] = (byte)0x78;
    oemhook[5] = (byte)0x9A;
    oemhook[6] = (byte)0xBC;
    break;
[/SIZE]
c) If we can simplify the code to just send ONE hard-coded AT command and read the response.

d) alternatively use a completely different method, that will undoubtedly work, but will be device dependent. I'm talking about the (Samsung modified) IPC modem-communication protocols, as discussed in my older threads...

e) Find out how to use a local shell + device to send AT commands directly to BP.
 
Last edited:

E:V:A

Inactive Recognized Developer
Dec 6, 2011
1,449
2,212
0
-∇ϕ
To monitor the radio and related messages from the App (on a Sumsung) , you can use:
Code:
[SIZE=2]adb shell logcat AndroidRuntime:* ActivityManager:* dalvikvm:* DataRouter:E NetdConnector:D *:s
[/SIZE]
 

bigrushdog

Inactive Recognized Developer
Apr 23, 2007
3,547
7,244
263
I've done similar work in my SprintDiagnostics app included in our Eos project. Its in the sprint gnex thread. There's no way to make this a user app as you have to be on the Phone looper thread. Meaning you have to declare the phone process in the manifest for the activity calling the raw ril requests. I can grab msl, write prl, and some other good stuff. And enable diagnostic mode based on shell work from Autoprime.

Edit: http://git.teameos.org/eos/device/samsung/toroplus.git/tree/SprintDiagnostics?h=jellybean
 
Last edited:
  • Like
Reactions: E:V:A

E:V:A

Inactive Recognized Developer
Dec 6, 2011
1,449
2,212
0
-∇ϕ
I've done similar work in my SprintDiagnostics app included in our Eos project. Its in the sprint gnex thread. There's no way to make this a user app as you have to be on the Phone looper thread. Meaning you have to declare the phone process in the manifest for the activity calling the raw ril requests. I can grab msl, write prl, and some other good stuff. And enable diagnostic mode based on shell work from Autoprime.

Edit: http://git.teameos.org/eos/device/samsung/toroplus.git/tree/SprintDiagnostics?h=jellybean
Hi! Thanks for interesting info, but unfortunately I don't understand all you're saying. But I got many more questions that answers.

First of all, what thread are you referring to? (Could you give a link?) Second, how do you do that declaration? (Code example?) BTW. I looked briefly at the code and must admit it seem a bit cryptic, as I didn't quite find the where AT's goes or are created. Third, what is "msl"? Do you have an APK to try on? Finally, what specific modem (cellular) processor are you running in that device? LTE?
Screenshots?

Thanks in advance.
 

trevd

Inactive Recognized Developer
Jul 19, 2011
893
1,269
123
Hull
Hi There

Forgive me if I'm oversimplifying it here but wouldn't minicom or some similar terminal program do this? I believe minicom is included in busybox.
Surely you could just wrap that around using JNI

AT Commands in android are sent natively by the vendor implemented ril library, normally set in global properties as rild.libpath. It may be worth stepping away from the JAVA code for a moment and looking at the rild and reference-ril sources in the aosp source. The atchannel.c is where the "magic" happens. Also If you haven't already, read PDK Telephony Documentation

When you get down to it, all you really want to do is read and write from a tty character device so doing it "raw" is always an option.

Also to monitor the Radio log in android use adb logcat -b radio , You will be enlightened as you watch the AT commands fly by! :)
 
Last edited:

E:V:A

Inactive Recognized Developer
Dec 6, 2011
1,449
2,212
0
-∇ϕ
Forgive me if I'm oversimplifying it here but ...
Also to monitor the Radio log in android use adb logcat -b radio , You will be enlightened as you watch the AT commands fly by! :)
No, you are missing the entire point of this thread. We are trying to circumvent actually using the vendor RIL, by tunneling the commands via the OEM_RAW requests. That is because it is often filtering out non-standard OEM AT commands that are not part of the common standard. These are all dependent on the BP/CP and and varies widely from device to device. In addition on many devices the direct modem serial is either not possible (because there is no such connection/transport) or it has been blocked/disabled. The Java way of circumventing this, is what this thread is all about. In addition the "-b radio" logcat doesn't fetch ATs sent by vendor specific OEM IPCs, for example. This is the case for the SGS2 (GT-I9100) and many other devices.
 

E:V:A

Inactive Recognized Developer
Dec 6, 2011
1,449
2,212
0
-∇ϕ
Ah, Okay...If I had a SGS2 too play with I'd probably join in on this little adventure, but I don't :(
Well again... The point is that: RIL_OEM_HOOK_RAW and RIL_OEM_HOOK_STR are (internally) accessible for all RIL's. Which means that you CAN join in!
 

bigrushdog

Inactive Recognized Developer
Apr 23, 2007
3,547
7,244
263
Hi! Thanks for interesting info, but unfortunately I don't understand all you're saying. But I got many more questions that answers.

First of all, what thread are you referring to? (Could you give a link?) Second, how do you do that declaration? (Code example?) BTW. I looked briefly at the code and must admit it seem a bit cryptic, as I didn't quite find the where AT's goes or are created. Third, what is "msl"? Do you have an APK to try on? Finally, what specific modem (cellular) processor are you running in that device? LTE?
Screenshots?

Thanks in advance.
My apologies for not responding sooner. I forgot to subscribe ;( . I'd like to try and clear up my previous post as well as try to shed some light on this topic. First, I'm by no means a telephony expert. I've read some of your other threads and found them remarkable. I write Java and do feature development in a AOSP project. I currently am doing telephony work on Samsun Sprint CDMA devices including galaxy nexus, nexus s, and working on s3. As you know, those use the VIA chipset. However, working through the Android radio layer makes that irrelevant, for the most part. I've also worked with Autoprime on some telephony/modem/ril matters.

First some code and background on what I have done on Sprint Galaxy Nexus. These are some code fragments from my CDMATools app.

Manifest:

Code:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.teameos.settings.device"
    android:sharedUserId="android.uid.system"
    android:versionCode="1"
    android:versionName="1.0" >
Of importance if the android.uid.system uid. This allows the app to access the phone process, which is required for PhoneFactory.getDefaultPhone(); The following activity queries ril for a Master Subsidy Lock code (msl)
Code:
        <activity
            android:name=".MslActivity"
            android:label="@string/msl_activity"
            android:process="com.android.phone" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
And the actual method which is used to query the radio...

Code:
    private void checkMSLCode()
    {
        ByteArrayOutputStream bytearrayoutputstream;
        DataOutputStream dataoutputstream;
        bytearrayoutputstream = new ByteArrayOutputStream();
        dataoutputstream = new DataOutputStream(bytearrayoutputstream);
        try {
            dataoutputstream.writeByte(main_cmd_hidden);
            dataoutputstream.writeByte(OEM_SUB_CMD_GET_MSL);
            dataoutputstream.writeShort(device_short);
            if (isTuna) {
                dataoutputstream.writeByte(OEM_SUB_RAW_MSL);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        mPhone.invokeOemRilRequestRaw(bytearrayoutputstream.toByteArray(),
                mHandler.obtainMessage(GET_MSL_DONE));
    }
A snipit of the handler code to receive and process incoming messages from radio.

Code:
        mHandler = new Handler() {
            public void handleMessage(Message message) {
                Log.i(LOG_TAG, "MSL response incoming!!");
                AsyncResult asyncresult = (AsyncResult) message.obj;
                if (asyncresult.exception != null)
                {
                    Log.i(LOG_TAG, "AsyncResult Exception Occur!!!");

                } else
                if (asyncresult.result == null)
                {
                    Log.i(LOG_TAG, "ar.result == NULL! - No answer for MSL response");
                } else
                {
                    byte abyte0[] = (byte[]) (byte[]) asyncresult.result;
                    String s = new String("");
                    for (int j = 0; j < 6; j++)
                        s = (new StringBuilder()).append(s).append((char) abyte0[j]).toString();
                    Intent intent = new Intent().setAction(getString(R.string.msl_action));
                    intent.putExtra(getString(R.string.msl_key), Integer.parseInt(s));
                    mContext.sendBroadcast(intent);
                    finish();
                }
            }

        };
I have been able to get the raw commands from RE'ing various device proprietary apk's. Of importance to this topic is this checkMSLCode() function. This is the equivalent of raw AT commands, but being passed though the Android radio layer. From looking at the code for that AT command application you posted in the OP, it uses a similar structure. In fact, if time permits, i'm confident i can expand on it and make it somewhat more robust. One problem is see is finding an effective way to interpret the AT command responses from the radio. Requests often get a response in different forms, thus requiring a unique handler for each function. Of course, we could always do a Object.toString() to the log and try to decipher it. I hope this info sheds some light on the topic. I'll post when I come up with more.

Edit: also I should note, i build this apk inside of my AOSP repo, so it sees all the internal api automatically. I'm now looking at using reflection to do some telephony stuff, but it's proving rather tricky.
 
Last edited:
  • Like
Reactions: E:V:A and autoprime

E:V:A

Inactive Recognized Developer
Dec 6, 2011
1,449
2,212
0
-∇ϕ
Very nice! (That was an understatement!)
I just wish I knew how to apply that...

Regarding the raw command (and their appropriate responses), I think there is both code and documents available for this, for Qualcomm chips. I know nothing about the VIA chipsets, but a whole lot more about the Qualcomm MSM stuff... Many CDMA devices use just Qualcomm, so perhaps you've been across some of these. I bet we could get this working on them, somehow.

Since, just as you said, the RIL should take care of much of the details. We just need to apply the command requests and responses. But my Java App making skills are really not even worthy a try at the moment.

Somebody else who'd care to join us, to give this a try?



As an aside and a note of reference, mostly to myself. (For a professional OEM programmer, this may be obvious, but me it's not. ) After having dug through some of the QC MSM code, I've come to the conclusion that QC like to use what they (?) call SMD (Shared memory Device) for doing their IPC stuff, which include talking to modem. While for Infineon/Intel modem, we know that Samsung have developed their own (non-standard) IPC protocol version for this communication...
 
Last edited:

bigrushdog

Inactive Recognized Developer
Apr 23, 2007
3,547
7,244
263
While rewriting my Cdmatools app making it fragment based, I used reflection to access all the hidden apis. I'll fork the source for the at command app and apply the reflected classes.
 

enigma99a

Senior Member
Sep 2, 2007
85
18
0
I also got access to my Samsung Galaxy S3 via Reflection... although I had to go AOSP and sign with they same system key to run as looper. But now I just need help with what to send........ via RAW/String
 
  • Like
Reactions: E:V:A

E:V:A

Inactive Recognized Developer
Dec 6, 2011
1,449
2,212
0
-∇ϕ
While rewriting my Cdmatools app making it fragment based, I used reflection to access all the hidden apis. I'll fork the source for the at command app and apply the reflected classes.
Excellent. Where can we download this?
Have you been able to make demo App or something?


I also got access to my Samsung Galaxy S3 via Reflection... although I had to go AOSP and sign with they same system key to run as looper. But now I just need help with what to send........ via RAW/String
Can you elaborate? Do you need info on what AT commands to send, or are you asking about the protocol?

PS. I would be great if you could say something more about how you did it, so that perhaps other interested people can join in. We need more people on this, so that we can start working on THIS project.
 

bigrushdog

Inactive Recognized Developer
Apr 23, 2007
3,547
7,244
263
my apologies that i've been unable to continue efforts on that project. My aosp project consumes all of my development time and then some. Here is the source for CDMATools. I was looking for ways to monetize it. However, due to android's permissions scheme, it's not gonna happen lol. so here ya go.

www.miuimods.com/bigrushdog/CDMATools.tar.bz2

compile in eclipse then sign with aosp platorm test keys. I use some libraries that require it be compiled in eclipse. and because of the internal telephony imports, it must have the platform signature. Also, because it's compiled in eclipse, i use reflection to access internal telephony. Of interest will be the Phone service class. everything else is just ui. Look at how i structure the reflection. You can reflect all the internal telephony calls in the same fashion. any issues, just hit me. but my time now is very limited as I have a large team to manage and my plate is more than full. Good luck!

feel free to post on github, distribute, or whatever.
 

E:V:A

Inactive Recognized Developer
Dec 6, 2011
1,449
2,212
0
-∇ϕ
So I have not yet had time to modify OP app or using bigrushdog's CDMAtools. But I will soon. In the meantime I just post the internals for the _OEM_HOOK_ statements.

The code base is here:
https://android.googlesource.com/platform/frameworks/base.git/

So from the JellyBean RIL.java:

Code:
[SIZE=2]public void invokeOemRilRequestRaw(byte[] data, Message response) {
    RILRequest rr = RILRequest.obtain(RIL_REQUEST_OEM_HOOK_RAW, response);
    if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                                             + "[" + IccUtils.bytesToHexString(data) 
                                             + "]");
    rr.mp.writeByteArray(data);
    send(rr);
}
public void invokeOemRilRequestStrings(String[] strings, Message response) {
    RILRequest rr = RILRequest.obtain(RIL_REQUEST_OEM_HOOK_STRINGS, response);
    if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
    rr.mp.writeStringArray(strings);
    send(rr);
}[/SIZE]
And the expected response can be found in the ril.h:
Code:
[SIZE=2]#define [B]RIL_REQUEST_DATA_REGISTRATION_STATE[/B] 21

/**
 * RIL_REQUEST_DATA_REGISTRATION_STATE
 *
 * Request current DATA registration state
 *
 * "data" is NULL
 * "response" is a "char **"
 * ((const char **)response)[0] is registration state 0-5 from TS 27.007 10.1.20 AT+CGREG
 * ((const char **)response)[1] is LAC if registered or NULL if not
 * ((const char **)response)[2] is CID if registered or NULL if not
 * ((const char **)response)[3] indicates the available data radio technology,
 *                              valid values as defined by RIL_RadioTechnology.
 * ((const char **)response)[4] if registration state is 3 (Registration
 *                               denied) this is an enumerated reason why
 *                               registration was denied.  See 3GPP TS 24.008,
 *                               Annex G.6 "Additonal cause codes for GMM".
 *      7 == GPRS services not allowed
 *      8 == GPRS services and non-GPRS services not allowed
 *      9 == MS identity cannot be derived by the network
 *      10 == Implicitly detached
 *      14 == GPRS services not allowed in this PLMN
 *      16 == MSC temporarily not reachable
 *      40 == No PDP context activated
 * ((const char **)response)[5] The maximum number of simultaneous Data Calls that can be
 *                              established using RIL_REQUEST_SETUP_DATA_CALL.
 *
 * [/SIZE]The values at offsets 6..10 are [COLOR=Blue][B]optional LTE[/B][/COLOR] location information in decimal.[SIZE=2]
 * If a value is unknown that value may be NULL. If all values are NULL,
 * none need to be present.
 *  ((const char **)response)[6] is TAC, a 16-bit Tracking Area Code.
 *  ((const char **)response)[7] is CID, a 0-503 Physical Cell Identifier.
 *  ((const char **)response)[8] is ECI, a 28-bit E-UTRAN Cell Identifier.
 *  ((const char **)response)[9] is CSGID, a 27-bit Closed Subscriber Group Identity.
 *  [COLOR=Red]((const char **)response)[10] is TADV, a 6-bit timing advance value.[/COLOR]
 *
 * LAC and CID are in hexadecimal format.
 * valid LAC are 0x0000 - 0xffff
 * valid CID are 0x00000000 - 0x0fffffff
 *
 * Please note that registration state 4 ("unknown") is treated
 * as "out of service" in the Android telephony system
 *
 * Valid errors:
 *  SUCCESS
 *  RADIO_NOT_AVAILABLE
 *  GENERIC_FAILURE
 */


#define [B]RIL_REQUEST_OEM_HOOK_RAW[/B] 59

/**
 * 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()
 *
 * "data" is a char * of bytes copied from the byte[] data argument in java
 * "response" is a char * of bytes that will returned via the
 * caller's "response" Message here:
 * (byte[])(((AsyncResult)response.obj).result)
 *
 * An error response here will result in
 * (((AsyncResult)response.obj).result) == null and
 * (((AsyncResult)response.obj).exception) being an instance of
 * com.android.internal.telephony.gsm.CommandException
 *
 * Valid errors:
 *  All
 */

#define [B]RIL_REQUEST_OEM_HOOK_STRINGS[/B] 60

/**
 * RIL_REQUEST_OEM_HOOK_STRINGS
 *
 * This request reserved for OEM-specific uses. It passes strings
 * back and forth.
 *
 * It can be invoked on the Java side from
 * com.android.internal.telephony.Phone.invokeOemRilRequestStrings()
 *
 * "data" is a const char **, representing an array of null-terminated UTF-8
 * strings copied from the "String[] strings" argument to
 * invokeOemRilRequestStrings()
 *
 * "response" is a const char **, representing an array of null-terminated UTF-8
 * stings that will be returned via the caller's response message here:
 *
 * (String[])(((AsyncResult)response.obj).result)
 *
 * An error response here will result in
 * (((AsyncResult)response.obj).result) == null and
 * (((AsyncResult)response.obj).exception) being an instance of
 * com.android.internal.telephony.gsm.CommandException
 *
 * Valid errors:
 *  All
 */

[SIZE=2]#define [COLOR=Purple][B]RIL_REQUEST_RADIO_POWER[/B][/COLOR] 23

/**
 * RIL_REQUEST_RADIO_POWER
 *
 * Toggle radio on and off (for "airplane" mode)
 * If the radio is is turned off/on the radio modem subsystem
 * is expected return to an initialized state. For instance,
 * any voice and data calls will be terminated and all associated
 * lists emptied.
 *
 * "data" is int *
 * ((int *)data)[0] is > 0 for "Radio On"
 * ((int *)data)[0] is == 0 for "Radio Off"
 *
 * "response" is NULL
 *
 * Turn radio on if "on" > 0
 * Turn radio off if "on" == 0
 *
 * Valid errors:
 *  SUCCESS
 *  RADIO_NOT_AVAILABLE
 *  GENERIC_FAILURE
 */
[/SIZE]
[/SIZE]
The last one seem to imply that there could be other "bytes" to be read from that data[] array... Some suggestions have been the Transmitted power... But this was assuming a Qualcomm based modem, so there is no telling if there is another standard there. We don't know...
 
Last edited:

E:V:A

Inactive Recognized Developer
Dec 6, 2011
1,449
2,212
0
-∇ϕ