blob: c0d8b06aa048c0a9bdc8aedac782d1e905b6c309 [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#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 "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;
};
// The class assumes transfer input to viz is supported, so instantiate only
// when |input::IsTransferInputToVizSupported()| returns true.
// The class is responsible for coordinating with java side InputTransferHandler
// which may end up issuing |WindowManager.transferTouchGesture| Android API
// call. In case of a successful transfer, rest of the touch sequence is
// consumed until a TOUCH_CANCEL is seen. InputTransferHandlerAndroid is owned
// by RenderWidgetHostViewAndroid, instantiated if
// |input::IsTransferInputToVizSupported()| returns true.
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 for testing.
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.TransferInputToVizResult";
static constexpr const char* kEventsInDroppedSequenceHistogram =
"Android.InputOnViz.Browser.NumEventsInDroppedSequence";
static constexpr const char* kEventTypesInDroppedSequenceHistogram =
"Android.InputOnViz.Browser.EventTypesInDroppedSequence";
static constexpr const char* kTouchSequenceDroppedReasonHistogram =
"Android.InputOnViz.Browser.SequenceDroppedReason";
bool touch_transferred() {
return handler_state_ == HandlerState::kConsumeEventsUntilCancel;
}
bool FilterRedundantDownEvent(const ui::MotionEvent& event);
enum class RequestInputBackReason {
kStartDragAndDropGesture = 0,
kStartTouchSelectionDragGesture = 1,
kStartOverscrollGestures = 2,
};
void RequestInputBack(RequestInputBackReason reason);
void OnTouchEnd(base::TimeTicks event_time);
// Virtual for testing.
virtual bool IsTouchSequencePotentiallyActiveOnViz() const;
RenderWidgetHost::InputEventObserver& GetInputObserver() {
return input_observer_;
}
private:
class InputObserver : public RenderWidgetHost::InputEventObserver {
public:
explicit InputObserver(InputTransferHandlerAndroid& transfer_handler);
~InputObserver() override;
// Start RenderWidgetHost::InputEventObserver overrides
void OnInputEvent(const RenderWidgetHost& host,
const blink::WebInputEvent& event) override;
// End RenderWidgetHost::InputEventObserver overrides
private:
const raw_ref<InputTransferHandlerAndroid> transfer_handler_;
};
void Reset();
void OnTouchTransferredSuccessfully(const ui::MotionEventAndroid& event,
bool browser_would_have_handled);
void EmitTransferResultHistogramAndTraceEvent(
TransferInputToVizResult result);
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
//
// LINT.IfChange(InputOnVizSequenceDroppedReason)
enum class InputOnVizSequenceDroppedReason {
kActiveSeqOnVizAbnormalDownTime = 0,
kFailedToTransferPotentialPointer = 1,
kMaxValue = kFailedToTransferPotentialPointer,
};
// LINT.ThenChange(//tools/metrics/histograms/metadata/android/enums.xml:InputOnVizSequenceDroppedReason)
void OnStartDroppingSequence(const ui::MotionEventAndroid& event,
InputOnVizSequenceDroppedReason reason);
void DropCurrentSequence(const ui::MotionEventAndroid& event);
void ConsumeEventsUntilCancel(const ui::MotionEventAndroid& event);
void ConsumeSequence(const ui::MotionEventAndroid& event);
friend class MockInputTransferHandler;
InputTransferHandlerAndroid();
raw_ptr<InputTransferHandlerAndroidClient> client_ = nullptr;
// Stores the event time of first down event of the most recent touch sequence
// transferred to VizCompositor. See
// (https://developer.android.com/reference/android/view/MotionEvent#getDownTime())
base::TimeTicks cached_transferred_sequence_down_time_ms_;
int num_events_in_dropped_sequence_ = 0;
enum class HandlerState {
// Handler is just passively listening for events in this state.
kIdle,
// The sequence is being dropped since a potential pointer sequence failed
// to transfer.
kDroppingCurrentSequence,
// The touch sequence was transferred to Viz and the handler is consuming
// rest of sequence that might hit Browser.
kConsumeEventsUntilCancel,
// Consume current sequence until an action cancel or action up comes in.
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;
base::TimeTicks last_seen_touch_end_ts_;
InputObserver input_observer_;
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_TRANSFER_HANDLER_ANDROID_H_