1 /*
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 "Session.h"
18
19 #include <android-base/logging.h>
20
21 #include "util/CancellationSignal.h"
22
23 #undef LOG_TAG
24 #define LOG_TAG "FingerprintVirtualHalSession"
25
26 namespace aidl::android::hardware::biometrics::fingerprint {
27
onClientDeath(void * cookie)28 void onClientDeath(void* cookie) {
29 LOG(INFO) << "FingerprintService has died";
30 Session* session = static_cast<Session*>(cookie);
31 if (session && !session->isClosed()) {
32 session->close();
33 }
34 }
35
Session(int sensorId,int userId,std::shared_ptr<ISessionCallback> cb,FakeFingerprintEngine * engine,WorkerThread * worker)36 Session::Session(int sensorId, int userId, std::shared_ptr<ISessionCallback> cb,
37 FakeFingerprintEngine* engine, WorkerThread* worker)
38 : mSensorId(sensorId),
39 mUserId(userId),
40 mCb(std::move(cb)),
41 mEngine(engine),
42 mWorker(worker),
43 mScheduledState(SessionState::IDLING),
44 mCurrentState(SessionState::IDLING) {
45 CHECK_GE(mSensorId, 0);
46 CHECK_GE(mUserId, 0);
47 CHECK(mEngine);
48 CHECK(mWorker);
49 CHECK(mCb);
50
51 mDeathRecipient = AIBinder_DeathRecipient_new(onClientDeath);
52 }
53
linkToDeath(AIBinder * binder)54 binder_status_t Session::linkToDeath(AIBinder* binder) {
55 return AIBinder_linkToDeath(binder, mDeathRecipient, this);
56 }
57
scheduleStateOrCrash(SessionState state)58 void Session::scheduleStateOrCrash(SessionState state) {
59 // TODO(b/166800618): call enterIdling from the terminal callbacks and restore these checks.
60 // CHECK(mScheduledState == SessionState::IDLING);
61 // CHECK(mCurrentState == SessionState::IDLING);
62 mScheduledState = state;
63 }
64
enterStateOrCrash(SessionState state)65 void Session::enterStateOrCrash(SessionState state) {
66 CHECK(mScheduledState == state);
67 mCurrentState = state;
68 mScheduledState = SessionState::IDLING;
69 }
70
enterIdling()71 void Session::enterIdling() {
72 // TODO(b/166800618): call enterIdling from the terminal callbacks and rethink this conditional.
73 if (mCurrentState != SessionState::CLOSED) {
74 mCurrentState = SessionState::IDLING;
75 }
76 }
77
isClosed()78 bool Session::isClosed() {
79 return mCurrentState == SessionState::CLOSED;
80 }
81
generateChallenge()82 ndk::ScopedAStatus Session::generateChallenge() {
83 LOG(INFO) << "generateChallenge";
84 scheduleStateOrCrash(SessionState::GENERATING_CHALLENGE);
85
86 mWorker->schedule(Callable::from([this] {
87 enterStateOrCrash(SessionState::GENERATING_CHALLENGE);
88 mEngine->generateChallengeImpl(mCb.get());
89 enterIdling();
90 }));
91
92 return ndk::ScopedAStatus::ok();
93 }
94
revokeChallenge(int64_t challenge)95 ndk::ScopedAStatus Session::revokeChallenge(int64_t challenge) {
96 LOG(INFO) << "revokeChallenge";
97 scheduleStateOrCrash(SessionState::REVOKING_CHALLENGE);
98
99 mWorker->schedule(Callable::from([this, challenge] {
100 enterStateOrCrash(SessionState::REVOKING_CHALLENGE);
101 mEngine->revokeChallengeImpl(mCb.get(), challenge);
102 enterIdling();
103 }));
104
105 return ndk::ScopedAStatus::ok();
106 }
107
enroll(const keymaster::HardwareAuthToken & hat,std::shared_ptr<common::ICancellationSignal> * out)108 ndk::ScopedAStatus Session::enroll(const keymaster::HardwareAuthToken& hat,
109 std::shared_ptr<common::ICancellationSignal>* out) {
110 LOG(INFO) << "enroll";
111 scheduleStateOrCrash(SessionState::ENROLLING);
112
113 std::promise<void> cancellationPromise;
114 auto cancFuture = cancellationPromise.get_future();
115
116 mWorker->schedule(Callable::from([this, hat, cancFuture = std::move(cancFuture)] {
117 enterStateOrCrash(SessionState::ENROLLING);
118 if (shouldCancel(cancFuture)) {
119 mCb->onError(Error::CANCELED, 0 /* vendorCode */);
120 } else {
121 mEngine->enrollImpl(mCb.get(), hat, cancFuture);
122 }
123 enterIdling();
124 }));
125
126 *out = SharedRefBase::make<CancellationSignal>(std::move(cancellationPromise));
127 return ndk::ScopedAStatus::ok();
128 }
129
authenticate(int64_t operationId,std::shared_ptr<common::ICancellationSignal> * out)130 ndk::ScopedAStatus Session::authenticate(int64_t operationId,
131 std::shared_ptr<common::ICancellationSignal>* out) {
132 LOG(INFO) << "authenticate";
133 scheduleStateOrCrash(SessionState::AUTHENTICATING);
134
135 std::promise<void> cancPromise;
136 auto cancFuture = cancPromise.get_future();
137
138 mWorker->schedule(Callable::from([this, operationId, cancFuture = std::move(cancFuture)] {
139 enterStateOrCrash(SessionState::AUTHENTICATING);
140 if (shouldCancel(cancFuture)) {
141 mCb->onError(Error::CANCELED, 0 /* vendorCode */);
142 } else {
143 mEngine->authenticateImpl(mCb.get(), operationId, cancFuture);
144 }
145 enterIdling();
146 }));
147
148 *out = SharedRefBase::make<CancellationSignal>(std::move(cancPromise));
149 return ndk::ScopedAStatus::ok();
150 }
151
detectInteraction(std::shared_ptr<common::ICancellationSignal> * out)152 ndk::ScopedAStatus Session::detectInteraction(std::shared_ptr<common::ICancellationSignal>* out) {
153 LOG(INFO) << "detectInteraction";
154 scheduleStateOrCrash(SessionState::DETECTING_INTERACTION);
155
156 std::promise<void> cancellationPromise;
157 auto cancFuture = cancellationPromise.get_future();
158
159 mWorker->schedule(Callable::from([this, cancFuture = std::move(cancFuture)] {
160 enterStateOrCrash(SessionState::DETECTING_INTERACTION);
161 if (shouldCancel(cancFuture)) {
162 mCb->onError(Error::CANCELED, 0 /* vendorCode */);
163 } else {
164 mEngine->detectInteractionImpl(mCb.get(), cancFuture);
165 }
166 enterIdling();
167 }));
168
169 *out = SharedRefBase::make<CancellationSignal>(std::move(cancellationPromise));
170 return ndk::ScopedAStatus::ok();
171 }
172
enumerateEnrollments()173 ndk::ScopedAStatus Session::enumerateEnrollments() {
174 LOG(INFO) << "enumerateEnrollments";
175 scheduleStateOrCrash(SessionState::ENUMERATING_ENROLLMENTS);
176
177 mWorker->schedule(Callable::from([this] {
178 enterStateOrCrash(SessionState::ENUMERATING_ENROLLMENTS);
179 mEngine->enumerateEnrollmentsImpl(mCb.get());
180 enterIdling();
181 }));
182
183 return ndk::ScopedAStatus::ok();
184 }
185
removeEnrollments(const std::vector<int32_t> & enrollmentIds)186 ndk::ScopedAStatus Session::removeEnrollments(const std::vector<int32_t>& enrollmentIds) {
187 LOG(INFO) << "removeEnrollments, size:" << enrollmentIds.size();
188 scheduleStateOrCrash(SessionState::REMOVING_ENROLLMENTS);
189
190 mWorker->schedule(Callable::from([this, enrollmentIds] {
191 enterStateOrCrash(SessionState::REMOVING_ENROLLMENTS);
192 mEngine->removeEnrollmentsImpl(mCb.get(), enrollmentIds);
193 enterIdling();
194 }));
195
196 return ndk::ScopedAStatus::ok();
197 }
198
getAuthenticatorId()199 ndk::ScopedAStatus Session::getAuthenticatorId() {
200 LOG(INFO) << "getAuthenticatorId";
201 scheduleStateOrCrash(SessionState::GETTING_AUTHENTICATOR_ID);
202
203 mWorker->schedule(Callable::from([this] {
204 enterStateOrCrash(SessionState::GETTING_AUTHENTICATOR_ID);
205 mEngine->getAuthenticatorIdImpl(mCb.get());
206 enterIdling();
207 }));
208
209 return ndk::ScopedAStatus::ok();
210 }
211
invalidateAuthenticatorId()212 ndk::ScopedAStatus Session::invalidateAuthenticatorId() {
213 LOG(INFO) << "invalidateAuthenticatorId";
214 scheduleStateOrCrash(SessionState::INVALIDATING_AUTHENTICATOR_ID);
215
216 mWorker->schedule(Callable::from([this] {
217 enterStateOrCrash(SessionState::INVALIDATING_AUTHENTICATOR_ID);
218 mEngine->invalidateAuthenticatorIdImpl(mCb.get());
219 enterIdling();
220 }));
221
222 return ndk::ScopedAStatus::ok();
223 }
224
resetLockout(const keymaster::HardwareAuthToken & hat)225 ndk::ScopedAStatus Session::resetLockout(const keymaster::HardwareAuthToken& hat) {
226 LOG(INFO) << "resetLockout";
227 scheduleStateOrCrash(SessionState::RESETTING_LOCKOUT);
228
229 mWorker->schedule(Callable::from([this, hat] {
230 enterStateOrCrash(SessionState::RESETTING_LOCKOUT);
231 mEngine->resetLockoutImpl(mCb.get(), hat);
232 enterIdling();
233 }));
234
235 return ndk::ScopedAStatus::ok();
236 }
237
close()238 ndk::ScopedAStatus Session::close() {
239 LOG(INFO) << "close";
240 // TODO(b/166800618): call enterIdling from the terminal callbacks and restore this check.
241 // CHECK(mCurrentState == SessionState::IDLING) << "Can't close a non-idling session.
242 // Crashing.";
243 mCurrentState = SessionState::CLOSED;
244 mCb->onSessionClosed();
245 AIBinder_DeathRecipient_delete(mDeathRecipient);
246 return ndk::ScopedAStatus::ok();
247 }
248
onPointerDown(int32_t pointerId,int32_t x,int32_t y,float minor,float major)249 ndk::ScopedAStatus Session::onPointerDown(int32_t pointerId, int32_t x, int32_t y, float minor,
250 float major) {
251 LOG(INFO) << "onPointerDown";
252 mEngine->notifyFingerdown();
253 mWorker->schedule(Callable::from([this, pointerId, x, y, minor, major] {
254 mEngine->onPointerDownImpl(pointerId, x, y, minor, major);
255 enterIdling();
256 }));
257 return ndk::ScopedAStatus::ok();
258 }
259
onPointerUp(int32_t pointerId)260 ndk::ScopedAStatus Session::onPointerUp(int32_t pointerId) {
261 LOG(INFO) << "onPointerUp";
262 mWorker->schedule(Callable::from([this, pointerId] {
263 mEngine->onPointerUpImpl(pointerId);
264 enterIdling();
265 }));
266 return ndk::ScopedAStatus::ok();
267 }
268
onUiReady()269 ndk::ScopedAStatus Session::onUiReady() {
270 LOG(INFO) << "onUiReady";
271 mWorker->schedule(Callable::from([this] {
272 mEngine->onUiReadyImpl();
273 enterIdling();
274 }));
275 return ndk::ScopedAStatus::ok();
276 }
277
authenticateWithContext(int64_t operationId,const common::OperationContext &,std::shared_ptr<common::ICancellationSignal> * out)278 ndk::ScopedAStatus Session::authenticateWithContext(
279 int64_t operationId, const common::OperationContext& /*context*/,
280 std::shared_ptr<common::ICancellationSignal>* out) {
281 return authenticate(operationId, out);
282 }
283
enrollWithContext(const keymaster::HardwareAuthToken & hat,const common::OperationContext &,std::shared_ptr<common::ICancellationSignal> * out)284 ndk::ScopedAStatus Session::enrollWithContext(const keymaster::HardwareAuthToken& hat,
285 const common::OperationContext& /*context*/,
286 std::shared_ptr<common::ICancellationSignal>* out) {
287 return enroll(hat, out);
288 }
289
detectInteractionWithContext(const common::OperationContext &,std::shared_ptr<common::ICancellationSignal> * out)290 ndk::ScopedAStatus Session::detectInteractionWithContext(
291 const common::OperationContext& /*context*/,
292 std::shared_ptr<common::ICancellationSignal>* out) {
293 return detectInteraction(out);
294 }
295
onPointerDownWithContext(const PointerContext & context)296 ndk::ScopedAStatus Session::onPointerDownWithContext(const PointerContext& context) {
297 return onPointerDown(context.pointerId, context.x, context.y, context.minor, context.major);
298 }
299
onPointerUpWithContext(const PointerContext & context)300 ndk::ScopedAStatus Session::onPointerUpWithContext(const PointerContext& context) {
301 return onPointerUp(context.pointerId);
302 }
303
onContextChanged(const common::OperationContext &)304 ndk::ScopedAStatus Session::onContextChanged(const common::OperationContext& /*context*/) {
305 return ndk::ScopedAStatus::ok();
306 }
307
onPointerCancelWithContext(const PointerContext &)308 ndk::ScopedAStatus Session::onPointerCancelWithContext(const PointerContext& /*context*/) {
309 return ndk::ScopedAStatus::ok();
310 }
311
setIgnoreDisplayTouches(bool)312 ndk::ScopedAStatus Session::setIgnoreDisplayTouches(bool /*shouldIgnore*/) {
313 return ndk::ScopedAStatus::ok();
314 }
315
316 } // namespace aidl::android::hardware::biometrics::fingerprint
317