# Instrumenting Android

There are multiple ways to use the profiler with Android. There is the "Java"
profiler feature (via <about:profiling>), which enables profiling for JVM code.
This is most likely turned on already for the preset if you are profiling an
Android device.

In addition to sampling, markers can be created to specifically mark an instant
in time, or a duration. This can be helpful to make sense of a particular piece
of the front-end, or record events that normally wouldn't show up in samples.

:::{note}
This guide explains Android markers in depth. To learn more about how to add a
marker in C++, JavaScript or Rust, please take a look at their documentation
in {doc}`markers-guide`, {doc}`instrumenting-javascript` or
{doc}`instrumenting-rust` respectively.
:::

## Markers in the GeckoView Java codebase

If you are in the GeckoView codebase, then you should have access to `ProfilerController`.
See the {searchfox}`ProfilerController Java file <mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ProfilerController.java>` ([javadoc]) to find which methods you can use to
instrument your source code.

Here's an example:

```java
// Simple marker
ProfilerController().addMarker("Marker Name");

// Simple marker with additional information
ProfilerController().addMarker("Marker Name", "info");

// Duration marker
Double startTime = ProfilerController().getProfilerTime();
// ...some code you want to measure...
ProfilerController().addMarker("Marker Name", startTime);

// Duration marker with additional information
ProfilerController().addMarker("Marker Name", startTime, "info");
```

There are various overloads of `addMarker` you can choose depending on your need.

If you need to compute some information before adding it to a marker, it's
recommended to wrap that code with a `isProfilerActive` if check to make sure
that it's only executed while the profiler is active. Here's an example:

```java
ProfilerController profilerController = runtime.getProfilerController();
if (profilerController.isProfilerActive()) {
  // Compute the information you want to include.
  String info = ...
  sGeckoRuntime.getProfilerController().addMarker("Marker Name", info);
}
```

## Markers in the Fenix codebase

If you are in the Fenix codebase, then you should have access to the Android
components. The Android components includes a {searchfox}`Profiler interface here <mobile/android/android-components/components/concept/base/src/main/java/mozilla/components/concept/base/profiler/Profiler.kt>`, with
its corresponding {searchfox}`implementation here <mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/profiler/Profiler.kt>`. You should be able to do everything
you can do with the `ProfilerController`. Here's an example on how to call them:

```kotlin
// Simple marker
components.core.engine.profiler?.addMarker("Marker Name");

// Simple marker with additional information
components.core.engine.profiler?.addMarker("Marker Name", "info");

// Duration marker
val startTime = components.core.engine.profiler?.getProfilerTime()
// ...some code you want to measure...
components.core.engine.profiler?.addMarker("Marker Name", startTime, "additional info")

// Duration marker with additional information
components.core.engine.profiler?.addMarker("Marker Name", startTime, "info");
```

Similarly, there are various overloads of `addMarker` you can choose depending on your needs.

Like for the GeckoView example above, if you need to compute some information
before adding it to a marker, it's recommended to wrap that code with a
`isProfilerActive` if check to make sure that it's only executed while the
profiler is active. Here's an example:

```kotlin
if (components.core.engine.profiler?.isProfilerActive() == true) {
  // Compute the information you want to include.
  var info = ...
  components.core.engine.profiler?.addMarker("Marker Name", info)
}
```

[javadoc]: https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/ProfilerController.html
