• Introducing XDA Computing: Discussion zones for Hardware, Software, and more!    Check it out!
  • Fill out your device list and let everyone know which phones you have!    Edit Your Device Inventory

Joying 2GB - Steering wheel key customization - V6 (NO KILL)

Search This thread

gustden

Senior Member
Oct 19, 2010
366
327
Chicago
THIS MOD IS ONLY FOR THE JOYING / 2GB / Sofia models - It is stable and working well .

Please use V4.1 if you have not upgraded to Marshmallow!

History:

V6.4: Update using code base 9/1/2017 Joying Update ( Android 6.0 ) (updated Oct 7)
Changes:
- Meida keys - Removed support for media keys customization. No longer sent to launcher.sh due to slow response time.
- Media keys - Modified code to only send media keys to the active media player.
- Changed reboot timer from 1/2 second to 2 seconds. Should help eliminate random reboots when coming from standby.
- Updated player_app.txt and navi_app.txt to latest from @surfer63
- Fixed issue with button 33 not working

- Files included:
- V6.4-Sofia-1-C9-Server_NOKILL.zip - Original file with task killer removed
- V6.4-Sofia-1-C9-Server_NOKILL_GVS.zip - Task killer removed, Google Voice Search on 'SRC' key
- V6.4-Custom_Keys-Mods.zip - Complete key modifications ( requires launcher.sh - description below )


V6.3: Update using code base 5/25/2017 Joying Update ( Android 6.0 )
- Files included:
- V6.3-Sofia-1-C9-Server_NOKILL.zip - Original file with task killer removed
- V6.3-Sofia-1-C9-Server_NOKILL_GVS.zip - Task killer removed, Google Voice Search on 'SRC' key
- V6.3-Custom_Keys-Mods.zip - Complete key modifications ( requires launcher.sh - description below )

V6.2: Updated using code base 5/8/2017 Joying Update ( Android 6.0 )
- Added fix for google maps voice output on radio from @xdamember2

V6.1: Updated code base using 5/8/2017 Joying Update ( Android 6.0 )

V6: Updated code base using 4/27/2017 Joying Update ( Android 6.0 )

Android 5.1.1
V4.1 - Fixed issue with "Google Voice Search" not lowering music volume (3/23/2017) - Android 5.1.1
V4: Updated code base using 3/14/2017 Joying ROM
Changes/Added support for:
- MEDIA KEY - hard key on unit
- BAND KEY - hard key on unit
- ACC_ON - Triggers on key on
- Minor changes to example shell scripts to add cases for MEDIA, BAND, ACC_ON ( launcher.sh )
- FIX/UPDATE - Updated list of NAVI APPS in assets/property/navi_app.txt ( allows more applications to speak during radio )
- Many thanks to @surfer63 for navi app radio fix and windows install script

V3 - Rebuilt using latest Joying ROM dated 2/22/2017 - Includes V1 & V2 steering wheel / key modifications.
Changes/Added support for:
- ACC_OFF - Added support for running actions at key off (case 98 )
- Added case 98 to example scripts to perform "PAUSE" - to stop current music player when key off

V2 Removed killAppWhenSleep(); - Eliminates tasks being killed on sleep
Added support for additional keys / Minor changes to example shell script ( launcher.sh )
- HANG - steering wheel softkey
- DVD - hard key on unit (if available)
- EJECT- hard key on unit (if available)
- CALL/BT softkey - Fixed issue where key would not respond after call disconnect.

V1 Initial version
There is little risk with this mod, but please understand what you are doing, and make backup of the original apk file ( in case you want to revert back ). The installer script does make a backup, but will overwrite the backup if installed more than once.

I also added a simpler "launcher_simple.sh" into the zip, which only changes the functionality of the Source (rotates radio, pandora, spotify ) and Call buttons ( google voice command ). These scripts are working examples of what can be done. If you want the simpler version, just rename "launcher_simple.sh" to "launcher.sh" before installing.

---------------------- Original Post -----------------
I have spent quite a bit of time working on being able to customize the steering wheel keys of my Joying 2GB headunit (JY-UL135N2 / 2GB / Sofia unit). I have made some good progress and thought I would share what I have done so far.

