Repository navigation
Dynamic Call Graph
-mc records callsites reached during execution and, when possible, the method implementation that was entered. The resulting graph describes the supplied run; it does not enumerate all calls that could occur.
Enable -mc when instrumenting and when reporting. Adding it only during parsing cannot recover runtime dispatch information that was never recorded. It can be used alone for a graph-only report, or with coverage options.
Consider this virtual call:
Animal animal = new Dog();
animal.speak();The bytecode refers to Animal.speak(). If execution enters an instrumented override Dog.speak(), AndroLog can record the actual relationship:
caller → Dog.speak()
The same mechanism applies to interface dispatch. If one callsite reaches several implementations during the captured execution, it can contribute several confirmed targets.
AndroLog correlates the callsite and callee entry inside the app process. It checks the same thread, exact method subsignature, receiver identity for instance calls, and the direct caller stack. It does not infer a target simply from the next method name appearing in logcat. Normal polymorphic calls between instrumented methods should be confirmed when matching observations are retained.
| Style | What AndroLog recorded |
|---|---|
| Solid: confirmed runtime target | A matching instrumented entry confirmed the callee |
| Dashed: declared target | The callsite was reached, but no callee entry was confirmed; the bytecode target is retained |
The dashed style currently means missing entry confirmation, not necessarily an unknown target. The current report uses the same style for several different situations:
| Situation | Why an edge may be dashed |
|---|---|
| Constructor | Constructor entry confirmation is deliberately skipped by the current tracer |
| Framework or native code | The method body is outside the instrumented APK |
| Excluded APK code | Scope filters prevented instrumentation of the callee |
| Dynamic invoke | The current tracer records its declaration without confirming entry |
| Failure before method entry | For example, an instance call on a null receiver |
| Incomplete observations | A confirmation record was not retained, or matching failed |
Legacy CALL= record |
The older format contains declared targets only |
Constructors are non-overridable direct calls, not virtual dispatch. For new Dog(), the constructor selected in the bytecode is already known. Android documents constructors under invoke-direct. Android bytecode specification
AndroLog's normal matching hook passes the receiver object. The current implementation avoids exposing an uninitialized receiver by skipping constructor entry confirmation. Consequently, even an app constructor with a known target is displayed as dashed. This is an implementation choice, not evidence that constructor dispatch is ambiguous. Constructor-specific confirmation and a separate known-target edge category are not implemented in the current version.
A direct or static framework call can have a known target despite the absence of a framework entry probe. Such calls still appear dashed under the current two-style scheme.
A virtual reference to a framework class is different. For example, View.draw() can dispatch to an app's MyView.draw() override. The declared framework class alone does not establish the implementation that ran. If the override is instrumented and matches the pending call, it can be confirmed normally.
A framework callback may be observed by coverage probes without a confirmed incoming call edge, because its caller is not instrumented. Reflection, uninstrumented intermediaries, and asynchronous work are not inferred as direct calls from a previously recorded app callsite. A temporal relationship is not enough to establish a direct caller-to-callee edge.
The default class comes from manifest launcher metadata: MAIN with LAUNCHER, or LEANBACK_LAUNCHER for TV. Aliases resolve to their target activity classes. If several launcher classes have recorded calls, the first in alphabetical order opens.
Selecting a class shows relationships directly incident to its methods, including endpoints outside the class. Clicking a node emphasizes its incoming and outgoing edges and fades the others. Reset graph clears that emphasis; Fit adjusts the view. If no launcher has matching data, select a class manually. The report does not open the whole application's graph by default.
See HTML Report for screenshots and controls.
Each callsite declaration and each callsite/actual-target pair is emitted once per process. Edge counts represent distinct accepted records, not invocation frequency. Several callsites between the same methods can contribute to one edge. A callsite with confirmed targets contributes those targets instead of a declared fallback edge.
Missing records can omit edges or leave a declared edge. The tracer also captures stack traces and adds runtime overhead. Narrowing scope or selecting fewer probes can reduce work, but changes what the report can measure. Keep those choices consistent when comparing runs.
The JSON and Logs guide explains edge fields, callsite identifiers, and MC2 records. The troubleshooting guide covers unexpectedly missing confirmations.
Home · Quick Start · CLI Reference · Report an issue
AndroLog by Jordan Samhi · LGPL v2.1 · Documentation checked against 68b3312, 23 October 2026.
Start here
Understand your results
Reference