Bowgo Tsai | d0ecf0b | 2020-04-13 13:07:43 +0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2020 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include "system_properties/prop_trace.h" |
| 18 | |
| 19 | #include <errno.h> |
| 20 | #include <fcntl.h> |
| 21 | #include <stdio.h> |
| 22 | #include <stdlib.h> |
| 23 | #include <string.h> |
| 24 | |
| 25 | #include "private/CachedProperty.h" |
| 26 | #include "private/bionic_lock.h" |
| 27 | #include "private/bionic_systrace.h" |
| 28 | |
| 29 | #include <async_safe/log.h> |
| 30 | #include <cutils/trace.h> // For ATRACE_TAG_SYSPROP. |
| 31 | |
| 32 | #define PROP_TRACE_MSG_LENGTH 1024 |
| 33 | |
| 34 | static bool should_trace_prop(const char* prop_name) { |
| 35 | // Should not trace kTraceTagsProp to avoid infinite recursion. |
| 36 | // Because the following g_trace_enable_flags.Get() will get the property value |
| 37 | // of kTraceTagsProp again, which in turn invokes should_trace_prop() here. |
| 38 | if (prop_name == nullptr || !strcmp(prop_name, kTraceTagsProp)) { |
| 39 | return false; |
| 40 | } |
| 41 | |
| 42 | return should_trace(ATRACE_TAG_SYSPROP); |
| 43 | } |
| 44 | |
| 45 | static void sysprop_trace_end() { |
| 46 | int trace_marker_fd = get_trace_marker_fd(); |
| 47 | if (trace_marker_fd == -1) { |
| 48 | return; |
| 49 | } |
| 50 | |
| 51 | TEMP_FAILURE_RETRY(write(trace_marker_fd, "E|", 2)); |
| 52 | } |
| 53 | |
| 54 | static void get_sysprop_trace_end(const prop_info* pi, const char* prop_value, |
| 55 | bool read_only = false) { |
| 56 | const char* output_value; |
| 57 | char message[PROP_TRACE_MSG_LENGTH]; |
| 58 | |
| 59 | if (read_only) { |
| 60 | if (pi->is_long()) { |
| 61 | output_value = pi->long_value(); |
| 62 | } else { |
| 63 | output_value = pi->value; |
| 64 | } |
| 65 | } else { |
| 66 | output_value = prop_value; |
| 67 | } |
| 68 | |
| 69 | snprintf(message, sizeof(message), "prop_get: %s, value: %s", pi->name, |
| 70 | output_value ? output_value : "null_value"); |
| 71 | output_trace(message, 'E'); // 'E' for end. |
| 72 | } |
| 73 | |
| 74 | SyspropTrace::SyspropTrace(const char* prop_name, const char* prop_value, const prop_info* pi, |
| 75 | PropertyAction action) |
| 76 | : prop_name_(prop_name), |
| 77 | prop_value_(prop_value), |
| 78 | prop_info_(pi), |
| 79 | prop_action_(action), |
| 80 | output_trace_(false) { |
| 81 | if (!should_trace_prop(prop_name)) { |
| 82 | return; |
| 83 | } |
| 84 | |
| 85 | char message[PROP_TRACE_MSG_LENGTH]; |
| 86 | if (prop_action_ == PropertyAction::kPropertyFind) { |
| 87 | snprintf(message, sizeof(message), "prop_find: %s", prop_name_); |
| 88 | } else if (prop_action_ == PropertyAction::kPropertySet) { |
| 89 | snprintf(message, sizeof(message), "prop_set: %s, value: %s", prop_name_, |
| 90 | prop_value_ ? prop_value_ : "null_value"); |
| 91 | } else { |
| 92 | // For property get, the prop_value_ will be resolved then printed in the destructor. |
| 93 | snprintf(message, sizeof(message), "prop_get: %s", prop_name_); |
| 94 | } |
| 95 | |
| 96 | output_trace(message, 'B'); // 'B' for begin. |
| 97 | output_trace_ = true; |
| 98 | } |
| 99 | |
| 100 | SyspropTrace::~SyspropTrace() { |
| 101 | if (!output_trace_) { |
| 102 | return; |
| 103 | } |
| 104 | if (prop_action_ == PropertyAction::kPropertyFind || |
| 105 | prop_action_ == PropertyAction::kPropertySet) { |
| 106 | sysprop_trace_end(); |
| 107 | } else if (prop_action_ == PropertyAction::kPropertyGetReadOnly) { |
| 108 | get_sysprop_trace_end(prop_info_, prop_value_, true /* read_only */); |
| 109 | } else if (prop_action_ == PropertyAction::kPropertyGetReadWrite) { |
| 110 | get_sysprop_trace_end(prop_info_, prop_value_, false /* read_only */); |
| 111 | } |
| 112 | output_trace_ = false; |
| 113 | } |