The system package /system/app/Sofia-1-C9-Server-V1.0/Sofia-1-C9-Server-V1.0.apk has been modified to intercept the keys sent by the MCU, and thus able to change the behavior of the key presses. The keys listed below are supported, and will launch a "shell" process, so any action that can be done by the command line can be performed. If your not familiar with the Android command line, you might be surprised how powerful it is. As a side note, this works very fast and efficient. From my testing the overhead of the system call and shell script is almost non-existent, and key presses are registered with no delay. In other words, it is working very nicely.

In addition to the steering wheel button mods, also provided is the ability to launch a command or series of commands when a RESUME is received.

Included is my shell script (example) that can be used as a model for your own customization. The example script included performs the following actions:

CALL/BT PHONE(27) - One press is HOME, 2 presses is BACK, 3 presses brings up Google Voice Commands

MODE/SRC(37) - Rotates through music apps: Radio, Pandora, Spotify, Stock Music App - If it has been longer than 1 minute since the last press it will return you to the last selected music app with first press, then continue with the rotation. ( I'm working on a more intelligent way of doing this, that looks at the process list and will post soon)

NAVI(9) - One press is Torque, 2 presses is google maps

PAUSE/PLAY(85*),NEXT(87*), PREVIOUS(88*), FASTBACK(89*), FASTFWD(90*),HOME(3), BACK(4) - Currently set to perform stock functions. They ARE passed to script so they can be assigned other functions if wanted.

ACC_ON(97) - Executes at ignition switch on. Sample script has a 'play' here to restart music player that was paused at key off.

ACC_OFF(98) - Executes at ignition switch off. I suggest you assign "pause" on this case, to stop current music player. Resolves issue of music player advancing for several minutes after key is turned off.

RESUME(99) - Executes on system resume.

Please note the media control keys marked with a (*) are hardcoded to specific functions within the stock Joying applications. They are only passed through to the shell script when you are NOT using a Joying media application. They will ONLY work as the original keys when you are within the Joying media applications.

Remember, the apk is just handing codes to you, what you do with them after that is up to you! I have tried to comment the example script enough to be understandable to someone with basic programming knowledge.

Attached is a zip file with the updated Sofia-1-C9-Server-V1.0.apk, launcher.sh ( my example script), and install script. The launcher.sh script must be placed in the /data directory ( /data/launcher.sh ), as it is hardcoded in the apk file.

The install script is a shell/linux script, but you can easily copy/paste the adb commands if your using windows.

[NOTE: Please update to the latest version of busybox! I found some bugs in the version included by Joying that caused several issues.]
 

Attachments

  • V4.1-Custom-Keys-Mods.zip
    1.2 MB · Views: 1,438
  • V6.2-Custom_Keys-Mods.zip
    1.2 MB · Views: 353
  • V6.2-Sofia-1-C9-Server_NOKILL_GVS.zip
    1.1 MB · Views: 210
  • V6.2-Sofia-1-C9-Server_NOKILL.zip
    1.1 MB · Views: 216
  • V6.3-Custom_Keys-Mods.zip
    1.2 MB · Views: 822
  • V6.3-Sofia-1-C9-Server_NOKILL_GVS.zip
    1.2 MB · Views: 434
  • V6.3-Sofia-1-C9-Server_NOKILL.zip
    1.2 MB · Views: 624
  • V6.4-Custom_Keys-Mods.zip
    1.3 MB · Views: 1,150
  • V6.4.Sofia-1-C9-Server_NOKILL_GVS.zip
    1.2 MB · Views: 500
  • V6.4-Sofia-1-C9-Server_NOKILL.zip
    1.2 MB · Views: 1,033
Last edited:

naplesbill

Senior Member
Jun 13, 2008
938
81
Awesome work. I will mess with this sometime this week. I still need to root my unit. Just installed it last week.

Sent from my SAMSUNG-SM-G935A using Tapatalk
 

sonof

Senior Member
Aug 16, 2010
299
46
Excellent work, sir! Before I start modifying the script for personal taste, could you help how to find key number for DVD and Eject buttons that currently have no function as the DVD drive is non-existent? Maybe logcat or something?
 

gustden

Senior Member
Oct 19, 2010
366
327
Chicago
Excellent work, sir! Before I start modifying the script for personal taste, could you help how to find key number for DVD and Eject buttons that currently have no function as the DVD drive is non-existent? Maybe logcat or something?

I see a few references in the code for the DVD/eject button in the common code. My 'best guess' would be to add a system call to the cases listed below, but I seriously doubt the MCU would even send the codes if there is no DVD present.

bsp/FinalBsp.java
public static final int KEY_CODE_DVD = 242;
public static final int KEY_CODE_EJECT = 231;

bsp/HandlerBspKey.java
public static void keyEvent(int paramInt1, int paramInt2)
case 242:
bspKeyDvd(paramInt2);
return;
case 231:
bspKeyEject(paramInt2);
return;
 

sonof

Senior Member
Aug 16, 2010
299
46
I see a few references in the code for the DVD/eject button in the common code. My 'best guess' would be to add a system call to the cases listed below, but I seriously doubt the MCU would even send the codes if there is no DVD present.

bsp/FinalBsp.java
public static final int KEY_CODE_DVD = 242;
public static final int KEY_CODE_EJECT = 231;

bsp/HandlerBspKey.java
public static void keyEvent(int paramInt1, int paramInt2)
case 242:
bspKeyDvd(paramInt2);
return;
case 231:
bspKeyEject(paramInt2);
return;

Seems that MCU does send the codes as seen here.

I will see what I can do but I doubt I am able to do anything as I just installed apktool the first time today and am new with apk's. Thanks for your efforts! Very appreciated. :)
 

gustden

Senior Member
Oct 19, 2010
366
327
Chicago
Excellent work, sir! Before I start modifying the script for personal taste, could you help how to find key number for DVD and Eject buttons that currently have no function as the DVD drive is non-existent? Maybe logcat or something?

Seems that MCU does send the codes as seen here.

I will see what I can do but I doubt I am able to do anything as I just installed apktool the first time today and am new with apk's. Thanks for your efforts! Very appreciated. :)

If I create and send you a apk file with additional debug statements, would you be able to install it, and capture the 'logcat' of the buttons being pressed? It makes it much more difficult since I don't have the DVD buttons. Hacking smali code is a LOT of trial and errors. Their code is quite complex, and doesn't decompile into Java very nicely in some critical areas.
 

sonof

Senior Member
Aug 16, 2010
299
46
If I create and send you a apk file with additional debug statements, would you be able to install it, and capture the 'logcat' of the buttons being pressed? It makes it much more difficult since I don't have the DVD buttons. Hacking smali code is a LOT of trial and errors. Their code is quite complex, and doesn't decompile into Java very nicely in some critical areas.
Yes I am capable of doing that!
 

gustden

Senior Member
Oct 19, 2010
366
327
Chicago
Excellent work, sir! Before I start modifying the script for personal taste, could you help how to find key number for DVD and Eject buttons that currently have no function as the DVD drive is non-existent? Maybe logcat or something?

Yes I am capable of doing that!

I put in debugging code that parses the data stream from the MCU and dumps the first 4 bytes of EVERY message that is received from the MCU (skipping checksum info). Simply replace the original file (make a copy first ) and reboot. When looking for the keys, I suggest you do not use the radio, as it sends a constant flood of messages, such as RDS updates.

Even when the radio is off, there are still messages constantly being sent. If you filter on the debug messages MCUKEY in adb, and press the button in question a few times quickly, you should see a consistent pattern. I was able to identify the 'HANG' key in a couple minutes using this method. You should see something like this in the logcat:

D/MCUKEY ( 693): MCUKEYINPUT: B1=1 B2=0 B2=5 B2=224
D/MCUKEY ( 693): MCUKEYINPUT: B1=1 B2=7 B2=16 B2=0
D/MCUKEY ( 693): MCUKEYINPUT: B1=1 B2=0 B2=0 B2=49
D/MCUKEY ( 693): MCUKEYINPUT: B1=1 B2=7 B2=16 B2=0
D/MCUKEY ( 693): MCUKEYINPUT: B1=1 B2=3 B2=34 B2=0

In this case the HANG key is in bold ( 1, 7, 16, 0 ) messages. IF the DVD and eject keys are sent, they should definitely show up here. Not every key is sent by the MCU, if it is not relevant to the current state of the system. For example the media buttons are not sent when the radio is on, since the MCU is in control of the radio, however it does send the results such as a frequency change resulting from the button press.

It is possible that the MCU knows there is no DVD present and suppresses the messages. From looking at the code, it may be the action of a disc being ejected that is sent from the MCU, with the eject button press handled internally by the MCU. Your more likely to find the press of the DVD button than the eject button, but may find both.

When your done searching, you want to put back the original file and reboot. If you find the codes, I can certainly add them to trigger the shell script and you can take whatever action you want with them.
 

Attachments

  • Sofia-1-C9-Server-V1.0_DEBUG.apk
    1.2 MB · Views: 138

gustden

Senior Member
Oct 19, 2010
366
327
Chicago
Question: if I remove a customization from the script file for a key, the key should then perform its default functions, correct?
The keys being passed to the shell script (launcher.sh) is hard-coded in the APK file and is just sent to the script. If you remove it from the script, the key would no longer do anything.

If you want to keep the stock functionality of a specific button, it should be fairly easy to duplicate it in the shell script. For example:

BT/CALL button: "am start com.syu.bt/com.syu.bt.BtAct"
NAVI: By default, I think NAVI just toggles between a Navi app, and the previous activity on the stack.

The code below should behave the same as the original for both the NAVI an BTPHONE buttons ( assuming your using google maps )
Code:
case $key in
        9) # NAVI
              x=`dumpsys activity activities | grep "Run #"  | cut -f 13 -d" "| head -1 | grep maps`
        if  [ "$x" =  ""  ]
        then      
                $maps                     
        else
                am start `dumpsys activity activities | grep "Run #"  | cut -f 13 -d" " | grep -v launcher | grep -v systemui | grep -v maps |head -1`
           fi
        ;;            
        27) # BTPHONE/PTT                                                              
            am start com.syu.bt/com.syu.bt.BtAct
        ;;

