summaryrefslogtreecommitdiff
path: root/sensors/common/default/2.X/multihal/include/HalProxy.h
blob: 61745281f875af97940000298ef5ef701e74e589 (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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
/*
 * Copyright (C) 2019 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 "EventMessageQueueWrapper.h"
#include "HalProxyCallback.h"
#include "ISensorsCallbackWrapper.h"
#include "SubHalWrapper.h"
#include "V2_0/ScopedWakelock.h"
#include "V2_0/SubHal.h"
#include "V2_1/SubHal.h"
#include "WakeLockMessageQueueWrapper.h"
#include "convertV2_1.h"

#include <android/hardware/sensors/2.1/ISensors.h>
#include <android/hardware/sensors/2.1/types.h>
#include <fmq/MessageQueue.h>
#include <hardware_legacy/power.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>

#include <atomic>
#include <condition_variable>
#include <map>
#include <mutex>
#include <queue>
#include <thread>
#include <utility>

namespace android {
namespace hardware {
namespace sensors {
namespace V2_1 {
namespace implementation {

/**
 * HalProxy is the main interface for Multi-HAL. It is responsible for managing  subHALs and
 * proxying function calls to/from the subHAL APIs from the sensors framework. It also manages any
 * wakelocks allocated through the IHalProxyCallback and manages posting events to the sensors
 * framework.
 */
class HalProxy : public V2_0::implementation::IScopedWakelockRefCounter,
                 public V2_0::implementation::ISubHalCallback {
  public:
    using Event = ::android::hardware::sensors::V2_1::Event;
    using OperationMode = ::android::hardware::sensors::V1_0::OperationMode;
    using RateLevel = ::android::hardware::sensors::V1_0::RateLevel;
    using Result = ::android::hardware::sensors::V1_0::Result;
    using SensorInfo = ::android::hardware::sensors::V2_1::SensorInfo;
    using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo;
    using IHalProxyCallbackV2_0 = V2_0::implementation::IHalProxyCallback;
    using IHalProxyCallbackV2_1 = V2_1::implementation::IHalProxyCallback;
    using ISensorsSubHalV2_0 = V2_0::implementation::ISensorsSubHal;
    using ISensorsSubHalV2_1 = V2_1::implementation::ISensorsSubHal;
    using ISensorsV2_0 = V2_0::ISensors;
    using ISensorsV2_1 = V2_1::ISensors;
    using HalProxyCallbackBase = V2_0::implementation::HalProxyCallbackBase;

    explicit HalProxy();
    // Test only constructor.
    explicit HalProxy(std::vector<ISensorsSubHalV2_0*>& subHalList);
    explicit HalProxy(std::vector<ISensorsSubHalV2_0*>& subHalList,
                      std::vector<ISensorsSubHalV2_1*>& subHalListV2_1);
    ~HalProxy();

    // Methods from ::android::hardware::sensors::V2_1::ISensors follow.
    Return<void> getSensorsList_2_1(ISensorsV2_1::getSensorsList_2_1_cb _hidl_cb);

    Return<Result> initialize_2_1(
            const ::android::hardware::MQDescriptorSync<V2_1::Event>& eventQueueDescriptor,
            const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
            const sp<V2_1::ISensorsCallback>& sensorsCallback);

    Return<Result> injectSensorData_2_1(const Event& event);

    // Methods from ::android::hardware::sensors::V2_0::ISensors follow.
    Return<void> getSensorsList(ISensorsV2_0::getSensorsList_cb _hidl_cb);

    Return<Result> setOperationMode(OperationMode mode);

    Return<Result> activate(int32_t sensorHandle, bool enabled);

    Return<Result> initialize(
            const ::android::hardware::MQDescriptorSync<V1_0::Event>& eventQueueDescriptor,
            const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
            const sp<V2_0::ISensorsCallback>& sensorsCallback);

    Return<Result> initializeCommon(std::unique_ptr<EventMessageQueueWrapperBase>& eventQueue,
                                    std::unique_ptr<WakeLockMessageQueueWrapperBase>& wakeLockQueue,
                                    const sp<ISensorsCallbackWrapperBase>& sensorsCallback);

    Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
                         int64_t maxReportLatencyNs);

    Return<Result> flush(int32_t sensorHandle);

    Return<Result> injectSensorData(const V1_0::Event& event);

    Return<void> registerDirectChannel(const SharedMemInfo& mem,
                                       ISensorsV2_0::registerDirectChannel_cb _hidl_cb);

    Return<Result> unregisterDirectChannel(int32_t channelHandle);

    Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
                                    ISensorsV2_0::configDirectReport_cb _hidl_cb);

    Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args);

    Return<void> onDynamicSensorsConnected(const hidl_vec<SensorInfo>& dynamicSensorsAdded,
                                           int32_t subHalIndex) override;

    Return<void> onDynamicSensorsDisconnected(const hidl_vec<int32_t>& dynamicSensorHandlesRemoved,
                                              int32_t subHalIndex) override;

    void postEventsToMessageQueue(const std::vector<Event>& events, size_t numWakeupEvents,
                                  V2_0::implementation::ScopedWakelock wakelock) override;

    const SensorInfo& getSensorInfo(int32_t sensorHandle) override {
        return mSensors[sensorHandle];
    }

    bool areThreadsRunning() override { return mThreadsRun.load(); }

    // Below methods are from IScopedWakelockRefCounter interface
    bool incrementRefCountAndMaybeAcquireWakelock(size_t delta,
                                                  int64_t* timeoutStart = nullptr) override;

    void decrementRefCountAndMaybeReleaseWakelock(size_t delta, int64_t timeoutStart = -1) override;

    const std::map<int32_t, SensorInfo>& getSensors() { return mSensors; }

  private:
    using EventMessageQueueV2_1 = MessageQueue<V2_1::Event, kSynchronizedReadWrite>;
    using EventMessageQueueV2_0 = MessageQueue<V1_0::Event, kSynchronizedReadWrite>;
    using WakeLockMessageQueue = MessageQueue<uint32_t, kSynchronizedReadWrite>;

    /**
     * The Event FMQ where sensor events are written
     */
    std::unique_ptr<EventMessageQueueWrapperBase> mEventQueue;

    /**
     * The Wake Lock FMQ that is read to determine when the framework has handled WAKE_UP events
     */
    std::unique_ptr<WakeLockMessageQueueWrapperBase> mWakeLockQueue;

    /**
     * Event Flag to signal to the framework when sensor events are available to be read and to
     * interrupt event queue blocking write.
     */
    EventFlag* mEventQueueFlag = nullptr;

    //! Event Flag to signal internally that the wakelock queue should stop its blocking read.
    EventFlag* mWakelockQueueFlag = nullptr;

    /**
     * Callback to the sensors framework to inform it that new sensors have been added or removed.
     */
    sp<ISensorsCallbackWrapperBase> mDynamicSensorsCallback;

    /**
     * SubHal objects that have been saved from vendor dynamic libraries.
     */
    std::vector<std::shared_ptr<ISubHalWrapperBase>> mSubHalList;

    /**
     * Map of sensor handles to SensorInfo objects that contains the sensor info from subhals as
     * well as the modified sensor handle for the framework.
     *
     * The subhal index is encoded in the first byte of the sensor handle and the remaining
     * bytes are generated by the subhal to identify the sensor.
     */
    std::map<int32_t, SensorInfo> mSensors;

    //! Map of the dynamic sensors that have been added to halproxy.
    std::map<int32_t, SensorInfo> mDynamicSensors;

    //! The current operation mode for all subhals.
    OperationMode mCurrentOperationMode = OperationMode::NORMAL;

    //! The single subHal that supports directChannel reporting.
    std::shared_ptr<ISubHalWrapperBase> mDirectChannelSubHal;

    //! The timeout for each pending write on background thread for events.
    static const int64_t kPendingWriteTimeoutNs = 5 * INT64_C(1000000000) /* 5 seconds */;

    //! The bit mask used to get the subhal index from a sensor handle.
    static constexpr int32_t kSensorHandleSubHalIndexMask = 0xFF000000;

    /**
     * A FIFO queue of pairs of vector of events and the number of wakeup events in that vector
     * which are waiting to be written to the events fmq in the background thread.
     */
    std::queue<std::pair<std::vector<Event>, size_t>> mPendingWriteEventsQueue;

    //! The most events observed on the pending write events queue for debug purposes.
    size_t mMostEventsObservedPendingWriteEventsQueue = 0;

    //! The max number of events allowed in the pending write events queue
    static constexpr size_t kMaxSizePendingWriteEventsQueue = 100000;

    //! The number of events in the pending write events queue
    size_t mSizePendingWriteEventsQueue = 0;

    //! The mutex protecting writing to the fmq and the pending events queue
    std::mutex mEventQueueWriteMutex;

    //! The condition variable waiting on pending write events to stack up
    std::condition_variable mEventQueueWriteCV;

    //! The thread object ptr that handles pending writes
    std::thread mPendingWritesThread;

    //! The thread object that handles wakelocks
    std::thread mWakelockThread;

    //! The bool indicating whether to end the threads started in initialize
    std::atomic_bool mThreadsRun = true;

    //! The mutex protecting access to the dynamic sensors added and removed methods.
    std::mutex mDynamicSensorsMutex;

    // WakelockRefCount membar vars below

    //! The mutex protecting the wakelock refcount and subsequent wakelock releases and
    //! acquisitions
    std::recursive_mutex mWakelockMutex;

    std::condition_variable_any mWakelockCV;

    //! The refcount of how many ScopedWakelocks and pending wakeup events are active
    size_t mWakelockRefCount = 0;

    int64_t mWakelockTimeoutStartTime = V2_0::implementation::getTimeNow();

    int64_t mWakelockTimeoutResetTime = V2_0::implementation::getTimeNow();

    const char* kWakelockName = "SensorsHAL_WAKEUP";

    /**
     * Initialize the list of SubHal objects in mSubHalList by reading from dynamic libraries
     * listed in a config file.
     */
    void initializeSubHalListFromConfigFile(const char* configFileName);

    /**
     * Initialize the HalProxyCallback vector using the list of subhals.
     */
    void initializeSubHalCallbacks();

    /**
     * Initialize the list of SensorInfo objects in mSensorList by getting sensors from each
     * subhal.
     */
    void initializeSensorList();

    /**
     * Try using the default include directories as well as the directories defined in
     * kSubHalShareObjectLocations to get a handle for dlsym for a subhal.
     *
     * @param filename The file name to search for.
     *
     * @return The handle or nullptr if search failed.
     */
    void* getHandleForSubHalSharedObject(const std::string& filename);

    /**
     * Calls the helper methods that all ctors use.
     */
    void init();

    /**
     * Stops all threads by setting the threads running flag to false and joining to them.
     */
    void stopThreads();

    /**
     * Disable all the sensors observed by the HalProxy.
     */
    void disableAllSensors();

    /**
     * Starts the thread that handles pending writes to event fmq.
     *
     * @param halProxy The HalProxy object pointer.
     */
    static void startPendingWritesThread(HalProxy* halProxy);

    //! Handles the pending writes on events to eventqueue.
    void handlePendingWrites();

    /**
     * Starts the thread that handles decrementing the ref count on wakeup events processed by the
     * framework and timing out wakelocks.
     *
     * @param halProxy The HalProxy object pointer.
     */
    static void startWakelockThread(HalProxy* halProxy);

    //! Handles the wakelocks.
    void handleWakelocks();

    /**
     * @param timeLeft The variable that should be set to the timeleft before timeout will occur or
     * unmodified if timeout occurred.
     *
     * @return true if the shared wakelock has been held passed the timeout and should be released
     */
    bool sharedWakelockDidTimeout(int64_t* timeLeft);

    /**
     * Reset all the member variables associated with the wakelock ref count and maybe release
     * the shared wakelock.
     */
    void resetSharedWakelock();

    /**
     * Clear direct channel flags if the HalProxy has already chosen a subhal as its direct channel
     * subhal. Set the directChannelSubHal pointer to the subHal passed in if this is the first
     * direct channel enabled sensor seen.
     *
     * @param sensorInfo The SensorInfo object that may be altered to have direct channel support
     *    disabled.
     * @param subHal The subhal pointer that the current sensorInfo object came from.
     */
    void setDirectChannelFlags(SensorInfo* sensorInfo, std::shared_ptr<ISubHalWrapperBase> subHal);

    /*
     * Get the subhal pointer which can be found by indexing into the mSubHalList vector
     * using the index from the first byte of sensorHandle.
     *
     * @param sensorHandle The handle used to identify a sensor in one of the subhals.
     */
    std::shared_ptr<ISubHalWrapperBase> getSubHalForSensorHandle(int32_t sensorHandle);

    /**
     * Checks that sensorHandle's subhal index byte is within bounds of mSubHalList.
     *
     * @param sensorHandle The sensor handle to check.
     *
     * @return true if sensorHandles's subhal index byte is valid.
     */
    bool isSubHalIndexValid(int32_t sensorHandle);

    /**
     * Count the number of wakeup events in the first n events of the vector.
     *
     * @param events The vector of Event objects.
     * @param n The end index not inclusive of events to consider.
     *
     * @return The number of wakeup events of the considered events.
     */
    size_t countNumWakeupEvents(const std::vector<Event>& events, size_t n);

    /*
     * Clear out the subhal index bytes from a sensorHandle.
     *
     * @param sensorHandle The sensor handle to modify.
     *
     * @return The modified version of the sensor handle.
     */
    static int32_t clearSubHalIndex(int32_t sensorHandle);

    /**
     * @param sensorHandle The sensor handle to modify.
     *
     * @return true if subHalIndex byte of sensorHandle is zeroed.
     */
    static bool subHalIndexIsClear(int32_t sensorHandle);
};

