Home | History | Annotate | Download | only in include
      1 /*
      2  * Copyright 2018 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 #pragma once
     18 
     19 #include <dlfcn.h>
     20 #include <memory>
     21 
     22 #include <android/log.h>
     23 #include <android/trace.h>
     24 
     25 namespace samples {
     26 
     27 class Trace {
     28 public:
     29     using ATrace_beginSection_type = void (*)(const char *sectionName);
     30     using ATrace_endSection_type = void (*)();
     31     using ATrace_isEnabled_type = bool (*)();
     32 
     33     Trace() {
     34         __android_log_print(ANDROID_LOG_INFO, "Trace", "Unable to load NDK tracing APIs");
     35     }
     36 
     37     Trace(ATrace_beginSection_type beginSection,
     38           ATrace_endSection_type endSection,
     39           ATrace_isEnabled_type isEnabled)
     40         : ATrace_beginSection(beginSection),
     41           ATrace_endSection(endSection),
     42           ATrace_isEnabled(isEnabled) {}
     43 
     44     static std::unique_ptr<Trace> create() {
     45         void *libandroid = dlopen("libandroid.so", RTLD_NOW | RTLD_LOCAL);
     46         if (!libandroid) {
     47             return std::make_unique<Trace>();
     48         }
     49 
     50         auto beginSection = reinterpret_cast<ATrace_beginSection_type>(
     51             dlsym(libandroid, "ATrace_beginSection"));
     52         if (!beginSection) {
     53             return std::make_unique<Trace>();
     54         }
     55 
     56         auto endSection = reinterpret_cast<ATrace_endSection_type>(
     57             dlsym(libandroid, "ATrace_endSection"));
     58         if (!endSection) {
     59             return std::make_unique<Trace>();
     60         }
     61 
     62         auto isEnabled = reinterpret_cast<ATrace_isEnabled_type>(
     63             dlsym(libandroid, "ATrace_isEnabled"));
     64         if (!isEnabled) {
     65             return std::make_unique<Trace>();
     66         }
     67 
     68         return std::make_unique<Trace>(beginSection, endSection, isEnabled);
     69     }
     70 
     71     bool isAvailable() const {
     72         return ATrace_beginSection != nullptr;
     73     }
     74 
     75     bool isEnabled() const {
     76         return (ATrace_isEnabled != nullptr) && ATrace_isEnabled();
     77     }
     78 
     79     void beginSection(const char *name) const {
     80         if (!ATrace_beginSection) {
     81             return;
     82         }
     83 
     84         ATrace_beginSection(name);
     85     }
     86 
     87     void endSection() const {
     88         if (!ATrace_endSection) {
     89             return;
     90         }
     91 
     92         ATrace_endSection();
     93     }
     94 
     95     static Trace *getInstance() {
     96         static std::unique_ptr<Trace> trace = Trace::create();
     97         return trace.get();
     98     };
     99 
    100 private:
    101     const ATrace_beginSection_type ATrace_beginSection = nullptr;
    102     const ATrace_endSection_type ATrace_endSection = nullptr;
    103     const ATrace_isEnabled_type ATrace_isEnabled = nullptr;
    104 };
    105 
    106 struct ScopedTrace {
    107     ScopedTrace(const char *name) {
    108         Trace *trace = Trace::getInstance();
    109         if (!trace->isAvailable() || !trace->isEnabled()) {
    110             return;
    111         }
    112 
    113         trace->beginSection(name);
    114         mIsTracing = true;
    115     }
    116 
    117     ~ScopedTrace() {
    118         if (!mIsTracing) {
    119             return;
    120         }
    121 
    122         Trace *trace = Trace::getInstance();
    123         trace->endSection();
    124     }
    125 
    126 private:
    127     bool mIsTracing = false;
    128 };
    129 
    130 } // namespace samples {
    131 
    132 #define PASTE_HELPER_HELPER(a, b) a ## b
    133 #define PASTE_HELPER(a, b) PASTE_HELPER_HELPER(a, b)
    134 #define SAMPLES_TRACE_CALL() samples::ScopedTrace PASTE_HELPER(scopedTrace, __LINE__)(__PRETTY_FUNCTION__)
    135