Play/Pause: you can just remove the 85 case, it would just hit the default case and pass "input keyevent 85" which is identical in functionality.
 
Last edited:

vassandrei

Senior Member
Jan 9, 2015
144
40
Moscow
The keys being passed to the shell script (launcher.sh) is hard-coded in the APK file and is just sent to the script. If you remove it from the script, the key would no longer do anything.

If you want to keep the stock functionality of a specific button, it should be fairly easy to duplicate it in the shell script. For example:

BT/CALL button: "am start com.syu.bt/com.syu.bt.BtAct"
NAVI: By default, I think NAVI just toggles between a Navi app, and the previous activity on the stack.

The code below should behave the same as the original for both the NAVI an BTPHONE buttons ( assuming your using google maps )
Code:
        9)  # NAVI    
         x=`dumpsys activity activities | grep "Run #"  | cut -f 13 -d" "|  grep -v launcher | grep -v systemui | head -1 | grep maps`
        if  [ "$x" =  ""  ]
        then                              
            $maps
        else                                                                    
            am start `dumpsys activity activities | grep "Run #"  | cut -f 13 -d" " | grep -v launcher | grep -v systemui | head -2 | tail -1`       
        fi                                                         
         ;;         
        27) # BTPHONE/PTT                                                              
            am start com.syu.bt/com.syu.bt.BtAct
        ;;