/**
 * Since a newer HAL can't masquerade as a older HAL, IHalProxy enables the HalProxy to be compiled
 * either for HAL 2.0 or HAL 2.1 depending on the build configuration.
 */
template <class ISensorsVersion>
class IHalProxy : public HalProxy, public ISensorsVersion {
    Return<void> getSensorsList(ISensorsV2_0::getSensorsList_cb _hidl_cb) override {
        return HalProxy::getSensorsList(_hidl_cb);
    }

    Return<Result> setOperationMode(OperationMode mode) override {
        return HalProxy::setOperationMode(mode);
    }

    Return<Result> activate(int32_t sensorHandle, bool enabled) override {
        return HalProxy::activate(sensorHandle, enabled);
    }

    Return<Result> initialize(
            const ::android::hardware::MQDescriptorSync<V1_0::Event>& eventQueueDescriptor,
            const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
            const sp<V2_0::ISensorsCallback>& sensorsCallback) override {
        return HalProxy::initialize(eventQueueDescriptor, wakeLockDescriptor, sensorsCallback);
    }

    Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
                         int64_t maxReportLatencyNs) override {
        return HalProxy::batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
    }

    Return<Result> flush(int32_t sensorHandle) override { return HalProxy::flush(sensorHandle); }

    Return<Result> injectSensorData(const V1_0::Event& event) override {
        return HalProxy::injectSensorData(event);
    }

    Return<void> registerDirectChannel(const SharedMemInfo& mem,
                                       ISensorsV2_0::registerDirectChannel_cb _hidl_cb) override {
        return HalProxy::registerDirectChannel(mem, _hidl_cb);
    }

    Return<Result> unregisterDirectChannel(int32_t channelHandle) override {
        return HalProxy::unregisterDirectChannel(channelHandle);
    }

    Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
                                    ISensorsV2_0::configDirectReport_cb _hidl_cb) override {
        return HalProxy::configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
    }

    Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) override {
        return HalProxy::debug(fd, args);
    }
};

class HalProxyV2_0 : public IHalProxy<V2_0::ISensors> {};

class HalProxyV2_1 : public IHalProxy<V2_1::ISensors> {
    Return<void> getSensorsList_2_1(ISensorsV2_1::getSensorsList_2_1_cb _hidl_cb) override {
        return HalProxy::getSensorsList_2_1(_hidl_cb);
    }

    Return<Result> initialize_2_1(
            const ::android::hardware::MQDescriptorSync<V2_1::Event>& eventQueueDescriptor,
            const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
            const sp<V2_1::ISensorsCallback>& sensorsCallback) override {
        return HalProxy::initialize_2_1(eventQueueDescriptor, wakeLockDescriptor, sensorsCallback);
    }

    Return<Result> injectSensorData_2_1(const Event& event) override {
        return HalProxy::injectSensorData_2_1(event);
    }
};

}  // namespace implementation
}  // namespace V2_1
}  // namespace sensors
}  // namespace hardware
}  // namespace android