blob: a9e39d1630f04d0836af226917bbbb40bef01e3b [file] [log] [blame]
/*
* Copyright 2023 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.
*/
#pragma once
#include "InputDispatcherPolicyInterface.h"
#include "InputDispatcherInterface.h"
#include "NotifyArgs.h"
#include <condition_variable>
#include <functional>
#include <memory>
#include <mutex>
#include <optional>
#include <queue>
#include <string>
#include <vector>
#include <android-base/logging.h>
#include <android-base/thread_annotations.h>
#include <binder/IBinder.h>
#include <gui/PidUid.h>
#include <gui/WindowInfo.h>
#include <input/BlockingQueue.h>
#include <input/Input.h>
namespace android {
class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
public:
FakeInputDispatcherPolicy() = default;
virtual ~FakeInputDispatcherPolicy() = default;
struct AnrResult {
sp<IBinder> token{};
std::optional<gui::Pid> pid{};
};
struct UserActivityPokeEvent {
nsecs_t eventTime;
int32_t eventType;
ui::LogicalDisplayId displayId;
bool operator==(const UserActivityPokeEvent& rhs) const = default;
inline friend std::ostream& operator<<(std::ostream& os, const UserActivityPokeEvent& ev) {
os << "UserActivityPokeEvent[time=" << ev.eventTime << ", eventType=" << ev.eventType
<< ", displayId=" << ev.displayId << "]";
return os;
}
};
void assertFilterInputEventWasCalled(const NotifyKeyArgs& args);
void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point);
void assertFilterInputEventWasNotCalled();
void assertNotifySwitchWasCalled(const NotifySwitchArgs& args);
void assertOnPointerDownEquals(const sp<IBinder>& touchedToken);
void assertOnPointerDownWasNotCalled();
/**
* This function must be called soon after the expected ANR timer starts,
* because we are also checking how much time has passed.
*/
void assertNotifyNoFocusedWindowAnrWasCalled(
std::chrono::nanoseconds timeout,
const std::shared_ptr<InputApplicationHandle>& expectedApplication);
void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
const sp<gui::WindowInfoHandle>& window);
void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
const sp<IBinder>& expectedToken,
std::optional<gui::Pid> expectedPid);
/** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout);
void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
std::optional<gui::Pid> expectedPid);
/** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
sp<IBinder> getResponsiveWindowToken();
void assertNotifyAnrWasNotCalled();
PointerCaptureRequest assertSetPointerCaptureCalled(const sp<gui::WindowInfoHandle>& window,
bool enabled);
void assertSetPointerCaptureNotCalled();
void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
const sp<IBinder>& targetToken);
void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token);
/**
* Set policy timeout. A value of zero means next key will not be intercepted.
*/
void setInterceptKeyTimeout(std::chrono::milliseconds timeout);
std::chrono::nanoseconds getKeyWaitingForEventsTimeout() override;
void setStaleEventTimeout(std::chrono::nanoseconds timeout);
void assertUserActivityNotPoked();
/**
* Asserts that a user activity poke has happened. The earliest recorded poke event will be
* cleared after this call.
*
* If an expected UserActivityPokeEvent is provided, asserts that the given event is the
* earliest recorded poke event.
*/
void assertUserActivityPoked(std::optional<UserActivityPokeEvent> expectedPokeEvent = {});
void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids);
void assertNotifyDeviceInteractionWasNotCalled();
void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler);
void assertUnhandledKeyReported(int32_t keycode);
void assertUnhandledKeyNotReported();
void setConsumeKeyBeforeDispatching(bool consumeKeyBeforeDispatching);
void assertFocusedDisplayNotified(ui::LogicalDisplayId expectedDisplay);
private:
std::mutex mLock;
std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
std::condition_variable mPointerCaptureChangedCondition;
std::optional<ui::LogicalDisplayId> mNotifiedFocusedDisplay GUARDED_BY(mLock);
std::condition_variable mFocusedDisplayNotifiedCondition;
std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
// ANR handling
std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
std::condition_variable mNotifyAnr;
std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
std::condition_variable mNotifyInputChannelBroken;
sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
std::condition_variable mNotifyUserActivity;
std::queue<UserActivityPokeEvent> mUserActivityPokeEvents;
std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
bool mConsumeKeyBeforeDispatching = false;
BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
std::condition_variable mNotifyUnhandledKey;
std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
/**
* All three ANR-related callbacks behave the same way, so we use this generic function to wait
* for a specific container to become non-empty. When the container is non-empty, return the
* first entry from the container and erase it.
*/
template <class T>
T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
std::unique_lock<std::mutex>& lock) REQUIRES(mLock);
template <class T>
std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
std::queue<T>& storage,
std::unique_lock<std::mutex>& lock,
std::condition_variable& condition)
REQUIRES(mLock);
void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
const std::string&) override;
void notifyWindowResponsive(const sp<IBinder>& connectionToken,
std::optional<gui::Pid> pid) override;
void notifyNoFocusedWindowAnr(
const std::shared_ptr<InputApplicationHandle>& applicationHandle) override;
void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override;
void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override;
void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
const std::vector<float>& values) override;
void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
InputDeviceSensorAccuracy accuracy) override;
void notifyVibratorState(int32_t deviceId, bool isOn) override;
bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override;
void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override;
void interceptMotionBeforeQueueing(ui::LogicalDisplayId, uint32_t, int32_t, nsecs_t,
uint32_t&) override;
nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override;
std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
uint32_t) override;
void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
uint32_t policyFlags) override;
void pokeUserActivity(nsecs_t eventTime, int32_t eventType,
ui::LogicalDisplayId displayId) override;
bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override;
void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override;
void setPointerCapture(const PointerCaptureRequest& request) override;
void notifyDropWindow(const sp<IBinder>& token, float x, float y) override;
void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
const std::set<gui::Uid>& uids) override;
void notifyFocusedDisplayChanged(ui::LogicalDisplayId displayId) override;
void assertFilterInputEventWasCalledInternal(
const std::function<void(const InputEvent&)>& verify);
};
} // namespace android