Play/Pause: you can just remove the 85 case, it would just hit the default case and pass "input keyevent 85" which is identical in functionality.

brilliant! thank you so much!

Last thing: I want to have viper4android launch on resume (in the background ideally). where can I find the "app identifier" to put in the shell script?
 

gustden

Senior Member
Oct 19, 2010
366
327
Chicago
Question: if I remove a customization from the script file for a key, the key should then perform its default functions, correct?

brilliant! thank you so much!

Last thing: I want to have viper4android launch on resume (in the background ideally). where can I find the "app identifier" to put in the shell script?

I made a slight change to the 'CODE' section of my previous post, so if you copy it make sure you get the edited version. I tested it and made a couple of changes.

There are several ways to get the package name and activity.

What I typically do is start the application on the unit and do the following in adb:
> adb shell
> dumpsys activity activities | grep "Run #"

This shows you a list of the activities ( package/activity ) in the task list with most recent at the top.

You should be able to pick it out pretty easily. If it is the app that I found with google, this should work to start it.
> am start com.vipercn.viper4android_v2/.activity.ViPER4Android

In most cases, you can just give the package name when using 'am start' with no need for the activity. It will default to the 'LAUNCHER' activity in the package. I usually always give the activity, just to be safe. I would sleep for a couple seconds to give it time to initialize and then $home to take you back to the Home screen. So whole command would look like this. It is easy to test using adb.

am start com.vipercn.viper4android_v2/.activity.ViPER4Android ; sleep 2 ; $home
 
Last edited:

akuma148

Senior Member
May 24, 2008
59
7
Thanks for this, it's working great on my Joying (JY-UL135N2 ).
My only issue is that the CALL/BT PHONE (27) button is assigned to my "Pick Up/Call Out" button on my steering wheel. So I can't use it to pick up calls. I actually have another dedicated button on my steering to activate voice commands, so I'd rather assign the CALL/BT PHONE function to that. Do you happen to know how to find out what numbers corresponds to each button press?
 

