Notes on Android.mk parsing and compiling procedure in AOSP

Here is a drawio diagram[png version] that shows the flow of how Android.mk file is parsed and the build command is executed.

Mind you, this is a note taken while I was trying to link the su binary with libcap.so which is newly introduced as a part of my modification.

  • suprisingly, the LOCAL_SHARED_LIBRARIES modifier didn’t seem to actually do anything…

  • the gcc command is located inside /build/core/definitions.mk file. Not sure when this is executed. If you want to see the actual gcc command, you should tweak it toi print out the command.
  • the linking command is also located inside /build/core/definitions.mk file. Not sure when this is executed.

  • In the linking command, I cannot find a flow where LOCAL_SHARED_LIBRARIES values are related. On the other hand I have found a flow where LOCAL_LDFLAGS is related.

  • LOCAL_LDDIRS by default directs to the /out/.../intermediates/lib directory. If I have already built the libcap.so beforehand, the original copy will be located under this directory.
  • Adding -lcap to the LOCAL_LDFLAGS is enough to let the linker know that it should link the libcap.so as well. It is normal to omit the lib characters at the front of libcap.so.

Advertisements

adding shared library in `Android.mk`

Linking a shared library in Android.mk

This document is based on my experience of modifying su binary.

Working with Android.mk for C source files

Sharing my experiences of trying to build su binary which a small modification of my own: linking with libcap.so shared library. Assumes that I already have libcap.so built.

At first it was confusing because I didn’t know which options to modify in my Android.mk file.

Initially I thought that I had to refer to libcap through the LOCAL_SHARED_LIBRARIES option. However, this was not the case. The additions that I added were:

LOCAL_CFLAGS := -fPIE
LOCAL_LDFLAGS:= -lcap -fPIE -pie
LOCAL_C_INCLUDES += external/libcap-for-Android-master/libcap/include

I am actually referring to the libcap.so through the -lcap option in LOCAL_LDFLAGS. the pie, PIE is added in order to make the output as a position independent executable. I may have overwritten things about pie here. Perhaps it would have been enough to specify pie either in LOCAL_CFLAGS or LOCAL_LDFLAGS. But I haven’t tested that part. But hey, specifying it in both options seems like a safe bet.

If I don’t specify the PIE related flags, then the built executable will cause the following error when executed.

error: only position independent executables (PIE) are supported.

Note that I have also added the path to the header files of libcap in LOCAL_C_INCLUDES. This is necessary for the su.c code to refer to the libcap header files.

Working with Android.mk for C++ source files

I also had to link the libcap.so with Zygote source code. Linking the libcap.so even for cpp source code’s Android.mk was not so different.

LOCAL_LDFLAGS +=  -lcap -fPIE -pie
LOCAL_C_INCLUDES += external/libcap-for-Android-master/libcap/include

“Unsupported major.minor version 52.0” error when gradle build

when I tried to build a specific module only by using /gradlew command, it gave me the error

> java.lang.UnsupportedClassVersionError: com/android/build/gradle/AppPlugin : Unsupported major.minor version 52.0

It usually worked but suddenly it didn’t. I noticed that I have changed the default java, javac to jdk7 from jdk8. I reset both tool to jdk8 with update-alternatives and it now works fine.

fixing memory leak

an app that I am developing has shown significant memory leak when I to orientation rotations. I tried to debug this by dumping the heap and recording allocations with the android profiler. I was able to identify that old Activities persisted when they should not. The tool showed all the references that were made to each of the Activity instance. However, there were too many references and it did not show which one was causing the memory leak.

At that point I turned to LeakCanary, and eventually this help me identify what my problem was in a short time. I found that the root cause of leaking Activity was due to not cancelling JsonArrayRequests that I had added to the Volley Request Queue.

It does take a bit of time for LeakCanary to analyze its trackers and report the leak and log to the user. But it really is a life and time saver.

adding kotlin class for application context access

Currently, kotlin doesn’t support native access to application context and instead it provides access to Activity context. I needed application context for memory-leak safe coding. In order to access application context, a class that extends the Application() class should be added and registered as the default class to execute in the AndroidManifest.xml file. Continue reading “adding kotlin class for application context access”

cautions when dealing with orientation change activity restart

Since all the views and components are initialized, the user would probably only have to deal with the onCreate method. If the activity is created for the first time, savedInstanceState would be null. If the activity is recreated due to events such as orientation change, then the savedInstanceState  would not be null and instead contain all data that was used in the previous running activity. Therefore if the user can check if the current invocation of onCreate is a first-time creation or recreation and if it is a recreation, better skip most of the initialization of the activity done in onCreate. An example would be like the following: Continue reading “cautions when dealing with orientation change activity restart”