Analyze an Android App with JQAssistant

Stefan Bieliauskas
5 min readApr 27, 2020

--

This article describes a method to analyze Android APK’s via a graph-based static code analysis tool. I will probe the Amazon Go App and will discover some improvements, interesting metrics, and a potential user-facing bug.

The source code for all queries and software I used is available at Github

graph representation of source-code

The method

Static code analyze is a method to find potential code-smells, bugs and ensure that certain coding standards. There are several tools out there to do such analyzes with some exciting approaches like machine learning, 👉 see here, or here for a general overview.

My approach is rather simple and can be done by everyone within a couple of hours. To analyze an android app we need to follow the next few steps.

APK processing

Preprocessing

An Android APK file is an executable representation of a jar file. The APK file contains classes and other information in the DEX file format. The dex2Jar transforms the dex file into a regular jar file, but be aware that there will be some classes that can’t be transformed. The reason for those errors are various, e.g. security measurements during the build process. In the end, you have to work with what you got. 😉

Analyze — JQAssistant

Now the fun starts! In a nutshell, JQAssistant is a tool to save the AST model of the source code into a searchable graph-database. This allows us to explore the source code via its nodes and relationships. Here is an excellent article about the idea and the tool itself 👉 software as a database.

Graph representation of a Java Annotation

The diagram above describes the relationship between a method or class annotation and the annotation class. The corresponding source code could look like this.

class @interface GetMapping {
....
}
class HelloController {

@GetMapping("/hello")
public void helllp() {
...
}
}

I will not get deeper into the method, but I hope you have a rough idea, how it works — if you have some question marks over your head — don’t worry, it will be more clear at the end of the article.

The Questions

Here comes your creativity in play! Think of code-smells or potential bugs most likely could express it as a Neo4j query and get quick results. I picked some simple ones to identify possible code sections that could be improved!

1. Some metrics

I got some general metrics to get to know the source code:

╒═════════╤════════════╤═══════╤═════════════╤═════════╤════════╕
│"classes"│"interfaces"│"enums"│"annotations"│"methods"│"fields"│
╞═════════╪════════════╪═══════╪═════════════╪═════════╪════════╡
│7696 │834 │331 │87 │64598 │35924 │
└─────────┴────────────┴───────┴─────────────┴─────────┴────────┘
// Chypher query: https://github.com/B-Stefan/amz-apk-analysis#queries

Nothing really to get out of the raw metrics; besides, we could assume that this project does not rely on annotations as much as, e.g. a spring boot application would do. 👏👏

2. Usage of deprecated methods

Question: Are we still using some deprecated methods?

The caller calls a deprecated method — that would mean that the caller class should be refactored to remove the usage of the deprecated method.

The following table displays a summary grouped by the package. These packages will need some refactoring in the future, so a great place to start housekeeping 🙌

╒══════════════════════════╤═══════════════════════════╕
│"packagePrefix" │"numberOfDeprecationUsages"│
╞══════════════════════════╪═══════════════════════════╡
│"com.amazon.ihm" │50 │
├──────────────────────────┼───────────────────────────┤
│"com.amazon.identity" │17 │
├──────────────────────────┼───────────────────────────┤
│"com.amazon.coral" │3 │
├──────────────────────────┼───────────────────────────┤
│"com.amazon.client" │2 │
├──────────────────────────┼───────────────────────────┤
│"com.amazon.communication"│3 │
└──────────────────────────┴───────────────────────────┘
// Chypher query: https://github.com/B-Stefan/amz-apk-analysis#queries

That shows us that we have 50 code lines that depend on deprecated function in com.amazon.ihm.

3. Exception Handling

Question: Are there and misused standard java lang exception?

In Java there are many best practices and patterns that a project can enforce, and every software project follows there own slightly different rules. So let’s see if we find something odd within the exception handling:

╒══════════════════════════════════════════╤══════════╕
│"exception" │"threw" │
╞══════════════════════════════════════════╪══════════╡
│"java.lang.ArrayIndexOutOfBoundsException"│2 │
├──────────────────────────────────────────┼──────────┤
│"java.lang.CloneNotSupportedException" │2 │
├──────────────────────────────────────────┼──────────┤
│"java.lang.Exception" │2 │
├──────────────────────────────────────────┼──────────┤
│"java.lang.IllegalAccessException" │15 │
├──────────────────────────────────────────┼──────────┤
│"java.lang.IllegalArgumentException" │313 │
├──────────────────────────────────────────┼──────────┤
│"java.lang.IllegalStateException" │118 │
├──────────────────────────────────────────┼──────────┤
│"java.lang.IndexOutOfBoundsException" │4 │
├──────────────────────────────────────────┼──────────┤
│"java.lang.NullPointerException" │32 │
├──────────────────────────────────────────┼──────────┤
│"java.lang.RuntimeException" │93 │
├──────────────────────────────────────────┼──────────┤
│"java.lang.SecurityException" │6 │
├──────────────────────────────────────────┼──────────┤
│"java.lang.UnsupportedOperationException" │140 │
└──────────────────────────────────────────┴──────────┘
// Chypher query: https://github.com/B-Stefan/amz-apk-analysis#queries

There we have something: java.lang.Exception is used directly. And only in one Class, that seems a little bit odd.
It could lead to an error on the customer UI — so let’s look into this.

Here we have the two nodes. The first one: CategoriesFragment in some menu, and the second node: The standard Exception itself. We see here that the CategoriesFragment depends on the Exception but we don’t know what kind of dependency exists between them and it could be totally fine. But it is an unusual dependency for this particular App.

If I would like to improve the stability of the App that might be a good point to look into! 👈👈

Conclusion

Let’s wrap up this — JQAssistent gives a great place to start searching source code via a graph-database!

  • 📊📈Saw some general metrics: 7K classes and 64K methods analyzed.
  • 🧹🏠 Housekeeping: The com.amazon.ihm package needs refactoring due to the usage of deprecated methods
  • ❗⛔ Exception handling: I discovered that the CategoriesFragment might handle Exceptions not as supposed to. This could affect customer experience and might be a bug!

There are many ideas on how to extends this analysis, for example, detect more complex patterns that should be avoided, e.g. “don’t create a log entry and re-throw the exception”.

Do you have any questions? Don’t hesitate to contact me. I am happy to answer any questions!

--

--