gustden

Senior Member
Oct 19, 2010
366
327
Chicago
Thanks for this, it's working great on my Joying (JY-UL135N2 ).
My only issue is that the CALL/BT PHONE (27) button is assigned to my "Pick Up/Call Out" button on my steering wheel. So I can't use it to pick up calls. I actually have another dedicated button on my steering to activate voice commands, so I'd rather assign the CALL/BT PHONE function to that. Do you happen to know how to find out what numbers corresponds to each button press?

I make and receive so few voice calls, It wasn't worth having a steering wheel button dedicated for the dialer/call pickup . I just tap the screen to answer and use google voice to make calls.

If you want to have a button answer a call, there *should* be a way to do it given the right command. I will play around with it more. Worse case I can just back out the changes for the (27) , and send you an updated apk.
 

akuma148

Senior Member
May 24, 2008
59
7
I used the joying steering wheel control app and switched the dialer/call pickup to my voice button and that works, but my dialer/call pickup doesn't do anything. Please let me know if you want me to test anything. Thank you.
 

sonof

Senior Member
Aug 16, 2010
299
46
I put in debugging code that parses the data stream from the MCU and dumps the first 4 bytes of EVERY message that is received from the MCU (skipping checksum info). Simply replace the original file (make a copy first ) and reboot. When looking for the keys, I suggest you do not use the radio, as it sends a constant flood of messages, such as RDS updates.

Even when the radio is off, there are still messages constantly being sent. If you filter on the debug messages MCUKEY in adb, and press the button in question a few times quickly, you should see a consistent pattern. I was able to identify the 'HANG' key in a couple minutes using this method. You should see something like this in the logcat:

D/MCUKEY ( 693): MCUKEYINPUT: B1=1 B2=0 B2=5 B2=224
D/MCUKEY ( 693): MCUKEYINPUT: B1=1 B2=7 B2=16 B2=0
D/MCUKEY ( 693): MCUKEYINPUT: B1=1 B2=0 B2=0 B2=49
D/MCUKEY ( 693): MCUKEYINPUT: B1=1 B2=7 B2=16 B2=0
D/MCUKEY ( 693): MCUKEYINPUT: B1=1 B2=3 B2=34 B2=0

In this case the HANG key is in bold ( 1, 7, 16, 0 ) messages. IF the DVD and eject keys are sent, they should definitely show up here. Not every key is sent by the MCU, if it is not relevant to the current state of the system. For example the media buttons are not sent when the radio is on, since the MCU is in control of the radio, however it does send the results such as a frequency change resulting from the button press.

It is possible that the MCU knows there is no DVD present and suppresses the messages. From looking at the code, it may be the action of a disc being ejected that is sent from the MCU, with the eject button press handled internally by the MCU. Your more likely to find the press of the DVD button than the eject button, but may find both.

When your done searching, you want to put back the original file and reboot. If you find the codes, I can certainly add them to trigger the shell script and you can take whatever action you want with them.

Luckily the eject key was also found! :) Here are the codes:

DVD:
D/MCUKEY ( 691): MCUKEYINPUT: B1=1 B2=0 B2=16 B2=80

EJECT:
D/MCUKEY ( 691): MCUKEYINPUT: B1=1 B2=161 B2=2 B2=91

Looking forward to the modified apk. If you happen to take donations I'd be willing to give you a beer. Thank you.

Model number for reference: JY-AL003N2
 
Last edited:

gustden

Senior Member
Oct 19, 2010
366
327
Chicago
Luckily the eject key was also found! :) Here are the codes:

DVD:
D/MCUKEY ( 691): MCUKEYINPUT: B1=1 B2=0 B2=16 B2=80

EJECT:
D/MCUKEY ( 691): MCUKEYINPUT: B1=1 B2=161 B2=2 B2=91

Looking forward to the modified apk. If you happen to take donations I'd be willing to give you a beer. Thank you.

Model number for reference: JY-AL003N2

Here is an updated apk file that should catch the code you listed. In the zip there is a file "keys.txt" and also updated APK file. The keys.txt is a complete list button codes for both the soft-keys ( steering wheel ) and hard-keys (on unit ) that the new apk sends to the script. This is a beta of V2.0 which I added:

