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