diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-05-10 16:11:58 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-05-10 16:11:58 +0000 |
commit | ca8ce29a4adf39f65fbd522013f38b9b0a18030a (patch) | |
tree | 5cc65c6a06e2fa8e7e7b178485355ea72ef89627 | |
parent | 2e3a4cbb7d911a8d74e1ef5243f73f55fd5ed9df (diff) | |
parent | 781b8df8fa3b02c22baf0b9e80c164c7e84e84a5 (diff) | |
download | libchrome-gestures-aml_tz5_341510010.tar.gz |
Snap for 10103804 from 781b8df8fa3b02c22baf0b9e80c164c7e84e84a5 to mainline-tzdata5-releaseaml_tz5_341510070aml_tz5_341510050aml_tz5_341510010aml_tz5_341510010
Change-Id: I48363bd338bc2daf28cbd32ee9f96a8546f4d471
29 files changed, 401 insertions, 696 deletions
@@ -132,7 +132,6 @@ cc_test { "src/immediate_interpreter_unittest.cc", "src/integral_gesture_filter_interpreter_unittest.cc", "src/interpreter_unittest.cc", - "src/list_unittest.cc", "src/logging_filter_interpreter_unittest.cc", "src/lookahead_filter_interpreter_unittest.cc", "src/mouse_interpreter_unittest.cc", diff --git a/METADATA.android b/METADATA.android index 00233ca..f12b10f 100644 --- a/METADATA.android +++ b/METADATA.android @@ -6,7 +6,7 @@ third_party { type: GIT value: "https://chromium.googlesource.com/chromiumos/platform/gestures/" } - version: "3059225019e295de1138574a16c0102c6845fefb" - last_upgrade_date { year: 2023 month: 02 day: 27 } + version: "b6ae21cf67acbc76254be3677264b0ea472fce09" + last_upgrade_date { year: 2023 month: 04 day: 05 } license_type: NOTICE } @@ -60,7 +60,6 @@ TEST_OBJECTS=\ $(OBJDIR)/immediate_interpreter_unittest.o \ $(OBJDIR)/integral_gesture_filter_interpreter_unittest.o \ $(OBJDIR)/interpreter_unittest.o \ - $(OBJDIR)/list_unittest.o \ $(OBJDIR)/logging_filter_interpreter_unittest.o \ $(OBJDIR)/lookahead_filter_interpreter_unittest.o \ $(OBJDIR)/non_linearity_filter_interpreter_unittest.o \ @@ -112,7 +111,7 @@ DESTDIR = . CXXFLAGS+=\ -g \ - -std=gnu++11 \ + -std=gnu++17 \ -fno-exceptions \ -fno-strict-aliasing \ -fPIC \ diff --git a/include/gestures.h b/include/gestures.h index e4f7cc2..f3005a0 100644 --- a/include/gestures.h +++ b/include/gestures.h @@ -55,7 +55,8 @@ struct HardwareProperties { float right; // The maximum Y coordinate that the device can report. float bottom; - // The resolutions of the X and Y axes, in units per mm. + // The resolutions of the X and Y axes, in units per mm. Set to 0 if the + // resolution is unknown. float res_x; float res_y; @@ -105,15 +106,6 @@ struct HardwareProperties { #endif // __cplusplus }; -// position is the (x,y) cartesian coord of the finger on the trackpad. -// touch_major/minor are the large/small radii of the ellipse of the touching -// finger. width_major/minor are also radii, but of the finger itself, -// including a little bit that isn't touching. So, width* is generally a tad -// larger than touch*. -// tracking_id: If a finger is the same physical finger across two -// consecutive frames, it must have the same tracking id; if it's a different -// finger, it may (should) have a different tracking id. - // Warp: If a finger has the 'warp' flag set for an axis, it means that while // the finger may have moved, it should not cause any motion in that direction. // This may occur is some situations where we thought a finger was in one place, @@ -167,16 +159,27 @@ struct HardwareProperties { #define GESTURES_FINGER_WARP_Y (GESTURES_FINGER_WARP_Y_NON_MOVE | \ GESTURES_FINGER_WARP_Y_MOVE) -// Describes a single contact on a touch surface. Unless otherwise noted, the -// fields have the same meaning as the equivalent ABS_MT_... axis in the Linux -// evdev protocol. +// Describes a single contact on a touch surface. Generally, the fields have the +// same meaning as the equivalent ABS_MT_... axis in the Linux evdev protocol. struct FingerState { + // The large and small radii of the ellipse of the finger touching the pad. float touch_major, touch_minor; + + // The large and small radii of the ellipse of the finger, including parts + // that are hovering over the pad but not quite touching. Devices normally + // don't report these values, in which case they should be left at 0. float width_major, width_minor; float pressure; float orientation; + float position_x; float position_y; + + // A number that identifies a single physical finger across consecutive + // frames. If a finger is the same physical finger across two consecutive + // frames, it must have the same tracking ID; if it's a different finger, it + // should have a different tracking ID. It should be ≥ 0 (see documentation + // comment for HardwareState::fingers). short tracking_id; // A bit field of flags that are used internally by the library. (See the @@ -228,8 +231,13 @@ struct HardwareState { unsigned short finger_cnt; // The number of fingers touching the pad, which may be more than finger_cnt. unsigned short touch_cnt; - // A pointer to finger_cnt FingerState structs representing the contacts - // currently being tracked. + // A pointer to an array of FingerState structs with finger_cnt entries, + // representing the contacts currently being tracked. The order in which + // FingerStates appear need not be stable between HardwareStates — only the + // tracking ID is used to track individual contacts over time. Accordingly, + // when a finger is lifted from the pad (and therefore its ABS_MT_TRACKING_ID + // becomes -1), the client should simply stop including it in this array, + // rather than including a final FingerState for it. struct FingerState* fingers; // Mouse axes, which have the same meanings as the Linux evdev axes of the diff --git a/include/list.h b/include/list.h deleted file mode 100644 index d5d94c4..0000000 --- a/include/list.h +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2011 The ChromiumOS Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GESTURES_LIST_H__ -#define GESTURES_LIST_H__ - -#include "include/logging.h" -#include "include/memory_manager.h" - -namespace gestures { - -// Elt must have the following members: -// Elt* next_; -// Elt* prev_; - -template<typename Elt> -class List { - public: - List() { Init(); } - ~List() { DeleteAll(); } - - // inserts new_elt before existing. Assumes existing is in list already. - void InsertBefore(Elt *existing, Elt* new_elt) { - size_++; - Elt* pre_new = existing->prev_; - pre_new->next_ = new_elt; - new_elt->prev_ = pre_new; - new_elt->next_ = existing; - existing->prev_ = new_elt; - } - - Elt* Unlink(Elt* existing) { - if (Empty()) { - Err("Can't pop from empty list!"); - return NULL; - } - size_--; - existing->prev_->next_ = existing->next_; - existing->next_->prev_ = existing->prev_; - existing->prev_ = existing->next_ = NULL; - return existing; - } - - void PushFront(Elt* elt) { InsertBefore(sentinel_.next_, elt); } - Elt* PopFront() { return Unlink(sentinel_.next_); } - void PushBack(Elt* elt) { InsertBefore(&sentinel_, elt); } - Elt* PopBack() { return Unlink(sentinel_.prev_); } - - virtual void DeleteAll() { - while (!Empty()) - delete PopFront(); - } - - Elt* Head() const { return sentinel_.next_; } - Elt* Tail() const { return sentinel_.prev_; } - size_t size() const { return size_; } - bool Empty() const { return size() == 0; } - - // Iterator-like methods - Elt* Begin() const { return Head(); } - Elt* End() const { return const_cast<Elt*>(&sentinel_); } - - void Init() { - size_ = 0; - sentinel_.next_ = sentinel_.prev_ = &sentinel_; - } - - private: - // sentinel element - Elt sentinel_; - - size_t size_; -}; - - -template<typename Elt> -class MemoryManagedList : public List<Elt> { - public: - using List<Elt>::Empty; - using List<Elt>::PopBack; - using List<Elt>::PopFront; - using List<Elt>::PushBack; - using List<Elt>::PushFront; - - MemoryManagedList() { }; - ~MemoryManagedList() { DeleteAll(); } - - void Init(MemoryManager<Elt>* memory_manager) { - memory_manager_ = memory_manager; - List<Elt>::Init(); - } - - Elt* NewElt() { - Elt* elt = memory_manager_->Allocate(); - AssertWithReturnValue(elt, NULL); - elt->next_ = elt->prev_ = NULL; - return elt; - } - - Elt* PushNewEltBack() { - AssertWithReturnValue(memory_manager_, NULL); - Elt* elt = NewElt(); - AssertWithReturnValue(elt, NULL); - PushBack(elt); - return elt; - } - - Elt* PushNewEltFront() { - AssertWithReturnValue(memory_manager_, NULL); - Elt* elt = NewElt(); - AssertWithReturnValue(elt, NULL); - PushFront(elt); - return elt; - } - - void DeleteFront() { - AssertWithReturn(memory_manager_); - memory_manager_->Free(PopFront()); - } - - void DeleteBack() { - AssertWithReturn(memory_manager_); - memory_manager_->Free(PopBack()); - } - - virtual void DeleteAll() { - while (!Empty()) - DeleteFront(); - } - private: - MemoryManager<Elt>* memory_manager_; -}; - - -} // namespace gestures - -#endif // GESTURES_LIST_H__ diff --git a/include/lookahead_filter_interpreter.h b/include/lookahead_filter_interpreter.h index 33dcc9b..2658daa 100644 --- a/include/lookahead_filter_interpreter.h +++ b/include/lookahead_filter_interpreter.h @@ -11,9 +11,9 @@ #include "include/filter_interpreter.h" #include "include/finger_metrics.h" #include "include/gestures.h" -#include "include/list.h" #include "include/prop_registry.h" #include "include/tracer.h" +#include "include/util.h" #ifndef GESTURES_LOOKAHEAD_FILTER_INTERPRETER_H_ #define GESTURES_LOOKAHEAD_FILTER_INTERPRETER_H_ @@ -33,6 +33,7 @@ class LookaheadFilterInterpreter : public FilterInterpreter { FRIEND_TEST(LookaheadFilterInterpreterTest, SimpleTest); FRIEND_TEST(LookaheadFilterInterpreterTest, SpuriousCallbackTest); FRIEND_TEST(LookaheadFilterInterpreterTest, VariableDelayTest); + public: LookaheadFilterInterpreter(PropRegistry* prop_reg, Interpreter* next, Tracer* tracer); @@ -62,10 +63,7 @@ class LookaheadFilterInterpreter : public FilterInterpreter { std::map<short, short> output_ids_; // input tracking ids -> output stime_t due_; - bool completed_; - - QState* next_; - QState* prev_; + bool completed_ = false; }; void LogVectors(); @@ -109,7 +107,6 @@ class LookaheadFilterInterpreter : public FilterInterpreter { stime_t ExtraVariableDelay() const; List<QState> queue_; - List<QState> free_list_; // The last id assigned to a contact (part of drumroll suppression) short last_id_; diff --git a/include/memory_manager.h b/include/memory_manager.h deleted file mode 100644 index 26e096a..0000000 --- a/include/memory_manager.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2011 The ChromiumOS Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GESTURES_MEMORY_MANAGER_H_ -#define GESTURES_MEMORY_MANAGER_H_ - -#include <new> - -#include "include/logging.h" -#include "include/macros.h" - -namespace gestures { - -// A simple memory manager class that pre-allocates a size of -// buffer and garbage collects freed variables. It is not intended -// to be used directly. User classes should inherit the -// MemoryManaged wrapper class and use the provided Allocate/Free -// interface instead (see below). - -template<typename T> -class MemoryManager { - public: - explicit MemoryManager(size_t size) : buf_(new T[size]), - free_slots_(new T *[size]), used_mark_(new bool[size]()), - max_size_(size), head_(size) { - for (size_t i = 0; i < max_size_; i++) - free_slots_[i] = buf_.get() + i; - } - - size_t Size() const { return max_size_ - head_; } - size_t MaxSize() const { return max_size_; } - - T* Allocate() { - if (!head_) { - Err("MemoryManager::Allocate: out of space"); - return NULL; - } - - T* ptr = free_slots_[--head_]; - used_mark_[ptr - buf_.get()] = true; - return ptr; - } - - bool Free(T* ptr) { - // Check for invalid pointer and double-free - if (ptr < buf_.get() || ptr >= buf_.get() + max_size_) { - Err("MemoryManager::Free: pointer out of bounds"); - return false; - } - size_t offset_in_bytes = reinterpret_cast<size_t>(ptr) - - reinterpret_cast<size_t>(buf_.get()); - if (offset_in_bytes % sizeof(T)) { - Err("MemoryManager::Free: unaligned pointer"); - return false; - } - size_t offset = ptr - buf_.get(); - if (!used_mark_[offset]) { - Err("MemoryManager::Free: double-free"); - return false; - } - - free_slots_[head_++] = ptr; - used_mark_[offset] = false; - return true; - } - - private: - std::unique_ptr<T[]> buf_; - std::unique_ptr<T*[]> free_slots_; - std::unique_ptr<bool[]> used_mark_; - size_t max_size_; - size_t head_; - DISALLOW_COPY_AND_ASSIGN(MemoryManager<T>); -}; - -} // namespace gestures - -#endif // MEMORY_MANAGER_H_ diff --git a/include/metrics_filter_interpreter.h b/include/metrics_filter_interpreter.h index 60d5898..518a47a 100644 --- a/include/metrics_filter_interpreter.h +++ b/include/metrics_filter_interpreter.h @@ -2,16 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <map> #include <gtest/gtest.h> // for FRIEND_TEST +#include <map> #include "include/filter_interpreter.h" #include "include/finger_metrics.h" #include "include/gestures.h" -#include "include/list.h" -#include "include/memory_manager.h" #include "include/prop_registry.h" #include "include/tracer.h" +#include "include/util.h" #ifndef GESTURES_METRICS_FILTER_INTERPRETER_H_ #define GESTURES_METRICS_FILTER_INTERPRETER_H_ @@ -43,31 +42,22 @@ class MetricsFilterInterpreter : public FilterInterpreter { template <class DataType, size_t kHistorySize> struct State { State() {} - State(const DataType& fs, const HardwareState& hwstate) { - Init(fs, hwstate); - } - - void Init(const DataType& fs, const HardwareState& hwstate) { - timestamp = hwstate.timestamp; - data = fs; - } + State(const DataType& fs, const HardwareState& hwstate) + : timestamp(hwstate.timestamp), data(fs) {} static size_t MaxHistorySize() { return kHistorySize; } stime_t timestamp; DataType data; - State<DataType, kHistorySize>* next_; - State<DataType, kHistorySize>* prev_; }; // struct for one finger's data of one frame. typedef State<FingerState, 3> MState; - typedef MemoryManagedList<MState> FingerHistory; + typedef List<MState> FingerHistory; // Push the new data into the buffer. - template <class StateType, class DataType> - void AddNewStateToBuffer(MemoryManagedList<StateType>* history, - const DataType& data, + void AddNewStateToBuffer(FingerHistory& history, + const FingerState& data, const HardwareState& hwstate); // Update the class with new finger data, check if there is any interesting @@ -75,7 +65,7 @@ class MetricsFilterInterpreter : public FilterInterpreter { void UpdateFingerState(const HardwareState& hwstate); // Detect the noisy ground pattern and send GestureMetrics - bool DetectNoisyGround(const FingerHistory* history); + bool DetectNoisyGround(FingerHistory& history); // Update the class with new mouse movement data. void UpdateMouseMovementState(const HardwareState& hwstate); @@ -83,12 +73,8 @@ class MetricsFilterInterpreter : public FilterInterpreter { // Compute interested statistics for the mouse history, send GestureMetrics. void ReportMouseStatistics(); - // memory managers to prevent malloc during interrupt calls - MemoryManager<MState> mstate_mm_; - MemoryManager<FingerHistory> history_mm_; - // A map to store each finger's past data - typedef std::map<short, FingerHistory*> FingerHistoryMap; + typedef std::map<short, FingerHistory> FingerHistoryMap; FingerHistoryMap histories_; // Device class (e.g. touchpad, mouse). diff --git a/include/prop_registry.h b/include/prop_registry.h index 836b98b..4545a33 100644 --- a/include/prop_registry.h +++ b/include/prop_registry.h @@ -46,9 +46,8 @@ class PropertyDelegate; class Property { public: - Property(PropRegistry* parent, const char* name, - PropertyDelegate* delegate) - : gprop_(NULL), parent_(parent), delegate_(delegate), name_(name) {} + Property(PropRegistry* parent, const char* name) + : parent_(parent), name_(name) {} virtual ~Property() { if (parent_) @@ -59,18 +58,9 @@ class Property { virtual void CreatePropImpl() = 0; void DestroyProp(); - // b/253585974 - // delegate used to get passed as a constructor parameter but that - // led to a chance that the delegate was 'this' and setting the - // delegate to 'this' in the initializer list allowed the property - // creation to use 'this' before it was initialized. This could - // lead to unexpected behavior and if you were lucky to a crash. - // - // Now the delegate is always NULL on initilization of the property - // instance and after the delegate and property are completely - // created the user should set the delegate in the constructor - // body. This will allow access to this in a safe manner. - void SetDelegate(PropertyDelegate* delegate); + void SetDelegate(PropertyDelegate* delegate) { + delegate_ = delegate; + } const char* name() { return name_; } // Returns a newly allocated Value object @@ -91,9 +81,9 @@ class Property { virtual void HandleGesturesPropWritten() = 0; protected: - GesturesProp* gprop_; + GesturesProp* gprop_ = NULL; PropRegistry* parent_; - PropertyDelegate* delegate_; + PropertyDelegate* delegate_ = NULL; private: const char* name_; @@ -101,9 +91,8 @@ class Property { class BoolProperty : public Property { public: - BoolProperty(PropRegistry* reg, const char* name, GesturesPropBool val, - PropertyDelegate* delegate = NULL) - : Property(reg, name, delegate), val_(val) { + BoolProperty(PropRegistry* reg, const char* name, GesturesPropBool val) + : Property(reg, name), val_(val) { if (parent_) parent_->Register(this); } @@ -118,8 +107,8 @@ class BoolProperty : public Property { class BoolArrayProperty : public Property { public: BoolArrayProperty(PropRegistry* reg, const char* name, GesturesPropBool* vals, - size_t count, PropertyDelegate* delegate = NULL) - : Property(reg, name, delegate), vals_(vals), count_(count) { + size_t count) + : Property(reg, name), vals_(vals), count_(count) { if (parent_) parent_->Register(this); } @@ -134,9 +123,8 @@ class BoolArrayProperty : public Property { class DoubleProperty : public Property { public: - DoubleProperty(PropRegistry* reg, const char* name, double val, - PropertyDelegate* delegate = NULL) - : Property(reg, name, delegate), val_(val) { + DoubleProperty(PropRegistry* reg, const char* name, double val) + : Property(reg, name), val_(val) { if (parent_) parent_->Register(this); } @@ -151,8 +139,8 @@ class DoubleProperty : public Property { class DoubleArrayProperty : public Property { public: DoubleArrayProperty(PropRegistry* reg, const char* name, double* vals, - size_t count, PropertyDelegate* delegate = NULL) - : Property(reg, name, delegate), vals_(vals), count_(count) { + size_t count) + : Property(reg, name), vals_(vals), count_(count) { if (parent_) parent_->Register(this); } @@ -167,9 +155,8 @@ class DoubleArrayProperty : public Property { class IntProperty : public Property { public: - IntProperty(PropRegistry* reg, const char* name, int val, - PropertyDelegate* delegate = NULL) - : Property(reg, name, delegate), val_(val) { + IntProperty(PropRegistry* reg, const char* name, int val) + : Property(reg, name), val_(val) { if (parent_) parent_->Register(this); } @@ -183,9 +170,9 @@ class IntProperty : public Property { class IntArrayProperty : public Property { public: - IntArrayProperty(PropRegistry* reg, const char* name, int* vals, size_t count, - PropertyDelegate* delegate = NULL) - : Property(reg, name, delegate), vals_(vals), count_(count) { + IntArrayProperty(PropRegistry* reg, const char* name, int* vals, + size_t count) + : Property(reg, name), vals_(vals), count_(count) { if (parent_) parent_->Register(this); } @@ -200,9 +187,8 @@ class IntArrayProperty : public Property { class StringProperty : public Property { public: - StringProperty(PropRegistry* reg, const char* name, const char* val, - PropertyDelegate* delegate = NULL) - : Property(reg, name, delegate), val_(val) { + StringProperty(PropRegistry* reg, const char* name, const char* val) + : Property(reg, name), val_(val) { if (parent_) parent_->Register(this); } diff --git a/include/trend_classifying_filter_interpreter.h b/include/trend_classifying_filter_interpreter.h index b2e8436..92ae3d2 100644 --- a/include/trend_classifying_filter_interpreter.h +++ b/include/trend_classifying_filter_interpreter.h @@ -2,17 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <map> -#include <set> #include <gtest/gtest.h> // for FRIEND_TEST +#include <map> #include "include/filter_interpreter.h" #include "include/finger_metrics.h" #include "include/gestures.h" -#include "include/list.h" -#include "include/memory_manager.h" #include "include/prop_registry.h" #include "include/tracer.h" +#include "include/util.h" #ifndef GESTURES_TREND_CLASSIFYING_FILTER_INTERPRETER_H_ #define GESTURES_TREND_CLASSIFYING_FILTER_INTERPRETER_H_ @@ -151,12 +149,9 @@ private: GESTURES_FINGER_TREND_DEC_TOUCH_MAJOR }; return flags[idx]; } - - KState* next_; - KState* prev_; }; - typedef MemoryManagedList<KState> FingerHistory; + typedef List<KState> FingerHistory; // Trend types for internal use enum TrendType { @@ -169,7 +164,7 @@ private: void UpdateFingerState(const HardwareState& hwstate); // Push new finger data into the buffer and update values - void AddNewStateToBuffer(FingerHistory* history, const FingerState& fs); + void AddNewStateToBuffer(FingerHistory& history, const FingerState& fs); // Assess statistical significance with a classic two-tail hypothesis test TrendType RunKTTest(const KState::KAxis* current, const size_t n_samples); @@ -220,13 +215,9 @@ private: const unsigned flag_decreasing, unsigned* flags); - // memory managers to prevent malloc during interrupt calls - MemoryManager<KState> kstate_mm_; - MemoryManager<FingerHistory> history_mm_; - // A map to store each finger's past coordinates and calculation // intermediates - typedef std::map<short, FingerHistory*> FingerHistoryMap; + typedef std::map<short, FingerHistory> FingerHistoryMap; FingerHistoryMap histories_; // Flag to turn on/off the trend classifying filter diff --git a/include/util.h b/include/util.h index 2e87a7b..f0c2a39 100644 --- a/include/util.h +++ b/include/util.h @@ -5,6 +5,7 @@ #ifndef GESTURES_UTIL_H_ #define GESTURES_UTIL_H_ +#include <list> #include <map> #include <set> @@ -61,28 +62,16 @@ bool MapContainsKey(const Map& the_map, const Key& the_key) { } // Removes any ids from the map that are not finger ids in hs. -// This implementation supports returning removed elements for -// further processing. -template<typename Data> -void RemoveMissingIdsFromMap(std::map<short, Data>* the_map, - const HardwareState& hs, - std::map<short, Data>* removed) { - removed->clear(); - for (typename std::map<short, Data>::const_iterator it = - the_map->begin(); it != the_map->end(); ++it) - if (!hs.GetFingerState((*it).first)) - (*removed)[it->first] = it->second; - for (typename std::map<short, Data>::const_iterator it = - removed->begin(); it != removed->end(); ++it) - the_map->erase(it->first); -} - -// Removes any ids from the map that are not finger ids in hs. template<typename Data> void RemoveMissingIdsFromMap(std::map<short, Data>* the_map, const HardwareState& hs) { std::map<short, Data> removed; - RemoveMissingIdsFromMap(the_map, hs, &removed); + for (const auto& [key, value] : *the_map) { + if (!hs.GetFingerState(key)) + removed[key] = value; + } + for (const auto& [key, value] : removed) + the_map->erase(key); } // Removes any ids from the set that are not finger ids in hs. @@ -105,6 +94,29 @@ inline bool SetContainsValue(const Set& the_set, return the_set.find(elt) != the_set.end(); } +template<typename Elem> +class List : public std::list<Elem> { +public: + Elem& at(int offset) { + // Traverse to the appropriate offset + if (offset < 0) { + // negative offset is from end to begin + for (auto iter = this->rbegin(); iter != this->rend(); ++iter) { + if (++offset == 0) + return *iter; + } + } else { + // positive offset is from begin to end + for (auto iter = this->begin(); iter != this->end(); ++iter) { + if (offset-- == 0) + return *iter; + } + } + // Invalid offset + abort(); + } +}; + } // namespace gestures #endif // GESTURES_UTIL_H_ diff --git a/src/iir_filter_interpreter.cc b/src/iir_filter_interpreter.cc index 0558ef6..042e0f5 100644 --- a/src/iir_filter_interpreter.cc +++ b/src/iir_filter_interpreter.cc @@ -41,6 +41,7 @@ IirFilterInterpreter::IirFilterInterpreter(PropRegistry* prop_reg, a2_(prop_reg, "IIR a2", 0.412801598096189), iir_dist_thresh_(prop_reg, "IIR Distance Threshold", 10), adjust_iir_on_warp_(prop_reg, "Adjust IIR History On Warp", false) { + InitName(); b0_.SetDelegate(this); b1_.SetDelegate(this); b2_.SetDelegate(this); @@ -48,7 +49,6 @@ IirFilterInterpreter::IirFilterInterpreter(PropRegistry* prop_reg, a1_.SetDelegate(this); a2_.SetDelegate(this); iir_dist_thresh_.SetDelegate(this); - InitName(); } void IirFilterInterpreter::SyncInterpretImpl(HardwareState* hwstate, diff --git a/src/immediate_interpreter.cc b/src/immediate_interpreter.cc index 70369eb..7af423c 100644 --- a/src/immediate_interpreter.cc +++ b/src/immediate_interpreter.cc @@ -1095,7 +1095,7 @@ ImmediateInterpreter::ImmediateInterpreter(PropRegistry* prop_reg, keyboard_touched_timeval_high_(prop_reg, "Keyboard Touched Timeval High", 0), keyboard_touched_timeval_low_(prop_reg, "Keyboard Touched Timeval Low", - 0, this), + 0), keyboard_palm_prevent_timeout_(prop_reg, "Keyboard Palm Prevent Timeout", 0.5), motion_tap_prevent_timeout_(prop_reg, "Motion Tap Prevent Timeout", @@ -1136,6 +1136,7 @@ ImmediateInterpreter::ImmediateInterpreter(PropRegistry* prop_reg, quick_acceleration_factor_(prop_reg, "Quick Acceleration Factor", 0.0) { InitName(); requires_metrics_ = true; + keyboard_touched_timeval_low_.SetDelegate(this); } void ImmediateInterpreter::SyncInterpretImpl(HardwareState* hwstate, diff --git a/src/list_unittest.cc b/src/list_unittest.cc deleted file mode 100644 index 9c8ea74..0000000 --- a/src/list_unittest.cc +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2011 The ChromiumOS Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <algorithm> -#include <set> - -#include <gtest/gtest.h> - -#include "include/list.h" -#include "include/util.h" - -namespace gestures { - -class ListTest : public ::testing::Test {}; - -namespace { -struct Node { - explicit Node() : val_(-1) {} - explicit Node(int val) : val_(val) {} - int val_; - Node* next_; - Node* prev_; -}; - -void VerifyList(List<Node>& list) { - Node* first = list.Head()->prev_; // sentinel - Node* second = list.Head(); // next elt (sentinel or first element) - std::set<Node*> seen_nodes; - if (!list.Empty()) - EXPECT_NE(first, second); - else - EXPECT_EQ(first, second); - seen_nodes.insert(second); - for (size_t i = 0; i <= list.size(); ++i) { - EXPECT_EQ(first->next_, second); - EXPECT_EQ(second->prev_, first); - if (i < list.size()) { - first = second; - second = second->next_; - EXPECT_FALSE(SetContainsValue(seen_nodes, second)); - seen_nodes.insert(second); - } - } - EXPECT_EQ(seen_nodes.size(), list.size() + 1); - // second should now be sentinal tail - Node* sen_tail = list.Tail()->next_; - EXPECT_EQ(second, sen_tail); -} -} - -TEST(ListTest, SimpleTest) { - List<Node> list; - VerifyList(list); - EXPECT_TRUE(list.Empty()); - EXPECT_EQ(0, list.size()); - list.PushFront(new Node(4)); - VerifyList(list); - EXPECT_FALSE(list.Empty()); - EXPECT_EQ(1, list.size()); - list.PushFront(new Node(5)); - VerifyList(list); - EXPECT_EQ(2, list.size()); - EXPECT_EQ(4, list.Tail()->val_); - EXPECT_EQ(5, list.Head()->val_); - list.PushBack(new Node(3)); - VerifyList(list); - EXPECT_EQ(3, list.size()); - - Node* node = list.PopFront(); - VerifyList(list); - ASSERT_TRUE(node); - EXPECT_EQ(5, node->val_); - delete node; - - node = list.PopBack(); - VerifyList(list); - ASSERT_TRUE(node); - EXPECT_EQ(3, node->val_); - delete node; - - node = list.PopBack(); - VerifyList(list); - ASSERT_TRUE(node); - EXPECT_EQ(4, node->val_); - delete node; - - node = list.PopBack(); - VerifyList(list); - EXPECT_EQ(NULL, node); -} - -} // namespace gestures diff --git a/src/logging_filter_interpreter.cc b/src/logging_filter_interpreter.cc index d504607..2c43238 100644 --- a/src/logging_filter_interpreter.cc +++ b/src/logging_filter_interpreter.cc @@ -17,15 +17,19 @@ LoggingFilterInterpreter::LoggingFilterInterpreter(PropRegistry* prop_reg, Interpreter* next, Tracer* tracer) : FilterInterpreter(prop_reg, next, tracer, true), - event_logging_enable_(prop_reg, "Event Logging Enable", false, this), - logging_notify_(prop_reg, "Logging Notify", 0, this), - logging_reset_(prop_reg, "Logging Reset", 0, this), + event_logging_enable_(prop_reg, "Event Logging Enable", false), + logging_notify_(prop_reg, "Logging Notify", 0), + logging_reset_(prop_reg, "Logging Reset", 0), log_location_(prop_reg, "Log Path", "/var/log/xorg/touchpad_activity_log.txt"), integrated_touchpad_(prop_reg, "Integrated Touchpad", false) { InitName(); if (prop_reg && log_.get()) prop_reg->set_activity_log(log_.get()); + event_logging_enable_.SetDelegate(this); + BoolWasWritten(&event_logging_enable_); + logging_notify_.SetDelegate(this); + logging_reset_.SetDelegate(this); } void LoggingFilterInterpreter::IntWasWritten(IntProperty* prop) { diff --git a/src/lookahead_filter_interpreter.cc b/src/lookahead_filter_interpreter.cc index f7abaf5..fea2c47 100644 --- a/src/lookahead_filter_interpreter.cc +++ b/src/lookahead_filter_interpreter.cc @@ -45,41 +45,32 @@ LookaheadFilterInterpreter::LookaheadFilterInterpreter( void LookaheadFilterInterpreter::SyncInterpretImpl(HardwareState* hwstate, stime_t* timeout) { - // Push back into queue - if (free_list_.Empty()) { - Err("Can't accept new hwstate b/c we're out of nodes!"); - Err("Now: %f, interpreter_due_ %f", hwstate->timestamp, interpreter_due_); - Err("Dump of queue:"); - for (QState* it = queue_.Begin(); it != queue_.End(); it = it->next_) - Err("Due: %f%s", it->due_, it->completed_ ? " (c)" : ""); - return; - } - QState* node = free_list_.PopFront(); - node->set_state(*hwstate); + // Keep track of where the last node is in the current queue_ + auto const queue_was_not_empty = !queue_.empty(); + QState* old_back_node = queue_was_not_empty ? &queue_.back() : nullptr; + // Allocate and initialize a new node on the end of the queue_ + auto& new_node = queue_.emplace_back(hwprops_->max_finger_cnt); + new_node.set_state(*hwstate); double delay = max(0.0, min<stime_t>(kMaxDelay, min_delay_.val_)); - node->due_ = hwstate->timestamp + delay; - node->completed_ = false; - if (queue_.Empty()) - node->output_ids_.clear(); - else - node->output_ids_ = queue_.Tail()->output_ids_; - // At this point, if ExtraVariableDelay() > 0, queue_.Tail()->due_ may have - // ExtraVariableDelay() applied, but node->due_ does not, yet. - if (!queue_.Empty() && - (queue_.Tail()->due_ - node->due_ > ExtraVariableDelay())) { + new_node.due_ = hwstate->timestamp + delay; + if (queue_was_not_empty) + new_node.output_ids_ = old_back_node->output_ids_; + // At this point, if ExtraVariableDelay() > 0, old_back_node.due_ may have + // ExtraVariableDelay() applied, but new_node.due_ does not, yet. + if (queue_was_not_empty && + (old_back_node->due_ - new_node.due_ > ExtraVariableDelay())) { Err("Clock changed backwards. Flushing queue."); stime_t next_timeout = NO_DEADLINE; - QState* q_node = queue_.Head(); + auto q_node_iter = queue_.begin(); do { - if (!q_node->completed_) - next_->SyncInterpret(&q_node->state_, &next_timeout); - q_node = q_node->next_; - free_list_.PushBack(queue_.PopFront()); - } while (!queue_.Empty()); + if (!(*q_node_iter).completed_) + next_->SyncInterpret(&(*q_node_iter).state_, &next_timeout); + ++q_node_iter; + queue_.pop_front(); + } while (queue_.size() > 1); interpreter_due_ = -1.0; last_interpreted_time_ = -1.0; } - queue_.PushBack(node); AssignTrackingIds(); AttemptInterpolation(); UpdateInterpreterDue(interpreter_due_ < 0.0 ? @@ -88,10 +79,10 @@ void LookaheadFilterInterpreter::SyncInterpretImpl(HardwareState* hwstate, HandleTimerImpl(hwstate->timestamp, timeout); // Copy finger flags for upstream filters. - QState* q_node = queue_.Head(); - if (q_node->state_.SameFingersAs(*hwstate)) { + QState& q_node = queue_.front(); + if (q_node.state_.SameFingersAs(*hwstate)) { for (size_t i = 0; i < hwstate->finger_cnt; i++) { - hwstate->fingers[i].flags = q_node->state_.fingers[i].flags; + hwstate->fingers[i].flags = q_node.state_.fingers[i].flags; } } } @@ -143,27 +134,27 @@ void LookaheadFilterInterpreter::AssignTrackingIds() { // Always reassign trackingID on the very first hwstate so that // the next hwstate can inherit the trackingID mapping. if (queue_.size() == 1) { - QState* tail = queue_.Tail(); - HardwareState* hs = &tail->state_; + QState& tail = queue_.back(); + HardwareState* hs = &tail.state_; for (size_t i = 0; i < hs->finger_cnt; i++) { FingerState* fs = &hs->fingers[i]; - tail->output_ids_[fs->tracking_id] = NextTrackingId(); - fs->tracking_id = tail->output_ids_[fs->tracking_id]; + tail.output_ids_[fs->tracking_id] = NextTrackingId(); + fs->tracking_id = tail.output_ids_[fs->tracking_id]; } if (hs->finger_cnt > 0) - tail->due_ += ExtraVariableDelay(); + tail.due_ += ExtraVariableDelay(); } return; } - QState* tail = queue_.Tail(); - HardwareState* hs = &tail->state_; - QState* prev_qs = queue_.size() < 2 ? NULL : tail->prev_; + auto& tail = queue_.at(-1); + HardwareState* hs = &tail.state_; + QState* prev_qs = queue_.size() < 2 ? NULL : &(queue_.at(-2)); HardwareState* prev_hs = prev_qs ? &prev_qs->state_ : NULL; - QState* prev2_qs = queue_.size() < 3 ? NULL : prev_qs->prev_; + QState* prev2_qs = queue_.size() < 3 ? NULL : &(queue_.at(-3)); HardwareState* prev2_hs = prev2_qs ? &prev2_qs->state_ : NULL; - RemoveMissingIdsFromMap(&tail->output_ids_, *hs); + RemoveMissingIdsFromMap(&tail.output_ids_, *hs); float dt = prev_hs ? hs->timestamp - prev_hs->timestamp : 1.0; float prev_dt = prev_hs && prev2_hs ? prev_hs->timestamp - prev2_hs->timestamp : 1.0; @@ -186,11 +177,11 @@ void LookaheadFilterInterpreter::AssignTrackingIds() { FingerState* fs = &hs->fingers[i]; const short old_id = fs->tracking_id; bool new_finger = false; - if (!MapContainsKey(tail->output_ids_, fs->tracking_id)) { - tail->output_ids_[fs->tracking_id] = NextTrackingId(); + if (!MapContainsKey(tail.output_ids_, fs->tracking_id)) { + tail.output_ids_[fs->tracking_id] = NextTrackingId(); new_finger_present = new_finger = true; } - fs->tracking_id = tail->output_ids_[fs->tracking_id]; + fs->tracking_id = tail.output_ids_[fs->tracking_id]; if (new_finger) continue; if (!prev_hs) { @@ -239,8 +230,8 @@ void LookaheadFilterInterpreter::AssignTrackingIds() { if (prev_qs->output_ids_[old_id] != prev2_qs->output_ids_[old_id]) { prev_qs->output_ids_[old_id] = prev2_qs->output_ids_[old_id]; prev_fs->tracking_id = prev_qs->output_ids_[old_id]; - tail->output_ids_[old_id] = prev2_qs->output_ids_[old_id]; - fs->tracking_id = tail->output_ids_[old_id]; + tail.output_ids_[old_id] = prev2_qs->output_ids_[old_id]; + fs->tracking_id = tail.output_ids_[old_id]; continue; } } @@ -269,7 +260,7 @@ void LookaheadFilterInterpreter::AssignTrackingIds() { continue; } separated_fingers.insert(old_id); - SeparateFinger(tail, fs, old_id); + SeparateFinger(&tail, fs, old_id); // Separating fingers shouldn't tap. fs->flags |= GESTURES_FINGER_NO_TAP; // Try to also flag the previous frame, if we didn't execute it yet @@ -298,10 +289,10 @@ void LookaheadFilterInterpreter::AssignTrackingIds() { Err("How is input ID missing from prev state? %d", input_id); continue; } - short new_bad_output_id = tail->output_ids_[input_id]; + short new_bad_output_id = tail.output_ids_[input_id]; short prev_output_id = prev_qs->output_ids_[input_id]; - tail->output_ids_[input_id] = prev_output_id; - FingerState* fs = tail->state_.GetFingerState(new_bad_output_id); + tail.output_ids_[input_id] = prev_output_id; + FingerState* fs = tail.state_.GetFingerState(new_bad_output_id); if (!fs) { Err("Can't find finger state."); continue; @@ -316,7 +307,7 @@ void LookaheadFilterInterpreter::AssignTrackingIds() { LiftoffJumpStarting(*hs, *prev_hs, *prev2_hs))) { // Possibly add some extra delay to correct, incase this separation // shouldn't have occurred or if the finger may be lifting from the pad. - tail->due_ += ExtraVariableDelay(); + tail.due_ += ExtraVariableDelay(); } } @@ -356,11 +347,12 @@ void LookaheadFilterInterpreter::TapDownOccurringGesture(stime_t now) { return; if (queue_.size() < 2) return; // Not enough data to know - HardwareState& hs = queue_.Tail()->state_; - if (queue_.Tail()->state_.timestamp != now) + HardwareState& hs = queue_.back().state_; + if (queue_.back().state_.timestamp != now) return; // We didn't push a new hardware state now - // See if latest hwstate has finger that previous doesn't - HardwareState& prev_hs = queue_.Tail()->prev_->state_; + // See if latest hwstate has finger that previous doesn't. + // Get the state_ of back->prev + HardwareState& prev_hs = queue_.at(-2).state_; if (hs.finger_cnt > prev_hs.finger_cnt) { // Finger was added. ProduceGesture(Gesture(kGestureFling, prev_hs.timestamp, hs.timestamp, @@ -396,33 +388,26 @@ short LookaheadFilterInterpreter::NextTrackingId() { void LookaheadFilterInterpreter::AttemptInterpolation() { if (queue_.size() < 2) return; - QState* new_node = queue_.Tail(); - QState* prev = new_node->prev_; - if (new_node->state_.timestamp - prev->state_.timestamp < - split_min_period_.val_) + QState& new_node = queue_.at(-1); + QState& prev = queue_.at(-2); + if (new_node.state_.timestamp - prev.state_.timestamp < + split_min_period_.val_) { return; // Nodes came in too quickly to need interpolation - if (!prev->state_.SameFingersAs(new_node->state_)) - return; - QState* node = free_list_.PopFront(); - if (!node) { - Err("out of nodes?"); - return; } - node->state_.fingers = node->fs_.get(); - node->completed_ = false; - Interpolate(prev->state_, new_node->state_, &node->state_); + if (!prev.state_.SameFingersAs(new_node.state_)) + return; + auto node = QState(hwprops_->max_finger_cnt); + node.state_.fingers = node.fs_.get(); + node.completed_ = false; + Interpolate(prev.state_, new_node.state_, &node.state_); double delay = max(0.0, min<stime_t>(kMaxDelay, min_delay_.val_)); - node->due_ = node->state_.timestamp + delay; + node.due_ = node.state_.timestamp + delay; - if (node->state_.timestamp <= last_interpreted_time_) { - // Time wouldn't seem monotonically increasing w/ this new event, so - // discard it. - free_list_.PushBack(node); - return; + // Make sure time seems monotonically increasing w/ this new event + if (node.state_.timestamp > last_interpreted_time_) { + queue_.insert(--queue_.end(), std::move(node)); } - - queue_.InsertBefore(new_node, node); } void LookaheadFilterInterpreter::HandleTimerImpl(stime_t now, @@ -440,12 +425,16 @@ void LookaheadFilterInterpreter::HandleTimerImpl(stime_t now, last_interpreted_time_ = now; next_->HandleTimer(now, &next_timeout); } else { - if (queue_.Empty()) + if (queue_.empty()) break; // Get next uncompleted and overdue hwstate - QState* node = queue_.Head(); - while (node != queue_.Tail() && node->completed_) - node = node->next_; + auto node = &queue_.back(); + for (auto& elem : queue_) { + if (!elem.completed_) { + node = &elem; + break; + } + } if (node->completed_ || node->due_ > now) break; next_timeout = NO_DEADLINE; @@ -471,8 +460,9 @@ void LookaheadFilterInterpreter::HandleTimerImpl(stime_t now, next_->SyncInterpret(&hs_copy, &next_timeout); // Clear previously completed nodes, but keep at least two nodes. - while (queue_.size() > 2 && queue_.Head()->completed_) - free_list_.PushBack(queue_.PopFront()); + while (queue_.size() > 2 && queue_.front().completed_) { + queue_.pop_front(); + } // Mark current node completed. This should be the only completed // node in the queue. @@ -489,7 +479,7 @@ void LookaheadFilterInterpreter::HandleTimerImpl(stime_t now, } void LookaheadFilterInterpreter::ConsumeGesture(const Gesture& gesture) { - QState* node = queue_.Head(); + QState& node = queue_.front(); float distance_sq = 0.0; // Slow movements should potentially be suppressed @@ -516,10 +506,11 @@ void LookaheadFilterInterpreter::ConsumeGesture(const Gesture& gesture) { return; } // Speed is slow. Suppress if fingers have changed. - for (QState* iter = node->next_; iter != queue_.End(); iter = iter->next_) - if (!node->state_.SameFingersAs(iter->state_) || - (node->state_.buttons_down != iter->state_.buttons_down)) + for (auto iter = ++queue_.begin(); iter != queue_.end(); ++iter) { + if (!node.state_.SameFingersAs((*iter).state_) || + (node.state_.buttons_down != (*iter).state_.buttons_down)) return; // suppress + } ProduceGesture(gesture); } @@ -532,11 +523,10 @@ void LookaheadFilterInterpreter::UpdateInterpreterDue( // timeout, so we use -DBL_MAX as the invalid value. stime_t next_hwstate_timeout = -DBL_MAX; // Scan queue_ to find when next hwstate is due. - for (QState* node = queue_.Begin(); node != queue_.End(); - node = node->next_) { - if (node->completed_) + for (auto& elem : queue_) { + if (elem.completed_) continue; - next_hwstate_timeout = node->due_ - now; + next_hwstate_timeout = elem.due_ - now; break; } @@ -557,13 +547,7 @@ void LookaheadFilterInterpreter::Initialize( MetricsProperties* mprops, GestureConsumer* consumer) { FilterInterpreter::Initialize(hwprops, NULL, mprops, consumer); - const size_t kMaxQNodes = 16; - queue_.DeleteAll(); - free_list_.DeleteAll(); - for (size_t i = 0; i < kMaxQNodes; ++i) { - QState* node = new QState(hwprops_->max_finger_cnt); - free_list_.PushBack(node); - } + queue_.clear(); } stime_t LookaheadFilterInterpreter::ExtraVariableDelay() const { @@ -571,13 +555,13 @@ stime_t LookaheadFilterInterpreter::ExtraVariableDelay() const { } LookaheadFilterInterpreter::QState::QState() - : max_fingers_(0), completed_(false), next_(NULL), prev_(NULL) { + : max_fingers_(0) { fs_.reset(); state_.fingers = NULL; } LookaheadFilterInterpreter::QState::QState(unsigned short max_fingers) - : max_fingers_(max_fingers), completed_(false), next_(NULL), prev_(NULL) { + : max_fingers_(max_fingers) { fs_.reset(new FingerState[max_fingers]); state_.fingers = fs_.get(); } diff --git a/src/lookahead_filter_interpreter_unittest.cc b/src/lookahead_filter_interpreter_unittest.cc index 788d785..1345daf 100644 --- a/src/lookahead_filter_interpreter_unittest.cc +++ b/src/lookahead_filter_interpreter_unittest.cc @@ -175,7 +175,7 @@ TEST(LookaheadFilterInterpreterTest, SimpleTest) { if (newtimeout < 0.0) EXPECT_DOUBLE_EQ(NO_DEADLINE, newtimeout); if (i == 5) { - EXPECT_EQ(reinterpret_cast<Gesture*>(NULL), out); + EXPECT_EQ(nullptr, out); } else { // Expect movement ASSERT_TRUE(out); @@ -389,19 +389,19 @@ TEST(LookaheadFilterInterpreterTest, SpuriousCallbackTest) { stime_t timeout = NO_DEADLINE; Gesture* out = wrapper.SyncInterpret(&hs, &timeout); - EXPECT_EQ(reinterpret_cast<Gesture*>(NULL), out); + EXPECT_EQ(nullptr, out); EXPECT_FLOAT_EQ(interpreter->min_delay_.val_, timeout); out = wrapper.HandleTimer(hs.timestamp + interpreter->min_delay_.val_, &timeout); - EXPECT_EQ(reinterpret_cast<Gesture*>(NULL), out); + EXPECT_EQ(nullptr, out); EXPECT_FLOAT_EQ(1.0, timeout); out = wrapper.HandleTimer(hs.timestamp + interpreter->min_delay_.val_ + 0.25, &timeout); - EXPECT_EQ(reinterpret_cast<Gesture*>(NULL), out); + EXPECT_EQ(nullptr, out); EXPECT_FLOAT_EQ(0.75, timeout); } @@ -640,20 +640,20 @@ TEST(LookaheadFilterInterpreterTest, InterpolationOverdueTest) { stime_t timeout = NO_DEADLINE; Gesture* out = wrapper.SyncInterpret(&hs[0], &timeout); - EXPECT_EQ(reinterpret_cast<Gesture*>(NULL), out); + EXPECT_EQ(nullptr, out); EXPECT_FLOAT_EQ(timeout, interpreter->min_delay_.val_); stime_t now = hs[0].timestamp + timeout; timeout = NO_DEADLINE; out = wrapper.HandleTimer(now, &timeout); - ASSERT_NE(reinterpret_cast<Gesture*>(NULL), out); + ASSERT_NE(nullptr, out); EXPECT_EQ(kGestureTypeMove, out->type); EXPECT_EQ(1, out->details.move.dy); EXPECT_DOUBLE_EQ(timeout, 0.700); timeout = NO_DEADLINE; out = wrapper.SyncInterpret(&hs[1], &timeout); - ASSERT_NE(reinterpret_cast<Gesture*>(NULL), out); + ASSERT_NE(nullptr, out); EXPECT_EQ(kGestureTypeMove, out->type); EXPECT_EQ(2, out->details.move.dy); EXPECT_GE(timeout, 0.0); @@ -788,42 +788,42 @@ TEST(LookaheadFilterInterpreterTest, QuickMoveTest) { wrapper.Reset(interpreter.get()); stime_t timeout = NO_DEADLINE; - List<LookaheadFilterInterpreter::QState>* queue = &interpreter->queue_; + const auto& queue = interpreter->queue_; // Pushing the first event wrapper.SyncInterpret(&hs[0], &timeout); - EXPECT_EQ(queue->size(), 1); - EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 1); + EXPECT_EQ(queue.size(), 1); + EXPECT_EQ(queue.back().fs_[0].tracking_id, 1); // Expecting Drumroll detected and ID reassigned 1 -> 2. wrapper.SyncInterpret(&hs[1], &timeout); - EXPECT_EQ(queue->size(), 2); - EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 2); + EXPECT_EQ(queue.size(), 2); + EXPECT_EQ(queue.back().fs_[0].tracking_id, 2); // Expecting Drumroll detected and ID reassigned 1 -> 3. wrapper.SyncInterpret(&hs[2], &timeout); - EXPECT_EQ(queue->size(), 3); - EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 3); + EXPECT_EQ(queue.size(), 3); + EXPECT_EQ(queue.back().fs_[0].tracking_id, 3); // Removing the touch. wrapper.SyncInterpret(&hs[3], &timeout); - EXPECT_EQ(queue->size(), 4); + EXPECT_EQ(queue.size(), 4); // New event comes, old events removed from the queue. // New finger tracking ID assigned 2 - > 4. wrapper.SyncInterpret(&hs[4], &timeout); - EXPECT_EQ(queue->size(), 2); - EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 4); + EXPECT_EQ(queue.size(), 2); + EXPECT_EQ(queue.back().fs_[0].tracking_id, 4); // Expecting Drumroll detected and ID reassigned 2 -> 5. wrapper.SyncInterpret(&hs[5], &timeout); - EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 5); + EXPECT_EQ(queue.back().fs_[0].tracking_id, 5); // Expecting Quick movement detected and ID correction 5 -> 4. wrapper.SyncInterpret(&hs[6], &timeout); - EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 4); - EXPECT_EQ(queue->Tail()->prev_->fs_[0].tracking_id, 4); - EXPECT_EQ(queue->Tail()->prev_->prev_->fs_[0].tracking_id, 4); + EXPECT_EQ(interpreter->queue_.at(-1).fs_[0].tracking_id, 4); + EXPECT_EQ(interpreter->queue_.at(-2).fs_[0].tracking_id, 4); + EXPECT_EQ(interpreter->queue_.at(-3).fs_[0].tracking_id, 4); } struct QuickSwipeTestInputs { @@ -1263,16 +1263,17 @@ TEST(LookaheadFilterInterpreterTest, SemiMtNoTrackingIdAssignmentTest) { wrapper.Reset(interpreter.get()); stime_t timeout = NO_DEADLINE; - List<LookaheadFilterInterpreter::QState>* queue = &interpreter->queue_; + const auto& queue = interpreter->queue_; wrapper.SyncInterpret(&hs[0], &timeout); - EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 20); + EXPECT_EQ(queue.back().fs_[0].tracking_id, 20); // Test if the fingers in queue have the same tracking ids from input. for (size_t i = 1; i < arraysize(hs); i++) { wrapper.SyncInterpret(&hs[i], &timeout); - EXPECT_EQ(queue->Tail()->fs_[0].tracking_id, 20); // the same input id - EXPECT_EQ(queue->Tail()->fs_[1].tracking_id, 21); + EXPECT_EQ(queue.back().fs_[0].tracking_id, 20); // the same input id + EXPECT_EQ(queue.back().fs_[1].tracking_id, 21); } } + } // namespace gestures diff --git a/src/metrics_filter_interpreter.cc b/src/metrics_filter_interpreter.cc index e608f23..a19b814 100644 --- a/src/metrics_filter_interpreter.cc +++ b/src/metrics_filter_interpreter.cc @@ -22,8 +22,6 @@ MetricsFilterInterpreter::MetricsFilterInterpreter( Tracer* tracer, GestureInterpreterDeviceClass devclass) : FilterInterpreter(NULL, next, tracer, false), - mstate_mm_(kMaxFingers * MState::MaxHistorySize()), - history_mm_(kMaxFingers), devclass_(devclass), mouse_movement_session_index_(0), mouse_movement_current_session_length(0), @@ -44,7 +42,7 @@ MetricsFilterInterpreter::MetricsFilterInterpreter( } void MetricsFilterInterpreter::SyncInterpretImpl(HardwareState* hwstate, - stime_t* timeout) { + stime_t* timeout) { if (devclass_ == GESTURES_DEVCLASS_TOUCHPAD) { // Right now, we only want to update finger states for built-in touchpads // because all the generated metrics gestures would be put under each @@ -66,22 +64,16 @@ void MetricsFilterInterpreter::SyncInterpretImpl(HardwareState* hwstate, next_->SyncInterpret(hwstate, timeout); } -template <class StateType, class DataType> void MetricsFilterInterpreter::AddNewStateToBuffer( - MemoryManagedList<StateType>* history, - const DataType& data, + FingerHistory& history, + const FingerState& data, const HardwareState& hwstate) { // The history buffer is already full, pop one - if (history->size() == StateType::MaxHistorySize()) - history->DeleteFront(); + if (history.size() == MState::MaxHistorySize()) + history.pop_front(); // Push the new finger state to the back of buffer - StateType* current = history->PushNewEltBack(); - if (!current) { - Err("MetricsFilterInterpreter buffer out of space"); - return; - } - current->Init(data, hwstate); + (void)history.emplace_back(data, hwstate); } void MetricsFilterInterpreter::UpdateMouseMovementState( @@ -138,67 +130,48 @@ void MetricsFilterInterpreter::ReportMouseStatistics() { void MetricsFilterInterpreter::UpdateFingerState( const HardwareState& hwstate) { - FingerHistoryMap removed; - RemoveMissingIdsFromMap(&histories_, hwstate, &removed); - for (FingerHistoryMap::const_iterator it = - removed.begin(); it != removed.end(); ++it) { - it->second->DeleteAll(); - history_mm_.Free(it->second); -} + RemoveMissingIdsFromMap(&histories_, hwstate); FingerState *fs = hwstate.fingers; for (short i = 0; i < hwstate.finger_cnt; i++) { - FingerHistory* hp; - // Update the map if the contact is new if (!MapContainsKey(histories_, fs[i].tracking_id)) { - hp = history_mm_.Allocate(); - if (!hp) { - Err("FingerHistory out of space"); - continue; - } - hp->Init(&mstate_mm_); - histories_[fs[i].tracking_id] = hp; - } else { - hp = histories_[fs[i].tracking_id]; + histories_[fs[i].tracking_id] = FingerHistory{}; } + auto& href = histories_[fs[i].tracking_id]; // Check if the finger history contains interesting patterns - AddNewStateToBuffer(hp, fs[i], hwstate); - DetectNoisyGround(hp); + AddNewStateToBuffer(href, fs[i], hwstate); + DetectNoisyGround(href); } } -bool MetricsFilterInterpreter::DetectNoisyGround( - const FingerHistory* history) { - MState* current = history->Tail(); - size_t n_samples = history->size(); +bool MetricsFilterInterpreter::DetectNoisyGround(FingerHistory& history) { // Noise pattern takes 3 samples - if (n_samples < 3) + if (history.size() < 3) return false; - MState* past_1 = current->prev_; - MState* past_2 = past_1->prev_; + auto current = history.at(-1); + auto past_1 = history.at(-2); + auto past_2 = history.at(-3); // Noise pattern needs to happen in a short period of time - if(current->timestamp - past_2->timestamp > - noisy_ground_time_threshold_.val_) { + if (current.timestamp - past_2.timestamp > noisy_ground_time_threshold_.val_) return false; - } // vec[when][x,y] float vec[2][2]; - vec[0][0] = current->data.position_x - past_1->data.position_x; - vec[0][1] = current->data.position_y - past_1->data.position_y; - vec[1][0] = past_1->data.position_x - past_2->data.position_x; - vec[1][1] = past_1->data.position_y - past_2->data.position_y; + vec[0][0] = current.data.position_x - past_1.data.position_x; + vec[0][1] = current.data.position_y - past_1.data.position_y; + vec[1][0] = past_1.data.position_x - past_2.data.position_x; + vec[1][1] = past_1.data.position_y - past_2.data.position_y; const float thr = noisy_ground_distance_threshold_.val_; // We dictate the noise pattern as two consecutive big moves in // opposite directions in either X or Y for (size_t i = 0; i < arraysize(vec[0]); i++) if ((vec[0][i] < -thr && vec[1][i] > thr) || (vec[0][i] > thr && vec[1][i] < -thr)) { - ProduceGesture(Gesture(kGestureMetrics, past_2->timestamp, - current->timestamp, kGestureMetricsTypeNoisyGround, + ProduceGesture(Gesture(kGestureMetrics, past_2.timestamp, + current.timestamp, kGestureMetricsTypeNoisyGround, vec[0][i], vec[1][i])); return true; } diff --git a/src/mouse_interpreter.cc b/src/mouse_interpreter.cc index b26de8f..f3055b3 100644 --- a/src/mouse_interpreter.cc +++ b/src/mouse_interpreter.cc @@ -29,8 +29,7 @@ MouseInterpreter::MouseInterpreter(PropRegistry* prop_reg, Tracer* tracer) scroll_accel_curve_, sizeof(scroll_accel_curve_) / sizeof(double)), scroll_max_allowed_input_speed_(prop_reg, "Mouse Scroll Max Input Speed", - 177.0, - this), + 177.0), force_scroll_wheel_emulation_(prop_reg, "Force Scroll Wheel Emulation", false), @@ -53,6 +52,7 @@ MouseInterpreter::MouseInterpreter(PropRegistry* prop_reg, Tracer* tracer) scroll_accel_curve_[2] = 2.5737e-02; scroll_accel_curve_[3] = 8.0428e-05; scroll_accel_curve_[4] = -9.1149e-07; + scroll_max_allowed_input_speed_.SetDelegate(this); } void MouseInterpreter::SyncInterpretImpl(HardwareState* hwstate, diff --git a/src/prop_registry.cc b/src/prop_registry.cc index 58e3a1a..2d9d454 100644 --- a/src/prop_registry.cc +++ b/src/prop_registry.cc @@ -70,18 +70,6 @@ void Property::DestroyProp() { gprop_ = NULL; } -void Property::SetDelegate(PropertyDelegate* delegate) { - bool delegate_was_late_set = !delegate_ && delegate; - delegate_ = delegate; - // In the normal path of creation of a property with a parent, the - // delegate is set late and the CreatePropImpl will not call the - // WasWritten method. So catch the transition from NULL to not - // NULL in this condition and make sure to call the initial - // WasWritten to mimick the original code. - if (delegate_was_late_set && parent_ && parent_->PropProvider()) - HandleGesturesPropWritten(); -} - void BoolProperty::CreatePropImpl() { GesturesPropBool orig_val = val_; gprop_ = parent_->PropProvider()->create_bool_fn( diff --git a/src/prop_registry_unittest.cc b/src/prop_registry_unittest.cc index 23ba9d8..503a552 100644 --- a/src/prop_registry_unittest.cc +++ b/src/prop_registry_unittest.cc @@ -48,7 +48,8 @@ TEST(PropRegistryTest, SimpleTest) { PropRegistryTestDelegate delegate; int expected_call_cnt = 0; - BoolProperty bp1(®, "hi", false, &delegate); + BoolProperty bp1(®, "hi", false); + bp1.SetDelegate(&delegate); EXPECT_TRUE(strstr(ValueForProperty(bp1).c_str(), "false")); bp1.HandleGesturesPropWritten(); EXPECT_EQ(++expected_call_cnt, delegate.call_cnt_); @@ -58,7 +59,8 @@ TEST(PropRegistryTest, SimpleTest) { bp2.HandleGesturesPropWritten(); EXPECT_EQ(expected_call_cnt, delegate.call_cnt_); - DoubleProperty dp1(®, "hi", 2721.0, &delegate); + DoubleProperty dp1(®, "hi", 2721.0); + dp1.SetDelegate(&delegate); EXPECT_TRUE(strstr(ValueForProperty(dp1).c_str(), "2721")); dp1.HandleGesturesPropWritten(); EXPECT_EQ(++expected_call_cnt, delegate.call_cnt_); @@ -68,7 +70,8 @@ TEST(PropRegistryTest, SimpleTest) { dp2.HandleGesturesPropWritten(); EXPECT_EQ(expected_call_cnt, delegate.call_cnt_); - IntProperty ip1(®, "hi", 567, &delegate); + IntProperty ip1(®, "hi", 567); + ip1.SetDelegate(&delegate); EXPECT_TRUE(strstr(ValueForProperty(ip1).c_str(), "567")); ip1.HandleGesturesPropWritten(); EXPECT_EQ(++expected_call_cnt, delegate.call_cnt_); @@ -78,7 +81,8 @@ TEST(PropRegistryTest, SimpleTest) { ip2.HandleGesturesPropWritten(); EXPECT_EQ(expected_call_cnt, delegate.call_cnt_); - StringProperty stp1(®, "hi", "foo", &delegate); + StringProperty stp1(®, "hi", "foo"); + stp1.SetDelegate(&delegate); EXPECT_TRUE(strstr(ValueForProperty(stp1).c_str(), "foo")); stp1.HandleGesturesPropWritten(); EXPECT_EQ(++expected_call_cnt, delegate.call_cnt_); @@ -194,29 +198,31 @@ TEST(PropRegistryTest, SetAtCreateShouldNotifyTest) { PropRegistry reg; PropRegistryTestDelegate delegate; - BoolProperty my_bool(®, "MyBool", 0, &delegate); - DoubleProperty my_double(®, "MyDouble", 0.0, &delegate); - IntProperty my_int(®, "MyInt", 0, &delegate); - IntProperty my_int_no_change(®, "MyIntNoChange", 1, &delegate); - StringProperty my_string(®, "MyString", "mine", &delegate); + BoolProperty my_bool(®, "MyBool", 0); + my_bool.SetDelegate(&delegate); + DoubleProperty my_double(®, "MyDouble", 0.0); + my_double.SetDelegate(&delegate); + IntProperty my_int(®, "MyInt", 0); + my_int.SetDelegate(&delegate); + IntProperty my_int_no_change(®, "MyIntNoChange", 1); + my_int_no_change.SetDelegate(&delegate); + StringProperty my_string(®, "MyString", "mine"); + my_string.SetDelegate(&delegate); EXPECT_EQ(0, delegate.call_cnt_); reg.SetPropProvider(&mock_gestures_props_provider, NULL); EXPECT_EQ(4, delegate.call_cnt_); - - BoolProperty my_bool2(®, "MyBool2", 1); - EXPECT_EQ(4, delegate.call_cnt_); - my_bool2.SetDelegate(&delegate); - EXPECT_EQ(5, delegate.call_cnt_); } TEST(PropRegistryTest, DoublePromoteIntTest) { PropRegistry reg; PropRegistryTestDelegate delegate; - DoubleProperty my_double(®, "MyDouble", 1234.5, &delegate); + DoubleProperty my_double(®, "MyDouble", 1234.5); + my_double.SetDelegate(&delegate); EXPECT_TRUE(strstr(ValueForProperty(my_double).c_str(), "1234.5")); - IntProperty my_int(®, "MyInt", 321, &delegate); + IntProperty my_int(®, "MyInt", 321); + my_int.SetDelegate(&delegate); Json::Value my_int_val = my_int.NewValue(); EXPECT_TRUE(my_double.SetValue(my_int_val)); EXPECT_TRUE(strstr(ValueForProperty(my_double).c_str(), "321")); @@ -229,15 +235,18 @@ TEST(PropRegistryTest, BoolArrayTest) { GesturesPropBool vals[] = { false, true }; BoolArrayProperty my_bool_array_w_delegate( - ®, "MyBoolArray", vals, 2, &delegate); + ®, "MyBoolArray", vals, 2); + my_bool_array_w_delegate.SetDelegate(&delegate); EXPECT_EQ(0, delegate.call_cnt_); my_bool_array_w_delegate.HandleGesturesPropWritten(); EXPECT_EQ(1, delegate.call_cnt_); delegate.BoolArrayWasWritten(&my_bool_array_w_delegate); EXPECT_EQ(2, delegate.call_cnt_); - IntProperty ip1(®, "hi", 567, &delegate); - StringProperty stp1(®, "hi", "foo", &delegate); + IntProperty ip1(®, "hi", 567); + ip1.SetDelegate(&delegate); + StringProperty stp1(®, "hi", "foo"); + stp1.SetDelegate(&delegate); Json::Value my_bool_array_val = my_bool_array_w_delegate.NewValue(); Json::Value my_int_val = ip1.NewValue(); Json::Value my_str_val = stp1.NewValue(); @@ -261,15 +270,18 @@ TEST(PropRegistryTest, DoubleArrayTest) { double vals[] = { 0.0, 1.0 }; DoubleArrayProperty my_double_array_w_delegate( - ®, "MyDoubleArray", vals, 2, &delegate); + ®, "MyDoubleArray", vals, 2); + my_double_array_w_delegate.SetDelegate(&delegate); EXPECT_EQ(0, delegate.call_cnt_); my_double_array_w_delegate.HandleGesturesPropWritten(); EXPECT_EQ(1, delegate.call_cnt_); delegate.DoubleArrayWasWritten(&my_double_array_w_delegate); EXPECT_EQ(2, delegate.call_cnt_); - IntProperty ip1(®, "hi", 567, &delegate); - StringProperty stp1(®, "hi", "foo", &delegate); + IntProperty ip1(®, "hi", 567); + ip1.SetDelegate(&delegate); + StringProperty stp1(®, "hi", "foo"); + stp1.SetDelegate(&delegate); Json::Value my_double_array_val = my_double_array_w_delegate.NewValue(); Json::Value my_int_val = ip1.NewValue(); Json::Value my_str_val = stp1.NewValue(); @@ -293,15 +305,18 @@ TEST(PropRegistryTest, IntArrayTest) { int vals[] = { 0, 1 }; IntArrayProperty my_int_array_w_delegate( - ®, "MyIntArray", vals, 2, &delegate); + ®, "MyIntArray", vals, 2); + my_int_array_w_delegate.SetDelegate(&delegate); EXPECT_EQ(0, delegate.call_cnt_); my_int_array_w_delegate.HandleGesturesPropWritten(); EXPECT_EQ(1, delegate.call_cnt_); delegate.IntArrayWasWritten(&my_int_array_w_delegate); EXPECT_EQ(2, delegate.call_cnt_); - IntProperty ip1(®, "hi", 567, &delegate); - StringProperty stp1(®, "hi", "foo", &delegate); + IntProperty ip1(®, "hi", 567); + ip1.SetDelegate(&delegate); + StringProperty stp1(®, "hi", "foo"); + stp1.SetDelegate(&delegate); Json::Value my_int_array_val = my_int_array_w_delegate.NewValue(); Json::Value my_int_val = ip1.NewValue(); Json::Value my_str_val = stp1.NewValue(); diff --git a/src/scaling_filter_interpreter.cc b/src/scaling_filter_interpreter.cc index 1094455..2d2aad9 100644 --- a/src/scaling_filter_interpreter.cc +++ b/src/scaling_filter_interpreter.cc @@ -318,8 +318,13 @@ void ScalingFilterInterpreter::Initialize(const HardwareProperties* hwprops, Metrics* metrics, MetricsProperties* mprops, GestureConsumer* consumer) { - tp_x_scale_ = 1.0 / hwprops->res_x; - tp_y_scale_ = 1.0 / hwprops->res_y; + // If the touchpad doesn't specify its resolution in one or both axes, use a + // reasonable default instead. + float res_x = hwprops->res_x != 0 ? hwprops->res_x : 32; + float res_y = hwprops->res_y != 0 ? hwprops->res_y : 32; + + tp_x_scale_ = 1.0 / res_x; + tp_y_scale_ = 1.0 / res_y; tp_x_translate_ = -1.0 * (hwprops->left * tp_x_scale_); tp_y_translate_ = -1.0 * (hwprops->top * tp_y_scale_); diff --git a/src/scaling_filter_interpreter_unittest.cc b/src/scaling_filter_interpreter_unittest.cc index d701c7f..93f8e79 100644 --- a/src/scaling_filter_interpreter_unittest.cc +++ b/src/scaling_filter_interpreter_unittest.cc @@ -68,7 +68,7 @@ class ScalingFilterInterpreterTestInterpreter : public Interpreter { EXPECT_FLOAT_EQ(expected_pressures_.front(), hwstate->fingers[0].pressure); expected_pressures_.pop_front(); - } else { + } else if (!expected_finger_cnt_.empty() && !expected_touch_cnt_.empty()) { // Test if the low pressure event is dropped EXPECT_EQ(expected_finger_cnt_.front(), hwstate->finger_cnt); expected_finger_cnt_.pop_front(); @@ -272,6 +272,47 @@ TEST(ScalingFilterInterpreterTest, SimpleTest) { out = wrapper.SyncInterpret(&hs2[2], NULL); } +TEST(ScalingFilterInterpreterTest, ResolutionFallback) { + ScalingFilterInterpreterTestInterpreter* base_interpreter = + new ScalingFilterInterpreterTestInterpreter; + ScalingFilterInterpreter interpreter(NULL, base_interpreter, NULL, + GESTURES_DEVCLASS_TOUCHPAD); + HardwareProperties initial_hwprops = { + 0, 0, 2000, 1000, // left, top, right, bottom + 0, 0, // X/Y resolutions (pixels/mm) + 0, 0, // screen DPI X, Y (deprecated) + -1, // orientation minimum + 2, // orientation maximum + 2, 5, // max fingers, max_touch + 0, 0, 0, // t5r2, semi, button pad + 0, 0, // has wheel, vertical wheel is high resolution + 0, // haptic pad + }; + HardwareProperties expected_hwprops = { + 0, 0, 2000 / 32.0, 1000 / 32.0, // left, top, right, bottom + 1, 1, // X/Y resolutions (pixels/mm) + 25.4, 25.4, // x DPI, y DPI + -M_PI_4, // orientation minimum (1 tick above X-axis) + M_PI_2, // orientation maximum + 2, 5, 0, 0, 0, // max_fingers, max_touch, t5r2, semi_mt, is button pad + 0, 0, // has wheel, vertical wheel is high resolution + 0, // is haptic pad + }; + base_interpreter->expected_hwprops_ = expected_hwprops; + + TestInterpreterWrapper wrapper(&interpreter, &initial_hwprops); + EXPECT_TRUE(base_interpreter->initialize_called_); + + FingerState fs = { 1, 0, 0, 0, 1, 0, 1000, 500, 1, 0 }; + HardwareState hs = make_hwstate(10000, 0, 1, 1, &fs); + + base_interpreter->expected_coordinates_.push_back( + std::vector<pair<float, float>>(1, make_pair( + static_cast<float>(1000 / 32.0), static_cast<float>(500 / 32.0)))); + + wrapper.SyncInterpret(&hs, NULL); +} + static void RunTouchMajorAndMinorTest( ScalingFilterInterpreterTestInterpreter* base_interpreter, ScalingFilterInterpreter* interpreter, diff --git a/src/trend_classifying_filter_interpreter.cc b/src/trend_classifying_filter_interpreter.cc index 45699a9..714cb68 100644 --- a/src/trend_classifying_filter_interpreter.cc +++ b/src/trend_classifying_filter_interpreter.cc @@ -30,8 +30,6 @@ namespace gestures { TrendClassifyingFilterInterpreter::TrendClassifyingFilterInterpreter( PropRegistry* prop_reg, Interpreter* next, Tracer* tracer) : FilterInterpreter(NULL, next, tracer, false), - kstate_mm_(kMaxFingers * kNumOfSamples), - history_mm_(kMaxFingers), trend_classifying_filter_enable_( prop_reg, "Trend Classifying Filter Enabled", true), second_order_enable_( @@ -72,37 +70,32 @@ void TrendClassifyingFilterInterpreter::InterpretTestResult( } void TrendClassifyingFilterInterpreter::AddNewStateToBuffer( - FingerHistory* history, const FingerState& fs) { + FingerHistory& history, const FingerState& fs) { // The history buffer is already full, pop one - if (history->size() == static_cast<size_t>(num_of_samples_.val_)) - history->DeleteFront(); + if (history.size() == static_cast<size_t>(num_of_samples_.val_)) + history.pop_front(); // Push the new finger state to the back of buffer - KState* previous_end = history->Tail(); - KState* current = history->PushNewEltBack(); - if (!current) { - Err("KState buffer out of space"); - return; - } - current->Init(fs); - if (history->size() == 1) + auto& current = history.emplace_back(fs); + if (history.size() == 1) return; + auto& previous_end = history.at(-2); - current->DxAxis()->val = current->XAxis()->val - previous_end->XAxis()->val; - current->DyAxis()->val = current->YAxis()->val - previous_end->YAxis()->val; + current.DxAxis()->val = current.XAxis()->val - previous_end.XAxis()->val; + current.DyAxis()->val = current.YAxis()->val - previous_end.YAxis()->val; // Update the nodes already in the buffer and compute the Kendall score/ // variance along the way. Complexity is O(|buffer|) per finger. int tie_n2[KState::n_axes_] = { 0, 0, 0, 0, 0, 0 }; int tie_n3[KState::n_axes_] = { 0, 0, 0, 0, 0, 0 }; - for (KState* it = history->Begin(); it != history->Tail(); it = it->next_) + for (auto it = history.begin(); it != history.end(); ++it) for (size_t i = 0; i < KState::n_axes_; i++) - if(it != history->Begin() || !KState::IsDelta(i)) { - UpdateKTValuePair(&it->axes_[i], ¤t->axes_[i], + if (it != history.begin() || !KState::IsDelta(i)) { + UpdateKTValuePair(&it->axes_[i], ¤t.axes_[i], &tie_n2[i], &tie_n3[i]); } - size_t n_samples = history->size(); + size_t n_samples = history.size(); for (size_t i = 0; i < KState::n_axes_; i++) { - current->axes_[i].var = ComputeKTVariance(tie_n2[i], tie_n3[i], + current.axes_[i].var = ComputeKTVariance(tie_n2[i], tie_n3[i], KState::IsDelta(i) ? n_samples - 1 : n_samples); } } @@ -132,38 +125,23 @@ TrendClassifyingFilterInterpreter::RunKTTest(const KState::KAxis* current, void TrendClassifyingFilterInterpreter::UpdateFingerState( const HardwareState& hwstate) { - FingerHistoryMap removed; - RemoveMissingIdsFromMap(&histories_, hwstate, &removed); - for (FingerHistoryMap::const_iterator it = - removed.begin(); it != removed.end(); ++it) { - it->second->DeleteAll(); - history_mm_.Free(it->second); - } + RemoveMissingIdsFromMap(&histories_, hwstate); - FingerState *fs = hwstate.fingers; + FingerState* fs = hwstate.fingers; for (short i = 0; i < hwstate.finger_cnt; i++) { - FingerHistory* hp; - // Update the map if the contact is new if (!MapContainsKey(histories_, fs[i].tracking_id)) { - hp = history_mm_.Allocate(); - if (!hp) { - Err("FingerHistory out of space"); - continue; - } - hp->Init(&kstate_mm_); - histories_[fs[i].tracking_id] = hp; - } else { - hp = histories_[fs[i].tracking_id]; + histories_[fs[i].tracking_id] = FingerHistory{}; } + auto& history = histories_[fs[i].tracking_id]; // Check if the score demonstrates statistical significance - AddNewStateToBuffer(hp, fs[i]); - KState* current = hp->Tail(); - size_t n_samples = hp->size(); + AddNewStateToBuffer(history, fs[i]); + const auto& current = history.back(); + const size_t n_samples = history.size(); for (size_t idx = 0; idx < KState::n_axes_; idx++) if (second_order_enable_.val_ || !KState::IsDelta(idx)) { - TrendType result = RunKTTest(¤t->axes_[idx], + TrendType result = RunKTTest(¤t.axes_[idx], KState::IsDelta(idx) ? n_samples - 1 : n_samples); InterpretTestResult(result, KState::IncFlag(idx), KState::DecFlag(idx), &(fs[i].flags)); diff --git a/src/util_unittest.cc b/src/util_unittest.cc index 5d0a435..f19fe1f 100644 --- a/src/util_unittest.cc +++ b/src/util_unittest.cc @@ -21,4 +21,51 @@ TEST(UtilTest, DistSqTest) { EXPECT_FLOAT_EQ(DistSqXY(fs[0], 4, 6), 25); } +TEST(UtilTest, ListAtTest) { + const int kMaxElements = 3; + struct element { + int x; + }; + + List<element> list; + + for (auto i = 0; i < kMaxElements; ++i) { + auto& elem = list.emplace_back(); + elem.x = i; + } + EXPECT_EQ(list.at(-1).x, list.at(list.size() - 1).x); + + for (auto i = 0; i < kMaxElements; ++i) { + for (auto j = 0; j < kMaxElements; ++j) { + if (i == j) { + EXPECT_EQ(list.at(i).x, list.at(j).x); + EXPECT_EQ(&(list.at(i)), &(list.at(j))); + } else { + EXPECT_NE(list.at(i).x, list.at(j).x); + EXPECT_NE(&(list.at(i)), &(list.at(j))); + } + } + } +} + +TEST(UtilTest, ListAtDeathForwardTest) { + List<int> list; + const int kMaxElements = 3; + + for (auto i = 0; i < kMaxElements; ++i) { + list.emplace_back(i); + } + EXPECT_DEATH(list.at(kMaxElements+1), ""); +} + +TEST(UtilTest, ListAtDeathBackwardTest) { + List<int> list; + const int kMaxElements = 3; + + for (auto i = 0; i < kMaxElements; ++i) { + list.emplace_back(i); + } + EXPECT_DEATH(list.at(-(kMaxElements+1)), ""); +} + } // namespace gestures diff --git a/tools/local_coverage_rate.sh b/tools/local_coverage_rate.sh index 710d91c..d1f9fff 100755 --- a/tools/local_coverage_rate.sh +++ b/tools/local_coverage_rate.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +# Copyright 2011 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/tools/regression_test.sh b/tools/regression_test.sh index db7535b..f97118a 100755 --- a/tools/regression_test.sh +++ b/tools/regression_test.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. +# Copyright 2012 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/tools/replay_log b/tools/replay_log index bfdca70..76ddbbd 100755 --- a/tools/replay_log +++ b/tools/replay_log @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. +# Copyright 2012 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/tools/tplog.py b/tools/tplog.py index b2a685f..7df13f8 100755 --- a/tools/tplog.py +++ b/tools/tplog.py @@ -1,6 +1,6 @@ #!/usr/bin/python # -# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. +# Copyright 2012 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -8,9 +8,9 @@ import getopt +import json import logging import os -import simplejson as json import sys from operator import ge, lt |