summaryrefslogtreecommitdiffstats
path: root/src/plugins/networkinformation/android/qandroidnetworkinformationbackend.cpp
blob: 44e4d447d21a4c35641d4b3db4f3745206ad750a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#include <QtNetwork/private/qnetworkinformation_p.h>

#include "wrapper/androidconnectivitymanager.h"

#include <QtCore/qglobal.h>

QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcNetInfoAndroid)
Q_LOGGING_CATEGORY(lcNetInfoAndroid, "qt.network.info.android");

static QString backendName() {
    return QString::fromUtf16(QNetworkInformationBackend::PluginNames
                                      [QNetworkInformationBackend::PluginNamesAndroidIndex]);
}

class QAndroidNetworkInformationBackend : public QNetworkInformationBackend
{
    Q_OBJECT
public:
    QAndroidNetworkInformationBackend();
    ~QAndroidNetworkInformationBackend() { m_valid = false; }

    QString name() const override { return backendName(); }
    QNetworkInformation::Features featuresSupported() const override
    {
        return featuresSupportedStatic();
    }

    static QNetworkInformation::Features featuresSupportedStatic()
    {
        using Feature = QNetworkInformation::Feature;
        return QNetworkInformation::Features(Feature::Reachability | Feature::CaptivePortal
                                             | Feature::TransportMedium);
    }

    bool isValid() { return m_valid; }

private:
    Q_DISABLE_COPY_MOVE(QAndroidNetworkInformationBackend);

    void updateConnectivity(AndroidConnectivityManager::AndroidConnectivity connectivity);
    void updateTransportMedium(AndroidConnectivityManager::AndroidTransport transport);

    bool m_valid = false;
};

class QAndroidNetworkInformationBackendFactory : public QNetworkInformationBackendFactory
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID QNetworkInformationBackendFactory_iid)
    Q_INTERFACES(QNetworkInformationBackendFactory)
public:
    QAndroidNetworkInformationBackendFactory() = default;
    ~QAndroidNetworkInformationBackendFactory() = default;
    QString name() const override { return backendName(); }
    QNetworkInformation::Features featuresSupported() const override
    {
        return QAndroidNetworkInformationBackend::featuresSupportedStatic();
    }

    QNetworkInformationBackend *
    create(QNetworkInformation::Features requiredFeatures) const override
    {
        if ((requiredFeatures & featuresSupported()) != requiredFeatures)
            return nullptr;
        auto backend = new QAndroidNetworkInformationBackend();
        if (!backend->isValid())
            delete std::exchange(backend, nullptr);
        return backend;
    }

private:
    Q_DISABLE_COPY_MOVE(QAndroidNetworkInformationBackendFactory);
};

QAndroidNetworkInformationBackend::QAndroidNetworkInformationBackend()
{
    auto conman = AndroidConnectivityManager::getInstance();
    if (!conman)
        return;
    m_valid = true;
    setReachability(QNetworkInformation::Reachability::Unknown);
    connect(conman, &AndroidConnectivityManager::connectivityChanged, this,
            &QAndroidNetworkInformationBackend::updateConnectivity);

    connect(conman, &AndroidConnectivityManager::captivePortalChanged, this,
            &QAndroidNetworkInformationBackend::setBehindCaptivePortal);

    connect(conman, &AndroidConnectivityManager::transportMediumChanged, this,
            &QAndroidNetworkInformationBackend::updateTransportMedium);

    connect(conman, &AndroidConnectivityManager::meteredChanged, this,
            &QAndroidNetworkInformationBackend::setMetered);
}

void QAndroidNetworkInformationBackend::updateConnectivity(
        AndroidConnectivityManager::AndroidConnectivity connectivity)
{
    using AndroidConnectivity = AndroidConnectivityManager::AndroidConnectivity;
    static const auto mapState = [](AndroidConnectivity state) {
        switch (state) {
        case AndroidConnectivity::Connected:
            return QNetworkInformation::Reachability::Online;
        case AndroidConnectivity::Disconnected:
            return QNetworkInformation::Reachability::Disconnected;
        case AndroidConnectivity::Unknown:
        default:
            return QNetworkInformation::Reachability::Unknown;
        }
    };

    setReachability(mapState(connectivity));
}

void QAndroidNetworkInformationBackend::updateTransportMedium(
        AndroidConnectivityManager::AndroidTransport transport)
{
    using AndroidTransport = AndroidConnectivityManager::AndroidTransport;
    using TransportMedium = QNetworkInformation::TransportMedium;
    static const auto mapTransport = [](AndroidTransport state) -> TransportMedium {
        switch (state) {
        case AndroidTransport::Cellular:
            return TransportMedium::Cellular;
        case AndroidTransport::WiFi:
            return TransportMedium::WiFi;
        case AndroidTransport::Bluetooth:
            return TransportMedium::Bluetooth;
        case AndroidTransport::Ethernet:
            return TransportMedium::Ethernet;
        // These are not covered yet (but may be in the future)
        case AndroidTransport::Usb:
        case AndroidTransport::LoWPAN:
        case AndroidTransport::WiFiAware:
        case AndroidTransport::Unknown:
            return TransportMedium::Unknown;
        }
    };

    setTransportMedium(mapTransport(transport));
}

QT_END_NAMESPACE

#include "qandroidnetworkinformationbackend.moc"