widget/gonk/libui/InputTransport.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 * Copyright (C) 2010 The Android Open Source Project
michael@0 3 *
michael@0 4 * Licensed under the Apache License, Version 2.0 (the "License");
michael@0 5 * you may not use this file except in compliance with the License.
michael@0 6 * You may obtain a copy of the License at
michael@0 7 *
michael@0 8 * http://www.apache.org/licenses/LICENSE-2.0
michael@0 9 *
michael@0 10 * Unless required by applicable law or agreed to in writing, software
michael@0 11 * distributed under the License is distributed on an "AS IS" BASIS,
michael@0 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michael@0 13 * See the License for the specific language governing permissions and
michael@0 14 * limitations under the License.
michael@0 15 */
michael@0 16
michael@0 17 #ifndef _ANDROIDFW_INPUT_TRANSPORT_H
michael@0 18 #define _ANDROIDFW_INPUT_TRANSPORT_H
michael@0 19
michael@0 20 /**
michael@0 21 * Native input transport.
michael@0 22 *
michael@0 23 * The InputChannel provides a mechanism for exchanging InputMessage structures across processes.
michael@0 24 *
michael@0 25 * The InputPublisher and InputConsumer each handle one end-point of an input channel.
michael@0 26 * The InputPublisher is used by the input dispatcher to send events to the application.
michael@0 27 * The InputConsumer is used by the application to receive events from the input dispatcher.
michael@0 28 */
michael@0 29
michael@0 30 #include "Input.h"
michael@0 31 #include <utils/Errors.h>
michael@0 32 #include <utils/Timers.h>
michael@0 33 #include <utils/RefBase.h>
michael@0 34 #include <utils/String8.h>
michael@0 35 #include <utils/Vector.h>
michael@0 36 #include <utils/BitSet.h>
michael@0 37
michael@0 38 namespace android {
michael@0 39
michael@0 40 /*
michael@0 41 * Intermediate representation used to send input events and related signals.
michael@0 42 */
michael@0 43 struct InputMessage {
michael@0 44 enum {
michael@0 45 TYPE_KEY = 1,
michael@0 46 TYPE_MOTION = 2,
michael@0 47 TYPE_FINISHED = 3,
michael@0 48 };
michael@0 49
michael@0 50 struct Header {
michael@0 51 uint32_t type;
michael@0 52 uint32_t padding; // 8 byte alignment for the body that follows
michael@0 53 } header;
michael@0 54
michael@0 55 union Body {
michael@0 56 struct Key {
michael@0 57 uint32_t seq;
michael@0 58 nsecs_t eventTime;
michael@0 59 int32_t deviceId;
michael@0 60 int32_t source;
michael@0 61 int32_t action;
michael@0 62 int32_t flags;
michael@0 63 int32_t keyCode;
michael@0 64 int32_t scanCode;
michael@0 65 int32_t metaState;
michael@0 66 int32_t repeatCount;
michael@0 67 nsecs_t downTime;
michael@0 68
michael@0 69 inline size_t size() const {
michael@0 70 return sizeof(Key);
michael@0 71 }
michael@0 72 } key;
michael@0 73
michael@0 74 struct Motion {
michael@0 75 uint32_t seq;
michael@0 76 nsecs_t eventTime;
michael@0 77 int32_t deviceId;
michael@0 78 int32_t source;
michael@0 79 int32_t action;
michael@0 80 int32_t flags;
michael@0 81 int32_t metaState;
michael@0 82 int32_t buttonState;
michael@0 83 int32_t edgeFlags;
michael@0 84 nsecs_t downTime;
michael@0 85 float xOffset;
michael@0 86 float yOffset;
michael@0 87 float xPrecision;
michael@0 88 float yPrecision;
michael@0 89 size_t pointerCount;
michael@0 90 struct Pointer {
michael@0 91 PointerProperties properties;
michael@0 92 PointerCoords coords;
michael@0 93 } pointers[MAX_POINTERS];
michael@0 94
michael@0 95 int32_t getActionId() const {
michael@0 96 uint32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
michael@0 97 >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
michael@0 98 return pointers[index].properties.id;
michael@0 99 }
michael@0 100
michael@0 101 inline size_t size() const {
michael@0 102 return sizeof(Motion) - sizeof(Pointer) * MAX_POINTERS
michael@0 103 + sizeof(Pointer) * pointerCount;
michael@0 104 }
michael@0 105 } motion;
michael@0 106
michael@0 107 struct Finished {
michael@0 108 uint32_t seq;
michael@0 109 bool handled;
michael@0 110
michael@0 111 inline size_t size() const {
michael@0 112 return sizeof(Finished);
michael@0 113 }
michael@0 114 } finished;
michael@0 115 } body;
michael@0 116
michael@0 117 bool isValid(size_t actualSize) const;
michael@0 118 size_t size() const;
michael@0 119 };
michael@0 120
michael@0 121 /*
michael@0 122 * An input channel consists of a local unix domain socket used to send and receive
michael@0 123 * input messages across processes. Each channel has a descriptive name for debugging purposes.
michael@0 124 *
michael@0 125 * Each endpoint has its own InputChannel object that specifies its file descriptor.
michael@0 126 *
michael@0 127 * The input channel is closed when all references to it are released.
michael@0 128 */
michael@0 129 class InputChannel : public RefBase {
michael@0 130 protected:
michael@0 131 virtual ~InputChannel();
michael@0 132
michael@0 133 public:
michael@0 134 InputChannel(const String8& name, int fd);
michael@0 135
michael@0 136 /* Creates a pair of input channels.
michael@0 137 *
michael@0 138 * Returns OK on success.
michael@0 139 */
michael@0 140 static status_t openInputChannelPair(const String8& name,
michael@0 141 sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel);
michael@0 142
michael@0 143 inline String8 getName() const { return mName; }
michael@0 144 inline int getFd() const { return mFd; }
michael@0 145
michael@0 146 /* Sends a message to the other endpoint.
michael@0 147 *
michael@0 148 * If the channel is full then the message is guaranteed not to have been sent at all.
michael@0 149 * Try again after the consumer has sent a finished signal indicating that it has
michael@0 150 * consumed some of the pending messages from the channel.
michael@0 151 *
michael@0 152 * Returns OK on success.
michael@0 153 * Returns WOULD_BLOCK if the channel is full.
michael@0 154 * Returns DEAD_OBJECT if the channel's peer has been closed.
michael@0 155 * Other errors probably indicate that the channel is broken.
michael@0 156 */
michael@0 157 status_t sendMessage(const InputMessage* msg);
michael@0 158
michael@0 159 /* Receives a message sent by the other endpoint.
michael@0 160 *
michael@0 161 * If there is no message present, try again after poll() indicates that the fd
michael@0 162 * is readable.
michael@0 163 *
michael@0 164 * Returns OK on success.
michael@0 165 * Returns WOULD_BLOCK if there is no message present.
michael@0 166 * Returns DEAD_OBJECT if the channel's peer has been closed.
michael@0 167 * Other errors probably indicate that the channel is broken.
michael@0 168 */
michael@0 169 status_t receiveMessage(InputMessage* msg);
michael@0 170
michael@0 171 /* Returns a new object that has a duplicate of this channel's fd. */
michael@0 172 sp<InputChannel> dup() const;
michael@0 173
michael@0 174 private:
michael@0 175 String8 mName;
michael@0 176 int mFd;
michael@0 177 };
michael@0 178
michael@0 179 /*
michael@0 180 * Publishes input events to an input channel.
michael@0 181 */
michael@0 182 class InputPublisher {
michael@0 183 public:
michael@0 184 /* Creates a publisher associated with an input channel. */
michael@0 185 explicit InputPublisher(const sp<InputChannel>& channel);
michael@0 186
michael@0 187 /* Destroys the publisher and releases its input channel. */
michael@0 188 ~InputPublisher();
michael@0 189
michael@0 190 /* Gets the underlying input channel. */
michael@0 191 inline sp<InputChannel> getChannel() { return mChannel; }
michael@0 192
michael@0 193 /* Publishes a key event to the input channel.
michael@0 194 *
michael@0 195 * Returns OK on success.
michael@0 196 * Returns WOULD_BLOCK if the channel is full.
michael@0 197 * Returns DEAD_OBJECT if the channel's peer has been closed.
michael@0 198 * Returns BAD_VALUE if seq is 0.
michael@0 199 * Other errors probably indicate that the channel is broken.
michael@0 200 */
michael@0 201 status_t publishKeyEvent(
michael@0 202 uint32_t seq,
michael@0 203 int32_t deviceId,
michael@0 204 int32_t source,
michael@0 205 int32_t action,
michael@0 206 int32_t flags,
michael@0 207 int32_t keyCode,
michael@0 208 int32_t scanCode,
michael@0 209 int32_t metaState,
michael@0 210 int32_t repeatCount,
michael@0 211 nsecs_t downTime,
michael@0 212 nsecs_t eventTime);
michael@0 213
michael@0 214 /* Publishes a motion event to the input channel.
michael@0 215 *
michael@0 216 * Returns OK on success.
michael@0 217 * Returns WOULD_BLOCK if the channel is full.
michael@0 218 * Returns DEAD_OBJECT if the channel's peer has been closed.
michael@0 219 * Returns BAD_VALUE if seq is 0 or if pointerCount is less than 1 or greater than MAX_POINTERS.
michael@0 220 * Other errors probably indicate that the channel is broken.
michael@0 221 */
michael@0 222 status_t publishMotionEvent(
michael@0 223 uint32_t seq,
michael@0 224 int32_t deviceId,
michael@0 225 int32_t source,
michael@0 226 int32_t action,
michael@0 227 int32_t flags,
michael@0 228 int32_t edgeFlags,
michael@0 229 int32_t metaState,
michael@0 230 int32_t buttonState,
michael@0 231 float xOffset,
michael@0 232 float yOffset,
michael@0 233 float xPrecision,
michael@0 234 float yPrecision,
michael@0 235 nsecs_t downTime,
michael@0 236 nsecs_t eventTime,
michael@0 237 size_t pointerCount,
michael@0 238 const PointerProperties* pointerProperties,
michael@0 239 const PointerCoords* pointerCoords);
michael@0 240
michael@0 241 /* Receives the finished signal from the consumer in reply to the original dispatch signal.
michael@0 242 * If a signal was received, returns the message sequence number,
michael@0 243 * and whether the consumer handled the message.
michael@0 244 *
michael@0 245 * The returned sequence number is never 0 unless the operation failed.
michael@0 246 *
michael@0 247 * Returns OK on success.
michael@0 248 * Returns WOULD_BLOCK if there is no signal present.
michael@0 249 * Returns DEAD_OBJECT if the channel's peer has been closed.
michael@0 250 * Other errors probably indicate that the channel is broken.
michael@0 251 */
michael@0 252 status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled);
michael@0 253
michael@0 254 private:
michael@0 255 sp<InputChannel> mChannel;
michael@0 256 };
michael@0 257
michael@0 258 /*
michael@0 259 * Consumes input events from an input channel.
michael@0 260 */
michael@0 261 class InputConsumer {
michael@0 262 public:
michael@0 263 /* Creates a consumer associated with an input channel. */
michael@0 264 explicit InputConsumer(const sp<InputChannel>& channel);
michael@0 265
michael@0 266 /* Destroys the consumer and releases its input channel. */
michael@0 267 ~InputConsumer();
michael@0 268
michael@0 269 /* Gets the underlying input channel. */
michael@0 270 inline sp<InputChannel> getChannel() { return mChannel; }
michael@0 271
michael@0 272 /* Consumes an input event from the input channel and copies its contents into
michael@0 273 * an InputEvent object created using the specified factory.
michael@0 274 *
michael@0 275 * Tries to combine a series of move events into larger batches whenever possible.
michael@0 276 *
michael@0 277 * If consumeBatches is false, then defers consuming pending batched events if it
michael@0 278 * is possible for additional samples to be added to them later. Call hasPendingBatch()
michael@0 279 * to determine whether a pending batch is available to be consumed.
michael@0 280 *
michael@0 281 * If consumeBatches is true, then events are still batched but they are consumed
michael@0 282 * immediately as soon as the input channel is exhausted.
michael@0 283 *
michael@0 284 * The frameTime parameter specifies the time when the current display frame started
michael@0 285 * rendering in the CLOCK_MONOTONIC time base, or -1 if unknown.
michael@0 286 *
michael@0 287 * The returned sequence number is never 0 unless the operation failed.
michael@0 288 *
michael@0 289 * Returns OK on success.
michael@0 290 * Returns WOULD_BLOCK if there is no event present.
michael@0 291 * Returns DEAD_OBJECT if the channel's peer has been closed.
michael@0 292 * Returns NO_MEMORY if the event could not be created.
michael@0 293 * Other errors probably indicate that the channel is broken.
michael@0 294 */
michael@0 295 status_t consume(InputEventFactoryInterface* factory, bool consumeBatches,
michael@0 296 nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent);
michael@0 297
michael@0 298 /* Sends a finished signal to the publisher to inform it that the message
michael@0 299 * with the specified sequence number has finished being process and whether
michael@0 300 * the message was handled by the consumer.
michael@0 301 *
michael@0 302 * Returns OK on success.
michael@0 303 * Returns BAD_VALUE if seq is 0.
michael@0 304 * Other errors probably indicate that the channel is broken.
michael@0 305 */
michael@0 306 status_t sendFinishedSignal(uint32_t seq, bool handled);
michael@0 307
michael@0 308 /* Returns true if there is a deferred event waiting.
michael@0 309 *
michael@0 310 * Should be called after calling consume() to determine whether the consumer
michael@0 311 * has a deferred event to be processed. Deferred events are somewhat special in
michael@0 312 * that they have already been removed from the input channel. If the input channel
michael@0 313 * becomes empty, the client may need to do extra work to ensure that it processes
michael@0 314 * the deferred event despite the fact that the input channel's file descriptor
michael@0 315 * is not readable.
michael@0 316 *
michael@0 317 * One option is simply to call consume() in a loop until it returns WOULD_BLOCK.
michael@0 318 * This guarantees that all deferred events will be processed.
michael@0 319 *
michael@0 320 * Alternately, the caller can call hasDeferredEvent() to determine whether there is
michael@0 321 * a deferred event waiting and then ensure that its event loop wakes up at least
michael@0 322 * one more time to consume the deferred event.
michael@0 323 */
michael@0 324 bool hasDeferredEvent() const;
michael@0 325
michael@0 326 /* Returns true if there is a pending batch.
michael@0 327 *
michael@0 328 * Should be called after calling consume() with consumeBatches == false to determine
michael@0 329 * whether consume() should be called again later on with consumeBatches == true.
michael@0 330 */
michael@0 331 bool hasPendingBatch() const;
michael@0 332
michael@0 333 private:
michael@0 334 // True if touch resampling is enabled.
michael@0 335 const bool mResampleTouch;
michael@0 336
michael@0 337 // The input channel.
michael@0 338 sp<InputChannel> mChannel;
michael@0 339
michael@0 340 // The current input message.
michael@0 341 InputMessage mMsg;
michael@0 342
michael@0 343 // True if mMsg contains a valid input message that was deferred from the previous
michael@0 344 // call to consume and that still needs to be handled.
michael@0 345 bool mMsgDeferred;
michael@0 346
michael@0 347 // Batched motion events per device and source.
michael@0 348 struct Batch {
michael@0 349 Vector<InputMessage> samples;
michael@0 350 };
michael@0 351 Vector<Batch> mBatches;
michael@0 352
michael@0 353 // Touch state per device and source, only for sources of class pointer.
michael@0 354 struct History {
michael@0 355 nsecs_t eventTime;
michael@0 356 BitSet32 idBits;
michael@0 357 int32_t idToIndex[MAX_POINTER_ID + 1];
michael@0 358 PointerCoords pointers[MAX_POINTERS];
michael@0 359
michael@0 360 void initializeFrom(const InputMessage* msg) {
michael@0 361 eventTime = msg->body.motion.eventTime;
michael@0 362 idBits.clear();
michael@0 363 for (size_t i = 0; i < msg->body.motion.pointerCount; i++) {
michael@0 364 uint32_t id = msg->body.motion.pointers[i].properties.id;
michael@0 365 idBits.markBit(id);
michael@0 366 idToIndex[id] = i;
michael@0 367 pointers[i].copyFrom(msg->body.motion.pointers[i].coords);
michael@0 368 }
michael@0 369 }
michael@0 370
michael@0 371 const PointerCoords& getPointerById(uint32_t id) const {
michael@0 372 return pointers[idToIndex[id]];
michael@0 373 }
michael@0 374 };
michael@0 375 struct TouchState {
michael@0 376 int32_t deviceId;
michael@0 377 int32_t source;
michael@0 378 size_t historyCurrent;
michael@0 379 size_t historySize;
michael@0 380 History history[2];
michael@0 381 History lastResample;
michael@0 382
michael@0 383 void initialize(int32_t deviceId, int32_t source) {
michael@0 384 this->deviceId = deviceId;
michael@0 385 this->source = source;
michael@0 386 historyCurrent = 0;
michael@0 387 historySize = 0;
michael@0 388 lastResample.eventTime = 0;
michael@0 389 lastResample.idBits.clear();
michael@0 390 }
michael@0 391
michael@0 392 void addHistory(const InputMessage* msg) {
michael@0 393 historyCurrent ^= 1;
michael@0 394 if (historySize < 2) {
michael@0 395 historySize += 1;
michael@0 396 }
michael@0 397 history[historyCurrent].initializeFrom(msg);
michael@0 398 }
michael@0 399
michael@0 400 const History* getHistory(size_t index) const {
michael@0 401 return &history[(historyCurrent + index) & 1];
michael@0 402 }
michael@0 403 };
michael@0 404 Vector<TouchState> mTouchStates;
michael@0 405
michael@0 406 // Chain of batched sequence numbers. When multiple input messages are combined into
michael@0 407 // a batch, we append a record here that associates the last sequence number in the
michael@0 408 // batch with the previous one. When the finished signal is sent, we traverse the
michael@0 409 // chain to individually finish all input messages that were part of the batch.
michael@0 410 struct SeqChain {
michael@0 411 uint32_t seq; // sequence number of batched input message
michael@0 412 uint32_t chain; // sequence number of previous batched input message
michael@0 413 };
michael@0 414 Vector<SeqChain> mSeqChains;
michael@0 415
michael@0 416 status_t consumeBatch(InputEventFactoryInterface* factory,
michael@0 417 nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent);
michael@0 418 status_t consumeSamples(InputEventFactoryInterface* factory,
michael@0 419 Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent);
michael@0 420
michael@0 421 void updateTouchState(InputMessage* msg);
michael@0 422 void rewriteMessage(const TouchState& state, InputMessage* msg);
michael@0 423 void resampleTouchState(nsecs_t frameTime, MotionEvent* event,
michael@0 424 const InputMessage *next);
michael@0 425
michael@0 426 ssize_t findBatch(int32_t deviceId, int32_t source) const;
michael@0 427 ssize_t findTouchState(int32_t deviceId, int32_t source) const;
michael@0 428
michael@0 429 status_t sendUnchainedFinishedSignal(uint32_t seq, bool handled);
michael@0 430
michael@0 431 static void initializeKeyEvent(KeyEvent* event, const InputMessage* msg);
michael@0 432 static void initializeMotionEvent(MotionEvent* event, const InputMessage* msg);
michael@0 433 static void addSample(MotionEvent* event, const InputMessage* msg);
michael@0 434 static bool canAddSample(const Batch& batch, const InputMessage* msg);
michael@0 435 static ssize_t findSampleNoLaterThan(const Batch& batch, nsecs_t time);
michael@0 436 static bool shouldResampleTool(int32_t toolType);
michael@0 437
michael@0 438 static bool isTouchResamplingEnabled();
michael@0 439 };
michael@0 440
michael@0 441 } // namespace android
michael@0 442
michael@0 443 #endif // _ANDROIDFW_INPUT_TRANSPORT_H

mercurial