• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021, 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 //! Provides interface for logging events to binary log buffers.
16 
17 use log_event_list_bindgen as log_bindgen;
18 use std::os::raw::c_char;
19 
20 pub use log_bindgen::log_id_LOG_ID_SECURITY as LogIdSecurity;
21 
22 /// Whether security logging is enabled.
security_log_enabled() -> bool23 fn security_log_enabled() -> bool {
24     // The call doesn't require any preconditions and only returns an int, so must be safe.
25     unsafe {
26         log_bindgen::__android_log_security() != 0
27     }
28 }
29 
30 /// Event log context.
31 pub struct LogContext {
32     ctx: log_bindgen::android_log_context,
33     log_type: log_bindgen::log_id
34 }
35 
36 /// Log context is essentially a buffer with some associated state. All data that is appended to
37 /// the context is copied into the buffers, no references are ever stored.
38 unsafe impl Send for LogContext {}
39 
40 impl LogContext {
41     /// Creates a context for a given event tag.
new(log_type: log_bindgen::log_id, tag: u32) -> Option<LogContext>42     pub fn new(log_type: log_bindgen::log_id, tag: u32) -> Option<LogContext> {
43         if log_type == log_bindgen::log_id_LOG_ID_SECURITY && !security_log_enabled() {
44             return None;
45         }
46 
47         // The method returns a pointer that is stored and always freed exactly once via Drop below.
48         let ctx = unsafe { log_bindgen::create_android_logger(tag) };
49         if !ctx.is_null() {
50             Some(LogContext{ ctx, log_type })
51         } else {
52             None
53         }
54     }
55 
56     /// Appends an i32 to the context.
append_i32(self, data: i32) -> Self57     pub fn append_i32(self, data: i32) -> Self {
58         // This will only be called on a non-null pointer returned from create_android_logger
59         // previously, so should be safe.
60         unsafe { log_bindgen::android_log_write_int32(self.ctx, data) };
61         self
62     }
63 
64     /// Append a string to the context.
append_str(self, data: &str) -> Self65     pub fn append_str(self, data: &str) -> Self {
66         // This will only be called on a non-null pointer returned from create_android_logger
67         // previously, and the function will only read data.len() characters from the str, the
68         // pointer itself won't be stored, so should be safe.
69         unsafe {
70             log_bindgen::android_log_write_string8_len(
71                 self.ctx, data.as_ptr() as *const c_char, data.len())
72         };
73         self
74     }
75 
76     /// Writes the context to a given buffer type and consumes the context.
write(self)77     pub fn write(self) {
78         // This will only be called on a non-null pointer returned from create_android_logger
79         // previously, so should be safe.
80         unsafe { log_bindgen::android_log_write_list(self.ctx, self.log_type) };
81     }
82 }
83 
84 impl Drop for LogContext {
drop(&mut self)85     fn drop(&mut self) {
86         // This will only be called on a non-null pointer returned from create_android_logger
87         // previously, so should be safe.
88         unsafe { log_bindgen::android_log_destroy(&mut self.ctx) };
89     }
90 }
91