BLN in Samsung stock SMS application on Samsung Galaxy S

What is BLN anyway ?

Some Android phones are lucky to be made with a notification light. Some that are really lucky even have a RGB one. But many phones shipped in 2010 lacked one and so did Samsungs flagship at the time, the Galaxy S.

Looks nice, but no LED.

Looks nice, but no LED.

Then came a a developer called neldar who thought the both capacitive touch keys backlights were too good to be used for occasional key light only. He figured it out how to enable them on demand and released a kernel modification called BLN1 and an Android app for controlling it BLN control2. There was also a Pro version which enabled LED notifications for missed calls, blinking, quiet hours for nighttime and was well worth the money.

User would only need to find an appropriate kernel for his phone/Android build and flash it with a special service tool called Odin to get the BLN support. This topic is out of scope for this tutorial, but more information about what a kernel is and what it has to do with Android is here. More details on how to flash a BLN compatible kernel for Galaxy S can be found on xda-developers, this was the kernel I used personally. Being all set, there was only one thing left to do …


Samsung and their SMS application

While the notifications were now working with basically all apps that had LED notifications enabled, there was an issue with the Samsung SMS application which came with their system (MMS.apk) - it didn’t support them. Of course, Samsung engineers didn’t enable the support since their phone didn’t ship with an LED in the first place.

But that didn’t hold anyone down. Xda-developers user montymintypie found out where and how to modify the Android System framework and let the community know.3 Since the framework on the phone was Samsungs and there was no source posted for it (most vendors don’t open source their Android modifications), the only option was to decompile the services.odex, make the changes and compile it back again.


.odex ?

This also goes far out of the technical scope of this post, but to summarize :

  • Android runs on a VM (Virtual Machine) called Dalvik
  • Dalvik knows how to run only Dex bytecode, which is transported in .dex files
  • .odex file complement the .apk (applications) and .jar (framework) files.

More about the topic can be found here.


Procedure for the modification

To modify the framework files, there is a tool called dexopt-wrapper. It needs to be placed on a working phone with the framework you want to modify. Put the downloaded dexopt-wrapper onto your phone from the PC.

$ adb push dexopt-wrapper /sdcard

Then copy all of the /system/framework files onto your PC.

$ adb pull /system/framework

Now, we wish to make the change in services.odex, so we decompile the .odex file using the baksmali tool.

$ baksmali -x services.odex -o services.out

Then edit the desired .smali file in the services.out folder, there are two lines that need to be commented out in NotificationManagerService.smali file, here’s the diff.

diff -urN a/smali/com/android/server/NotificationManagerService.smali b/smali/com/android/server/NotificationManagerService.smali
--- a/smali/com/android/server/NotificationManagerService.smali
+++ b/smali/com/android/server/NotificationManagerService.smali
@@ -2064,7 +2064,7 @@
     :goto_0
     iget-boolean v4, p0, Lcom/android/server/NotificationManagerService;->mScreenOn:Z
 
-    if-nez v4, :cond_0
+    #if-nez v4, :cond_0
 
     iget-object v4, p0, Lcom/android/server/NotificationManagerService;->mLedNotification:Lcom/android/server/NotificationManagerService$NotificationRecord;
 
@@ -2114,7 +2114,7 @@
 
     iget-boolean v4, p0, Lcom/android/server/NotificationManagerService;->mScreenOn:Z
 
-    if-nez v4, :cond_3
+    #if-nez v4, :cond_3
 
     .line 1147
     iput-boolean v7, p0, Lcom/android/server/NotificationManagerService;->mPendingPulseNotification:Z

After the change, we rebuild the classes.dex file for services.odex.

$ smali -o classes.dex services.out

Now we put classes.dex into services.jar (WinRAR works fine, but other ZIP utilities should work). After that, we put the new .jar file on the phone.

$ adb push services.jar /sdcard

From PCm, we enter the phone shell.

$ adb shell

We need super user access to finish the task.

# su

We put the dexopt-wrapper utility into the bin folder with the correct permissions (we only need to do this once).

# cd /system/bin
# busybox cp /sdcard/dexopt-wrapper
# busybox chmod 755 dexopt-wrapper

Then we go back to the phone storage.

# cd /sdcard

We create a new .odex file from the new .jar file. [BOOTCLASSPATH] is ROM/device specific, but can be easily found in /init.rc file in root of the phone.

# dexopt-wrapper services.jar new.odex [BOOTCLASSPATH]

Here’s a special tip: we copy over the “signature” from the current .odex file into the new .odex file and do NOT continue until this command succeeds. The file size of the new.odex file should not change!

# busybox dd if=/system/framework/services.odex of=new.odex bs=1 count=20 skip=52 seek=52 conv=notrunc

Now we replace the old .odex file with the new .odex file.

# cd /system/framework
# busybox cp /sdcard/new.odex services.odex
# busybox chmod 644 services.odex

That’s it, we’re done.

# sync
# reboot

Conclusion

I’ve been doing this modification for about three months while having the phone, since there were always new Android builds coming out for the phone which broke the modification. Flashing newer builds was always exciting to see what new features and bugfixes were implemented.

Of course I shared my work back to xda-developers community as well, it was a great learning experience.