1 /*
2  * Copyright (C) 2019 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 <android/hardware/sensors/2.0/types.h>
20 
21 namespace android {
22 namespace hardware {
23 namespace sensors {
24 namespace V2_0 {
25 namespace implementation {
26 
27 using ::android::hardware::sensors::V2_0::SensorTimeout;
28 
29 const int64_t kWakelockTimeoutNs =
30         static_cast<int64_t>(SensorTimeout::WAKE_LOCK_SECONDS) * INT64_C(1000000000);
31 
32 int64_t getTimeNow();
33 
34 class IScopedWakelockRefCounter : public RefBase {
35   public:
36     /**
37      * Increment the wakelock ref count and maybe acquire the shared wakelock if incrementing
38      * from 0 then return the time of incrementing back to caller.
39      *
40      * @param delta The amount to change ref count by.
41      * @param timeoutStart The ptr to the timestamp in ns that the increment occurred which will be
42      *        set in the function or nullptr if not specified.
43      *
44      * @return true if successfully incremented the wakelock ref count.
45      */
46     virtual bool incrementRefCountAndMaybeAcquireWakelock(size_t delta,
47                                                           int64_t* timeoutStart = nullptr) = 0;
48     /**
49      * Decrement the wakelock ref count and maybe release wakelock if ref count ends up 0.
50      *
51      * @param delta The amount to change ref count by.
52      * @param timeoutStart The timestamp in ns that the calling context kept track of when
53      *        incrementing the ref count or -1 by default
54      */
55     virtual void decrementRefCountAndMaybeReleaseWakelock(size_t delta,
56                                                           int64_t timeoutStart = -1) = 0;
57     // Virtual dtor needed for compilation success
~IScopedWakelockRefCounter()58     virtual ~IScopedWakelockRefCounter(){};
59 };
60 
61 /**
62  * Wrapper around wake lock acquisition functions (acquire/release_wake_lock) that provides a
63  * RAII-style mechanism for keeping a wake lock held for the duration of a scoped block.
64  * When a ScopedWakelock is created, it increments the reference count stored in the HalProxy
65  * for the sub-HALs specific wake lock, acquiring the wake lock if necessary. When the object goes
66  * out of scope, the ref count is decremented, potentially releasing the wake lock if no other
67  * references to the wake lock exist.
68  *
69  * This class is allocated through the createScopedWakelock callback inside the IHalProxyCallback
70  * provided to sub-HALs during initialization and should be used for all wake lock acquisition
71  * inside of the sub-HAL to ensure wake locks are not held indefinitely.
72  *
73  * The most prevalent use case for this class will be for posting events to the framework through
74  * the postEvents HalProxy callback. The expectation is that sub-HALs will create this
75  * ScopedWakelock through the createScopedWakelock upon receiving a sensor events. The lock boolean
76  * provided to createScopedWakelock will be set the according to whether the sensor events are
77  * from wakeup sensors. Then, the sub-HAL will perform any processing necessary before invoking the
78  * postEvents callback passing in the previously created ScopedWakelock. At this point, ownership
79  * of the object will be passed to the HalProxy that will then be responsible for ensuring any
80  * wake locks continue to be held, if necessary.
81  */
82 class ScopedWakelock {
83   public:
84     ScopedWakelock(ScopedWakelock&& other);
85     ScopedWakelock& operator=(ScopedWakelock&& other);
86     virtual ~ScopedWakelock();
87 
isLocked()88     bool isLocked() const { return mLocked; }
89 
90   private:
91     friend class HalProxyCallbackBase;
92     friend class ScopedWakelockTest;
93     IScopedWakelockRefCounter* mRefCounter;
94     int64_t mCreatedAtTimeNs;
95     bool mLocked;
96     ScopedWakelock(IScopedWakelockRefCounter* refCounter, bool locked);
97     ScopedWakelock(const ScopedWakelock&) = delete;
98     ScopedWakelock& operator=(const ScopedWakelock&) = delete;
99 };
100 
101 }  // namespace implementation
102 }  // namespace V2_0
103 }  // namespace sensors
104 }  // namespace hardware
105 }  // namespace android