Tuesday, September 01, 2015

Modding Android SystemUI.apk - UIAutomatorViewer Tool

Previously I looked at how to extract the SystemUI package and analyze the layout files to create mods. However, SystemUI is a gigantic package with a lot of branching resource structures. It is not easy figuring out how the packages are structured. With Web applications running on Chrome and Firefox, this is easy. Simply use the DOM Inspector or related tools to click on the element you want to customize, find the id, and do a quick grep search to figure out what source file that element is referenced in. With Android, there isn't a DOM inspector - there is a UIAutomatorViewer. This is a tool intended to help QA Engineers to identify app elements and create automation scripts in frameworks such as Appium. This tool however can also help facilitate the modding process.

The UIAutomatorViewer is a tool found in Google's Android SDK under sdk/tools/uiautomatorviewer. In conjunction with adb, you can obtain an xml screenshot of the current screen with a connected device by pressing the "Device Screenshot" button on the toolbar (the second one from the left). What this does is it takes a dump of the current screen on your device and dump the xml layout structure to you.

As an example, let's try to mod something. My previous mod for my Teclast X98 Air 3G missed something. The brightness slider isn't centered as shown in the screenshot.

My quick guess is the decoding added a "left" in the layout_gravity property. So we'll need to change the layout_gravity from "center|top|left" back to "center|top". Of course you can do a quick grep to look for the "center|top" keyword in the resources subdirectories and look for each occurrence to see if they are it. That's not the best way to do things. To figure out what the id of that slider is, we put the tablet into the condition we want and press the "Device Screenshot" button in the toolbar to get something like the following image:

Note: I had to keep my finger on the slider in order to get this screenshot

Then what follows is very similar to the DOM Inspectors. Simply click on the slider, the selected xml element will be indicated on the right. Keep clicking on the parent views until you get to the parent view that holds the entire slider dialog. In this case, it happens to a be FrameLayout. The resource-id of this layout is indicated on the bottom right. This also shows many other properties of the views you are inspecting.

The resource-id says com.android.systemui:id/brightness_mirror The first bit is just the package name. The id is really @+id/brightness_mirror So we'll simply need to do a grep on the resources directory of the decoded SystemUI package to look for brightness_mirror.

grep -r . -e 'brightness_mirror'

My returned result is:

$ grep -r . -e "brightness_mirror"
./SystemUI/res/values/public.xml:    <public type="drawable" name="brightness_mirror_background" id="0x7f020004" />
./SystemUI/res/values/public.xml:    <public type="id" name="brightness_mirror" id="0x7f0e0115" />
./SystemUI/res/values/ids.xml:    <item type="id" name="brightness_mirror">false</item>
./SystemUI/res/layout/super_status_bar.xml:    <FrameLayout android:layout_gravity="center|left|top" android:id="@id/brightness_mirror" android:paddingLeft="@dimen/notification_side_padding" android:paddingRight="@dimen/notification_side_padding" android:visibility="gone" android:layout_width="@dimen/notification_panel_width" android:layout_height="wrap_content">
./SystemUI/res/layout/super_status_bar.xml:        <FrameLayout android:background="@drawable/brightness_mirror_background" android:layout_width="fill_parent" android:layout_height="fill_parent" android:elevation="2.0dip">
Binary file ./SystemUI/dist/SystemUI.apk matches
Binary file ./SystemUI/build/apk/resources.arsc matches
./SystemUI/original/META-INF/CERT.SF:Name: res/drawable/brightness_mirror_background.xml
./SystemUI/original/META-INF/MANIFEST.MF:Name: res/drawable/brightness_mirror_background.xml
Binary file ./SystemUI.apk matches
Binary file ./new.apk matches

From this result, I see that the line gives us details about where it is referenced (super_staus_bar.xml):

./SystemUI/res/layout/super_status_bar.xml:    <FrameLayout android:layout_gravity="center|left|top" android:id="@id/brightness_mirror" android:paddingLeft="@dimen/notification_side_padding" android:paddingRight="@dimen/notification_side_padding" android:visibility="gone" android:layout_width="@dimen/notification_panel_width" android:layout_height="wrap_content">

Furthermore, it also shows the layout_gravity property that we're interested in with the value "center|left|top", change that, repackage, push back onto the device and you're good to go.


Here are my edits for my lockscreen, I've removed the carrier text as I'm not using 3G. I've removed the icons for camera and phone because they're not used very often. And I've also removed the cell network signal status icon. Just the way I like it.

No comments :

Post a Comment