ukui-screensaver/BiometricAuth/biometricauthwidget.cpp

345 lines
9.1 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright (C) 2018 Tianjin KYLIN Information Technology 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 2, 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301, USA.
**/
#include "biometricauthwidget.h"
#include <QLabel>
#include <QDebug>
#include <QDBusUnixFileDescriptor>
#include <unistd.h>
#include <pwd.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#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<int, int> 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);
}