Sunday, 19 March 2017

Creating a new Xposed module in Android

How Xposed works

Before we start lets see how Xposed works -

There is a process that is called "Zygote". This is the heart of the Android runtime. Every application is started as a copy ("fork") of it. This process is started by an /init.rc script when the phone is booted. The process start is done with /system/bin/app_process, which loads the needed classes and invokes the initialization methods.

This is where Xposed comes into play. When you install the framework, an extended app_process executable is copied to /system/bin. This extended startup process adds an additional jar to the classpath and calls methods from there at certain places. For instance, just after the VM has been created, even before the main method of Zygote has been called. And inside that method, we are part of Zygote and can act in its context.

The jar is located at /data/data/de.robv.android.xposed.installer/bin/XposedBridge.jar and its source code can be found here. Looking at the class XposedBridge, you can see the main method. This is what I wrote about above, this gets called in the very beginning of the process. Some initializations are done there and also the modules are loaded.

NOTE : Here we have used XC_MethodHook as callback so that we can execute methods before and after original method is executed. Other alternative is to replace the original method entirely - original hooked method will never get executed.

When you call XposedHelpers.findAndHookMethod the callback can either be

XC_MethodHook : Callback class for method hooks. Usually, anonymous subclasses of this class are created which override beforeHookedMethod(XC_MethodHook.MethodHookParam) and/or afterHookedMethod(XC_MethodHook.MethodHookParam).

XC_MethodReplacement : A special case of XC_MethodHook which completely replaces the original method.

1st one just provides you the hooks to execute methods before and after original method where as 2nd one replaces it completely.

Next create a file called xposed_init in your assets folder and add your fully qualified class name to it. This file tells xposed installer where to look for the module class. For eg in our case it will be -

com.osfg.flashlightxpmodule.XPFlashLightKiller

Finally download XposedbridgeApi.jar from here and add it in your app folder. Make sure the version of this jar should be same as xposedminversion set in the meta data tags in step 1.

Now build your app and deploy on your device. Once done Xposed installed should detect it. Just enable the module and reboot the device -

Testing out the module

Just to give you some background on the original Flashlight app. It's code is something like below -

It first asks for permission. If you give it then it will check if flash is supported on the device. So if you have already given Flashlight app camera permission then remove it from settings and open the app again. Now when it prompts for permissions again give it. But now you can see that the app shuts down with toast message - "Flash not supported on this device". This is because we hooked into isFlashSupported() method and made it always return false. So that the app never works :)

NOTE : From next time it will work fine. Since permission is already given next time it will not prompt and never execute isFlashSupported() method. To retest remove the permissions from settings again.