blob: c3be46814e6bf6d29f782cf907bc4364f30b09d6 [file] [log] [blame]
Lais Andrade80b18612020-10-12 18:44:40 +00001/*
2 * Copyright (C) 2020 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#include "vibrator-impl/VibratorManager.h"
Lais Andradef1120b12024-08-23 15:12:12 +010018#include "vibrator-impl/VibrationSession.h"
19
20#include <aidl/android/hardware/vibrator/BnVibratorCallback.h>
Lais Andrade80b18612020-10-12 18:44:40 +000021
22#include <android-base/logging.h>
23#include <thread>
24
25namespace aidl {
26namespace android {
27namespace hardware {
28namespace vibrator {
29
30static constexpr int32_t kDefaultVibratorId = 1;
31
Lais Andradef1120b12024-08-23 15:12:12 +010032class VibratorCallback : public BnVibratorCallback {
33 public:
34 VibratorCallback(const std::function<void()>& callback) : mCallback(callback) {}
35 ndk::ScopedAStatus onComplete() override {
36 mCallback();
37 return ndk::ScopedAStatus::ok();
38 }
39
40 private:
41 std::function<void()> mCallback;
42};
43
Lais Andrade80b18612020-10-12 18:44:40 +000044ndk::ScopedAStatus VibratorManager::getCapabilities(int32_t* _aidl_return) {
Lais Andradef1120b12024-08-23 15:12:12 +010045 LOG(VERBOSE) << "Vibrator manager reporting capabilities";
46 std::lock_guard lock(mMutex);
47 if (mCapabilities == 0) {
48 int32_t version;
49 if (!getInterfaceVersion(&version).isOk()) {
50 return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_STATE));
51 }
52 mCapabilities = IVibratorManager::CAP_SYNC | IVibratorManager::CAP_PREPARE_ON |
53 IVibratorManager::CAP_PREPARE_PERFORM |
54 IVibratorManager::CAP_PREPARE_COMPOSE |
55 IVibratorManager::CAP_MIXED_TRIGGER_ON |
56 IVibratorManager::CAP_MIXED_TRIGGER_PERFORM |
57 IVibratorManager::CAP_MIXED_TRIGGER_COMPOSE |
58 IVibratorManager::CAP_TRIGGER_CALLBACK;
59
60 if (version >= 3) {
61 mCapabilities |= IVibratorManager::CAP_START_SESSIONS;
62 }
63 }
64
65 *_aidl_return = mCapabilities;
Lais Andrade80b18612020-10-12 18:44:40 +000066 return ndk::ScopedAStatus::ok();
67}
68
69ndk::ScopedAStatus VibratorManager::getVibratorIds(std::vector<int32_t>* _aidl_return) {
Lais Andradef1120b12024-08-23 15:12:12 +010070 LOG(VERBOSE) << "Vibrator manager getting vibrator ids";
Lais Andrade80b18612020-10-12 18:44:40 +000071 *_aidl_return = {kDefaultVibratorId};
72 return ndk::ScopedAStatus::ok();
73}
74
75ndk::ScopedAStatus VibratorManager::getVibrator(int32_t vibratorId,
76 std::shared_ptr<IVibrator>* _aidl_return) {
Lais Andradef1120b12024-08-23 15:12:12 +010077 LOG(VERBOSE) << "Vibrator manager getting vibrator " << vibratorId;
Lais Andrade80b18612020-10-12 18:44:40 +000078 if (vibratorId == kDefaultVibratorId) {
79 *_aidl_return = mDefaultVibrator;
80 return ndk::ScopedAStatus::ok();
81 } else {
82 *_aidl_return = nullptr;
83 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
84 }
85}
86
87ndk::ScopedAStatus VibratorManager::prepareSynced(const std::vector<int32_t>& vibratorIds) {
Lais Andradef1120b12024-08-23 15:12:12 +010088 LOG(VERBOSE) << "Vibrator Manager prepare synced";
89 if (vibratorIds.size() != 1 || vibratorIds[0] != kDefaultVibratorId) {
Lais Andrade80b18612020-10-12 18:44:40 +000090 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
91 }
Lais Andradef1120b12024-08-23 15:12:12 +010092 std::lock_guard lock(mMutex);
93 if (mIsPreparing) {
94 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
95 }
96 mIsPreparing = true;
97 return ndk::ScopedAStatus::ok();
Lais Andrade80b18612020-10-12 18:44:40 +000098}
99
100ndk::ScopedAStatus VibratorManager::triggerSynced(
101 const std::shared_ptr<IVibratorCallback>& callback) {
Lais Andradef1120b12024-08-23 15:12:12 +0100102 LOG(VERBOSE) << "Vibrator Manager trigger synced";
103 std::lock_guard lock(mMutex);
104 if (!mIsPreparing) {
105 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
106 }
Simon Bowden608655b2022-06-01 12:09:41 +0000107 std::thread([callback] {
Lais Andrade80b18612020-10-12 18:44:40 +0000108 if (callback != nullptr) {
Lais Andradef1120b12024-08-23 15:12:12 +0100109 LOG(VERBOSE) << "Notifying perform complete";
Lais Andrade80b18612020-10-12 18:44:40 +0000110 callback->onComplete();
111 }
112 }).detach();
Lais Andradef1120b12024-08-23 15:12:12 +0100113 mIsPreparing = false;
Lais Andrade80b18612020-10-12 18:44:40 +0000114 return ndk::ScopedAStatus::ok();
115}
116
117ndk::ScopedAStatus VibratorManager::cancelSynced() {
Lais Andradef1120b12024-08-23 15:12:12 +0100118 LOG(VERBOSE) << "Vibrator Manager cancel synced";
119 std::lock_guard lock(mMutex);
120 mIsPreparing = false;
Lais Andrade80b18612020-10-12 18:44:40 +0000121 return ndk::ScopedAStatus::ok();
122}
123
Lais Andradef1120b12024-08-23 15:12:12 +0100124ndk::ScopedAStatus VibratorManager::startSession(const std::vector<int32_t>& vibratorIds,
125 const VibrationSessionConfig&,
126 const std::shared_ptr<IVibratorCallback>& callback,
127 std::shared_ptr<IVibrationSession>* _aidl_return) {
128 LOG(VERBOSE) << "Vibrator Manager start session";
129 *_aidl_return = nullptr;
130 int32_t capabilities = 0;
131 if (!getCapabilities(&capabilities).isOk()) {
132 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
133 }
134 if ((capabilities & IVibratorManager::CAP_START_SESSIONS) == 0) {
135 return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
136 }
137 if (vibratorIds.size() != 1 || vibratorIds[0] != kDefaultVibratorId) {
138 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
139 }
140 std::lock_guard lock(mMutex);
141 if (mIsPreparing || mSession) {
142 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
143 }
144 mSessionCallback = callback;
145 mSession = ndk::SharedRefBase::make<VibrationSession>(this->ref<VibratorManager>());
146 *_aidl_return = static_cast<std::shared_ptr<IVibrationSession>>(mSession);
147 return ndk::ScopedAStatus::ok();
148}
149
150ndk::ScopedAStatus VibratorManager::clearSessions() {
151 LOG(VERBOSE) << "Vibrator Manager clear sessions";
152 abortSession();
153 return ndk::ScopedAStatus::ok();
154}
155
156void VibratorManager::abortSession() {
157 std::shared_ptr<IVibrationSession> session;
158 {
159 std::lock_guard lock(mMutex);
160 session = mSession;
161 }
162 if (session) {
163 mDefaultVibrator->off();
164 clearSession(session);
165 }
166}
167
168void VibratorManager::closeSession(int32_t delayMs) {
169 std::shared_ptr<IVibrationSession> session;
170 {
171 std::lock_guard lock(mMutex);
172 if (mIsClosingSession) {
173 // Already closing session, ignore this.
174 return;
175 }
176 session = mSession;
177 mIsClosingSession = true;
178 }
179 if (session) {
180 auto callback = ndk::SharedRefBase::make<VibratorCallback>(
181 [session, delayMs, sharedThis = this->ref<VibratorManager>()] {
182 LOG(VERBOSE) << "Closing session after vibrator became idle";
183 usleep(delayMs * 1000);
184
185 if (sharedThis) {
186 sharedThis->clearSession(session);
187 }
188 });
189 mDefaultVibrator->setGlobalVibrationCallback(callback);
190 }
191}
192
193void VibratorManager::clearSession(const std::shared_ptr<IVibrationSession>& session) {
194 std::lock_guard lock(mMutex);
195 if (mSession != session) {
196 // Probably a delayed call from an old session that was already cleared, ignore it.
197 return;
198 }
199 std::shared_ptr<IVibratorCallback> callback = mSessionCallback;
200 mSession = nullptr;
201 mSessionCallback = nullptr; // make sure any delayed call will not trigger this again.
202 mIsClosingSession = false;
203 if (callback) {
204 std::thread([callback] {
205 LOG(VERBOSE) << "Notifying session complete";
206 if (!callback->onComplete().isOk()) {
207 LOG(ERROR) << "Failed to call onComplete";
208 }
209 }).detach();
210 }
211}
212
Lais Andrade80b18612020-10-12 18:44:40 +0000213} // namespace vibrator
214} // namespace hardware
215} // namespace android
216} // namespace aidl