summaryrefslogtreecommitdiff
path: root/libs/binder/Utils.h
blob: 881cdf3f4c122ebf1e071656852091e235c8c109 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <stddef.h>
#include <sys/uio.h>
#include <chrono>
#include <cstdint>
#include <optional>

#include <binder/Common.h>
#include <log/log.h>
#include <utils/Errors.h>

#define PLOGE(fmt, ...)                                                     \
    do {                                                                    \
        auto savedErrno = errno;                                            \
        ALOGE(fmt ": %s" __VA_OPT__(, ) __VA_ARGS__, strerror(savedErrno)); \
    } while (0)
#define PLOGF(fmt, ...)                                                                \
    do {                                                                               \
        auto savedErrno = errno;                                                       \
        LOG_ALWAYS_FATAL(fmt ": %s" __VA_OPT__(, ) __VA_ARGS__, strerror(savedErrno)); \
    } while (0)

/* TEMP_FAILURE_RETRY is not available on macOS and Trusty. */
#ifndef TEMP_FAILURE_RETRY
/* Used to retry syscalls that can return EINTR. */
#define TEMP_FAILURE_RETRY(exp)                \
    ({                                         \
        __typeof__(exp) _rc;                   \
        do {                                   \
            _rc = (exp);                       \
        } while (_rc == -1 && errno == EINTR); \
        _rc;                                   \
    })
#endif

#define TEST_AND_RETURN(value, expr)            \
    do {                                        \
        if (!(expr)) {                          \
            ALOGE("Failed to call: %s", #expr); \
            return value;                       \
        }                                       \
    } while (0)

#define LIBBINDER_PRAGMA(arg) _Pragma(#arg)
#if defined(__clang__)
#define LIBBINDER_PRAGMA_FOR_COMPILER(arg) LIBBINDER_PRAGMA(clang arg)
#elif defined(__GNUC__)
#define LIBBINDER_PRAGMA_FOR_COMPILER(arg) LIBBINDER_PRAGMA(GCC arg)
#else
#define LIBBINDER_PRAGMA_FOR_COMPILER(arg)
#endif
#define LIBBINDER_IGNORE(warning_flag)             \
    LIBBINDER_PRAGMA_FOR_COMPILER(diagnostic push) \
    LIBBINDER_PRAGMA_FOR_COMPILER(diagnostic ignored warning_flag)
#define LIBBINDER_IGNORE_END() LIBBINDER_PRAGMA_FOR_COMPILER(diagnostic pop)

namespace android {

/**
 * Get the size of a statically initialized array.
 *
 * \param N the array to get the size of.
 * \return the size of the array.
 */
template <typename T, size_t N>
constexpr size_t countof(T (&)[N]) {
    return N;
}

// avoid optimizations
void zeroMemory(uint8_t* data, size_t size);

// View of contiguous sequence. Similar to std::span.
template <typename T>
struct Span {
    T* data = nullptr;
    size_t size = 0;

    size_t byteSize() { return size * sizeof(T); }

    iovec toIovec() { return {const_cast<std::remove_const_t<T>*>(data), byteSize()}; }

    // Truncates `this` to a length of `offset` and returns a span with the
    // remainder.
    //
    // `std::nullopt` iff offset > size.
    std::optional<Span<T>> splitOff(size_t offset) {
        if (offset > size) {
            return std::nullopt;
        }
        Span<T> rest = {data + offset, size - offset};
        size = offset;
        return rest;
    }

    // Returns nullopt if the byte size of `this` isn't evenly divisible by sizeof(U).
    template <typename U>
    std::optional<Span<U>> reinterpret() const {
        // Only allow casting from bytes for simplicity.
        static_assert(std::is_same_v<std::remove_const_t<T>, uint8_t>);
        if (size % sizeof(U) != 0) {
            return std::nullopt;
        }
        return Span<U>{reinterpret_cast<U*>(data), size / sizeof(U)};
    }
};

// Converts binary data into a hexString.
//
// Hex values are printed in order, e.g. 0xDEAD will result in 'adde' because
// Android is little-endian.
LIBBINDER_INTERNAL_EXPORTED std::string HexString(const void* bytes, size_t len);

// Converts any std::chrono duration to the number of milliseconds
template <class Rep, class Period>
uint64_t to_ms(std::chrono::duration<Rep, Period> duration) {
    return std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
}

}   // namespace android