3 - HOME ( On unit hard key )
4 - BACK ( On unit hard key )
28 - HANG/CALL END ( Steering wheel softkey)
31 - DVD ( On unit hard key )
32 - EJECT ( On unit hard key )

The HOME/BACK keys are sending the keycodes for the home/back actions. You don't need to map them in a script, as long as you have a default that passes keycodes at the end of the script.
*) input keyevent $key
;;

I have used it the last couple of days and it is working fine for me, but can't test the dvd or eject.

Let me know if it registers the keys.
 

Attachments

  • JY-Button-Mod-V2.0-beta.zip
    1.1 MB · Views: 112

Top Liked Posts

  • There are no posts matching your filters.
  • 24
    THIS MOD IS ONLY FOR THE JOYING / 2GB / Sofia models - It is stable and working well .

    Please use V4.1 if you have not upgraded to Marshmallow!

    History:

    V6.4: Update using code base 9/1/2017 Joying Update ( Android 6.0 ) (updated Oct 7)
    Changes:
    - Meida keys - Removed support for media keys customization. No longer sent to launcher.sh due to slow response time.
    - Media keys - Modified code to only send media keys to the active media player.
    - Changed reboot timer from 1/2 second to 2 seconds. Should help eliminate random reboots when coming from standby.
    - Updated player_app.txt and navi_app.txt to latest from @surfer63
    - Fixed issue with button 33 not working

    - Files included:
    - V6.4-Sofia-1-C9-Server_NOKILL.zip - Original file with task killer removed
    - V6.4-Sofia-1-C9-Server_NOKILL_GVS.zip - Task killer removed, Google Voice Search on 'SRC' key
    - V6.4-Custom_Keys-Mods.zip - Complete key modifications ( requires launcher.sh - description below )


    V6.3: Update using code base 5/25/2017 Joying Update ( Android 6.0 )
    - Files included:
    - V6.3-Sofia-1-C9-Server_NOKILL.zip - Original file with task killer removed
    - V6.3-Sofia-1-C9-Server_NOKILL_GVS.zip - Task killer removed, Google Voice Search on 'SRC' key
    - V6.3-Custom_Keys-Mods.zip - Complete key modifications ( requires launcher.sh - description below )

    V6.2: Updated using code base 5/8/2017 Joying Update ( Android 6.0 )
    - Added fix for google maps voice output on radio from @xdamember2

    V6.1: Updated code base using 5/8/2017 Joying Update ( Android 6.0 )

    V6: Updated code base using 4/27/2017 Joying Update ( Android 6.0 )

    Android 5.1.1
    V4.1 - Fixed issue with "Google Voice Search" not lowering music volume (3/23/2017) - Android 5.1.1
    V4: Updated code base using 3/14/2017 Joying ROM
    Changes/Added support for:
    - MEDIA KEY - hard key on unit
    - BAND KEY - hard key on unit
    - ACC_ON - Triggers on key on
    - Minor changes to example shell scripts to add cases for MEDIA, BAND, ACC_ON ( launcher.sh )
    - FIX/UPDATE - Updated list of NAVI APPS in assets/property/navi_app.txt ( allows more applications to speak during radio )
    - Many thanks to @surfer63 for navi app radio fix and windows install script

    V3 - Rebuilt using latest Joying ROM dated 2/22/2017 - Includes V1 & V2 steering wheel / key modifications.
    Changes/Added support for:
    - ACC_OFF - Added support for running actions at key off (case 98 )
    - Added case 98 to example scripts to perform "PAUSE" - to stop current music player when key off

    V2 Removed killAppWhenSleep(); - Eliminates tasks being killed on sleep
    Added support for additional keys / Minor changes to example shell script ( launcher.sh )
    - HANG - steering wheel softkey
    - DVD - hard key on unit (if available)
    - EJECT- hard key on unit (if available)
    - CALL/BT softkey - Fixed issue where key would not respond after call disconnect.

    V1 Initial version
    There is little risk with this mod, but please understand what you are doing, and make backup of the original apk file ( in case you want to revert back ). The installer script does make a backup, but will overwrite the backup if installed more than once.

    I also added a simpler "launcher_simple.sh" into the zip, which only changes the functionality of the Source (rotates radio, pandora, spotify ) and Call buttons ( google voice command ). These scripts are working examples of what can be done. If you want the simpler version, just rename "launcher_simple.sh" to "launcher.sh" before installing.

    ---------------------- Original Post -----------------
    I have spent quite a bit of time working on being able to customize the steering wheel keys of my Joying 2GB headunit (JY-UL135N2 / 2GB / Sofia unit). I have made some good progress and thought I would share what I have done so far.

    The system package /system/app/Sofia-1-C9-Server-V1.0/Sofia-1-C9-Server-V1.0.apk has been modified to intercept the keys sent by the MCU, and thus able to change the behavior of the key presses. The keys listed below are supported, and will launch a "shell" process, so any action that can be done by the command line can be performed. If your not familiar with the Android command line, you might be surprised how powerful it is. As a side note, this works very fast and efficient. From my testing the overhead of the system call and shell script is almost non-existent, and key presses are registered with no delay. In other words, it is working very nicely.

    In addition to the steering wheel button mods, also provided is the ability to launch a command or series of commands when a RESUME is received.

    Included is my shell script (example) that can be used as a model for your own customization. The example script included performs the following actions:

    CALL/BT PHONE(27) - One press is HOME, 2 presses is BACK, 3 presses brings up Google Voice Commands

    MODE/SRC(37) - Rotates through music apps: Radio, Pandora, Spotify, Stock Music App - If it has been longer than 1 minute since the last press it will return you to the last selected music app with first press, then continue with the rotation. ( I'm working on a more intelligent way of doing this, that looks at the process list and will post soon)

    NAVI(9) - One press is Torque, 2 presses is google maps

    PAUSE/PLAY(85*),NEXT(87*), PREVIOUS(88*), FASTBACK(89*), FASTFWD(90*),HOME(3), BACK(4) - Currently set to perform stock functions. They ARE passed to script so they can be assigned other functions if wanted.

    ACC_ON(97) - Executes at ignition switch on. Sample script has a 'play' here to restart music player that was paused at key off.

    ACC_OFF(98) - Executes at ignition switch off. I suggest you assign "pause" on this case, to stop current music player. Resolves issue of music player advancing for several minutes after key is turned off.

    RESUME(99) - Executes on system resume.

    Please note the media control keys marked with a (*) are hardcoded to specific functions within the stock Joying applications. They are only passed through to the shell script when you are NOT using a Joying media application. They will ONLY work as the original keys when you are within the Joying media applications.

    Remember, the apk is just handing codes to you, what you do with them after that is up to you! I have tried to comment the example script enough to be understandable to someone with basic programming knowledge.

    Attached is a zip file with the updated Sofia-1-C9-Server-V1.0.apk, launcher.sh ( my example script), and install script. The launcher.sh script must be placed in the /data directory ( /data/launcher.sh ), as it is hardcoded in the apk file.

    The install script is a shell/linux script, but you can easily copy/paste the adb commands if your using windows.

    [NOTE: Please update to the latest version of busybox! I found some bugs in the version included by Joying that caused several issues.]
    15
    I totally agree. Would be extremely thankful if we could get an APK to fix the resume problem. Thank you very much in advance.
    Regards
    Kurt

    Attached is an updated Sofia-1-C9-Server-V1.0.apk , this is the original apk with the task kill function commented out and re-packaged. This does NOT modify any keys or buttons.

    To install, you need to replace the system file: /system/app/Sofia-1-C9-Server-V1.0/Sofia-1-C9-Server-V1.0.apk
    with the one in the zip file and reboot.

    Since it is just one file, you can just put it on an sdcard and copy it into place using root explorer, es explorer, or similar type tool. Make sure the file permissions match the original file - which is readable by all. I also suggest to make a copy of the original, just in case you want to revert back.

    There were some changes to this package with the recent ROM update from Joying. Please use the correct package for the ROM you are on.

    V1 - Built from the Jan 4, 2017 Joying ROM
    V2 - Built from Feb 22, 2017 Joying ROM
    V3 - Built from Mar 14, 2017 Joying ROM - Includes Navigation TTS patch for radio from @surfer63
    10
    Ok, while finishing up my dac mod, I stumbled upon how/why Google Search won't talk back to us. For some reason Google Search's reply is streamed on the "Alarm" stream on our Joyings, and if you look at Settings->Sound & notifications, you'll see that the Alarm sound level is forced to stay at 0. Funny thing is that Bluetooth's audio is also on the Alarm stream. I finally figured out their logic. Joying's software maxes the Alarm stream when you connect via Bluetooth and use their Bt Music app. Media stream is muted at that point. Basically, they mute the Alarm stream or Media stream so that you can't hear both streams at the same time. This has the side effect of not allowing us to hear Google Search because the it's on the Alarm stream which is usually muted unless the Bt Music app is on top and playing music.

    Luckily, the fix was easy (easy after days of following the code all around). Basically, we just have to intercept where Joying is muting the Alarm stream, and tell it to stop it! The only thing is you gotta remember to turn off the Bt Music app before you listen to your favorite media player, else they both will be playing music. Not that big of a deal of course. Let me know if there are any other side effects that you discover!

    Here is the code so @gustden can include it in his future updates to his mods (just find the method and replace it in ToolkitApp):

    Code:
    .method public static setStreamVol(II)V
        .locals 3
        .param p0, "streamType"    # I
        .param p1, "vol"    # I
    
        .prologue
        .line 553
    	const/4 v1, 0x4
    	
    	if-eq v1, p0, :cond_1
    	
    	invoke-static {}, Lapp/ObjApp;->getAudioManager()Landroid/media/AudioManager;
    
        move-result-object v0
    
        .line 554
        .local v0, "am":Landroid/media/AudioManager;
        invoke-virtual {v0, p0}, Landroid/media/AudioManager;->getStreamVolume(I)I
    
        move-result v1
    
        .line 556
        .local v1, "value":I
        if-eq v1, p1, :cond_0
    
        .line 557
        const/4 v2, 0x0
    
        invoke-virtual {v0, p0, p1, v2}, Landroid/media/AudioManager;->setStreamVolume(III)V
    
        .line 559
        :cond_0
        return-void
    	:cond_1
        return-void
    .end method

    Basically, if Joying's software is trying to change stream 4 (Alarm Stream), then just skip.

    I will also upload a copy of gustden's latest 4.1 mod with my mod already in it. I haven't done anything else to it except add a few lines to the "player_app.txt" file and "unkill_app.txt"

    player_app.txt
    Code:
    com.audlabs.viperfx #updated viper4android package name
    org.videolan.vlc #updated VLC package name
    com.google.android.youtube #Just in case

    unkill_app.txt
    Code:
    com.audlabs.viperfx #updated viper4android package name

    Let me know how it goes if you use the apk. Don't forget to make a backup of your apk before copying this one in. Also, after you replace the file,
    change permissions to 0644 and reboot, and then go into settings->sound&notifications and adjust the Alarm volume to your liking and test out google search.
    5
    Is there a version of this that just has the Google Voice for PTT Key, Maps Toggle to Previous APP and No Kill for the Marshmallow Firmware? I checked the 1st Page, but I only saw 5.1.1 related apps.
    I just added updates for the latest Joying ROM dated 5/8/2017 to the first post of the thread.

    There are 3 separate files depending on what you want. I believe that the 2nd one is what your looking for. I have had issues with the music player advancing with the no kill patch, so I added a "pause" on sleep to the nokill code.

    It is working real good on my unit with the latest ROM. There is a bug with the current ROM where google navigation does NOT speak while listening to the RADIO. This is unrelated to this mod.

    All include additional navigation apps listed in the navi_app.txt file within the apk.

    V6.1-Sofia-1-C9-Server_NOKILL.zip - Original file with task killer removed, pauses music before sleep, .

    V6.1-Sofia-1-C9-Server_NOKILL_GVS.zip - Task killer removed, Google Voice Search on 'SRC' key, pauses music before sleep.

    V6.1-Custom_Keys-Mods.zip - Complete key modifications ( requires launcher.sh )
    4
    Are you sure it does go to sleep when killAppWhenSleep(); has been commented out? Any way to check if it has? Maybe with multimeter after half an hour just to see if the radio still draws current from the battery. Maybe there are some apps that could prevent it from going to sleep.

    That is the only reason I haven't put the updated version up. I still need to do some deeper investigation into this. I have a program installed called CPU spy that is supposed to measure the times at each of the CPU frequencies. I just reset the timers and ran a full wake lock program, will check in the morning. It's not even supposed to let wifi disconnect ( which it already has ). I would expect overnight, the entire time should show up under the 'deep sleep' heading, even with the wakelock.

    I left torque, 2 nav apps (gmaps & here), pandora playing, set a forced wakelock, and forced wifi lock all running overnight. I also had a shell script running that printed a date/time to a file every minute. It was missing about 8 hours worth of time. Far as I can tell, she slept like a baby.