• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2023 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! ATrace instrumentation methods from cutils.
16 
17 use std::ffi::CString;
18 
19 #[cfg(not(test))]
20 use cutils_trace_bindgen as trace_bind;
21 
22 // Wrap tags into a mod to allow missing docs.
23 // We have to use the mod for this because Rust won't apply the attribute to the bitflags macro
24 // invocation.
25 pub use self::tags::*;
26 pub mod tags {
27     // Tag constants are not documented in libcutils, so we don't document them here.
28     #![allow(missing_docs)]
29 
30     use bitflags::bitflags;
31     use static_assertions::const_assert_eq;
32 
33     bitflags! {
34         /// The trace tag is used to filter tracing in userland to avoid some of the runtime cost of
35         /// tracing when it is not desired.
36         ///
37         /// Using `AtraceTag::Always` will result in the tracing always being enabled - this should
38         /// ONLY be done for debug code, as userland tracing has a performance cost even when the
39         /// trace is not being recorded. `AtraceTag::Never` will result in the tracing always being
40         /// disabled.
41         ///
42         /// `AtraceTag::Hal` should be bitwise ORed with the relevant tags for tracing
43         /// within a hardware module. For example a camera hardware module would use
44         /// `AtraceTag::Camera | AtraceTag::Hal`.
45         ///
46         /// Source of truth is `system/core/libcutils/include/cutils/trace.h`.
47         #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
48         pub struct AtraceTag: u64 {
49             const Never           = cutils_trace_bindgen::ATRACE_TAG_NEVER as u64;
50             const Always          = cutils_trace_bindgen::ATRACE_TAG_ALWAYS as u64;
51             const Graphics        = cutils_trace_bindgen::ATRACE_TAG_GRAPHICS as u64;
52             const Input           = cutils_trace_bindgen::ATRACE_TAG_INPUT as u64;
53             const View            = cutils_trace_bindgen::ATRACE_TAG_VIEW as u64;
54             const Webview         = cutils_trace_bindgen::ATRACE_TAG_WEBVIEW as u64;
55             const WindowManager   = cutils_trace_bindgen::ATRACE_TAG_WINDOW_MANAGER as u64;
56             const ActivityManager = cutils_trace_bindgen::ATRACE_TAG_ACTIVITY_MANAGER as u64;
57             const SyncManager     = cutils_trace_bindgen::ATRACE_TAG_SYNC_MANAGER as u64;
58             const Audio           = cutils_trace_bindgen::ATRACE_TAG_AUDIO as u64;
59             const Video           = cutils_trace_bindgen::ATRACE_TAG_VIDEO as u64;
60             const Camera          = cutils_trace_bindgen::ATRACE_TAG_CAMERA as u64;
61             const Hal             = cutils_trace_bindgen::ATRACE_TAG_HAL as u64;
62             const App             = cutils_trace_bindgen::ATRACE_TAG_APP as u64;
63             const Resources       = cutils_trace_bindgen::ATRACE_TAG_RESOURCES as u64;
64             const Dalvik          = cutils_trace_bindgen::ATRACE_TAG_DALVIK as u64;
65             const Rs              = cutils_trace_bindgen::ATRACE_TAG_RS as u64;
66             const Bionic          = cutils_trace_bindgen::ATRACE_TAG_BIONIC as u64;
67             const Power           = cutils_trace_bindgen::ATRACE_TAG_POWER as u64;
68             const PackageManager  = cutils_trace_bindgen::ATRACE_TAG_PACKAGE_MANAGER as u64;
69             const SystemServer    = cutils_trace_bindgen::ATRACE_TAG_SYSTEM_SERVER as u64;
70             const Database        = cutils_trace_bindgen::ATRACE_TAG_DATABASE as u64;
71             const Network         = cutils_trace_bindgen::ATRACE_TAG_NETWORK as u64;
72             const Adb             = cutils_trace_bindgen::ATRACE_TAG_ADB as u64;
73             const Vibrator        = cutils_trace_bindgen::ATRACE_TAG_VIBRATOR as u64;
74             const Aidl            = cutils_trace_bindgen::ATRACE_TAG_AIDL as u64;
75             const Nnapi           = cutils_trace_bindgen::ATRACE_TAG_NNAPI as u64;
76             const Rro             = cutils_trace_bindgen::ATRACE_TAG_RRO as u64;
77             const Thermal         = cutils_trace_bindgen::ATRACE_TAG_THERMAL as u64;
78             const Last            = cutils_trace_bindgen::ATRACE_TAG_LAST as u64;
79             const NotReady        = cutils_trace_bindgen::ATRACE_TAG_NOT_READY as u64;
80             const ValidMask       = cutils_trace_bindgen::ATRACE_TAG_VALID_MASK as u64;
81         }
82     }
83 
84     // Assertion to keep tags in sync. If it fails, it means there are new tags added to
85     // cutils/trace.h. Add them to the tags above and update the assertion.
86     const_assert_eq!(AtraceTag::Thermal.bits(), cutils_trace_bindgen::ATRACE_TAG_LAST as u64);
87 }
88 
89 /// RAII guard to close an event with tag.
90 pub struct ScopedEvent {
91     tag: AtraceTag,
92 }
93 
94 impl Drop for ScopedEvent {
drop(&mut self)95     fn drop(&mut self) {
96         atrace_end(self.tag);
97     }
98 }
99 
100 /// Begins an event via `atrace_begin` and returns a guard that calls `atrace_end` when dropped.
begin_scoped_event(tag: AtraceTag, name: &str) -> ScopedEvent101 pub fn begin_scoped_event(tag: AtraceTag, name: &str) -> ScopedEvent {
102     atrace_begin(tag, name);
103     ScopedEvent { tag }
104 }
105 
106 /// Creates a scoped event with the current method name.
107 #[macro_export]
108 macro_rules! trace_method {
109     {$tag:expr} => {
110         let mut _atrace_trace_method_name: &'static str = "";
111         {
112             // Declares function f inside current function.
113             fn f() {}
114             fn type_name_of<T>(_: T) -> &'static str {
115                 std::any::type_name::<T>()
116             }
117             // type name of f is struct_or_crate_name::calling_function_name::f
118             let name = type_name_of(f);
119             // Remove the third to last character ("::f")
120             _atrace_trace_method_name = &name[..name.len() - 3];
121         }
122         let _atrace_trace_method_guard = atrace::begin_scoped_event($tag, _atrace_trace_method_name);
123     };
124 }
125 
126 /// Set whether tracing is enabled for the current process. This is used to prevent tracing within
127 /// the Zygote process.
atrace_set_tracing_enabled(enabled: bool)128 pub fn atrace_set_tracing_enabled(enabled: bool) {
129     // SAFETY: No pointers are transferred.
130     unsafe {
131         trace_bind::atrace_set_tracing_enabled(enabled);
132     }
133 }
134 
135 /// `atrace_init` readies the process for tracing by opening the trace_marker file.
136 /// Calling any trace function causes this to be run, so calling it is optional.
137 /// This can be explicitly run to avoid setup delay on first trace function.
atrace_init()138 pub fn atrace_init() {
139     // SAFETY: Call with no arguments.
140     unsafe {
141         trace_bind::atrace_init();
142     }
143 }
144 
145 /// Returns enabled tags as a bitmask.
146 ///
147 /// The tag mask is converted into an `AtraceTag`, keeping flags that do not correspond to a tag.
atrace_get_enabled_tags() -> AtraceTag148 pub fn atrace_get_enabled_tags() -> AtraceTag {
149     // SAFETY: Call with no arguments that returns a 64-bit int.
150     unsafe { AtraceTag::from_bits_retain(trace_bind::atrace_get_enabled_tags()) }
151 }
152 
153 /// Test if a given tag is currently enabled.
154 ///
155 /// It can be used as a guard condition around more expensive trace calculations.
atrace_is_tag_enabled(tag: AtraceTag) -> bool156 pub fn atrace_is_tag_enabled(tag: AtraceTag) -> bool {
157     // SAFETY: No pointers are transferred.
158     unsafe { trace_bind::atrace_is_tag_enabled_wrap(tag.bits()) != 0 }
159 }
160 
161 /// Trace the beginning of a context. `name` is used to identify the context.
162 ///
163 /// This is often used to time function execution.
atrace_begin(tag: AtraceTag, name: &str)164 pub fn atrace_begin(tag: AtraceTag, name: &str) {
165     if !atrace_is_tag_enabled(tag) {
166         return;
167     }
168 
169     let name_cstr = CString::new(name.as_bytes()).expect("CString::new failed");
170     // SAFETY: The function does not accept the pointer ownership, only reads its contents.
171     // The passed string is guaranteed to be null-terminated by CString.
172     unsafe {
173         trace_bind::atrace_begin_wrap(tag.bits(), name_cstr.as_ptr());
174     }
175 }
176 
177 /// Trace the end of a context.
178 ///
179 /// This should match up (and occur after) a corresponding `atrace_begin`.
atrace_end(tag: AtraceTag)180 pub fn atrace_end(tag: AtraceTag) {
181     // SAFETY: No pointers are transferred.
182     unsafe {
183         trace_bind::atrace_end_wrap(tag.bits());
184     }
185 }
186 
187 /// Trace the beginning of an asynchronous event. Unlike `atrace_begin`/`atrace_end` contexts,
188 /// asynchronous events do not need to be nested.
189 ///
190 /// The name describes the event, and the cookie provides a unique identifier for distinguishing
191 /// simultaneous events.
192 ///
193 /// The name and cookie used to begin an event must be used to end it.
atrace_async_begin(tag: AtraceTag, name: &str, cookie: i32)194 pub fn atrace_async_begin(tag: AtraceTag, name: &str, cookie: i32) {
195     if !atrace_is_tag_enabled(tag) {
196         return;
197     }
198 
199     let name_cstr = CString::new(name.as_bytes()).expect("CString::new failed");
200     // SAFETY: The function does not accept the pointer ownership, only reads its contents.
201     // The passed string is guaranteed to be null-terminated by CString.
202     unsafe {
203         trace_bind::atrace_async_begin_wrap(tag.bits(), name_cstr.as_ptr(), cookie);
204     }
205 }
206 
207 /// Trace the end of an asynchronous event.
208 ///
209 /// This should have a corresponding `atrace_async_begin`.
atrace_async_end(tag: AtraceTag, name: &str, cookie: i32)210 pub fn atrace_async_end(tag: AtraceTag, name: &str, cookie: i32) {
211     if !atrace_is_tag_enabled(tag) {
212         return;
213     }
214 
215     let name_cstr = CString::new(name.as_bytes()).expect("CString::new failed");
216     // SAFETY: The function does not accept the pointer ownership, only reads its contents.
217     // The passed string is guaranteed to be null-terminated by CString.
218     unsafe {
219         trace_bind::atrace_async_end_wrap(tag.bits(), name_cstr.as_ptr(), cookie);
220     }
221 }
222 
223 /// Trace the beginning of an asynchronous event.
224 ///
225 /// In addition to the name and a cookie as in `atrace_async_begin`/`atrace_async_end`, a track name
226 /// argument is provided, which is the name of the row where this async event should be recorded.
227 ///
228 /// The track name and cookie used to begin an event must be used to end it.
229 ///
230 /// The cookie here must be unique on the track_name level, not the name level.
atrace_async_for_track_begin(tag: AtraceTag, track_name: &str, name: &str, cookie: i32)231 pub fn atrace_async_for_track_begin(tag: AtraceTag, track_name: &str, name: &str, cookie: i32) {
232     if !atrace_is_tag_enabled(tag) {
233         return;
234     }
235 
236     let name_cstr = CString::new(name.as_bytes()).expect("CString::new failed");
237     let track_name_cstr = CString::new(track_name.as_bytes()).expect("CString::new failed");
238     // SAFETY: The function does not accept the pointer ownership, only reads its contents.
239     // The passed strings are guaranteed to be null-terminated by CString.
240     unsafe {
241         trace_bind::atrace_async_for_track_begin_wrap(
242             tag.bits(),
243             track_name_cstr.as_ptr(),
244             name_cstr.as_ptr(),
245             cookie,
246         );
247     }
248 }
249 
250 /// Trace the end of an asynchronous event.
251 ///
252 /// This should correspond to a previous `atrace_async_for_track_begin`.
atrace_async_for_track_end(tag: AtraceTag, track_name: &str, cookie: i32)253 pub fn atrace_async_for_track_end(tag: AtraceTag, track_name: &str, cookie: i32) {
254     if !atrace_is_tag_enabled(tag) {
255         return;
256     }
257 
258     let track_name_cstr = CString::new(track_name.as_bytes()).expect("CString::new failed");
259     // SAFETY: The function does not accept the pointer ownership, only reads its contents.
260     // The passed string is guaranteed to be null-terminated by CString.
261     unsafe {
262         trace_bind::atrace_async_for_track_end_wrap(tag.bits(), track_name_cstr.as_ptr(), cookie);
263     }
264 }
265 
266 /// Trace an instantaneous context. `name` is used to identify the context.
267 ///
268 /// An "instant" is an event with no defined duration. Visually is displayed like a single marker
269 /// in the timeline (rather than a span, in the case of begin/end events).
270 ///
271 /// By default, instant events are added into a dedicated track that has the same name of the event.
272 /// Use `atrace_instant_for_track` to put different instant events into the same timeline track/row.
atrace_instant(tag: AtraceTag, name: &str)273 pub fn atrace_instant(tag: AtraceTag, name: &str) {
274     if !atrace_is_tag_enabled(tag) {
275         return;
276     }
277 
278     let name_cstr = CString::new(name.as_bytes()).expect("CString::new failed");
279     // SAFETY: The function does not accept the pointer ownership, only reads its contents.
280     // The passed string is guaranteed to be null-terminated by CString.
281     unsafe {
282         trace_bind::atrace_instant_wrap(tag.bits(), name_cstr.as_ptr());
283     }
284 }
285 
286 /// Trace an instantaneous context. `name` is used to identify the context. `track_name` is the name
287 /// of the row where the event should be recorded.
288 ///
289 /// An "instant" is an event with no defined duration. Visually is displayed like a single marker
290 /// in the timeline (rather than a span, in the case of begin/end events).
atrace_instant_for_track(tag: AtraceTag, track_name: &str, name: &str)291 pub fn atrace_instant_for_track(tag: AtraceTag, track_name: &str, name: &str) {
292     if !atrace_is_tag_enabled(tag) {
293         return;
294     }
295 
296     let name_cstr = CString::new(name.as_bytes()).expect("CString::new failed");
297     let track_name_cstr = CString::new(track_name.as_bytes()).expect("CString::new failed");
298     // SAFETY: The function does not accept the pointer ownership, only reads its contents.
299     // The passed string is guaranteed to be null-terminated by CString.
300     unsafe {
301         trace_bind::atrace_instant_for_track_wrap(
302             tag.bits(),
303             track_name_cstr.as_ptr(),
304             name_cstr.as_ptr(),
305         );
306     }
307 }
308 
309 /// Traces an integer counter value. `name` is used to identify the counter.
310 ///
311 /// This can be used to track how a value changes over time.
atrace_int(tag: AtraceTag, name: &str, value: i32)312 pub fn atrace_int(tag: AtraceTag, name: &str, value: i32) {
313     if !atrace_is_tag_enabled(tag) {
314         return;
315     }
316 
317     let name_cstr = CString::new(name.as_bytes()).expect("CString::new failed");
318     // SAFETY: The function does not accept the pointer ownership, only reads its contents.
319     // The passed string is guaranteed to be null-terminated by CString.
320     unsafe {
321         trace_bind::atrace_int_wrap(tag.bits(), name_cstr.as_ptr(), value);
322     }
323 }
324 
325 /// Traces a 64-bit integer counter value. `name` is used to identify the counter.
326 ///
327 /// This can be used to track how a value changes over time.
atrace_int64(tag: AtraceTag, name: &str, value: i64)328 pub fn atrace_int64(tag: AtraceTag, name: &str, value: i64) {
329     if !atrace_is_tag_enabled(tag) {
330         return;
331     }
332 
333     let name_cstr = CString::new(name.as_bytes()).expect("CString::new failed");
334     // SAFETY: The function does not accept the pointer ownership, only reads its contents.
335     // The passed string is guaranteed to be null-terminated by CString.
336     unsafe {
337         trace_bind::atrace_int64_wrap(tag.bits(), name_cstr.as_ptr(), value);
338     }
339 }
340 
341 #[cfg(test)]
342 use self::tests::mock_atrace as trace_bind;
343 
344 #[cfg(test)]
345 mod tests {
346     use super::*;
347 
348     use std::ffi::CStr;
349     use std::os::raw::c_char;
350 
351     /// Utilities to mock ATrace bindings.
352     ///
353     /// Normally, for behavior-driven testing we focus on the outcomes of the functions rather than
354     /// calls into bindings. However, since the purpose of the library is to forward data into
355     /// the underlying implementation (which we assume to be correct), that's what we test.
356     pub mod mock_atrace {
357         use std::cell::RefCell;
358         use std::os::raw::c_char;
359 
360         /// Contains logic to check binding calls.
361         /// Implement this trait in the test with mocking logic and checks in implemented functions.
362         /// Default implementations panic.
363         pub trait ATraceMocker {
atrace_set_tracing_enabled(&mut self, _enabled: bool)364             fn atrace_set_tracing_enabled(&mut self, _enabled: bool) {
365                 panic!("Unexpected call");
366             }
atrace_init(&mut self)367             fn atrace_init(&mut self) {
368                 panic!("Unexpected call");
369             }
atrace_get_enabled_tags(&mut self) -> u64370             fn atrace_get_enabled_tags(&mut self) -> u64 {
371                 panic!("Unexpected call");
372             }
atrace_is_tag_enabled_wrap(&mut self, _tag: u64) -> u64373             fn atrace_is_tag_enabled_wrap(&mut self, _tag: u64) -> u64 {
374                 panic!("Unexpected call");
375             }
atrace_begin_wrap(&mut self, _tag: u64, _name: *const c_char)376             fn atrace_begin_wrap(&mut self, _tag: u64, _name: *const c_char) {
377                 panic!("Unexpected call");
378             }
atrace_end_wrap(&mut self, _tag: u64)379             fn atrace_end_wrap(&mut self, _tag: u64) {
380                 panic!("Unexpected call");
381             }
atrace_async_begin_wrap(&mut self, _tag: u64, _name: *const c_char, _cookie: i32)382             fn atrace_async_begin_wrap(&mut self, _tag: u64, _name: *const c_char, _cookie: i32) {
383                 panic!("Unexpected call");
384             }
atrace_async_end_wrap(&mut self, _tag: u64, _name: *const c_char, _cookie: i32)385             fn atrace_async_end_wrap(&mut self, _tag: u64, _name: *const c_char, _cookie: i32) {
386                 panic!("Unexpected call");
387             }
atrace_async_for_track_begin_wrap( &mut self, _tag: u64, _track_name: *const c_char, _name: *const c_char, _cookie: i32, )388             fn atrace_async_for_track_begin_wrap(
389                 &mut self,
390                 _tag: u64,
391                 _track_name: *const c_char,
392                 _name: *const c_char,
393                 _cookie: i32,
394             ) {
395                 panic!("Unexpected call");
396             }
atrace_async_for_track_end_wrap( &mut self, _tag: u64, _track_name: *const c_char, _cookie: i32, )397             fn atrace_async_for_track_end_wrap(
398                 &mut self,
399                 _tag: u64,
400                 _track_name: *const c_char,
401                 _cookie: i32,
402             ) {
403                 panic!("Unexpected call");
404             }
atrace_instant_wrap(&mut self, _tag: u64, _name: *const c_char)405             fn atrace_instant_wrap(&mut self, _tag: u64, _name: *const c_char) {
406                 panic!("Unexpected call");
407             }
atrace_instant_for_track_wrap( &mut self, _tag: u64, _track_name: *const c_char, _name: *const c_char, )408             fn atrace_instant_for_track_wrap(
409                 &mut self,
410                 _tag: u64,
411                 _track_name: *const c_char,
412                 _name: *const c_char,
413             ) {
414                 panic!("Unexpected call");
415             }
atrace_int_wrap(&mut self, _tag: u64, _name: *const c_char, _value: i32)416             fn atrace_int_wrap(&mut self, _tag: u64, _name: *const c_char, _value: i32) {
417                 panic!("Unexpected call");
418             }
atrace_int64_wrap(&mut self, _tag: u64, _name: *const c_char, _value: i64)419             fn atrace_int64_wrap(&mut self, _tag: u64, _name: *const c_char, _value: i64) {
420                 panic!("Unexpected call");
421             }
422 
423             /// This method should contain checks to be performed at the end of the test.
finish(&self)424             fn finish(&self) {}
425         }
426 
427         struct DefaultMocker;
428         impl ATraceMocker for DefaultMocker {}
429 
430         // Global mock object is thread-local, so that the tests can run safely in parallel.
431         thread_local!(static MOCKER: RefCell<Box<dyn ATraceMocker>> = RefCell::new(Box::new(DefaultMocker{})));
432 
433         /// Sets the global mock object.
set_mocker(mocker: Box<dyn ATraceMocker>)434         fn set_mocker(mocker: Box<dyn ATraceMocker>) {
435             MOCKER.with(|m| *m.borrow_mut() = mocker)
436         }
437 
438         /// Calls the passed method `f` with a mutable reference to the global mock object.
439         /// Example:
440         /// ```
441         /// with_mocker(|mocker| mocker.atrace_begin_wrap(tag, name))
442         /// ```
with_mocker<F, R>(f: F) -> R where F: FnOnce(&mut dyn ATraceMocker) -> R,443         fn with_mocker<F, R>(f: F) -> R
444         where
445             F: FnOnce(&mut dyn ATraceMocker) -> R,
446         {
447             MOCKER.with(|m| f(m.borrow_mut().as_mut()))
448         }
449 
450         /// Finish the test and perform final checks in the mocker.
451         /// Calls `finish()` on the global mocker.
452         ///
453         /// Needs to be called manually at the end of each test that uses mocks.
454         ///
455         /// May panic, so it can not be called in `drop()` methods,
456         /// since it may result in double panic.
mocker_finish()457         pub fn mocker_finish() {
458             with_mocker(|m| m.finish())
459         }
460 
461         /// RAII guard that resets the mock to the default implementation.
462         pub struct MockerGuard;
463         impl Drop for MockerGuard {
drop(&mut self)464             fn drop(&mut self) {
465                 set_mocker(Box::new(DefaultMocker {}));
466             }
467         }
468 
469         /// Sets the mock object for the duration of the scope.
470         ///
471         /// Returns a RAII guard that resets the mock back to default on destruction.
set_scoped_mocker<T: ATraceMocker + 'static>(m: T) -> MockerGuard472         pub fn set_scoped_mocker<T: ATraceMocker + 'static>(m: T) -> MockerGuard {
473             set_mocker(Box::new(m));
474             MockerGuard {}
475         }
476 
477         // Wrapped functions that forward calls into mocker.
478         // The functions are marked as unsafe to match the binding interface, won't compile otherwise.
479         // The mocker methods themselves are not marked as unsafe.
480 
atrace_set_tracing_enabled(enabled: bool)481         pub unsafe fn atrace_set_tracing_enabled(enabled: bool) {
482             with_mocker(|m| m.atrace_set_tracing_enabled(enabled))
483         }
atrace_init()484         pub unsafe fn atrace_init() {
485             with_mocker(|m| m.atrace_init())
486         }
atrace_get_enabled_tags() -> u64487         pub unsafe fn atrace_get_enabled_tags() -> u64 {
488             with_mocker(|m| m.atrace_get_enabled_tags())
489         }
atrace_is_tag_enabled_wrap(tag: u64) -> u64490         pub unsafe fn atrace_is_tag_enabled_wrap(tag: u64) -> u64 {
491             with_mocker(|m| m.atrace_is_tag_enabled_wrap(tag))
492         }
atrace_begin_wrap(tag: u64, name: *const c_char)493         pub unsafe fn atrace_begin_wrap(tag: u64, name: *const c_char) {
494             with_mocker(|m| m.atrace_begin_wrap(tag, name))
495         }
atrace_end_wrap(tag: u64)496         pub unsafe fn atrace_end_wrap(tag: u64) {
497             with_mocker(|m| m.atrace_end_wrap(tag))
498         }
atrace_async_begin_wrap(tag: u64, name: *const c_char, cookie: i32)499         pub unsafe fn atrace_async_begin_wrap(tag: u64, name: *const c_char, cookie: i32) {
500             with_mocker(|m| m.atrace_async_begin_wrap(tag, name, cookie))
501         }
atrace_async_end_wrap(tag: u64, name: *const c_char, cookie: i32)502         pub unsafe fn atrace_async_end_wrap(tag: u64, name: *const c_char, cookie: i32) {
503             with_mocker(|m| m.atrace_async_end_wrap(tag, name, cookie))
504         }
atrace_async_for_track_begin_wrap( tag: u64, track_name: *const c_char, name: *const c_char, cookie: i32, )505         pub unsafe fn atrace_async_for_track_begin_wrap(
506             tag: u64,
507             track_name: *const c_char,
508             name: *const c_char,
509             cookie: i32,
510         ) {
511             with_mocker(|m| m.atrace_async_for_track_begin_wrap(tag, track_name, name, cookie))
512         }
atrace_async_for_track_end_wrap( tag: u64, track_name: *const c_char, cookie: i32, )513         pub unsafe fn atrace_async_for_track_end_wrap(
514             tag: u64,
515             track_name: *const c_char,
516             cookie: i32,
517         ) {
518             with_mocker(|m| m.atrace_async_for_track_end_wrap(tag, track_name, cookie))
519         }
atrace_instant_wrap(tag: u64, name: *const c_char)520         pub unsafe fn atrace_instant_wrap(tag: u64, name: *const c_char) {
521             with_mocker(|m| m.atrace_instant_wrap(tag, name))
522         }
atrace_instant_for_track_wrap( tag: u64, track_name: *const c_char, name: *const c_char, )523         pub unsafe fn atrace_instant_for_track_wrap(
524             tag: u64,
525             track_name: *const c_char,
526             name: *const c_char,
527         ) {
528             with_mocker(|m| m.atrace_instant_for_track_wrap(tag, track_name, name))
529         }
atrace_int_wrap(tag: u64, name: *const c_char, value: i32)530         pub unsafe fn atrace_int_wrap(tag: u64, name: *const c_char, value: i32) {
531             with_mocker(|m| m.atrace_int_wrap(tag, name, value))
532         }
atrace_int64_wrap(tag: u64, name: *const c_char, value: i64)533         pub unsafe fn atrace_int64_wrap(tag: u64, name: *const c_char, value: i64) {
534             with_mocker(|m| m.atrace_int64_wrap(tag, name, value))
535         }
536     }
537 
538     #[test]
forwards_set_tracing_enabled()539     fn forwards_set_tracing_enabled() {
540         #[derive(Default)]
541         struct CallCheck {
542             set_tracing_enabled_count: u32,
543         }
544 
545         impl mock_atrace::ATraceMocker for CallCheck {
546             fn atrace_set_tracing_enabled(&mut self, enabled: bool) {
547                 self.set_tracing_enabled_count += 1;
548                 assert!(self.set_tracing_enabled_count < 2);
549                 assert!(enabled);
550             }
551 
552             fn finish(&self) {
553                 assert_eq!(self.set_tracing_enabled_count, 1);
554             }
555         }
556 
557         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
558 
559         atrace_set_tracing_enabled(true);
560 
561         mock_atrace::mocker_finish();
562     }
563 
564     #[test]
forwards_atrace_init()565     fn forwards_atrace_init() {
566         #[derive(Default)]
567         struct CallCheck {
568             init_count: u32,
569         }
570 
571         impl mock_atrace::ATraceMocker for CallCheck {
572             fn atrace_init(&mut self) {
573                 self.init_count += 1;
574                 assert!(self.init_count < 2);
575             }
576 
577             fn finish(&self) {
578                 assert_eq!(self.init_count, 1);
579             }
580         }
581 
582         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
583 
584         atrace_init();
585 
586         mock_atrace::mocker_finish();
587     }
588 
589     #[test]
forwards_atrace_get_enabled_tags()590     fn forwards_atrace_get_enabled_tags() {
591         #[derive(Default)]
592         struct CallCheck {
593             get_enabled_tags_count: u32,
594         }
595 
596         impl mock_atrace::ATraceMocker for CallCheck {
597             fn atrace_get_enabled_tags(&mut self) -> u64 {
598                 self.get_enabled_tags_count += 1;
599                 assert!(self.get_enabled_tags_count < 2);
600                 (cutils_trace_bindgen::ATRACE_TAG_HAL | cutils_trace_bindgen::ATRACE_TAG_GRAPHICS)
601                     as u64
602             }
603 
604             fn finish(&self) {
605                 assert_eq!(self.get_enabled_tags_count, 1);
606             }
607         }
608 
609         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
610 
611         let res = atrace_get_enabled_tags();
612         assert_eq!(res, AtraceTag::Hal | AtraceTag::Graphics);
613 
614         mock_atrace::mocker_finish();
615     }
616 
617     #[test]
forwards_trace_begin()618     fn forwards_trace_begin() {
619         #[derive(Default)]
620         struct CallCheck {
621             begin_count: u32,
622         }
623 
624         impl mock_atrace::ATraceMocker for CallCheck {
625             fn atrace_is_tag_enabled_wrap(&mut self, _tag: u64) -> u64 {
626                 1
627             }
628             fn atrace_begin_wrap(&mut self, tag: u64, name: *const c_char) {
629                 self.begin_count += 1;
630                 assert!(self.begin_count < 2);
631                 assert_eq!(tag, cutils_trace_bindgen::ATRACE_TAG_APP as u64);
632                 // SAFETY: If the code under test is correct, the pointer is guaranteed to satisfy
633                 // the requirements of `CStr::from_ptr`. If the code is not correct, this section is
634                 // unsafe and will hopefully fail the test.
635                 unsafe {
636                     assert_eq!(CStr::from_ptr(name).to_str().expect("to_str failed"), "Test Name");
637                 }
638             }
639 
640             fn finish(&self) {
641                 assert_eq!(self.begin_count, 1);
642             }
643         }
644 
645         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
646 
647         atrace_begin(AtraceTag::App, "Test Name");
648 
649         mock_atrace::mocker_finish();
650     }
651 
652     #[test]
trace_begin_not_called_with_disabled_tag()653     fn trace_begin_not_called_with_disabled_tag() {
654         #[derive(Default)]
655         struct CallCheck {
656             is_tag_enabled_count: u32,
657         }
658 
659         impl mock_atrace::ATraceMocker for CallCheck {
660             fn atrace_is_tag_enabled_wrap(&mut self, _tag: u64) -> u64 {
661                 self.is_tag_enabled_count += 1;
662                 assert!(self.is_tag_enabled_count < 2);
663                 0
664             }
665             fn atrace_begin_wrap(&mut self, _tag: u64, _name: *const c_char) {
666                 panic!("Begin should not be called with disabled tag.")
667             }
668 
669             fn finish(&self) {
670                 assert_eq!(self.is_tag_enabled_count, 1);
671             }
672         }
673 
674         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
675 
676         atrace_begin(AtraceTag::App, "Ignore me");
677 
678         mock_atrace::mocker_finish();
679     }
680 
681     #[test]
forwards_trace_end()682     fn forwards_trace_end() {
683         #[derive(Default)]
684         struct CallCheck {
685             end_count: u32,
686         }
687 
688         impl mock_atrace::ATraceMocker for CallCheck {
689             fn atrace_end_wrap(&mut self, tag: u64) {
690                 self.end_count += 1;
691                 assert!(self.end_count < 2);
692                 assert_eq!(tag, cutils_trace_bindgen::ATRACE_TAG_APP as u64);
693             }
694 
695             fn finish(&self) {
696                 assert_eq!(self.end_count, 1);
697             }
698         }
699 
700         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
701 
702         atrace_end(AtraceTag::App);
703 
704         mock_atrace::mocker_finish();
705     }
706 
707     #[test]
can_combine_tags()708     fn can_combine_tags() {
709         #[derive(Default)]
710         struct CallCheck {
711             begin_count: u32,
712         }
713 
714         impl mock_atrace::ATraceMocker for CallCheck {
715             fn atrace_is_tag_enabled_wrap(&mut self, _tag: u64) -> u64 {
716                 1
717             }
718             fn atrace_begin_wrap(&mut self, tag: u64, _name: *const c_char) {
719                 self.begin_count += 1;
720                 assert!(self.begin_count < 2);
721                 assert_eq!(
722                     tag,
723                     (cutils_trace_bindgen::ATRACE_TAG_HAL | cutils_trace_bindgen::ATRACE_TAG_CAMERA)
724                         as u64
725                 );
726             }
727 
728             fn finish(&self) {
729                 assert_eq!(self.begin_count, 1);
730             }
731         }
732 
733         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
734 
735         atrace_begin(AtraceTag::Hal | AtraceTag::Camera, "foo");
736 
737         mock_atrace::mocker_finish();
738     }
739 
740     #[test]
forwards_is_tag_enabled()741     fn forwards_is_tag_enabled() {
742         #[derive(Default)]
743         struct CallCheck {
744             is_tag_enabled_count: u32,
745         }
746 
747         impl mock_atrace::ATraceMocker for CallCheck {
748             fn atrace_is_tag_enabled_wrap(&mut self, tag: u64) -> u64 {
749                 self.is_tag_enabled_count += 1;
750                 assert!(self.is_tag_enabled_count < 2);
751                 assert_eq!(tag, cutils_trace_bindgen::ATRACE_TAG_ADB as u64);
752                 1
753             }
754 
755             fn finish(&self) {
756                 assert_eq!(self.is_tag_enabled_count, 1);
757             }
758         }
759 
760         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
761 
762         let res = atrace_is_tag_enabled(AtraceTag::Adb);
763         assert!(res);
764 
765         mock_atrace::mocker_finish();
766     }
767 
768     #[test]
forwards_async_begin()769     fn forwards_async_begin() {
770         #[derive(Default)]
771         struct CallCheck {
772             async_begin_count: u32,
773         }
774 
775         impl mock_atrace::ATraceMocker for CallCheck {
776             fn atrace_is_tag_enabled_wrap(&mut self, _tag: u64) -> u64 {
777                 1
778             }
779             fn atrace_async_begin_wrap(&mut self, tag: u64, name: *const c_char, cookie: i32) {
780                 self.async_begin_count += 1;
781                 assert!(self.async_begin_count < 2);
782                 assert_eq!(tag, cutils_trace_bindgen::ATRACE_TAG_APP as u64);
783                 // SAFETY: If the code under test is correct, the pointer is guaranteed to satisfy
784                 // the requirements of `CStr::from_ptr`. If the code is not correct, this section is
785                 // unsafe and will hopefully fail the test.
786                 unsafe {
787                     assert_eq!(CStr::from_ptr(name).to_str().expect("to_str failed"), "Test Name");
788                 }
789                 assert_eq!(cookie, 123);
790             }
791 
792             fn finish(&self) {
793                 assert_eq!(self.async_begin_count, 1);
794             }
795         }
796 
797         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
798 
799         atrace_async_begin(AtraceTag::App, "Test Name", 123);
800 
801         mock_atrace::mocker_finish();
802     }
803 
804     #[test]
forwards_async_end()805     fn forwards_async_end() {
806         #[derive(Default)]
807         struct CallCheck {
808             async_end_count: u32,
809         }
810 
811         impl mock_atrace::ATraceMocker for CallCheck {
812             fn atrace_is_tag_enabled_wrap(&mut self, _tag: u64) -> u64 {
813                 1
814             }
815             fn atrace_async_end_wrap(&mut self, tag: u64, name: *const c_char, cookie: i32) {
816                 self.async_end_count += 1;
817                 assert!(self.async_end_count < 2);
818                 assert_eq!(tag, cutils_trace_bindgen::ATRACE_TAG_APP as u64);
819                 // SAFETY: If the code under test is correct, the pointer is guaranteed to satisfy
820                 // the requirements of `CStr::from_ptr`. If the code is not correct, this section is
821                 // unsafe and will hopefully fail the test.
822                 unsafe {
823                     assert_eq!(CStr::from_ptr(name).to_str().expect("to_str failed"), "Test Name");
824                 }
825                 assert_eq!(cookie, 123);
826             }
827 
828             fn finish(&self) {
829                 assert_eq!(self.async_end_count, 1);
830             }
831         }
832 
833         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
834 
835         atrace_async_end(AtraceTag::App, "Test Name", 123);
836 
837         mock_atrace::mocker_finish();
838     }
839 
840     #[test]
forwards_async_for_track_begin()841     fn forwards_async_for_track_begin() {
842         #[derive(Default)]
843         struct CallCheck {
844             async_for_track_begin_count: u32,
845         }
846 
847         impl mock_atrace::ATraceMocker for CallCheck {
848             fn atrace_is_tag_enabled_wrap(&mut self, _tag: u64) -> u64 {
849                 1
850             }
851             fn atrace_async_for_track_begin_wrap(
852                 &mut self,
853                 tag: u64,
854                 track_name: *const c_char,
855                 name: *const c_char,
856                 cookie: i32,
857             ) {
858                 self.async_for_track_begin_count += 1;
859                 assert!(self.async_for_track_begin_count < 2);
860                 assert_eq!(tag, cutils_trace_bindgen::ATRACE_TAG_APP as u64);
861                 // SAFETY: If the code under test is correct, the pointer is guaranteed to satisfy
862                 // the requirements of `CStr::from_ptr`. If the code is not correct, this section is
863                 // unsafe and will hopefully fail the test.
864                 unsafe {
865                     assert_eq!(
866                         CStr::from_ptr(track_name).to_str().expect("to_str failed"),
867                         "Track"
868                     );
869                     assert_eq!(CStr::from_ptr(name).to_str().expect("to_str failed"), "Test Name");
870                 }
871                 assert_eq!(cookie, 123);
872             }
873 
874             fn finish(&self) {
875                 assert_eq!(self.async_for_track_begin_count, 1);
876             }
877         }
878 
879         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
880 
881         atrace_async_for_track_begin(AtraceTag::App, "Track", "Test Name", 123);
882 
883         mock_atrace::mocker_finish();
884     }
885 
886     #[test]
forwards_async_for_track_end()887     fn forwards_async_for_track_end() {
888         #[derive(Default)]
889         struct CallCheck {
890             async_for_track_end_count: u32,
891         }
892 
893         impl mock_atrace::ATraceMocker for CallCheck {
894             fn atrace_is_tag_enabled_wrap(&mut self, _tag: u64) -> u64 {
895                 1
896             }
897             fn atrace_async_for_track_end_wrap(
898                 &mut self,
899                 tag: u64,
900                 track_name: *const c_char,
901                 cookie: i32,
902             ) {
903                 self.async_for_track_end_count += 1;
904                 assert!(self.async_for_track_end_count < 2);
905                 assert_eq!(tag, cutils_trace_bindgen::ATRACE_TAG_APP as u64);
906                 // SAFETY: If the code under test is correct, the pointer is guaranteed to satisfy
907                 // the requirements of `CStr::from_ptr`. If the code is not correct, this section is
908                 // unsafe and will hopefully fail the test.
909                 unsafe {
910                     assert_eq!(
911                         CStr::from_ptr(track_name).to_str().expect("to_str failed"),
912                         "Track"
913                     );
914                 }
915                 assert_eq!(cookie, 123);
916             }
917 
918             fn finish(&self) {
919                 assert_eq!(self.async_for_track_end_count, 1);
920             }
921         }
922 
923         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
924 
925         atrace_async_for_track_end(AtraceTag::App, "Track", 123);
926 
927         mock_atrace::mocker_finish();
928     }
929 
930     #[test]
forwards_trace_instant()931     fn forwards_trace_instant() {
932         #[derive(Default)]
933         struct CallCheck {
934             trace_instant_count: u32,
935         }
936 
937         impl mock_atrace::ATraceMocker for CallCheck {
938             fn atrace_is_tag_enabled_wrap(&mut self, _tag: u64) -> u64 {
939                 1
940             }
941             fn atrace_instant_wrap(&mut self, tag: u64, name: *const c_char) {
942                 self.trace_instant_count += 1;
943                 assert!(self.trace_instant_count < 2);
944                 assert_eq!(tag, cutils_trace_bindgen::ATRACE_TAG_APP as u64);
945                 // SAFETY: If the code under test is correct, the pointer is guaranteed to satisfy
946                 // the requirements of `CStr::from_ptr`. If the code is not correct, this section is
947                 // unsafe and will hopefully fail the test.
948                 unsafe {
949                     assert_eq!(CStr::from_ptr(name).to_str().expect("to_str failed"), "Test Name");
950                 }
951             }
952 
953             fn finish(&self) {
954                 assert_eq!(self.trace_instant_count, 1);
955             }
956         }
957 
958         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
959 
960         atrace_instant(AtraceTag::App, "Test Name");
961 
962         mock_atrace::mocker_finish();
963     }
964 
965     #[test]
forwards_trace_instant_for_track()966     fn forwards_trace_instant_for_track() {
967         #[derive(Default)]
968         struct CallCheck {
969             trace_instant_for_track_count: u32,
970         }
971 
972         impl mock_atrace::ATraceMocker for CallCheck {
973             fn atrace_is_tag_enabled_wrap(&mut self, _tag: u64) -> u64 {
974                 1
975             }
976             fn atrace_instant_for_track_wrap(
977                 &mut self,
978                 tag: u64,
979                 track_name: *const c_char,
980                 name: *const c_char,
981             ) {
982                 self.trace_instant_for_track_count += 1;
983                 assert!(self.trace_instant_for_track_count < 2);
984                 assert_eq!(tag, cutils_trace_bindgen::ATRACE_TAG_APP as u64);
985                 // SAFETY: If the code under test is correct, the pointer is guaranteed to satisfy
986                 // the requirements of `CStr::from_ptr`. If the code is not correct, this section is
987                 // unsafe and will hopefully fail the test.
988                 unsafe {
989                     assert_eq!(
990                         CStr::from_ptr(track_name).to_str().expect("to_str failed"),
991                         "Track"
992                     );
993                     assert_eq!(CStr::from_ptr(name).to_str().expect("to_str failed"), "Test Name");
994                 }
995             }
996 
997             fn finish(&self) {
998                 assert_eq!(self.trace_instant_for_track_count, 1);
999             }
1000         }
1001 
1002         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
1003 
1004         atrace_instant_for_track(AtraceTag::App, "Track", "Test Name");
1005 
1006         mock_atrace::mocker_finish();
1007     }
1008 
1009     #[test]
forwards_trace_int()1010     fn forwards_trace_int() {
1011         #[derive(Default)]
1012         struct CallCheck {
1013             trace_int_count: u32,
1014         }
1015 
1016         impl mock_atrace::ATraceMocker for CallCheck {
1017             fn atrace_is_tag_enabled_wrap(&mut self, _tag: u64) -> u64 {
1018                 1
1019             }
1020             fn atrace_int_wrap(&mut self, tag: u64, name: *const c_char, value: i32) {
1021                 self.trace_int_count += 1;
1022                 assert!(self.trace_int_count < 2);
1023                 assert_eq!(tag, cutils_trace_bindgen::ATRACE_TAG_APP as u64);
1024                 // SAFETY: If the code under test is correct, the pointer is guaranteed to satisfy
1025                 // the requirements of `CStr::from_ptr`. If the code is not correct, this section is
1026                 // unsafe and will hopefully fail the test.
1027                 unsafe {
1028                     assert_eq!(CStr::from_ptr(name).to_str().expect("to_str failed"), "Test Name");
1029                 }
1030                 assert_eq!(value, 32);
1031             }
1032 
1033             fn finish(&self) {
1034                 assert_eq!(self.trace_int_count, 1);
1035             }
1036         }
1037 
1038         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
1039 
1040         atrace_int(AtraceTag::App, "Test Name", 32);
1041 
1042         mock_atrace::mocker_finish();
1043     }
1044 
1045     #[test]
forwards_trace_int64()1046     fn forwards_trace_int64() {
1047         #[derive(Default)]
1048         struct CallCheck {
1049             trace_int64_count: u32,
1050         }
1051 
1052         impl mock_atrace::ATraceMocker for CallCheck {
1053             fn atrace_is_tag_enabled_wrap(&mut self, _tag: u64) -> u64 {
1054                 1
1055             }
1056             fn atrace_int64_wrap(&mut self, tag: u64, name: *const c_char, value: i64) {
1057                 self.trace_int64_count += 1;
1058                 assert!(self.trace_int64_count < 2);
1059                 assert_eq!(tag, cutils_trace_bindgen::ATRACE_TAG_APP as u64);
1060                 // SAFETY: If the code under test is correct, the pointer is guaranteed to satisfy
1061                 // the requirements of `CStr::from_ptr`. If the code is not correct, this section is
1062                 // unsafe and will hopefully fail the test.
1063                 unsafe {
1064                     assert_eq!(CStr::from_ptr(name).to_str().expect("to_str failed"), "Test Name");
1065                 }
1066                 assert_eq!(value, 64);
1067             }
1068 
1069             fn finish(&self) {
1070                 assert_eq!(self.trace_int64_count, 1);
1071             }
1072         }
1073 
1074         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
1075 
1076         atrace_int64(AtraceTag::App, "Test Name", 64);
1077 
1078         mock_atrace::mocker_finish();
1079     }
1080 
1081     #[test]
scoped_event_starts_and_ends_in_order()1082     fn scoped_event_starts_and_ends_in_order() {
1083         #[derive(Default)]
1084         struct CallCheck {
1085             begin_count: u32,
1086             end_count: u32,
1087             instant_count: u32,
1088         }
1089 
1090         impl mock_atrace::ATraceMocker for CallCheck {
1091             fn atrace_is_tag_enabled_wrap(&mut self, _tag: u64) -> u64 {
1092                 1
1093             }
1094 
1095             fn atrace_begin_wrap(&mut self, tag: u64, name: *const c_char) {
1096                 assert_eq!(self.end_count, 0);
1097                 assert_eq!(self.instant_count, 0);
1098 
1099                 self.begin_count += 1;
1100                 assert!(self.begin_count < 2);
1101                 assert_eq!(tag, cutils_trace_bindgen::ATRACE_TAG_APP as u64);
1102                 // SAFETY: If the code under test is correct, the pointer is guaranteed to satisfy
1103                 // the requirements of `CStr::from_ptr`. If the code is not correct, this section is
1104                 // unsafe and will hopefully fail the test.
1105                 unsafe {
1106                     assert_eq!(
1107                         CStr::from_ptr(name).to_str().expect("to_str failed"),
1108                         "Scoped Event"
1109                     );
1110                 }
1111             }
1112 
1113             fn atrace_instant_wrap(&mut self, _tag: u64, _name: *const c_char) {
1114                 // We don't care about the contents of the event, we only use it to check begin/end ordering.
1115                 assert_eq!(self.begin_count, 1);
1116                 assert_eq!(self.end_count, 0);
1117 
1118                 self.instant_count += 1;
1119                 assert!(self.instant_count < 2);
1120             }
1121 
1122             fn atrace_end_wrap(&mut self, tag: u64) {
1123                 assert_eq!(self.begin_count, 1);
1124                 assert_eq!(self.instant_count, 1);
1125 
1126                 self.end_count += 1;
1127                 assert!(self.end_count < 2);
1128                 assert_eq!(tag, cutils_trace_bindgen::ATRACE_TAG_APP as u64);
1129             }
1130 
1131             fn finish(&self) {
1132                 assert_eq!(self.begin_count, 1);
1133                 assert_eq!(self.end_count, 1);
1134                 assert_eq!(self.instant_count, 1);
1135             }
1136         }
1137 
1138         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
1139 
1140         {
1141             let _event_guard = begin_scoped_event(AtraceTag::App, "Scoped Event");
1142             atrace_instant(AtraceTag::App, "Instant event called within scoped event");
1143         }
1144 
1145         mock_atrace::mocker_finish();
1146     }
1147 
1148     // Need to have this alias to make the macro work, since it calls atrace::begin_scoped_event.
1149     use crate as atrace;
traced_method_for_test()1150     fn traced_method_for_test() {
1151         trace_method!(AtraceTag::App);
1152         atrace_instant(AtraceTag::App, "Instant event called within method");
1153     }
1154 
1155     #[test]
method_trace_starts_and_ends_in_order()1156     fn method_trace_starts_and_ends_in_order() {
1157         #[derive(Default)]
1158         struct CallCheck {
1159             begin_count: u32,
1160             end_count: u32,
1161             instant_count: u32,
1162         }
1163 
1164         impl mock_atrace::ATraceMocker for CallCheck {
1165             fn atrace_is_tag_enabled_wrap(&mut self, _tag: u64) -> u64 {
1166                 1
1167             }
1168 
1169             fn atrace_begin_wrap(&mut self, tag: u64, name: *const c_char) {
1170                 assert_eq!(self.end_count, 0);
1171                 assert_eq!(self.instant_count, 0);
1172 
1173                 self.begin_count += 1;
1174                 assert!(self.begin_count < 2);
1175                 assert_eq!(tag, cutils_trace_bindgen::ATRACE_TAG_APP as u64);
1176                 // SAFETY: If the code under test is correct, the pointer is guaranteed to satisfy
1177                 // the requirements of `CStr::from_ptr`. If the code is not correct, this section is
1178                 // unsafe and will hopefully fail the test.
1179                 unsafe {
1180                     assert_eq!(
1181                         CStr::from_ptr(name).to_str().expect("to_str failed"),
1182                         "lib::tests::traced_method_for_test"
1183                     );
1184                 }
1185             }
1186 
1187             fn atrace_instant_wrap(&mut self, _tag: u64, _name: *const c_char) {
1188                 // We don't care about the contents of the event, we only use it to check begin/end ordering.
1189                 assert_eq!(self.begin_count, 1);
1190                 assert_eq!(self.end_count, 0);
1191 
1192                 self.instant_count += 1;
1193                 assert!(self.instant_count < 2);
1194             }
1195 
1196             fn atrace_end_wrap(&mut self, tag: u64) {
1197                 assert_eq!(self.begin_count, 1);
1198                 assert_eq!(self.instant_count, 1);
1199 
1200                 self.end_count += 1;
1201                 assert!(self.end_count < 2);
1202                 assert_eq!(tag, cutils_trace_bindgen::ATRACE_TAG_APP as u64);
1203             }
1204 
1205             fn finish(&self) {
1206                 assert_eq!(self.begin_count, 1);
1207                 assert_eq!(self.end_count, 1);
1208                 assert_eq!(self.instant_count, 1);
1209             }
1210         }
1211 
1212         let _guard = mock_atrace::set_scoped_mocker(CallCheck::default());
1213 
1214         traced_method_for_test();
1215 
1216         mock_atrace::mocker_finish();
1217     }
1218 }
1219