QBluetoothPermission: introduce fine-grained permissions
This commit introduces fine-grained Bluetooth permissions control to the QBluetoothPermission class. For now the fine-tuning of the permissions is only supported on Android. On Apple enabling any of the permissions is equivalent to requesting full Bluetooth control. Task-number: QTBUG-109964 Change-Id: Ie7ac6577cf6a21419b73b33f8cf7e87bc3f8cf43 Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
parent
346dcc696b
commit
0198a74b72
@ -387,9 +387,60 @@ QT_PERMISSION_IMPL_COMMON(QMicrophonePermission)
|
||||
*/
|
||||
|
||||
QT_PERMISSION_IMPL_COMMON(QBluetoothPermission)
|
||||
: u{} // stateless, atm
|
||||
: u{ShortData{CommunicationMode::Default, {}}}
|
||||
{}
|
||||
|
||||
/*!
|
||||
\enum QBluetoothPermission::CommunicationMode
|
||||
\since 6.6
|
||||
|
||||
This enum is used to control the allowed Bluetooth communication modes.
|
||||
|
||||
\value Access Allow this device to access other Bluetooth devices. This
|
||||
includes scanning for nearby devices and connecting to them.
|
||||
\value Advertise Allow other Bluetooth devices to discover this device.
|
||||
\value Default This configuration is used by default.
|
||||
|
||||
\note The fine-grained permissions are currently supported only on
|
||||
Android 12 and newer. On older Android versions, as well as on Apple
|
||||
operating systems, any mode results in full Bluetooth access.
|
||||
|
||||
\note For now the \c Access mode on Android also requests the
|
||||
\l {QLocationPermission::Precise}{precise location} permission.
|
||||
This permission coupling may change in the future.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\since 6.6
|
||||
|
||||
Sets the allowed Bluetooth communication modes to \a modes.
|
||||
|
||||
\note A default-constructed instance of \l {QBluetoothPermission::}
|
||||
{CommunicationModes} has no sense, so an attempt to set such a mode will
|
||||
raise a \c {qWarning()} and fall back to using the
|
||||
\l {QBluetoothPermission::}{Default} mode.
|
||||
*/
|
||||
void QBluetoothPermission::setCommunicationModes(CommunicationModes modes)
|
||||
{
|
||||
if (modes == CommunicationModes{}) {
|
||||
qCWarning(lcPermissions, "QBluetoothPermission: trying to set an invalid empty mode. "
|
||||
"Falling back to CommunicationMode::Default.");
|
||||
u.data.mode = Default;
|
||||
} else {
|
||||
u.data.mode = static_cast<CommunicationMode>(modes.toInt());
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.6
|
||||
|
||||
Returns the allowed Bluetooth communication modes.
|
||||
*/
|
||||
QBluetoothPermission::CommunicationModes QBluetoothPermission::communicationModes() const
|
||||
{
|
||||
return u.data.mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QLocationPermission
|
||||
\brief Access the user's location.
|
||||
|
@ -173,6 +173,32 @@ private:
|
||||
};
|
||||
Q_DECLARE_SHARED(QContactsPermission)
|
||||
|
||||
class QBluetoothPermissionPrivate;
|
||||
class QBluetoothPermission
|
||||
{
|
||||
Q_GADGET_EXPORT(Q_CORE_EXPORT)
|
||||
public:
|
||||
enum CommunicationMode : quint8 {
|
||||
Access = 0x01,
|
||||
Advertise = 0x02,
|
||||
Default = Access | Advertise,
|
||||
};
|
||||
Q_DECLARE_FLAGS(CommunicationModes, CommunicationMode)
|
||||
Q_FLAG(CommunicationModes)
|
||||
|
||||
Q_CORE_EXPORT void setCommunicationModes(CommunicationModes modes);
|
||||
Q_CORE_EXPORT CommunicationModes communicationModes() const;
|
||||
|
||||
private:
|
||||
struct ShortData {
|
||||
CommunicationMode mode;
|
||||
char reserved[sizeof(void*) - sizeof(mode)];
|
||||
};
|
||||
QT_PERMISSION(QBluetoothPermission)
|
||||
};
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QBluetoothPermission::CommunicationModes)
|
||||
Q_DECLARE_SHARED(QBluetoothPermission)
|
||||
|
||||
#define Q_DECLARE_MINIMAL_PERMISSION(ClassName) \
|
||||
class ClassName##Private; \
|
||||
class ClassName \
|
||||
@ -184,7 +210,6 @@ Q_DECLARE_SHARED(QContactsPermission)
|
||||
|
||||
Q_DECLARE_MINIMAL_PERMISSION(QCameraPermission)
|
||||
Q_DECLARE_MINIMAL_PERMISSION(QMicrophonePermission)
|
||||
Q_DECLARE_MINIMAL_PERMISSION(QBluetoothPermission)
|
||||
|
||||
#undef QT_PERMISSION
|
||||
#undef Q_DECLARE_MINIMAL_PERMISSION
|
||||
|
@ -49,7 +49,7 @@ static QStringList nativeLocationPermission(const QLocationPermission &permissio
|
||||
return nativeLocationPermissionList;
|
||||
}
|
||||
|
||||
static QStringList nativeBluetoothPermission()
|
||||
static QStringList nativeBluetoothPermission(const QBluetoothPermission &permission)
|
||||
{
|
||||
// See https://developer.android.com/guide/topics/connectivity/bluetooth/permissions
|
||||
// for the details.
|
||||
@ -64,10 +64,17 @@ static QStringList nativeBluetoothPermission()
|
||||
// strictly necessary for API Level >= 31. See QTBUG-112164.
|
||||
static QString fineLocation = u"android.permission.ACCESS_FINE_LOCATION"_s;
|
||||
|
||||
if (QtAndroidPrivate::androidSdkVersion() < 31)
|
||||
if (QtAndroidPrivate::androidSdkVersion() < 31) {
|
||||
return {bluetoothGeneral, fineLocation};
|
||||
else
|
||||
return {bluetoothScan, bluetoothAdvertise, bluetoothConnect, fineLocation};
|
||||
} else {
|
||||
const auto modes = permission.communicationModes();
|
||||
QStringList permissionList;
|
||||
if (modes & QBluetoothPermission::Advertise)
|
||||
permissionList << bluetoothAdvertise;
|
||||
if (modes & QBluetoothPermission::Access)
|
||||
permissionList << bluetoothScan << bluetoothConnect << fineLocation;
|
||||
return permissionList;
|
||||
}
|
||||
}
|
||||
|
||||
static QStringList nativeStringsFromPermission(const QPermission &permission)
|
||||
@ -80,7 +87,7 @@ static QStringList nativeStringsFromPermission(const QPermission &permission)
|
||||
} else if (id == qMetaTypeId<QMicrophonePermission>()) {
|
||||
return { u"android.permission.RECORD_AUDIO"_s };
|
||||
} else if (id == qMetaTypeId<QBluetoothPermission>()) {
|
||||
return nativeBluetoothPermission();
|
||||
return nativeBluetoothPermission(*permission.value<QBluetoothPermission>());
|
||||
} else if (id == qMetaTypeId<QContactsPermission>()) {
|
||||
const auto readContactsString = u"android.permission.READ_CONTACTS"_s;
|
||||
switch (permission.value<QContactsPermission>()->accessMode()) {
|
||||
|
Loading…
Reference in New Issue
Block a user