1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "tools/trace/EventTracingPriv.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/utils/SkEventTracer.h"
11cb93a386Sopenharmony_ci#include "src/core/SkATrace.h"
12cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h"
13cb93a386Sopenharmony_ci#include "tools/flags/CommandLineFlags.h"
14cb93a386Sopenharmony_ci#include "tools/trace/ChromeTracingTracer.h"
15cb93a386Sopenharmony_ci#include "tools/trace/SkDebugfTracer.h"
16cb93a386Sopenharmony_ci
17cb93a386Sopenharmony_cistatic DEFINE_string(trace,
18cb93a386Sopenharmony_ci              "",
19cb93a386Sopenharmony_ci              "Log trace events in one of several modes:\n"
20cb93a386Sopenharmony_ci              "  debugf     : Show events using SkDebugf\n"
21cb93a386Sopenharmony_ci              "  atrace     : Send events to Android ATrace\n"
22cb93a386Sopenharmony_ci              "  <filename> : Any other string is interpreted as a filename. Writes\n"
23cb93a386Sopenharmony_ci              "               trace events to specified file as JSON, for viewing\n"
24cb93a386Sopenharmony_ci              "               with chrome://tracing");
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_cistatic DEFINE_string(traceMatch,
27cb93a386Sopenharmony_ci              "",
28cb93a386Sopenharmony_ci              "Filter which categories are traced.\n"
29cb93a386Sopenharmony_ci              "Uses same format as --match\n");
30cb93a386Sopenharmony_ci
31cb93a386Sopenharmony_civoid initializeEventTracingForTools(const char* traceFlag) {
32cb93a386Sopenharmony_ci    if (!traceFlag) {
33cb93a386Sopenharmony_ci        if (FLAGS_trace.isEmpty()) {
34cb93a386Sopenharmony_ci            return;
35cb93a386Sopenharmony_ci        }
36cb93a386Sopenharmony_ci        traceFlag = FLAGS_trace[0];
37cb93a386Sopenharmony_ci    }
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_ci    SkEventTracer* eventTracer = nullptr;
40cb93a386Sopenharmony_ci    if (0 == strcmp(traceFlag, "atrace")) {
41cb93a386Sopenharmony_ci        eventTracer = new SkATrace();
42cb93a386Sopenharmony_ci    } else if (0 == strcmp(traceFlag, "debugf")) {
43cb93a386Sopenharmony_ci        eventTracer = new SkDebugfTracer();
44cb93a386Sopenharmony_ci    } else {
45cb93a386Sopenharmony_ci        eventTracer = new ChromeTracingTracer(traceFlag);
46cb93a386Sopenharmony_ci    }
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_ci    SkAssertResult(SkEventTracer::SetInstance(eventTracer));
49cb93a386Sopenharmony_ci}
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_ciuint8_t* SkEventTracingCategories::getCategoryGroupEnabled(const char* name) {
52cb93a386Sopenharmony_ci    static_assert(0 == offsetof(CategoryState, fEnabled), "CategoryState");
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_ci    // We ignore the "disabled-by-default-" prefix in our internal tools
55cb93a386Sopenharmony_ci    if (SkStrStartsWith(name, TRACE_CATEGORY_PREFIX)) {
56cb93a386Sopenharmony_ci        name += strlen(TRACE_CATEGORY_PREFIX);
57cb93a386Sopenharmony_ci    }
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_ci    // Chrome's implementation of this API does a two-phase lookup (once without a lock, then again
60cb93a386Sopenharmony_ci    // with a lock. But the tracing macros avoid calling these functions more than once per site,
61cb93a386Sopenharmony_ci    // so just do something simple (and easier to reason about):
62cb93a386Sopenharmony_ci    SkAutoMutexExclusive lock(fMutex);
63cb93a386Sopenharmony_ci    for (int i = 0; i < fNumCategories; ++i) {
64cb93a386Sopenharmony_ci        if (0 == strcmp(name, fCategories[i].fName)) {
65cb93a386Sopenharmony_ci            return reinterpret_cast<uint8_t*>(&fCategories[i]);
66cb93a386Sopenharmony_ci        }
67cb93a386Sopenharmony_ci    }
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_ci    if (fNumCategories >= kMaxCategories) {
70cb93a386Sopenharmony_ci        SkDEBUGFAIL("Exhausted event tracing categories. Increase kMaxCategories.");
71cb93a386Sopenharmony_ci        return reinterpret_cast<uint8_t*>(&fCategories[0]);
72cb93a386Sopenharmony_ci    }
73cb93a386Sopenharmony_ci
74cb93a386Sopenharmony_ci    fCategories[fNumCategories].fEnabled =
75cb93a386Sopenharmony_ci            CommandLineFlags::ShouldSkip(FLAGS_traceMatch, name)
76cb93a386Sopenharmony_ci                    ? 0
77cb93a386Sopenharmony_ci                    : SkEventTracer::kEnabledForRecording_CategoryGroupEnabledFlags;
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_ci    fCategories[fNumCategories].fName = name;
80cb93a386Sopenharmony_ci    return reinterpret_cast<uint8_t*>(&fCategories[fNumCategories++]);
81cb93a386Sopenharmony_ci}
82cb93a386Sopenharmony_ci
83cb93a386Sopenharmony_ciconst char* SkEventTracingCategories::getCategoryGroupName(const uint8_t* categoryEnabledFlag) {
84cb93a386Sopenharmony_ci    if (categoryEnabledFlag) {
85cb93a386Sopenharmony_ci        return reinterpret_cast<const CategoryState*>(categoryEnabledFlag)->fName;
86cb93a386Sopenharmony_ci    }
87cb93a386Sopenharmony_ci    return nullptr;
88cb93a386Sopenharmony_ci}
89