/*
 * Copyright 2024 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.
 */

syntax = "proto2";

package perfetto.protos;

import "protos/perfetto/trace/android/typedef.proto";

// A representation of an Android MotionEvent.
// See: https://developer.android.com/reference/android/view/MotionEvent
//
// The timestamp of the TracePacket that contains this event corresponds to the
// time at which this event was processed by InputDispatcher.
message AndroidMotionEvent {
  // A representation of one pointer inside a MotionEvent.
  // Each Pointer contains the values present in its corresponding
  // MotionEvent.PointerCoords and MotionEvent.PointerProperties.
  message Pointer {
    message AxisValue {
      optional int32 axis = 1
          [(.perfetto.protos.typedef) = "android.view.MotionEvent.Axis"];
      optional float value = 2;
    }
    repeated AxisValue axis_value = 1;
    optional int32 pointer_id = 2;
    optional int32 tool_type = 3
        [(.perfetto.protos.typedef) = "android.view.MotionEvent.ToolType"];
  }

  // The randomly-generated ID used to track the event through the pipeline.
  optional fixed32 event_id = 1;
  // The event's timestamp - generated by the kernel.
  optional int64 event_time_nanos = 2 [jstype = JS_STRING];
  optional uint32 source = 3
      [(.perfetto.protos.typedef) = "android.view.InputDevice.Source"];
  optional int32 action = 4
      [(.perfetto.protos.typedef) = "android.view.MotionEvent.ActionMasked"];
  optional int32 device_id = 5;
  // Use a signed int for display_id, because -1 (DISPLAY_IS_NONE) is a common
  // value.
  optional sint32 display_id = 6;
  optional int32 classification = 7
      [(.perfetto.protos.typedef) = "android.view.MotionEvent.Classification"];
  optional uint32 flags = 8
      [(.perfetto.protos.typedef) = "android.view.MotionEvent.Flag"];
  repeated Pointer pointer = 9;

  // Field numbers 10-15 are reserved for commonly used fields.

  // If this event was synthesized as a result of one or more different
  // event, original_event_ids are the event_ids associated with the original
  // events. For example, if this is an ACTION_HOVER_ENTER event that is
  // synthesized due to an ACTION_HOVER_MOVE event entering the bounds of a
  // window, the id of the original hover move event will be listed here.
  repeated fixed32 original_event_id = 16 [packed = true];
  // The timestamp of the ACTION_DOWN event associated with this gesture.
  optional int64 down_time_nanos = 17 [jstype = JS_STRING];
  optional float cursor_position_x = 18;
  optional float cursor_position_y = 19;
  optional int32 action_button = 20
      [(.perfetto.protos.typedef) = "android.view.MotionEvent.Button"];
  optional uint32 button_state = 21
      [(.perfetto.protos.typedef) = "android.view.MotionEvent.Button"];
  optional uint32 meta_state = 22
      [(.perfetto.protos.typedef) = "android.view.KeyEvent.MetaState"];
  optional uint32 policy_flags = 23;
  optional float precision_x = 24;
  optional float precision_y = 25;
}

// A representation of an Android KeyEvent.
// See: https://developer.android.com/reference/android/view/KeyEvent
//
// The timestamp of the TracePacket that contains this event corresponds to the
// time at which this event was processed by InputDispatcher.
message AndroidKeyEvent {
  // The randomly-generated ID used to track the event through the pipeline.
  optional fixed32 event_id = 1;
  // The event's timestamp - generated by the kernel.
  optional int64 event_time_nanos = 2 [jstype = JS_STRING];
  // The timestamp of the ACTION_DOWN event associated with this gesture.
  optional int64 down_time_nanos = 3 [jstype = JS_STRING];
  optional uint32 source = 4
      [(.perfetto.protos.typedef) = "android.view.InputDevice.Source"];
  optional int32 action = 5
      [(.perfetto.protos.typedef) = "android.view.KeyEvent.Action"];
  optional int32 device_id = 6;
  // Use a signed int for display_id, because -1 (DISPLAY_IS_NONE) is a common
  // value.
  optional sint32 display_id = 7;
  optional int32 key_code = 8
      [(.perfetto.protos.typedef) = "android.view.KeyEvent.KeyCode"];
  optional uint32 scan_code = 9;
  optional uint32 meta_state = 10
      [(.perfetto.protos.typedef) = "android.view.KeyEvent.MetaState"];
  optional int32 repeat_count = 11;
  optional uint32 flags = 12
      [(.perfetto.protos.typedef) = "android.view.KeyEvent.Flag"];
  optional uint32 policy_flags = 13;
}

// An event that traces an input event being dispatched by the system to one
// window.
//
// The timestamp of the TracePacket that contains this event corresponds to the
// time at which this event was dispatched to the target window by
// InputDispatcher, also known as "delivery time".
message AndroidWindowInputDispatchEvent {
  // Stores x/y values for each pointer sent to the window for events
  // that are dispatched to a certain location on the screen. This is not
  // relevant for KeyEvents and MotionEvents that are dispatched to focused
  // windows.
  message DispatchedPointer {
    optional int32 pointer_id = 1;
    // The coordinates of the pointer in the logical display space, AKA "raw
    // coordinates".
    optional float x_in_display = 2;
    optional float y_in_display = 3;
    // The axis values for this pointer that were modified by the window
    // transform.
    repeated AndroidMotionEvent.Pointer.AxisValue axis_value_in_window = 4;
  }

  // The event_id of the event that was dispatched to the window.
  optional fixed32 event_id = 1;
  // The vsync_id of the frame in which the decision was made to dispatch the
  // event to the window.
  optional int64 vsync_id = 2 [jstype = JS_STRING];
  // The id of the window to which the event was dispatched.
  optional int32 window_id = 3;
  // Only relevant for MotionEvents that are dispatched to a screen location.
  // Each DispatchedPointer has a 1:1 correspondence with the Pointers in the
  // AndroidMotionEvent.
  repeated DispatchedPointer dispatched_pointer = 4;
  // The event flags that were used when dispatching the event to this window.
  // If the same event is dispatched to more than one window, it is possible
  // that they were dispatched using different flag values for each window.
  optional uint32 resolved_flags = 5;
}

// A wrapper type for input tracing on Android.
// The meaning of the timestamp of the TracePacket that contains this message
// will depend on the event that this message contains.
message AndroidInputEvent {
  oneof event {
    // Traces input events received by or generated by InputDispatcher
    AndroidMotionEvent dispatcher_motion_event = 1;
    AndroidMotionEvent dispatcher_motion_event_redacted = 2;
    AndroidKeyEvent dispatcher_key_event = 3;
    AndroidKeyEvent dispatcher_key_event_redacted = 4;

    // Traces an event being dispatched to a window.
    AndroidWindowInputDispatchEvent dispatcher_window_dispatch_event = 5;
    AndroidWindowInputDispatchEvent dispatcher_window_dispatch_event_redacted =
        6;
  }
}
