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