summaryrefslogtreecommitdiff
path: root/sensors/common/vts/utils/include/sensors-vts-utils/SensorsVtsEnvironmentBase.h
blob: 17a96ed7399d6e6400f099e27732a89846c28073 (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
138
139
140
141
142
143
144
145
146
/*
 * Copyright (C) 2018 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.
 */

#ifndef ANDROID_SENSORS_VTS_ENVIRONMENT_BASE_H
#define ANDROID_SENSORS_VTS_ENVIRONMENT_BASE_H

#include <gtest/gtest.h>

#include <atomic>
#include <memory>
#include <mutex>
#include <thread>
#include <vector>

#include <log/log.h>

template <class Event>
class IEventCallback {
  public:
    virtual ~IEventCallback() = default;
    virtual void onEvent(const Event& event) = 0;
};

template <class Event>
class SensorsVtsEnvironmentBase {
  public:
    virtual void SetUp() {
        ASSERT_TRUE(resetHal()) << "could not get hidl service";

        mCollectionEnabled = false;
        startPollingThread();

        // In case framework just stopped for test and there is sensor events in the pipe,
        // wait some time for those events to be cleared to avoid them messing up the test.
        std::this_thread::sleep_for(std::chrono::seconds(3));
    }

    virtual void TearDown() = 0;

    // Get and clear all events collected so far (like "cat" shell command).
    // If output is nullptr, it clears all collected events.
    void catEvents(std::vector<Event>* output) {
        std::lock_guard<std::mutex> lock(mEventsMutex);
        if (output) {
            output->insert(output->end(), mEvents.begin(), mEvents.end());
        }
        mEvents.clear();
    }

    // set sensor event collection status
    void setCollection(bool enable) {
        std::lock_guard<std::mutex> lock(mEventsMutex);
        mCollectionEnabled = enable;
    }

    void registerCallback(IEventCallback<Event>* callback) {
        std::lock_guard<std::mutex> lock(mEventsMutex);
        mCallback = callback;
    }

    void unregisterCallback() {
        std::lock_guard<std::mutex> lock(mEventsMutex);
        mCallback = nullptr;
    }

    std::vector<Event> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
                                     bool clearBeforeStart = true, bool changeCollection = true) {
        std::vector<Event> events;
        constexpr useconds_t SLEEP_GRANULARITY = 100 * 1000;  // granularity 100 ms

        ALOGI("collect max of %zu events for %d us, clearBeforeStart %d", nEventLimit, timeLimitUs,
              clearBeforeStart);

        if (changeCollection) {
            setCollection(true);
        }
        if (clearBeforeStart) {
            catEvents(nullptr);
        }

        while (timeLimitUs > 0) {
            useconds_t duration = std::min(SLEEP_GRANULARITY, timeLimitUs);
            usleep(duration);
            timeLimitUs -= duration;

            catEvents(&events);
            if (events.size() >= nEventLimit) {
                break;
            }
            ALOGV("time to go = %d, events to go = %d", (int)timeLimitUs,
                  (int)(nEventLimit - events.size()));
        }

        if (changeCollection) {
            setCollection(false);
        }
        return events;
    }

  protected:
    SensorsVtsEnvironmentBase(const std::string& service_name)
        : mCollectionEnabled(false), mCallback(nullptr) {
        mServiceName = service_name;
    }
    virtual ~SensorsVtsEnvironmentBase(){};

    void addEvent(const Event& ev) {
        std::lock_guard<std::mutex> lock(mEventsMutex);
        if (mCollectionEnabled) {
            mEvents.push_back(ev);
        }

        if (mCallback != nullptr) {
            mCallback->onEvent(ev);
        }
    }

    virtual void startPollingThread() = 0;
    virtual bool resetHal() = 0;

    std::string mServiceName;
    bool mCollectionEnabled;
    std::atomic_bool mStopThread;
    std::thread mPollThread;
    std::vector<Event> mEvents;
    std::mutex mEventsMutex;

    IEventCallback<Event>* mCallback;

    GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsVtsEnvironmentBase<Event>);
};

#endif  // ANDROID_SENSORS_VTS_ENVIRONMENT_BASE_H