Warning: That file was not part of the compilation database. It may have many parsing errors.

1/***************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtBluetooth module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include <QtCore/QLoggingCategory>
41#include "qbluetoothserver.h"
42#include "qbluetoothserver_p.h"
43#include "qbluetoothsocket.h"
44#include "qbluetoothsocket_android_p.h"
45#include "qbluetoothlocaldevice.h"
46#include "android/serveracceptancethread_p.h"
47
48#include <QCoreApplication>
49
50QT_BEGIN_NAMESPACE
51
52Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
53
54QHash<QBluetoothServerPrivate*, int> __fakeServerPorts;
55
56QBluetoothServerPrivate::QBluetoothServerPrivate(QBluetoothServiceInfo::Protocol sType)
57 : socket(0),maxPendingConnections(1), securityFlags(QBluetooth::NoSecurity), serverType(sType),
58 m_lastError(QBluetoothServer::NoError)
59{
60 thread = new ServerAcceptanceThread();
61 thread->setMaxPendingConnections(maxPendingConnections);
62}
63
64QBluetoothServerPrivate::~QBluetoothServerPrivate()
65{
66 Q_Q(QBluetoothServer);
67 if (isListening())
68 q->close();
69
70 __fakeServerPorts.remove(this);
71
72 thread->deleteLater();
73 thread = nullptr;
74}
75
76bool QBluetoothServerPrivate::initiateActiveListening(
77 const QBluetoothUuid& uuid, const QString &serviceName)
78{
79 qCDebug(QT_BT_ANDROID) << "Initiate active listening" << uuid.toString() << serviceName;
80
81 if (uuid.isNull() || serviceName.isEmpty())
82 return false;
83
84 //no change of SP profile details -> do nothing
85 if (uuid == m_uuid && serviceName == m_serviceName && thread->isRunning())
86 return true;
87
88 m_uuid = uuid;
89 m_serviceName = serviceName;
90 thread->setServiceDetails(m_uuid, m_serviceName, securityFlags);
91
92 thread->run();
93 if (!thread->isRunning())
94 return false;
95
96 return true;
97}
98
99bool QBluetoothServerPrivate::deactivateActiveListening()
100{
101 if (isListening()) {
102 //suppress last error signal due to intended closure
103 thread->disconnect();
104 thread->stop();
105 }
106 return true;
107}
108
109bool QBluetoothServerPrivate::isListening() const
110{
111 return __fakeServerPorts.contains(const_cast<QBluetoothServerPrivate *>(this));
112}
113
114void QBluetoothServer::close()
115{
116 Q_D(QBluetoothServer);
117
118 __fakeServerPorts.remove(d);
119 if (d->thread->isRunning()) {
120 //suppress last error signal due to intended closure
121 d->thread->disconnect();
122 d->thread->stop();
123 }
124}
125
126bool QBluetoothServer::listen(const QBluetoothAddress &localAdapter, quint16 port)
127{
128 Q_D(QBluetoothServer);
129 if (serverType() != QBluetoothServiceInfo::RfcommProtocol) {
130 d->m_lastError = UnsupportedProtocolError;
131 emit error(d->m_lastError);
132 return false;
133 }
134
135 const QList<QBluetoothHostInfo> localDevices = QBluetoothLocalDevice::allDevices();
136 if (!localDevices.count()) {
137 qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth";
138 d->m_lastError = QBluetoothServer::UnknownError;
139 emit error(d->m_lastError);
140 return false; //no Bluetooth device
141 }
142
143 if (!localAdapter.isNull()) {
144 bool found = false;
145 for (const QBluetoothHostInfo &hostInfo : localDevices) {
146 if (hostInfo.address() == localAdapter) {
147 found = true;
148 break;
149 }
150 }
151
152 if (!found) {
153 qCWarning(QT_BT_ANDROID) << localAdapter.toString() << "is not a valid local Bt adapter";
154 return false;
155 }
156 }
157
158 if (d->isListening())
159 return false;
160
161 //check Bluetooth is available and online
162 QAndroidJniObject btAdapter = QAndroidJniObject::callStaticObjectMethod(
163 "android/bluetooth/BluetoothAdapter",
164 "getDefaultAdapter",
165 "()Landroid/bluetooth/BluetoothAdapter;");
166 if (!btAdapter.isValid()) {
167 qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth";
168 d->m_lastError = QBluetoothServer::UnknownError;
169 emit error(d->m_lastError);
170 return false;
171 }
172
173 const int state = btAdapter.callMethod<jint>("getState");
174 if (state != 12 ) { //BluetoothAdapter.STATE_ON
175 d->m_lastError = QBluetoothServer::PoweredOffError;
176 emit error(d->m_lastError);
177 qCWarning(QT_BT_ANDROID) << "Bluetooth device is powered off";
178 return false;
179 }
180
181 //We can not register an actual Rfcomm port, because the platform does not allow it
182 //but we need a way to associate a server with a service
183 if (port == 0) { //Try to assign a non taken port id
184 for (int i=1; ; i++){
185 if (__fakeServerPorts.key(i) == 0) {
186 port = i;
187 break;
188 }
189 }
190 }
191
192 if (__fakeServerPorts.key(port) == 0) {
193 __fakeServerPorts[d] = port;
194
195 qCDebug(QT_BT_ANDROID) << "Port" << port << "registered";
196 } else {
197 qCWarning(QT_BT_ANDROID) << "server with port" << port << "already registered or port invalid";
198 d->m_lastError = ServiceAlreadyRegisteredError;
199 emit error(d->m_lastError);
200 return false;
201 }
202
203 connect(d->thread, SIGNAL(newConnection()),
204 this, SIGNAL(newConnection()));
205 connect(d->thread, SIGNAL(error(QBluetoothServer::Error)),
206 this, SIGNAL(error(QBluetoothServer::Error)), Qt::QueuedConnection);
207
208 return true;
209}
210
211void QBluetoothServer::setMaxPendingConnections(int numConnections)
212{
213 Q_D(QBluetoothServer);
214 d->maxPendingConnections = numConnections;
215 d->thread->setMaxPendingConnections(numConnections);
216}
217
218QBluetoothAddress QBluetoothServer::serverAddress() const
219{
220 //Android only supports one local adapter
221 QList<QBluetoothHostInfo> hosts = QBluetoothLocalDevice::allDevices();
222 Q_ASSERT(hosts.count() <= 1);
223
224 if (hosts.isEmpty())
225 return QBluetoothAddress();
226 else
227 return hosts.at(0).address();
228}
229
230quint16 QBluetoothServer::serverPort() const
231{
232 //We return the fake port
233 Q_D(const QBluetoothServer);
234 return __fakeServerPorts.value((QBluetoothServerPrivate*)d, 0);
235}
236
237bool QBluetoothServer::hasPendingConnections() const
238{
239 Q_D(const QBluetoothServer);
240
241 return d->thread->hasPendingConnections();
242}
243
244QBluetoothSocket *QBluetoothServer::nextPendingConnection()
245{
246 Q_D(const QBluetoothServer);
247
248 QAndroidJniObject socket = d->thread->nextPendingConnection();
249 if (!socket.isValid())
250 return 0;
251
252
253 QBluetoothSocket *newSocket = new QBluetoothSocket();
254 bool success = newSocket->d_ptr->setSocketDescriptor(socket, d->serverType);
255 if (!success) {
256 delete newSocket;
257 newSocket = nullptr;
258 }
259
260 return newSocket;
261}
262
263void QBluetoothServer::setSecurityFlags(QBluetooth::SecurityFlags security)
264{
265 Q_D(QBluetoothServer);
266 d->securityFlags = security;
267}
268
269QBluetooth::SecurityFlags QBluetoothServer::securityFlags() const
270{
271 Q_D(const QBluetoothServer);
272 return d->securityFlags;
273}
274
275QT_END_NAMESPACE
276
277

Warning: That file was not part of the compilation database. It may have many parsing errors.