#![doc = include_str!("../README.md")]
#[cfg(not(feature = "api_level_23"))]
use ffi::ATraceAPILevel23Methods;
#[cfg(not(feature = "api_level_29"))]
use ffi::ATraceAPILevel29Methods;
use core::ffi::CStr;
use std::fmt::Debug;
#[cfg(not(target_os = "android"))]
compile_error!(
r#"android_trace only supports Android. If you are depending on it, ensure that it is within
[target.'cfg(target_os = "android")'.dependencies]
in your Cargo.toml"#
);
mod ffi;
#[derive(Clone)]
pub struct AndroidTrace {
#[cfg(not(feature = "api_level_23"))]
api_level_23: Option<&'static ATraceAPILevel23Methods>,
#[cfg(not(feature = "api_level_29"))]
api_level_29: Option<&'static ATraceAPILevel29Methods>,
}
impl AndroidTrace {
pub fn new() -> Self {
Self {
#[cfg(not(feature = "api_level_23"))]
api_level_23: ATraceAPILevel23Methods::get(),
#[cfg(not(feature = "api_level_29"))]
api_level_29: ATraceAPILevel29Methods::get(),
}
}
pub fn new_downlevel() -> Self {
Self {
#[cfg(not(feature = "api_level_23"))]
api_level_23: ATraceAPILevel23Methods::get(),
#[cfg(not(feature = "api_level_29"))]
api_level_29: None,
}
}
#[doc(alias = "ATrace_isEnabled")]
#[must_use = "Detecting if tracing is enabled has no side effects"]
pub fn is_enabled(&self) -> Option<bool> {
#[cfg(feature = "api_level_23")]
unsafe {
Some(ffi::atrace_is_enabled_raw())
}
#[cfg(not(feature = "api_level_23"))]
if let Some(methods) = self.api_level_23 {
let result = unsafe { (methods.is_enabled)() };
Some(result)
} else {
None
}
}
#[doc(alias = "ATrace_beginSection")]
pub fn begin_section(&self, section_name: &CStr) {
#[cfg(feature = "api_level_23")]
unsafe {
ffi::atrace_begin_section_raw(section_name.as_ptr());
}
#[cfg(not(feature = "api_level_23"))]
if let Some(methods) = self.api_level_23 {
unsafe { (methods.begin_section)(section_name.as_ptr()) }
}
}
#[doc(alias = "ATrace_endSection")]
pub fn end_section(&self) {
#[cfg(feature = "api_level_23")]
unsafe {
ffi::atrace_end_section_raw();
}
#[cfg(not(feature = "api_level_23"))]
if let Some(methods) = self.api_level_23 {
unsafe { (methods.end_section)() }
}
}
#[doc(alias = "ATrace_beginAsyncSection")]
pub fn begin_async_section(&self, section_name: &CStr, cookie: i32) -> Option<()> {
#[cfg(feature = "api_level_29")]
unsafe {
ffi::atrace_begin_async_section_raw(section_name.as_ptr(), cookie);
Some(())
}
#[cfg(not(feature = "api_level_29"))]
if let Some(methods) = self.api_level_29 {
unsafe { (methods.begin_async_section)(section_name.as_ptr(), cookie) }
Some(())
} else {
None
}
}
#[doc(alias = "ATrace_endAsyncSection")]
pub fn end_async_section(&self, section_name: &CStr, cookie: i32) -> Option<()> {
#[cfg(feature = "api_level_29")]
unsafe {
ffi::atrace_end_async_section_raw(section_name.as_ptr(), cookie);
Some(())
}
#[cfg(not(feature = "api_level_29"))]
if let Some(methods) = self.api_level_29 {
unsafe { (methods.end_async_section)(section_name.as_ptr(), cookie) }
Some(())
} else {
None
}
}
pub fn could_use_api_level_29(&self) -> bool {
#[cfg(not(feature = "api_level_29"))]
return self.api_level_29.is_some();
#[cfg(feature = "api_level_29")]
true
}
#[doc(alias = "ATrace_setCounter")]
pub fn set_counter(&self, counter_name: &CStr, value: i64) -> Option<()> {
#[cfg(feature = "api_level_29")]
unsafe {
ffi::atrace_set_counter_raw(counter_name.as_ptr(), value);
Some(())
}
#[cfg(not(feature = "api_level_29"))]
if let Some(methods) = self.api_level_29 {
unsafe { (methods.set_counter)(counter_name.as_ptr(), value) }
Some(())
} else {
None
}
}
}
impl Default for AndroidTrace {
fn default() -> Self {
Self::new()
}
}
impl Debug for AndroidTrace {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
#[cfg(not(feature = "api_level_23"))]
let has_level_23 = self.api_level_23.is_some();
#[cfg(feature = "api_level_23")]
let has_level_23 = true;
#[cfg(not(feature = "api_level_29"))]
let has_level_29 = self.api_level_29.is_some();
#[cfg(feature = "api_level_29")]
let has_level_29 = true;
let api_level = match (has_level_29, has_level_23) {
(true, true) => "29",
(false, true) => "23",
(false, false) => "None",
(true, false) => "Unexpected: 29 but not 23",
};
f.debug_struct("AndroidTrace")
.field("api_level", &api_level)
.finish()
}
}
#[cfg(test)]
mod test {
use super::*;
use static_assertions as sa;
sa::assert_impl_all!(AndroidTrace: Send, Sync);
}