#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_TRANSFER_HANDLER_ANDROID_H_
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_TRANSFER_HANDLER_ANDROID_H_
#include <memory>
#include <optional>
#include "base/android/scoped_java_ref.h"
#include "base/memory/raw_ptr.h"
#include "components/viz/common/input/viz_touch_state.h"
#include "content/common/content_export.h"
#include "content/public/browser/android/transfer_input_to_viz_result.h"
#include "content/public/browser/render_widget_host.h"
#include "gpu/ipc/common/surface_handle.h"
#include "ui/events/android/motion_event_android.h"
namespace content {
class InputTransferHandlerAndroidClient {
public:
virtual gpu::SurfaceHandle GetRootSurfaceHandle() = 0;
virtual void SendStateOnTouchTransfer(const ui::MotionEvent& event,
bool browser_would_have_handled) = 0;
virtual bool IsMojoRIRDelegateConnectionSetup() = 0;
};
class CONTENT_EXPORT InputTransferHandlerAndroid {
public:
class JniDelegate {
public:
virtual ~JniDelegate() = default;
virtual int MaybeTransferInputToViz(int surface_id) = 0;
virtual int TransferInputToViz(int surface_id) = 0;
};
explicit InputTransferHandlerAndroid(
InputTransferHandlerAndroidClient* client);
virtual ~InputTransferHandlerAndroid();
virtual bool OnTouchEvent(const ui::MotionEventAndroid& event,
bool is_ignoring_input_events = false);
void set_jni_delegate_for_testing(std::unique_ptr<JniDelegate> delegate) {
jni_delegate_ = std::move(delegate);
}
static constexpr const char* kTouchMovesSeenHistogram =
"Android.InputOnViz.Browser.TouchMovesSeenAfterTransfer";
static constexpr const char* kEventsAfterTransferHistogram =
"Android.InputOnViz.Browser.EventsAfterTransfer";
static constexpr const char* kTransferInputToVizResultHistogram =
"Android.InputOnViz.Browser.TransferInputToVizResult2";
static constexpr const char* kEventsInDroppedSequenceHistogram =
"Android.InputOnViz.Browser.NumEventsInDroppedSequence2";
static constexpr const char* kEventTypesInDroppedSequenceHistogram =
"Android.InputOnViz.Browser.EventTypesInDroppedSequence";
static constexpr const char* kTouchSequenceDroppedReasonHistogram =
"Android.InputOnViz.Browser.SequenceDroppedReason3";
static constexpr const char* kNewSequenceTransferredByOSHistogram =
"Android.InputOnViz.Browser.NewSequenceTransferredByOS";
bool touch_transferred() {
return handler_state_ == HandlerState::kConsumeEventsUntilCancel;
}
bool FilterRedundantDownEvent(const ui::MotionEvent& event);
void OnDetachedFromWindow();
enum class RequestInputBackReason {
kStartDragAndDropGesture = 0,
kStartTouchSelectionDragGesture = 1,
kStartOverscrollGestures = 2,
};
void RequestInputBack(RequestInputBackReason reason);
virtual bool IsTouchSequencePotentiallyActiveOnViz() const;
RenderWidgetHost::InputEventObserver& GetInputObserver() {
return input_observer_;
}
protected:
virtual const viz::VizTouchState* GetVizTouchState() const;
private:
class InputObserver : public RenderWidgetHost::InputEventObserver {
public:
explicit InputObserver(InputTransferHandlerAndroid& transfer_handler);
~InputObserver() override;
void OnInputEvent(const RenderWidgetHost& host,
const blink::WebInputEvent& event,
InputEventSource source) override;
private:
const raw_ref<InputTransferHandlerAndroid> transfer_handler_;
};
void Reset();
void OnTouchTransferredSuccessfully(const ui::MotionEventAndroid& event,
bool browser_would_have_handled);
void EmitTransferResultHistogramAndTraceEvent(
TransferInputToVizResult result);
enum class TransferredSequenceType {
kActionDown = 0,
kPointerDown = 1,
kMaxValue = kPointerDown,
};
enum class InputOnVizSequenceDroppedReason {
kActiveSeqOnVizAbnormalDownTime = 0,
kFailedToTransferPotentialPointer = 1,
kAndroidOSTransferredANewSequence = 2,
kMaxValue = kAndroidOSTransferredANewSequence,
};
void EmitSequenceDroppedReasonTraceEvent(
InputOnVizSequenceDroppedReason reason);
void OnStartDroppingSequence(const ui::MotionEventAndroid& event,
InputOnVizSequenceDroppedReason reason);
void DropCurrentSequence(const ui::MotionEventAndroid& event);
bool ConsumeEventsUntilCancel(const ui::MotionEventAndroid& event);
void ConsumeSequence(const ui::MotionEventAndroid& event);
friend class MockInputTransferHandler;
InputTransferHandlerAndroid();
raw_ptr<InputTransferHandlerAndroidClient> client_ = nullptr;
base::TimeTicks cached_transferred_sequence_down_time_ms_;
base::TimeTicks last_successful_transfer_time_;
int num_events_in_dropped_sequence_ = 0;
enum class HandlerState {
kIdle,
kDroppingCurrentSequence,
kConsumeEventsUntilCancel,
kConsumeSequence,
} handler_state_ = HandlerState::kIdle;
bool requested_input_back_ = false;
std::optional<RequestInputBackReason> requested_input_back_reason_ =
std::nullopt;
int touch_moves_seen_after_transfer_ = 0;
std::unique_ptr<JniDelegate> jni_delegate_ = nullptr;
bool last_sent_browser_would_have_handled_ = false;
InputObserver input_observer_;
};
}
#endif