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 "CancellationSignal.h"
22 
23 namespace aidl::android::hardware::biometrics::fingerprint {
24 
Session(int sensorId,int userId,std::shared_ptr<ISessionCallback> cb,FakeFingerprintEngine * engine,WorkerThread * worker)25 Session::Session(int sensorId, int userId, std::shared_ptr<ISessionCallback> cb,
26                  FakeFingerprintEngine* engine, WorkerThread* worker)
27     : mSensorId(sensorId),
28       mUserId(userId),
29       mCb(std::move(cb)),
30       mEngine(engine),
31       mWorker(worker),
32       mScheduledState(SessionState::IDLING),
33       mCurrentState(SessionState::IDLING) {
34     CHECK_GE(mSensorId, 0);
35     CHECK_GE(mUserId, 0);
36     CHECK(mEngine);
37     CHECK(mWorker);
38     CHECK(mCb);
39 }
40 
scheduleStateOrCrash(SessionState state)41 void Session::scheduleStateOrCrash(SessionState state) {
42     // TODO(b/166800618): call enterIdling from the terminal callbacks and restore these checks.
43     // CHECK(mScheduledState == SessionState::IDLING);
44     // CHECK(mCurrentState == SessionState::IDLING);
45     mScheduledState = state;
46 }
47 
enterStateOrCrash(SessionState state)48 void Session::enterStateOrCrash(SessionState state) {
49     CHECK(mScheduledState == state);
50     mCurrentState = state;
51     mScheduledState = SessionState::IDLING;
52 }
53 
enterIdling()54 void Session::enterIdling() {
55     // TODO(b/166800618): call enterIdling from the terminal callbacks and rethink this conditional.
56     if (mCurrentState != SessionState::CLOSED) {
57         mCurrentState = SessionState::IDLING;
58     }
59 }
60 
isClosed()61 bool Session::isClosed() {
62     return mCurrentState == SessionState::CLOSED;
63 }
64 
generateChallenge()65 ndk::ScopedAStatus Session::generateChallenge() {
66     LOG(INFO) << "generateChallenge";
67     scheduleStateOrCrash(SessionState::GENERATING_CHALLENGE);
68 
69     mWorker->schedule(Callable::from([this] {
70         enterStateOrCrash(SessionState::GENERATING_CHALLENGE);
71         mEngine->generateChallengeImpl(mCb.get());
72         enterIdling();
73     }));
74 
75     return ndk::ScopedAStatus::ok();
76 }
77 
revokeChallenge(int64_t challenge)78 ndk::ScopedAStatus Session::revokeChallenge(int64_t challenge) {
79     LOG(INFO) << "revokeChallenge";
80     scheduleStateOrCrash(SessionState::REVOKING_CHALLENGE);
81 
82     mWorker->schedule(Callable::from([this, challenge] {
83         enterStateOrCrash(SessionState::REVOKING_CHALLENGE);
84         mEngine->revokeChallengeImpl(mCb.get(), challenge);
85         enterIdling();
86     }));
87 
88     return ndk::ScopedAStatus::ok();
89 }
90 
enroll(const keymaster::HardwareAuthToken & hat,std::shared_ptr<common::ICancellationSignal> * out)91 ndk::ScopedAStatus Session::enroll(const keymaster::HardwareAuthToken& hat,
92                                    std::shared_ptr<common::ICancellationSignal>* out) {
93     LOG(INFO) << "enroll";
94     scheduleStateOrCrash(SessionState::ENROLLING);
95 
96     std::promise<void> cancellationPromise;
97     auto cancFuture = cancellationPromise.get_future();
98 
99     mWorker->schedule(Callable::from([this, hat, cancFuture = std::move(cancFuture)] {
100         enterStateOrCrash(SessionState::ENROLLING);
101         if (shouldCancel(cancFuture)) {
102             mCb->onError(Error::CANCELED, 0 /* vendorCode */);
103         } else {
104             mEngine->enrollImpl(mCb.get(), hat);
105         }
106         enterIdling();
107     }));
108 
109     *out = SharedRefBase::make<CancellationSignal>(std::move(cancellationPromise));
110     return ndk::ScopedAStatus::ok();
111 }
112 
authenticate(int64_t operationId,std::shared_ptr<common::ICancellationSignal> * out)113 ndk::ScopedAStatus Session::authenticate(int64_t operationId,
114                                          std::shared_ptr<common::ICancellationSignal>* out) {
115     LOG(INFO) << "authenticate";
116     scheduleStateOrCrash(SessionState::AUTHENTICATING);
117 
118     std::promise<void> cancPromise;
119     auto cancFuture = cancPromise.get_future();
120 
121     mWorker->schedule(Callable::from([this, operationId, cancFuture = std::move(cancFuture)] {
122         enterStateOrCrash(SessionState::AUTHENTICATING);
123         if (shouldCancel(cancFuture)) {
124             mCb->onError(Error::CANCELED, 0 /* vendorCode */);
125         } else {
126             mEngine->authenticateImpl(mCb.get(), operationId);
127         }
128         enterIdling();
129     }));
130 
131     *out = SharedRefBase::make<CancellationSignal>(std::move(cancPromise));
132     return ndk::ScopedAStatus::ok();
133 }
134 
detectInteraction(std::shared_ptr<common::ICancellationSignal> * out)135 ndk::ScopedAStatus Session::detectInteraction(std::shared_ptr<common::ICancellationSignal>* out) {
136     LOG(INFO) << "detectInteraction";
137     scheduleStateOrCrash(SessionState::DETECTING_INTERACTION);
138 
139     std::promise<void> cancellationPromise;
140     auto cancFuture = cancellationPromise.get_future();
141 
142     mWorker->schedule(Callable::from([this, cancFuture = std::move(cancFuture)] {
143         enterStateOrCrash(SessionState::DETECTING_INTERACTION);
144         if (shouldCancel(cancFuture)) {
145             mCb->onError(Error::CANCELED, 0 /* vendorCode */);
146         } else {
147             mEngine->detectInteractionImpl(mCb.get());
148         }
149         enterIdling();
150     }));
151 
152     *out = SharedRefBase::make<CancellationSignal>(std::move(cancellationPromise));
153     return ndk::ScopedAStatus::ok();
154 }
155 
enumerateEnrollments()156 ndk::ScopedAStatus Session::enumerateEnrollments() {
157     LOG(INFO) << "enumerateEnrollments";
158     scheduleStateOrCrash(SessionState::ENUMERATING_ENROLLMENTS);
159 
160     mWorker->schedule(Callable::from([this] {
161         enterStateOrCrash(SessionState::ENUMERATING_ENROLLMENTS);
162         mEngine->enumerateEnrollmentsImpl(mCb.get());
163         enterIdling();
164     }));
165 
166     return ndk::ScopedAStatus::ok();
167 }
168 
removeEnrollments(const std::vector<int32_t> & enrollmentIds)169 ndk::ScopedAStatus Session::removeEnrollments(const std::vector<int32_t>& enrollmentIds) {
170     LOG(INFO) << "removeEnrollments";
171     scheduleStateOrCrash(SessionState::REMOVING_ENROLLMENTS);
172 
173     mWorker->schedule(Callable::from([this, enrollmentIds] {
174         enterStateOrCrash(SessionState::REMOVING_ENROLLMENTS);
175         mEngine->removeEnrollmentsImpl(mCb.get(), enrollmentIds);
176         enterIdling();
177     }));
178 
179     return ndk::ScopedAStatus::ok();
180 }
181 
getAuthenticatorId()182 ndk::ScopedAStatus Session::getAuthenticatorId() {
183     LOG(INFO) << "getAuthenticatorId";
184     scheduleStateOrCrash(SessionState::GETTING_AUTHENTICATOR_ID);
185 
186     mWorker->schedule(Callable::from([this] {
187         enterStateOrCrash(SessionState::GETTING_AUTHENTICATOR_ID);
188         mEngine->getAuthenticatorIdImpl(mCb.get());
189         enterIdling();
190     }));
191 
192     return ndk::ScopedAStatus::ok();
193 }
194 
invalidateAuthenticatorId()195 ndk::ScopedAStatus Session::invalidateAuthenticatorId() {
196     LOG(INFO) << "invalidateAuthenticatorId";
197     scheduleStateOrCrash(SessionState::INVALIDATING_AUTHENTICATOR_ID);
198 
199     mWorker->schedule(Callable::from([this] {
200         enterStateOrCrash(SessionState::INVALIDATING_AUTHENTICATOR_ID);
201         mEngine->invalidateAuthenticatorIdImpl(mCb.get());
202         enterIdling();
203     }));
204 
205     return ndk::ScopedAStatus::ok();
206 }
207 
resetLockout(const keymaster::HardwareAuthToken & hat)208 ndk::ScopedAStatus Session::resetLockout(const keymaster::HardwareAuthToken& hat) {
209     LOG(INFO) << "resetLockout";
210     scheduleStateOrCrash(SessionState::RESETTING_LOCKOUT);
211 
212     mWorker->schedule(Callable::from([this, hat] {
213         enterStateOrCrash(SessionState::RESETTING_LOCKOUT);
214         mEngine->resetLockoutImpl(mCb.get(), hat);
215         enterIdling();
216     }));
217 
218     return ndk::ScopedAStatus::ok();
219 }
220 
close()221 ndk::ScopedAStatus Session::close() {
222     LOG(INFO) << "close";
223     // TODO(b/166800618): call enterIdling from the terminal callbacks and restore this check.
224     // CHECK(mCurrentState == SessionState::IDLING) << "Can't close a non-idling session.
225     // Crashing.";
226     mCurrentState = SessionState::CLOSED;
227     mCb->onSessionClosed();
228     return ndk::ScopedAStatus::ok();
229 }
230 
onPointerDown(int32_t,int32_t,int32_t,float,float)231 ndk::ScopedAStatus Session::onPointerDown(int32_t /*pointerId*/, int32_t /*x*/, int32_t /*y*/,
232                                           float /*minor*/, float /*major*/) {
233     LOG(INFO) << "onPointerDown";
234     return ndk::ScopedAStatus::ok();
235 }
236 
onPointerUp(int32_t)237 ndk::ScopedAStatus Session::onPointerUp(int32_t /*pointerId*/) {
238     LOG(INFO) << "onPointerUp";
239     return ndk::ScopedAStatus::ok();
240 }
241 
onUiReady()242 ndk::ScopedAStatus Session::onUiReady() {
243     LOG(INFO) << "onUiReady";
244     return ndk::ScopedAStatus::ok();
245 }
246 
247 }  // namespace aidl::android::hardware::biometrics::fingerprint
248