blob: 6b7697dde636ef67b0ee73f7fda3816a301da5c4 [file] [log] [blame]
/*
* Copyright (C) 2019 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.
*/
#ifndef _UI_INPUT_INPUTDISPATCHER_ENTRY_H
#define _UI_INPUT_INPUTDISPATCHER_ENTRY_H
#include "InjectionState.h"
#include "InputTarget.h"
#include <input/Input.h>
#include <input/InputApplication.h>
#include <stdint.h>
#include <utils/Timers.h>
#include <functional>
#include <string>
namespace android::inputdispatcher {
struct EventEntry {
enum class Type {
CONFIGURATION_CHANGED,
DEVICE_RESET,
FOCUS,
KEY,
MOTION,
};
static const char* typeToString(Type type) {
switch (type) {
case Type::CONFIGURATION_CHANGED:
return "CONFIGURATION_CHANGED";
case Type::DEVICE_RESET:
return "DEVICE_RESET";
case Type::FOCUS:
return "FOCUS";
case Type::KEY:
return "KEY";
case Type::MOTION:
return "MOTION";
}
}
int32_t id;
mutable int32_t refCount;
Type type;
nsecs_t eventTime;
uint32_t policyFlags;
InjectionState* injectionState;
bool dispatchInProgress; // initially false, set to true while dispatching
/**
* Injected keys are events from an external (probably untrusted) application
* and are not related to real hardware state. They come in via
* InputDispatcher::injectInputEvent, which sets policy flag POLICY_FLAG_INJECTED.
*/
inline bool isInjected() const { return injectionState != nullptr; }
/**
* Synthesized events are either injected events, or events that come
* from real hardware, but aren't directly attributable to a specific hardware event.
* Key repeat is a synthesized event, because it is related to an actual hardware state
* (a key is currently pressed), but the repeat itself is generated by the framework.
*/
inline bool isSynthesized() const {
return isInjected() || IdGenerator::getSource(id) != IdGenerator::Source::INPUT_READER;
}
void release();
virtual void appendDescription(std::string& msg) const = 0;
std::string getDescription() const;
protected:
EventEntry(int32_t id, Type type, nsecs_t eventTime, uint32_t policyFlags);
virtual ~EventEntry();
void releaseInjectionState();
};
struct ConfigurationChangedEntry : EventEntry {
explicit ConfigurationChangedEntry(int32_t id, nsecs_t eventTime);
virtual void appendDescription(std::string& msg) const;
protected:
virtual ~ConfigurationChangedEntry();
};
struct DeviceResetEntry : EventEntry {
int32_t deviceId;
DeviceResetEntry(int32_t id, nsecs_t eventTime, int32_t deviceId);
virtual void appendDescription(std::string& msg) const;
protected:
virtual ~DeviceResetEntry();
};
struct FocusEntry : EventEntry {
sp<IBinder> connectionToken;
bool hasFocus;
FocusEntry(int32_t id, nsecs_t eventTime, sp<IBinder> connectionToken, bool hasFocus);
virtual void appendDescription(std::string& msg) const;
protected:
virtual ~FocusEntry();
};
struct KeyEntry : EventEntry {
int32_t deviceId;
uint32_t source;
int32_t displayId;
int32_t action;
int32_t flags;
int32_t keyCode;
int32_t scanCode;
int32_t metaState;
int32_t repeatCount;
nsecs_t downTime;
bool syntheticRepeat; // set to true for synthetic key repeats
enum InterceptKeyResult {
INTERCEPT_KEY_RESULT_UNKNOWN,
INTERCEPT_KEY_RESULT_SKIP,
INTERCEPT_KEY_RESULT_CONTINUE,
INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER,
};
InterceptKeyResult interceptKeyResult; // set based on the interception result
nsecs_t interceptKeyWakeupTime; // used with INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER
KeyEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, int32_t displayId,
uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
int32_t metaState, int32_t repeatCount, nsecs_t downTime);
virtual void appendDescription(std::string& msg) const;
void recycle();
protected:
virtual ~KeyEntry();
};
struct MotionEntry : EventEntry {
nsecs_t eventTime;
int32_t deviceId;
uint32_t source;
int32_t displayId;
int32_t action;
int32_t actionButton;
int32_t flags;
int32_t metaState;
int32_t buttonState;
MotionClassification classification;
int32_t edgeFlags;
float xPrecision;
float yPrecision;
float xCursorPosition;
float yCursorPosition;
nsecs_t downTime;
uint32_t pointerCount;
PointerProperties pointerProperties[MAX_POINTERS];
PointerCoords pointerCoords[MAX_POINTERS];
MotionEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, int32_t displayId,
uint32_t policyFlags, int32_t action, int32_t actionButton, int32_t flags,
int32_t metaState, int32_t buttonState, MotionClassification classification,
int32_t edgeFlags, float xPrecision, float yPrecision, float xCursorPosition,
float yCursorPosition, nsecs_t downTime, uint32_t pointerCount,
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
float xOffset, float yOffset);
virtual void appendDescription(std::string& msg) const;
protected:
virtual ~MotionEntry();
};
// Tracks the progress of dispatching a particular event to a particular connection.
struct DispatchEntry {
const uint32_t seq; // unique sequence number, never 0
EventEntry* eventEntry; // the event to dispatch
int32_t targetFlags;
float xOffset;
float yOffset;
float globalScaleFactor;
float windowXScale = 1.0f;
float windowYScale = 1.0f;
// Both deliveryTime and timeoutTime are only populated when the entry is sent to the app,
// and will be undefined before that.
nsecs_t deliveryTime; // time when the event was actually delivered
// An ANR will be triggered if a response for this entry is not received by timeoutTime
nsecs_t timeoutTime;
// Set to the resolved ID, action and flags when the event is enqueued.
int32_t resolvedEventId;
int32_t resolvedAction;
int32_t resolvedFlags;
DispatchEntry(EventEntry* eventEntry, int32_t targetFlags, float xOffset, float yOffset,
float globalScaleFactor, float windowXScale, float windowYScale);
~DispatchEntry();
inline bool hasForegroundTarget() const { return targetFlags & InputTarget::FLAG_FOREGROUND; }
inline bool isSplit() const { return targetFlags & InputTarget::FLAG_SPLIT; }
private:
static volatile int32_t sNextSeqAtomic;
static uint32_t nextSeq();
};
VerifiedKeyEvent verifiedKeyEventFromKeyEntry(const KeyEntry& entry);
VerifiedMotionEvent verifiedMotionEventFromMotionEntry(const MotionEntry& entry);
class InputDispatcher;
// A command entry captures state and behavior for an action to be performed in the
// dispatch loop after the initial processing has taken place. It is essentially
// a kind of continuation used to postpone sensitive policy interactions to a point
// in the dispatch loop where it is safe to release the lock (generally after finishing
// the critical parts of the dispatch cycle).
//
// The special thing about commands is that they can voluntarily release and reacquire
// the dispatcher lock at will. Initially when the command starts running, the
// dispatcher lock is held. However, if the command needs to call into the policy to
// do some work, it can release the lock, do the work, then reacquire the lock again
// before returning.
//
// This mechanism is a bit clunky but it helps to preserve the invariant that the dispatch
// never calls into the policy while holding its lock.
//
// Commands are implicitly 'LockedInterruptible'.
struct CommandEntry;
typedef std::function<void(InputDispatcher&, CommandEntry*)> Command;
class Connection;
struct CommandEntry {
explicit CommandEntry(Command command);
~CommandEntry();
Command command;
// parameters for the command (usage varies by command)
sp<Connection> connection;
nsecs_t eventTime;
KeyEntry* keyEntry;
sp<InputApplicationHandle> inputApplicationHandle;
std::string reason;
int32_t userActivityEventType;
uint32_t seq;
bool handled;
sp<InputChannel> inputChannel;
sp<IBinder> oldToken;
sp<IBinder> newToken;
};
} // namespace android::inputdispatcher
#endif // _UI_INPUT_INPUTDISPATCHER_ENTRY_H