
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Source of truth: http://ac/system/extras/simpleperf/cmd_report_sample.proto

// The file format generated by cmd_report_sample.proto is as below:
// char magic[10] = "SIMPLEPERF";
// LittleEndian16(version) = 1;
// LittleEndian32(record_size_0)
// message Record(record_0) (having record_size_0 bytes)
// LittleEndian32(record_size_1)
// message Record(record_1) (having record_size_1 bytes)
// ...
// LittleEndian32(record_size_N)
// message Record(record_N) (having record_size_N bytes)
// LittleEndian32(0)

syntax = "proto2";
option optimize_for = LITE_RUNTIME;
option java_package = "com.android.tools.profiler.proto";
option java_outer_classname = "SimpleperfReport";

// This is in perfetto.third_party to avoid clashing with potential other
// copies of this proto.
package perfetto.third_party.simpleperf.proto;

message Sample {
  // Monotonic clock time in nanoseconds. On kernel < 4.1, it's perf clock
  // instead.
  optional uint64 time = 1;
  optional int32 thread_id = 2;
  message CallChainEntry {
    // virtual address of the instruction in elf file
    optional uint64 vaddr_in_file = 1;
    // index of the elf file containing the instruction
    optional uint32 file_id = 2;
    // symbol_id refers to the name of the function containing the instruction.
    // If the function name is found, it is a valid index in the symbol table
    // of File with 'id' field being file_id, otherwise it is -1.
    optional int32 symbol_id = 3;
    enum ExecutionType {
      // methods belong to native libraries, AOT compiled JVM code and ART
      // methods not used near JVM methods
      NATIVE_METHOD = 0;
      INTERPRETED_JVM_METHOD = 1;
      JIT_JVM_METHOD = 2;
      // ART methods used near JVM methods. It's shown only when
      // --show-art-frames is used.
      ART_METHOD = 3;
    }
    optional ExecutionType execution_type = 4;
  }
  repeated CallChainEntry callchain = 3;
  // Simpleperf generates one sample whenever a specified amount of events
  // happen while running a monitored thread. So each sample belongs to one
  // event type. Event type can be cpu-cycles, cpu-clock, sched:sched_switch or
  // other types. By using '-e' option, we can ask simpleperf to record samples
  // for one or more event types. Each event type generates samples
  // independently. But recording more event types will cost more cpu time
  // generating samples, which may affect the monitored threads and sample lost
  // rate. event_count field shows the count of the events (belong to the
  // sample's event type) that have happened since last sample (belong to the
  // sample's event type) for the same thread. However, if there are lost
  // samples between current sample and previous sample, the event_count is the
  // count of events from the last lost sample.
  optional uint64 event_count = 4;
  // An index in meta_info.event_type, shows which event type current sample
  // belongs to.
  optional uint32 event_type_id = 5;
  message UnwindingResult {
    // error code provided by libunwindstack, in
    // https://cs.android.com/android/platform/superproject/+/master:system/unwinding/libunwindstack/include/unwindstack/Error.h
    optional uint32 raw_error_code = 1;
    // error addr provided by libunwindstack
    optional uint64 error_addr = 2;
    // error code interpreted by simpleperf
    enum ErrorCode {
      ERROR_NONE = 0;  // No error
      ERROR_UNKNOWN =
          1;  // Error not interpreted by simpleperf, see raw_error_code
      ERROR_NOT_ENOUGH_STACK =
          2;                     // Simpleperf doesn't record enough stack data
      ERROR_MEMORY_INVALID = 3;  // Memory read failed
      ERROR_UNWIND_INFO = 4;     // No debug info in binary to support unwinding
      ERROR_INVALID_MAP = 5;     // Unwind in an invalid map
      ERROR_MAX_FRAME_EXCEEDED =
          6;  // Stopped at MAX_UNWINDING_FRAMES, which is 512.
      ERROR_REPEATED_FRAME =
          7;                  // The last frame has the same pc/sp as the next.
      ERROR_INVALID_ELF = 8;  // Unwind in an invalid elf file
    }
    optional ErrorCode error_code = 3;
  }
  // Unwinding result is provided for samples without a complete callchain, when
  // recorded with
  // --keep-failed-unwinding-result or --keep-failed-unwinding-debug-info.
  optional UnwindingResult unwinding_result = 6;
}
message LostSituation {
  optional uint64 sample_count = 1;
  optional uint64 lost_count = 2;
}
message File {
  // unique id for each file, starting from 0, and add 1 each time.
  optional uint32 id = 1;
  // file path, like /system/lib/libc.so.
  optional string path = 2;
  // symbol table of the file.
  repeated string symbol = 3;
  // mangled symbol table of the file.
  repeated string mangled_symbol = 4;
}
message Thread {
  optional uint32 thread_id = 1;
  optional uint32 process_id = 2;
  optional string thread_name = 3;
}
message MetaInfo {
  repeated string event_type = 1;
  optional string app_package_name = 2;
  optional string app_type = 3;  // debuggable, profileable or non_profileable
  optional string android_sdk_version = 4;
  optional string android_build_type = 5;  // user, userdebug or eng
  // True if the profile is recorded with --trace-offcpu option.
  optional bool trace_offcpu = 6;
}
// Thread context switch info. It is available when MetaInfo.trace_offcpu =
// true.
message ContextSwitch {
  // If true, the thread is scheduled on cpu, otherwise it is scheduled off cpu.
  optional bool switch_on = 1;
  // Monotonic clock time in nanoseconds. On kernel < 4.1, it's perf clock
  // instead.
  optional uint64 time = 2;
  optional uint32 thread_id = 3;
}
message Record {
  oneof record_data {
    Sample sample = 1;
    LostSituation lost = 2;
    File file = 3;
    Thread thread = 4;
    MetaInfo meta_info = 5;
    ContextSwitch context_switch = 6;
  }
}
