/* * Copyright (C) 2023, KylinSoft Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "biometricauthwidget.h" #include #include #include #include #include #include #include #include #include #include "giodbus.h" BiometricAuthWidget::BiometricAuthWidget(BiometricProxy *proxy, QWidget *parent) : QWidget(parent), proxy(proxy), isInAuth(false), movieTimer(nullptr), failedCount(0), timeoutCount(0), beStopped(false), retrytimer(nullptr), usebind(false) { usebind = getAuthDouble(); initUI(); resize(400, 260); if(this->proxy) { connect(this->proxy, &BiometricProxy::StatusChanged, this, &BiometricAuthWidget::onStatusChanged); connect(this->proxy, &BiometricProxy::FrameWritten, this, &BiometricAuthWidget::onFrameWritten); } } void BiometricAuthWidget::initUI() { //显示提示信息 lblNotify = new QLabel(this); lblNotify->setWordWrap(true); lblNotify->setAlignment(Qt::AlignHCenter | Qt::AlignBottom); //显示当前设备 lblDevice = new QLabel(this); lblDevice->setWordWrap(true); lblDevice->setAlignment(Qt::AlignCenter); //显示图片 lblImage = new QLabel(this); lblImage->setFixedSize(100, 100); } void BiometricAuthWidget::resizeEvent(QResizeEvent */*event*/) { lblNotify->setGeometry(0, 0, width(), 45); lblDevice->setGeometry(0, lblNotify->geometry().bottom()+5, width(), 30); lblImage->setGeometry((width() - lblImage->width()) / 2, lblDevice->geometry().bottom() + 10, lblImage->width(), lblImage->height()); //qDebug() } void BiometricAuthWidget::startAuth(DeviceInfoPtr device, int uid) { if(!proxy) { qWarning() << "BiometricProxy doesn't exist."; return; } if(isInAuth) { qDebug() << "Identification is currently under way, stop it"; stopAuth(); } this->device = device; this->uid = uid; this->userName = getpwuid(uid)->pw_name; this->failedCount = 0; this->timeoutCount = 0; this->beStopped = false; proxy->StopOps(device->id); startAuth_(); if(device->deviceType != DeviceType::Type::Face){ updateImage(1); } } void BiometricAuthWidget::startAuth_() { lblDevice->setText(tr("Current device: ") + device->shortName); //qDebug().noquote() << QString("Identify:[drvid: %1, uid: %2]").arg(1).arg(2); isInAuth = true; dup_fd = -1; QDBusPendingCall call = proxy->Identify(device->id, uid); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, &BiometricAuthWidget::onIdentifyComplete); } void BiometricAuthWidget::stopAuth() { beStopped = true; if(!isInAuth) { return; } proxy->StopOps(device->id); if(retrytimer&&retrytimer->isActive()){ retrytimer->stop(); delete retrytimer; retrytimer = nullptr; } isInAuth = false; updateImage(0); } void BiometricAuthWidget::onIdentifyComplete(QDBusPendingCallWatcher *watcher) { QDBusPendingReply reply = *watcher; if(reply.isError()) { qWarning() << "Identify error: " << reply.error().message(); Q_EMIT authComplete(false); updateImage(0); return; } int result = reply.argumentAt(0).toInt(); int authUid = reply.argumentAt(1).toInt(); // 特征识别成功,而且用户id匹配 if(result == DBUS_RESULT_SUCCESS && authUid == uid) { qDebug() << "Identify success"; Q_EMIT authComplete(true); } // 特征识别不匹配 else if(result == DBUS_RESULT_NOTMATCH) { if(usebind){ Q_EMIT authComplete(false); return; } qDebug() << "Identify failed"; failedCount++; if(failedCount >= GetMaxFailedAutoRetry(userName)) { Q_EMIT authComplete(false); } else { lblNotify->setText(tr("Identify failed, Please retry.")); if(!beStopped){ // QTimer::singleShot(1000, this, &BiometricAuthWidget::startAuth_); if(!retrytimer){ retrytimer = new QTimer(this); retrytimer->setSingleShot(true); connect(retrytimer, &QTimer::timeout, this, &BiometricAuthWidget::startAuth_); } retrytimer->start(1000); } } } //识别发生错误 else if(result == DBUS_RESULT_ERROR) { if(usebind){ Q_EMIT authComplete(false); return; } StatusReslut ret = proxy->UpdateStatus(device->id); //识别操作超时 if(ret.result == 0 && ret.opsStatus == OPS_IDENTIFY_TIMEOUT) { timeoutCount++; if(timeoutCount >= GetMaxTimeoutAutoRetry(userName)) { Q_EMIT authComplete(false); } else { QTimer::singleShot(1000, [&]{ if(!beStopped) { startAuth_(); } }); } }else{ Q_EMIT authComplete(false); } }else{ Q_EMIT authComplete(false); } updateImage(0); } void BiometricAuthWidget::onFrameWritten(int drvid) { if(dup_fd == -1){ dup_fd = get_server_gvariant_stdout(drvid); } if(dup_fd <= 0) return ; cv::Mat img; lseek(dup_fd, 0, SEEK_SET); char base64_bufferData[1024*1024]; int rc = read(dup_fd, base64_bufferData, 1024*1024); printf("rc = %d\n", rc); cv::Mat mat2(1, sizeof(base64_bufferData), CV_8U, base64_bufferData); img = cv::imdecode(mat2, cv::IMREAD_COLOR); cv::cvtColor(img,img,cv::COLOR_BGR2RGB); QImage srcQImage = QImage((uchar*)(img.data), img.cols, img.rows, QImage::Format_RGB888); lblImage->setFixedSize(160,160); lblImage->setGeometry((width() - lblImage->width()) / 2, lblDevice->geometry().bottom() + 10, lblImage->width(), lblImage->height()); lblImage->setPixmap(QPixmap::fromImage(srcQImage).scaled(lblImage->size())); } void BiometricAuthWidget::onStatusChanged(int drvid, int status) { if(!isInAuth) { return; } if(drvid != device->id) { return; } // 显示来自服务的提示信息 if(status == STATUS_NOTIFY) { QString notifyMsg = proxy->GetNotifyMesg(drvid); lblNotify->setText(notifyMsg); } } static int count = 0; void BiometricAuthWidget::updateImage(int type) { if(device->deviceType == DeviceType::Type::Face) return ; if(type == 0) { if(movieTimer && movieTimer->isActive()) { movieTimer->stop(); } QString imagePath = QString(UKUI_BIOMETRIC_IMAGES_PATH "%1/01.png") .arg(DeviceType::getDeviceType(device->deviceType)); setImage(imagePath); } else { if(!movieTimer) { movieTimer = new QTimer(this); movieTimer->setInterval(100); connect(movieTimer, &QTimer::timeout, this, &BiometricAuthWidget::onMoviePixmapUpdate); } count = 0; movieTimer->start(); } } void BiometricAuthWidget::onMoviePixmapUpdate() { if(count >= 18) { count = 0; } count++; QString fileName = (count < 10 ? "0" : "") + QString::number(count); QString imagePath = QString(UKUI_BIOMETRIC_IMAGES_PATH "%1/%2.png") .arg(DeviceType::getDeviceType(device->deviceType)) .arg(fileName); setImage(imagePath); } void BiometricAuthWidget::setImage(const QString &path) { QPixmap image(path); image = image.scaled(lblImage->width(), lblImage->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); lblImage->setPixmap(image); } bool BiometricAuthWidget::getAuthDouble() { QSettings settings("/etc/biometric-auth/ukui-biometric.conf", QSettings::IniFormat); bool distribId = settings.value("DoubleAuth").toBool(); return distribId; } void BiometricAuthWidget::setMinImage(float val) { resize(400,100+100*val); lblImage->setFixedSize(100*val, 100*val); }