From 10242a825099d693b390d9598491c3bcecc336b7 Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Mon, 3 Apr 2023 15:57:15 +0200 Subject: [PATCH] QPermission: return the combined result of a permission group on Android QPermission might resolve to multiple underlying permissions on Android. The existing code was only using the first permission from the list in checkPermission(), and also checked only for the first result returned by requestPermissions(). This can lead to a situation when only one of the requested permissions is granted, but the API reports that all required permissions are granted. This patch fixes it by checking the combined status of all permissions. If at least one of the permissions is denied, the whole list of permissions in considered denied. Fixes: QTBUG-112527 Pick-to: 6.5 Change-Id: I243b73bb5a842197cd0ef70937b8eac344ff9596 Reviewed-by: Assam Boudjelthia --- src/corelib/kernel/qpermissions_android.cpp | 25 +++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/corelib/kernel/qpermissions_android.cpp b/src/corelib/kernel/qpermissions_android.cpp index 1def982f29..cda4c3f896 100644 --- a/src/corelib/kernel/qpermissions_android.cpp +++ b/src/corelib/kernel/qpermissions_android.cpp @@ -124,6 +124,18 @@ Q_GLOBAL_STATIC_WITH_ARGS(PermissionStatusHash, g_permissionStatusHash, ({ { qMetaTypeId(), Qt::PermissionStatus::Undetermined } })); +static Qt::PermissionStatus +getCombinedStatus(const QList &androidResults) +{ + // Android returns only Denied or Granted + for (const auto &result : androidResults) { + const auto status = permissionStatusForAndroidResult(result); + if (status == Qt::PermissionStatus::Denied) + return status; + } + return Qt::PermissionStatus::Granted; +} + namespace QPermissions::Private { Qt::PermissionStatus checkPermission(const QPermission &permission) @@ -132,8 +144,12 @@ namespace QPermissions::Private if (nativePermissionList.isEmpty()) return Qt::PermissionStatus::Granted; - const auto result = QtAndroidPrivate::checkPermission(nativePermissionList.first()).result(); - const auto status = permissionStatusForAndroidResult(result); + QList androidResults; + androidResults.reserve(nativePermissionList.size()); + for (const auto &nativePermission : nativePermissionList) + androidResults.push_back(QtAndroidPrivate::checkPermission(nativePermission).result()); + + const auto status = getCombinedStatus(androidResults); const auto it = g_permissionStatusHash->constFind(permission.type().id()); const bool foundStatus = (it != g_permissionStatusHash->constEnd()); const bool itUndetermined = foundStatus && (*it) == Qt::PermissionStatus::Undetermined; @@ -153,8 +169,9 @@ namespace QPermissions::Private QtAndroidPrivate::requestPermissions(nativePermissionList).then(qApp, [callback, permission](QFuture future) { - const auto result = future.isValid() ? future.result() : QtAndroidPrivate::Denied; - const auto status = permissionStatusForAndroidResult(result); + const auto androidResults = future.isValid() ? future.results() + : QList{QtAndroidPrivate::Denied}; + const auto status = getCombinedStatus(androidResults); g_permissionStatusHash->insert(permission.type().id(), status); callback(status); }