xref: /aosp_15_r20/system/chre/util/include/chre/util/duplicate_message_detector.h (revision 84e339476a462649f82315436d70fd732297a399)
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef CHRE_UTIL_DUPLICATE_MESSAGE_DETECTOR_H_
18 #define CHRE_UTIL_DUPLICATE_MESSAGE_DETECTOR_H_
19 
20 #include "chre/util/non_copyable.h"
21 #include "chre/util/optional.h"
22 #include "chre/util/priority_queue.h"
23 #include "chre/util/time.h"
24 #include "chre_api/chre.h"
25 
26 #include <functional>
27 
28 namespace chre {
29 
30 /**
31  * This class is used to detect duplicate reliable messages. It keeps a record
32  * of all reliable messages that have been sent from the host. If a message with
33  * the same message sequence number and host endpoint is sent again, it is
34  * considered a duplicate. This class is not thread-safe.
35  *
36  * A typical usage of this class would be as follows:
37  *
38  * Call findOrAdd() to add a new message to the detector. If the message is a
39  * duplicate, the detector will return the error code previously recorded.
40  * If the message is not a duplicate, the detector will return an empty
41  * Optional.
42  *
43  * Call findAndSetError() to set the error code for a message that has already
44  * been added to the detector.
45  *
46  * Call removeOldEntries() to remove any messages that have been in the detector
47  * for longer than the timeout specified in the constructor.
48  */
49 class DuplicateMessageDetector : public NonCopyable {
50  public:
51   struct ReliableMessageRecord {
52     Nanoseconds timestamp;
53     uint32_t messageSequenceNumber;
54     uint16_t hostEndpoint;
55     Optional<chreError> error;
56 
57     inline bool operator>(const ReliableMessageRecord &rhs) const {
58       return timestamp > rhs.timestamp;
59     }
60   };
61 
62   DuplicateMessageDetector() = delete;
DuplicateMessageDetector(Nanoseconds timeout)63   DuplicateMessageDetector(Nanoseconds timeout):
64       kTimeout(timeout) {}
65   ~DuplicateMessageDetector() = default;
66 
67   //! Finds the message with the given message sequence number and host
68   //! endpoint. If the message is not found, a new message is added to the
69   //! detector. Returns the error code previously recorded for the message, or
70   //! an empty Optional if the message is not a duplicate. If outIsDuplicate is
71   //! not nullptr, it will be set to true if the message is a duplicate (was
72   //! found), or false otherwise.
73   Optional<chreError> findOrAdd(uint32_t messageSequenceNumber,
74                                 uint16_t hostEndpoint,
75                                 bool *outIsDuplicate = nullptr);
76 
77   //! Sets the error code for a message that has already been added to the
78   //! detector. Returns true if the message was found and the error code was
79   //! set, or false if the message was not found.
80   bool findAndSetError(uint32_t messageSequenceNumber, uint16_t hostEndpoint,
81                        chreError error);
82 
83   //! Removes any messages that have been in the detector for longer than the
84   //! timeout specified in the constructor.
85   void removeOldEntries();
86 
87  private:
88   //! The timeout specified in the constructor. This should be the reliable
89   //! message timeout.
90   Nanoseconds kTimeout;
91 
92   //! The queue of reliable message records.
93   PriorityQueue<ReliableMessageRecord, std::greater<ReliableMessageRecord>>
94       mReliableMessageRecordQueue;
95 
96   //! Adds a new message to the detector. Returns the message record, or nullptr
97   //! if the message could not be added. Not thread safe.
98   ReliableMessageRecord *addLocked(uint32_t messageSequenceNumber,
99                                    uint16_t hostEndpoint);
100 
101   //! Finds the message with the given message sequence number and host
102   //! endpoint, else returns nullptr. Not thread safe. If reverse is true,
103   //! this function searches from the end of the queue.
104   ReliableMessageRecord *findLocked(uint32_t messageSequenceNumber,
105                                     uint16_t hostEndpoint,
106                                     bool reverse = false);
107 };
108 
109 }  // namespace chre
110 
111 #endif  // CHRE_UTIL_DUPLICATE_MESSAGE_DETECTOR_H_
112