blob: 73748f2d125d2d93c1ad2f0a5b52526556c70811 [file] [log] [blame]
Jim Millera34dc462015-05-07 18:52:53 -07001/*
2 * Copyright (C) 2015 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#define LOG_TAG "fingerprintd"
18
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -080019#include <android/hardware/biometrics/fingerprint/2.1/types.h>
20#include <android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprint.h>
21#include <android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprintClientCallback.h>
Jim Millera34dc462015-05-07 18:52:53 -070022#include <binder/IServiceManager.h>
Jim Millera34dc462015-05-07 18:52:53 -070023#include <keystore/IKeystoreService.h>
24#include <keystore/keystore.h> // for error codes
25#include <utils/Log.h>
26
27#include "FingerprintDaemonProxy.h"
28
29namespace android {
30
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -080031using hardware::hidl_string;
32using hardware::Return;
33using hardware::biometrics::fingerprint::V2_1::FingerprintMsg;
34using hardware::biometrics::fingerprint::V2_1::RequestStatus;
35using hardware::biometrics::fingerprint::V2_1::FingerprintError;
36using hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprintClientCallback;
37using Type = hardware::biometrics::fingerprint::V2_1::FingerprintMsgType;
38using IBiometricsFingerprint = hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprint;
Jim Millera34dc462015-05-07 18:52:53 -070039
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -080040FingerprintDaemonProxy* FingerprintDaemonProxy::sInstance = nullptr;
41static sp<IBiometricsFingerprint> gBFP = nullptr;
42static sp<IBiometricsFingerprintClientCallback> gClientCallback = nullptr;
Jim Millera34dc462015-05-07 18:52:53 -070043
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -080044template <typename E>
45constexpr typename std::underlying_type<E>::type to_native(E e) {
46 return static_cast<typename std::underlying_type<E>::type>(e);
47}
48
49const ssize_t hw_auth_token_size = 69;
50
51namespace hardware {
52
53class BiometricsFingerprintClientCallback : public IBiometricsFingerprintClientCallback {
54 public:
55 BiometricsFingerprintClientCallback() {};
56 virtual ~BiometricsFingerprintClientCallback() = default;
57 Return<void> notify(const FingerprintMsg& msg) {
58 FingerprintDaemonProxy::hal_notify_callback(msg);
59 return Void();
60 }
61};
62
63IBiometricsFingerprintClientCallback* HIDL_FETCH_IBiometricsFingerprintClientCallback(const char* /* name */) {
64 return new BiometricsFingerprintClientCallback();
65}
66
67} // namespace hardware
68
69FingerprintDaemonProxy::FingerprintDaemonProxy() : mCallback(nullptr) {
Jim Millera34dc462015-05-07 18:52:53 -070070
71}
72
73FingerprintDaemonProxy::~FingerprintDaemonProxy() {
74 closeHal();
75}
76
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -080077void FingerprintDaemonProxy::hal_notify_callback(const hardware::biometrics::fingerprint::V2_1::FingerprintMsg &msg) {
Jim Millera34dc462015-05-07 18:52:53 -070078 FingerprintDaemonProxy* instance = FingerprintDaemonProxy::getInstance();
79 const sp<IFingerprintDaemonCallback> callback = instance->mCallback;
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -080080 if (callback == nullptr) {
Jim Millera34dc462015-05-07 18:52:53 -070081 ALOGE("Invalid callback object");
82 return;
83 }
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -080084 switch (msg.type) {
85 case Type::ERROR:
86 ALOGD("onError(%d)", msg.data.error);
87 callback->onError(0, to_native(msg.data.error));
Jim Millera34dc462015-05-07 18:52:53 -070088 break;
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -080089 case Type::ACQUIRED:
90 ALOGD("onAcquired(%d)", msg.data.acquired.acquiredInfo);
91 callback->onAcquired(0, to_native(msg.data.acquired.acquiredInfo));
Jim Millera34dc462015-05-07 18:52:53 -070092 break;
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -080093 case Type::AUTHENTICATED:
Jim Millera34dc462015-05-07 18:52:53 -070094 ALOGD("onAuthenticated(fid=%d, gid=%d)",
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -080095 msg.data.authenticated.finger.fid,
96 msg.data.authenticated.finger.gid);
97 if (msg.data.authenticated.finger.fid != 0) {
98 const uint8_t* hat = reinterpret_cast<const uint8_t *>(&msg.data.authenticated.hat);
99 instance->notifyKeystore(hat, sizeof(msg.data.authenticated.hat));
Jim Millera34dc462015-05-07 18:52:53 -0700100 }
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800101 callback->onAuthenticated(0,
102 msg.data.authenticated.finger.fid,
103 msg.data.authenticated.finger.gid);
Jim Millera34dc462015-05-07 18:52:53 -0700104 break;
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800105 case Type::TEMPLATE_ENROLLING:
Jim Millera34dc462015-05-07 18:52:53 -0700106 ALOGD("onEnrollResult(fid=%d, gid=%d, rem=%d)",
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800107 msg.data.enroll.finger.fid,
108 msg.data.enroll.finger.gid,
109 msg.data.enroll.samplesRemaining);
110 callback->onEnrollResult(0,
111 msg.data.enroll.finger.fid,
112 msg.data.enroll.finger.gid,
113 msg.data.enroll.samplesRemaining);
Jim Millera34dc462015-05-07 18:52:53 -0700114 break;
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800115 case Type::TEMPLATE_REMOVED:
Jim Millera34dc462015-05-07 18:52:53 -0700116 ALOGD("onRemove(fid=%d, gid=%d)",
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800117 msg.data.removed.finger.fid,
118 msg.data.removed.finger.gid);
119 callback->onRemoved(0,
120 msg.data.removed.finger.fid,
121 msg.data.removed.finger.gid);
Jim Millera34dc462015-05-07 18:52:53 -0700122 break;
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800123 case Type::TEMPLATE_ENUMERATING:
Sasha Levitskiye270da92015-12-03 13:50:53 -0800124 ALOGD("onEnumerate(fid=%d, gid=%d, rem=%d)",
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800125 msg.data.enumerated.finger.fid,
126 msg.data.enumerated.finger.gid,
127 msg.data.enumerated.remainingTemplates);
128 callback->onEnumerate(0,
129 msg.data.enumerated.finger.fid,
130 msg.data.enumerated.finger.gid,
131 msg.data.enumerated.remainingTemplates);
Sasha Levitskiye270da92015-12-03 13:50:53 -0800132 break;
Jim Millera34dc462015-05-07 18:52:53 -0700133 default:
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800134 ALOGE("invalid msg type: %d", msg.type);
Jim Millera34dc462015-05-07 18:52:53 -0700135 return;
136 }
137}
138
Sasha Levitskiy53afac02015-06-09 16:47:09 -0700139void FingerprintDaemonProxy::notifyKeystore(const uint8_t *auth_token, const size_t auth_token_length) {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800140 if (auth_token != nullptr && auth_token_length > 0) {
Jim Millera34dc462015-05-07 18:52:53 -0700141 // TODO: cache service?
142 sp < IServiceManager > sm = defaultServiceManager();
143 sp < IBinder > binder = sm->getService(String16("android.security.keystore"));
144 sp < IKeystoreService > service = interface_cast < IKeystoreService > (binder);
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800145 if (service != nullptr) {
Jim Millera34dc462015-05-07 18:52:53 -0700146 status_t ret = service->addAuthToken(auth_token, auth_token_length);
147 if (ret != ResponseCode::NO_ERROR) {
148 ALOGE("Falure sending auth token to KeyStore: %d", ret);
149 }
150 } else {
151 ALOGE("Unable to communicate with KeyStore");
152 }
153 }
154}
155
156void FingerprintDaemonProxy::init(const sp<IFingerprintDaemonCallback>& callback) {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800157 if (mCallback != nullptr && IInterface::asBinder(callback) != IInterface::asBinder(mCallback)) {
Jim Millera34dc462015-05-07 18:52:53 -0700158 IInterface::asBinder(mCallback)->unlinkToDeath(this);
159 }
160 IInterface::asBinder(callback)->linkToDeath(this);
161 mCallback = callback;
162}
163
164int32_t FingerprintDaemonProxy::enroll(const uint8_t* token, ssize_t tokenSize, int32_t groupId,
165 int32_t timeout) {
166 ALOG(LOG_VERBOSE, LOG_TAG, "enroll(gid=%d, timeout=%d)\n", groupId, timeout);
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800167 if (tokenSize != hw_auth_token_size) {
168 ALOG(LOG_VERBOSE, LOG_TAG, "enroll() : invalid token size %zd, expected %zd\n", tokenSize, hw_auth_token_size);
Jim Millera34dc462015-05-07 18:52:53 -0700169 return -1;
170 }
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800171
172 hardware::hidl_array<uint8_t, hw_auth_token_size> hat(token);
173 Return<RequestStatus> ret = gBFP->enroll(hat, groupId, timeout);
Steven Moreland81330932017-01-03 17:01:27 -0800174 if (!ret.isOk()) {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800175 ALOGE("Unknown transport error");
176 return -1;
177 }
178
179 RequestStatus status = ret;
180 return to_native(status);
Jim Millera34dc462015-05-07 18:52:53 -0700181}
182
183uint64_t FingerprintDaemonProxy::preEnroll() {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800184 return gBFP->preEnroll();
Jim Millera34dc462015-05-07 18:52:53 -0700185}
186
Sasha Levitskiy7ded5792015-06-25 15:53:41 -0700187int32_t FingerprintDaemonProxy::postEnroll() {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800188 Return<RequestStatus> ret = gBFP->postEnroll();
Steven Moreland81330932017-01-03 17:01:27 -0800189 if (!ret.isOk()) {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800190 ALOGE("Unknown transport error");
191 return -1;
192 }
193
194 RequestStatus status = ret;
195 return to_native(status);
Sasha Levitskiy7ded5792015-06-25 15:53:41 -0700196}
197
Jim Millera34dc462015-05-07 18:52:53 -0700198int32_t FingerprintDaemonProxy::stopEnrollment() {
199 ALOG(LOG_VERBOSE, LOG_TAG, "stopEnrollment()\n");
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800200 Return<RequestStatus> ret = gBFP->cancel();
Steven Moreland81330932017-01-03 17:01:27 -0800201 if (!ret.isOk()) {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800202 ALOGE("Unknown transport error");
203 return -1;
204 }
205
206 RequestStatus status = ret;
207 return to_native(status);
Jim Millera34dc462015-05-07 18:52:53 -0700208}
209
210int32_t FingerprintDaemonProxy::authenticate(uint64_t sessionId, uint32_t groupId) {
211 ALOG(LOG_VERBOSE, LOG_TAG, "authenticate(sid=%" PRId64 ", gid=%d)\n", sessionId, groupId);
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800212 Return<RequestStatus> ret = gBFP->authenticate(sessionId, groupId);
Steven Moreland81330932017-01-03 17:01:27 -0800213 if (!ret.isOk()) {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800214 ALOGE("Unknown transport error");
215 return -1;
216 }
217
218 RequestStatus status = ret;
219 return to_native(status);
Jim Millera34dc462015-05-07 18:52:53 -0700220}
221
222int32_t FingerprintDaemonProxy::stopAuthentication() {
223 ALOG(LOG_VERBOSE, LOG_TAG, "stopAuthentication()\n");
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800224 Return<RequestStatus> ret = gBFP->cancel();
Steven Moreland81330932017-01-03 17:01:27 -0800225 if (!ret.isOk()) {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800226 ALOGE("Unknown transport error");
227 return -1;
228 }
229
230 RequestStatus status = ret;
231 return to_native(status);
Jim Millera34dc462015-05-07 18:52:53 -0700232}
233
234int32_t FingerprintDaemonProxy::remove(int32_t fingerId, int32_t groupId) {
235 ALOG(LOG_VERBOSE, LOG_TAG, "remove(fid=%d, gid=%d)\n", fingerId, groupId);
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800236 Return<RequestStatus> ret = gBFP->remove(groupId, fingerId);
Steven Moreland81330932017-01-03 17:01:27 -0800237 if (!ret.isOk()) {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800238 ALOGE("Unknown transport error");
239 return -1;
240 }
241
242 RequestStatus status = ret;
243 return to_native(status);
Jim Millera34dc462015-05-07 18:52:53 -0700244}
245
Sasha Levitskiye270da92015-12-03 13:50:53 -0800246int32_t FingerprintDaemonProxy::enumerate() {
247 ALOG(LOG_VERBOSE, LOG_TAG, "enumerate()\n");
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800248 Return<RequestStatus> ret = gBFP->enumerate();
Steven Moreland81330932017-01-03 17:01:27 -0800249 if (!ret.isOk()) {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800250 ALOGE("Unknown transport error");
251 return -1;
252 }
253
254 RequestStatus status = ret;
255 return to_native(status);
Sasha Levitskiye270da92015-12-03 13:50:53 -0800256}
257
Jim Millera34dc462015-05-07 18:52:53 -0700258uint64_t FingerprintDaemonProxy::getAuthenticatorId() {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800259 return gBFP->getAuthenticatorId();
Jim Millera34dc462015-05-07 18:52:53 -0700260}
261
262int32_t FingerprintDaemonProxy::setActiveGroup(int32_t groupId, const uint8_t* path,
263 ssize_t pathlen) {
Sasha Levitskiy99115b92015-06-18 16:08:14 -0700264 if (pathlen >= PATH_MAX || pathlen <= 0) {
265 ALOGE("Bad path length: %zd", pathlen);
Jim Millera34dc462015-05-07 18:52:53 -0700266 return -1;
267 }
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800268 hidl_string pathname;
269 pathname.setToExternal(reinterpret_cast<const char*>(path), pathlen);
270 ALOG(LOG_VERBOSE, LOG_TAG, "setActiveGroup(%d, %s, %zu)", groupId, pathname.c_str(), pathlen);
271 Return<RequestStatus> ret = gBFP->setActiveGroup(groupId, pathname);
Steven Moreland81330932017-01-03 17:01:27 -0800272 if (!ret.isOk()) {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800273 ALOGE("Unknown transport error");
274 return -1;
275 }
276
277 RequestStatus status = ret;
278 return to_native(status);
Jim Millera34dc462015-05-07 18:52:53 -0700279}
280
281int64_t FingerprintDaemonProxy::openHal() {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800282 if (gBFP == nullptr) {
283 // TODO(b/31632518)
284 gBFP = IBiometricsFingerprint::getService("fingerprint");
285 if(gBFP == nullptr) {
286 ALOGE("Can't get service fingerprint");
287 return 0;
288 }
Jim Millera34dc462015-05-07 18:52:53 -0700289 }
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800290 gClientCallback = hardware::HIDL_FETCH_IBiometricsFingerprintClientCallback(nullptr);
291 gBFP->setNotify(gClientCallback);
292 return reinterpret_cast<int64_t>(gBFP.get());
Jim Millera34dc462015-05-07 18:52:53 -0700293}
294
295int32_t FingerprintDaemonProxy::closeHal() {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800296 // Obsolete, return 0 for compatibility reasons.
Sasha Levitskiydae48372015-07-10 14:24:30 -0700297 return 0;
Jim Millera34dc462015-05-07 18:52:53 -0700298}
299
300void FingerprintDaemonProxy::binderDied(const wp<IBinder>& who) {
301 ALOGD("binder died");
Sasha Levitskiydae48372015-07-10 14:24:30 -0700302 int err;
303 if (0 != (err = closeHal())) {
304 ALOGE("Can't close fingerprint device, error: %d", err);
305 }
Jim Millera34dc462015-05-07 18:52:53 -0700306 if (IInterface::asBinder(mCallback) == who) {
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800307 mCallback = nullptr;
Jim Millera34dc462015-05-07 18:52:53 -0700308 }
309}
310
Sasha Levitskiy71f2a4b2016-11-07 10:18:21 -0800311} // namespace android