1 /*
2  * Copyright (C) 2018 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 #pragma once
18 
19 #include <string.h>
20 
21 #include <algorithm>
22 #include <memory>
23 #include <string>
24 #include <type_traits>
25 #include <utility>
26 #include <vector>
27 
28 #include <android-base/logging.h>
29 
30 #include "fdevent/fdevent.h"
31 #include "sysdeps/uio.h"
32 
33 // Essentially std::vector<char>, except without zero initialization or reallocation.
34 // Features a position attribute to allow sequential read/writes for copying between Blocks.
35 struct Block {
36     using iterator = char*;
37 
38     Block() = default;
39 
BlockBlock40     explicit Block(size_t size) { allocate(size); }
41 
BlockBlock42     explicit Block(const std::string& s) : Block(s.begin(), s.end()) {}
43 
44     template <typename Iterator>
BlockBlock45     Block(Iterator begin, Iterator end) : Block(end - begin) {
46         std::copy(begin, end, data_.get());
47     }
48 
49     Block(const Block& copy) = delete;
BlockBlock50     Block(Block&& move) noexcept
51         : data_(std::exchange(move.data_, nullptr)),
52           capacity_(std::exchange(move.capacity_, 0)),
53           size_(std::exchange(move.size_, 0)),
54           position_(std::exchange(move.position_, 0)) {}
55 
56     Block& operator=(const Block& copy) = delete;
57     Block& operator=(Block&& move) noexcept {
58         clear();
59         data_ = std::exchange(move.data_, nullptr);
60         capacity_ = std::exchange(move.capacity_, 0);
61         size_ = std::exchange(move.size_, 0);
62         position_ = std::exchange(move.size_, 0);
63         return *this;
64     }
65 
66     ~Block() = default;
67 
resizeBlock68     void resize(size_t new_size) {
69         if (!data_) {
70             allocate(new_size);
71         } else {
72             CHECK_GE(capacity_, new_size);
73             size_ = new_size;
74         }
75     }
76 
77     template <typename InputIt>
assignBlock78     void assign(InputIt begin, InputIt end) {
79         clear();
80         allocate(end - begin);
81         std::copy(begin, end, data_.get());
82     }
83 
clearBlock84     void clear() {
85         data_.reset();
86         capacity_ = 0;
87         size_ = 0;
88         position_ = 0;
89     }
90 
is_fullBlock91     bool is_full() const { return remaining() == 0; }
92 
remainingBlock93     size_t remaining() const { return size_ - position_; }
94 
fillFromBlock95     size_t fillFrom(Block& from) {
96         size_t size = std::min(remaining(), from.remaining());
97         memcpy(&data_[position_], &from.data_[from.position_], size);
98         position_ += size;
99         from.position_ += size;
100         return size;
101     }
102 
rewindBlock103     void rewind() { position_ = 0; }
positionBlock104     size_t position() const { return position_; }
105 
capacityBlock106     size_t capacity() const { return capacity_; }
sizeBlock107     size_t size() const { return size_; }
emptyBlock108     bool empty() const { return size() == 0; }
109 
dataBlock110     char* data() { return data_.get(); }
dataBlock111     const char* data() const { return data_.get(); }
112 
beginBlock113     char* begin() { return data_.get(); }
beginBlock114     const char* begin() const { return data_.get(); }
115 
endBlock116     char* end() { return data() + size_; }
endBlock117     const char* end() const { return data() + size_; }
118 
119     char& operator[](size_t idx) { return data()[idx]; }
120     const char& operator[](size_t idx) const { return data()[idx]; }
121 
122     bool operator==(const Block& rhs) const {
123         static_assert(std::is_standard_layout<decltype(data())>());
124         return size() == rhs.size() && memcmp(data(), rhs.data(), size()) == 0;
125     }
126 
127   private:
allocateBlock128     void allocate(size_t size) {
129         CHECK(data_ == nullptr);
130         CHECK_EQ(0ULL, capacity_);
131         CHECK_EQ(0ULL, size_);
132         if (size != 0) {
133             // This isn't std::make_unique because that's equivalent to `new char[size]()`, which
134             // value-initializes the array instead of leaving it uninitialized. As an optimization,
135             // call new without parentheses to avoid this costly initialization.
136             data_.reset(new char[size]);
137             capacity_ = size;
138             size_ = size;
139         }
140     }
141 
142     std::unique_ptr<char[]> data_;
143     size_t capacity_ = 0;
144     size_t size_ = 0;
145     size_t position_ = 0;
146 };
147 
148 struct amessage {
149     uint32_t command;     /* command identifier constant      */
150     uint32_t arg0;        /* first argument                   */
151     uint32_t arg1;        /* second argument                  */
152     uint32_t data_length; /* length of payload (0 is allowed) */
153     uint32_t data_check;  /* checksum of data payload         */
154     uint32_t magic;       /* command ^ 0xffffffff             */
155 };
156 
157 struct apacket {
158     using payload_type = Block;
159     amessage msg;
160     payload_type payload;
161 };
162 
163 struct IOVector {
164     using value_type = char;
165     using block_type = Block;
166     using size_type = size_t;
167 
168     IOVector() = default;
169 
IOVectorIOVector170     explicit IOVector(block_type&& block) { append(std::move(block)); }
171 
172     IOVector(const IOVector& copy) = delete;
IOVectorIOVector173     IOVector(IOVector&& move) noexcept : IOVector() { *this = std::move(move); }
174 
175     IOVector& operator=(const IOVector& copy) = delete;
176     IOVector& operator=(IOVector&& move) noexcept;
177 
front_dataIOVector178     const value_type* front_data() const {
179         if (chain_.empty()) {
180             return nullptr;
181         }
182 
183         return chain_[start_index_].data() + begin_offset_;
184     }
185 
front_sizeIOVector186     size_type front_size() const {
187         if (chain_.empty()) {
188             return 0;
189         }
190 
191         return chain_[start_index_].size() - begin_offset_;
192     }
193 
sizeIOVector194     size_type size() const { return chain_length_ - begin_offset_; }
emptyIOVector195     bool empty() const { return size() == 0; }
196 
197     // Return the last block so the caller can still reuse its allocated capacity
198     // or it can be simply ignored.
199     block_type clear();
200 
201     void drop_front(size_type len);
202 
203     // Split the first |len| bytes out of this chain into its own.
204     IOVector take_front(size_type len);
205 
206     // Add a nonempty block to the chain.
appendIOVector207     void append(block_type&& block) {
208         if (block.size() == 0) {
209             return;
210         }
211         CHECK_NE(0ULL, block.size());
212         chain_length_ += block.size();
213         chain_.emplace_back(std::move(block));
214     }
215 
216     void trim_front();
217 
218   private:
219     void trim_chain_front();
220 
221     // Drop the front block from the chain, and update chain_length_ appropriately.
222     void pop_front_block();
223 
224     // Iterate over the blocks with a callback with an operator()(const char*, size_t).
225     template <typename Fn>
iterate_blocksIOVector226     void iterate_blocks(Fn&& callback) const {
227         if (size() == 0) {
228             return;
229         }
230 
231         for (size_t i = start_index_; i < chain_.size(); ++i) {
232             const auto& block = chain_[i];
233             const char* begin = block.data();
234             size_t length = block.size();
235 
236             if (i == start_index_) {
237                 CHECK_GE(block.size(), begin_offset_);
238                 begin += begin_offset_;
239                 length -= begin_offset_;
240             }
241             callback(begin, length);
242         }
243     }
244 
245   public:
246     // Copy all of the blocks into a single block.
247     template <typename CollectionType = block_type>
coalesceIOVector248     CollectionType coalesce() const& {
249         CollectionType result;
250         if (size() == 0) {
251             return result;
252         }
253 
254         result.resize(size());
255 
256         size_t offset = 0;
257         iterate_blocks([&offset, &result](const char* data, size_t len) {
258             static_assert(std::is_standard_layout<decltype(result)>());
259             memcpy(&result[offset], data, len);
260             offset += len;
261         });
262 
263         return result;
264     }
265 
266     block_type coalesce() &&;
267 
268     template <typename FunctionType>
coalescedIOVector269     auto coalesced(FunctionType&& f) const {
270         if (chain_.size() == start_index_ + 1) {
271             // If we only have one block, we can use it directly.
272             return f(chain_[start_index_].data() + begin_offset_, size());
273         } else {
274             // Otherwise, copy to a single block.
275             auto data = coalesce();
276             return f(data.data(), data.size());
277         }
278     }
279 
280     // Get a list of iovecs that can be used to write out all of the blocks.
281     std::vector<adb_iovec> iovecs() const;
282 
283   private:
284     // Total length of all of the blocks in the chain.
285     size_t chain_length_ = 0;
286 
287     size_t begin_offset_ = 0;
288     size_t start_index_ = 0;
289     std::vector<block_type> chain_;
290 };
291 
292 // An implementation of weak pointers tied to the fdevent run loop.
293 //
294 // This allows for code to submit a request for an object, and upon receiving
295 // a response, know whether the object is still alive, or has been destroyed
296 // because of other reasons. We keep a list of living weak_ptrs in each object,
297 // and clear the weak_ptrs when the object is destroyed. This is safe, because
298 // we require that both the destructor of the referent and the get method on
299 // the weak_ptr are executed on the main thread.
300 template <typename T>
301 struct enable_weak_from_this;
302 
303 template <typename T>
304 struct weak_ptr {
305     weak_ptr() = default;
weak_ptrweak_ptr306     explicit weak_ptr(T* ptr) { reset(ptr); }
weak_ptrweak_ptr307     weak_ptr(const weak_ptr& copy) { reset(copy.get()); }
308 
weak_ptrweak_ptr309     weak_ptr(weak_ptr&& move) {
310         reset(move.get());
311         move.reset();
312     }
313 
~weak_ptrweak_ptr314     ~weak_ptr() { reset(); }
315 
316     weak_ptr& operator=(const weak_ptr& copy) {
317         if (&copy == this) {
318             return *this;
319         }
320 
321         reset(copy.get());
322         return *this;
323     }
324 
325     weak_ptr& operator=(weak_ptr&& move) {
326         if (&move == this) {
327             return *this;
328         }
329 
330         reset(move.get());
331         move.reset();
332         return *this;
333     }
334 
getweak_ptr335     T* get() const {
336         fdevent_check_looper();
337         return ptr_;
338     }
339 
340     void reset(T* ptr = nullptr) {
341         fdevent_check_looper();
342 
343         if (ptr == ptr_) {
344             return;
345         }
346 
347         if (ptr_) {
348             ptr_->weak_ptrs_.erase(
349                     std::remove(ptr_->weak_ptrs_.begin(), ptr_->weak_ptrs_.end(), this));
350         }
351 
352         ptr_ = ptr;
353         if (ptr_) {
354             ptr_->weak_ptrs_.push_back(this);
355         }
356     }
357 
358   private:
359     friend struct enable_weak_from_this<T>;
360     T* ptr_ = nullptr;
361 };
362 
363 template <typename T>
364 struct enable_weak_from_this {
365     ~enable_weak_from_this() {
366         if (!weak_ptrs_.empty()) {
367             fdevent_check_looper();
368             for (auto& weak : weak_ptrs_) {
369                 weak->ptr_ = nullptr;
370             }
371             weak_ptrs_.clear();
372         }
373     }
374 
375     weak_ptr<T> weak() { return weak_ptr<T>(static_cast<T*>(this)); }
376 
377     void schedule_deletion() {
378         fdevent_run_on_looper([this]() { delete static_cast<T*>(this); });
379     }
380 
381   private:
382     friend struct weak_ptr<T>;
383     std::vector<weak_ptr<T>*> weak_ptrs_;
384 };
385