Merge lp:~unity-api-team/indicator-network/data_usage_indication into lp:indicator-network

Proposed by Antti Kaijanmäki
Status: Merged
Approved by: Marcus Tomlinson
Approved revision: 647
Merged at revision: 640
Proposed branch: lp:~unity-api-team/indicator-network/data_usage_indication
Merge into: lp:indicator-network
Diff against target: 1857 lines (+1001/-84)
35 files modified
data/com.canonical.indicator.network.gschema.xml (+5/-12)
data/nm-device-statistics.xml (+12/-0)
src/CMakeLists.txt (+6/-2)
src/connectivity-api/connectivity-qt/CMakeLists.txt (+1/-10)
src/connectivity-api/connectivity-qt/connectivityqt/connectivity.cpp (+8/-8)
src/connectivity-api/connectivity-qt/connectivityqt/internal/modems-list-model-parameters.h (+2/-3)
src/connectivity-api/connectivity-qt/connectivityqt/internal/sims-list-model-parameters.h (+2/-2)
src/connectivity-api/connectivity-qt/connectivityqt/internal/vpn-connection-list-model-parameters.h (+2/-2)
src/connectivity-api/connectivity-qt/connectivityqt/modem.cpp (+6/-5)
src/connectivity-api/connectivity-qt/connectivityqt/modems-list-model.cpp (+2/-2)
src/connectivity-api/connectivity-qt/connectivityqt/openvpn-connection.cpp (+4/-4)
src/connectivity-api/connectivity-qt/connectivityqt/pptp-connection.cpp (+4/-4)
src/connectivity-api/connectivity-qt/connectivityqt/sim.cpp (+4/-4)
src/connectivity-api/connectivity-qt/connectivityqt/sims-list-model.cpp (+2/-2)
src/connectivity-api/connectivity-qt/connectivityqt/vpn-connection.cpp (+4/-4)
src/connectivity-api/connectivity-qt/connectivityqt/vpn-connections-list-model.cpp (+2/-2)
src/indicator/CMakeLists.txt (+1/-4)
src/indicator/nmofono/manager-impl.cpp (+65/-2)
src/indicator/nmofono/manager-impl.h (+4/-0)
src/indicator/nmofono/manager.h (+11/-0)
src/indicator/nmofono/nm-device-statistics-monitor.cpp (+363/-0)
src/indicator/nmofono/nm-device-statistics-monitor.h (+62/-0)
src/indicator/nmofono/wifi/wifi-link-impl.cpp (+2/-1)
src/indicator/nmofono/wwan/modem.cpp (+15/-0)
src/indicator/nmofono/wwan/modem.h (+3/-0)
src/indicator/root-state.cpp (+18/-0)
src/qdbus-stubs/CMakeLists.txt (+14/-0)
src/util/CMakeLists.txt (+5/-2)
src/util/dbus-property-cache.cpp (+2/-5)
src/util/dbus-property-cache.h (+1/-4)
tests/data/networkmanager.py (+71/-0)
tests/integration/CMakeLists.txt (+21/-0)
tests/integration/indicator-network-test-base.cpp (+105/-0)
tests/integration/indicator-network-test-base.h (+15/-0)
tests/integration/test-indicator.cpp (+157/-0)
To merge this branch: bzr merge lp:~unity-api-team/indicator-network/data_usage_indication
Reviewer Review Type Date Requested Status
Marcus Tomlinson (community) Approve
unity-api-1-bot continuous-integration Approve
Review via email: mp+309640@code.launchpad.net

Commit message

Show network data usage indication.

This feature is disabled by default, but can be enabled through gsettings/dconf.

This is a CTA Level 3 requirement.

Follows WiFi and modem data usage utilizing the new org.freedesktop.NetworkManager.Device.Statistics interface.

com.canonical.indicator.network.gschema.xml:
 - remove unused keys
 - add data-usage-indication key

Refactor connectivityqt::internal::DBusPropertyCache to util::DBusPropertyCache.

Under testing uses GKeyfileSettingsBackend to enable the feature.

Gets information from com.canonical.Unity.Screen (repowerd) and stops battery consuming updates when the screen if off.

Description of the change

.

To post a comment you must log in.
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:644
https://jenkins.canonical.com/unity-api-1/job/lp-indicator-network-ci/30/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/916/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/923
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/726
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/726/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/726
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/726/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/726/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/726
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/726/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/726
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/726/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/726
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/726/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/726
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/726/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/726
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/726/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/726/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-indicator-network-ci/30/rebuild

review: Needs Fixing (continuous-integration)
645. By Antti Kaijanmäki

remove debug from debian/rules

646. By Antti Kaijanmäki

remove unused device_udi

647. By Antti Kaijanmäki

remove useless comment

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:645
https://jenkins.canonical.com/unity-api-1/job/lp-indicator-network-ci/31/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/917/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/924
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/727/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/727/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/727
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/727/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/727
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/727/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/727
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/727/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/727
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/727/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/727
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/727/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/727
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/727/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/727
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/727/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-indicator-network-ci/31/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:647
https://jenkins.canonical.com/unity-api-1/job/lp-indicator-network-ci/32/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/918
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/925
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/728
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/728/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/728
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/728/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/728
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/728/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/728
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/728/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/728
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/728/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/728
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/728/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/728
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/728/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/728
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/728/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/728
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/728/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-indicator-network-ci/32/rebuild

review: Approve (continuous-integration)
Revision history for this message
Marcus Tomlinson (marcustomlinson) wrote :

Apart from having to run the DataUsageIndication_enabled test outside of CI at the moment (which we really should fix: Bug #1638024), looks good.

Also, tested on the unity8 desktop session and looks to be working. Nice.

review: Approve
Revision history for this message
Marcus Tomlinson (marcustomlinson) wrote :

Well... To be clear, what I was referring to by "looks good" is the diff and the outcome that was intended by it.

What doesn't look good is the icon popping up and disappearing between indicators. I think this is fine for a first iteration on this feature, but some serious design considerations need to be made. E.g. (I realise that we're currently limited to displaying icons only within our icon group, but) clearly what would look better is for the activity icon to appear in the left-most position as to avoid shifting indicators around each time it's shown.

Anyway, point is, I anticipate that there's still be some work to be done here, but as for building an MVP, looks good :)

Thanks Antti!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/com.canonical.indicator.network.gschema.xml'
2--- data/com.canonical.indicator.network.gschema.xml 2013-09-16 04:17:20 +0000
3+++ data/com.canonical.indicator.network.gschema.xml 2016-10-30 18:45:06 +0000
4@@ -1,17 +1,10 @@
5 <schemalist>
6 <schema id="com.canonical.indicator.network" path="/com/canonical/indicator/network/" gettext-domain="indicator-network">
7- <key name="prompt-on-new-wifi-ap" type="b">
8- <default>true</default>
9- <summary>Whether we should show a dialog when a possible Wi-Fi network appears</summary>
10- <description>
11- Configures the behavior for discovery of the new networks and whether they result in a dialog being shown which allows for selection of the network.
12- </description>
13- </key>
14- <key name="auto-join-previous" type="b">
15- <default>true</default>
16- <summary>Whether to join networks we've seen before automatically.</summary>
17- <description>
18- This gets set for the Wi-Fi device in Network Manager whether it autoconnects or not.
19+ <key name="data-usage-indication" type="b">
20+ <default>false</default>
21+ <summary>Show indication that data is being sent or received.</summary>
22+ <description>
23+ Show icon when device is sending or receiving data.
24 </description>
25 </key>
26 </schema>
27
28=== added file 'data/nm-device-statistics.xml'
29--- data/nm-device-statistics.xml 1970-01-01 00:00:00 +0000
30+++ data/nm-device-statistics.xml 2016-10-30 18:45:06 +0000
31@@ -0,0 +1,12 @@
32+<?xml version="1.0" encoding="UTF-8" ?>
33+<node>
34+ <interface name="org.freedesktop.NetworkManager.Device.Statistics">
35+ <signal name="PropertiesChanged">
36+ <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
37+ <arg type="a{sv}" name="properties"/>
38+ </signal>
39+ <property type="u" name="RefreshRateMs" access="readwrite"/>
40+ <property type="t" name="TxBytes" access="read"/>
41+ <property type="t" name="RxBytes" access="read"/>
42+ </interface>
43+</node>
44
45=== modified file 'src/CMakeLists.txt'
46--- src/CMakeLists.txt 2016-08-25 14:57:03 +0000
47+++ src/CMakeLists.txt 2016-10-30 18:45:06 +0000
48@@ -1,11 +1,15 @@
49+include_directories("${CMAKE_SOURCE_DIR}/src/")
50+include_directories("${CMAKE_SOURCE_DIR}/src/qdbus-stubs")
51+include_directories("${CMAKE_BINARY_DIR}/src/qdbus-stubs")
52+
53+add_subdirectory(qdbus-stubs)
54+add_subdirectory(util)
55
56 add_subdirectory(connectivity-api)
57
58 add_subdirectory(agent)
59 add_subdirectory(indicator)
60 add_subdirectory(menumodel-cpp)
61-add_subdirectory(qdbus-stubs)
62 add_subdirectory(qpowerd)
63 add_subdirectory(notify-cpp)
64 add_subdirectory(url-dispatcher-cpp)
65-add_subdirectory(util)
66
67=== modified file 'src/connectivity-api/connectivity-qt/CMakeLists.txt'
68--- src/connectivity-api/connectivity-qt/CMakeLists.txt 2016-05-19 09:06:42 +0000
69+++ src/connectivity-api/connectivity-qt/CMakeLists.txt 2016-10-30 18:45:06 +0000
70@@ -16,11 +16,8 @@
71
72 set(SYMBOL_MAP "${DATA_DIR}/connectivity-qt.map")
73
74-include_directories("${CMAKE_SOURCE_DIR}/src/qdbus-stubs")
75-
76 set(
77 CONNECTIVITY_QT_SRC
78- connectivityqt/internal/dbus-property-cache.cpp
79 connectivityqt/connectivity.cpp
80 connectivityqt/modem.cpp
81 connectivityqt/modems-list-model.cpp
82@@ -34,7 +31,6 @@
83 )
84
85 set_source_files_properties(
86- "${DATA_DIR}/org.freedesktop.DBus.Properties.xml"
87 "${DATA_DIR}/com.ubuntu.connectivity1.NetworkingStatus.xml"
88 "${DATA_DIR}/com.ubuntu.connectivity1.Private.xml"
89 "${DATA_DIR}/com.ubuntu.connectivity1.Modem.xml"
90@@ -88,12 +84,6 @@
91 PptpConnectionInterface
92 )
93
94-qt5_add_dbus_interface(
95- CONNECTIVITY_QT_SRC
96- "${DATA_DIR}/org.freedesktop.DBus.Properties.xml"
97- PropertiesInterface
98-)
99-
100 add_library(
101 ${CONNECTIVITY_QT_LIB_TARGET}
102 SHARED
103@@ -110,6 +100,7 @@
104 target_link_libraries(
105 ${CONNECTIVITY_QT_LIB_TARGET}
106 qdbus-stubs
107+ util
108 )
109
110 set(SO_VERSION ${CONNECTIVITY_QT_VERSION_MAJOR})
111
112=== modified file 'src/connectivity-api/connectivity-qt/connectivityqt/connectivity.cpp'
113--- src/connectivity-api/connectivity-qt/connectivityqt/connectivity.cpp 2016-06-16 09:16:45 +0000
114+++ src/connectivity-api/connectivity-qt/connectivityqt/connectivity.cpp 2016-10-30 18:45:06 +0000
115@@ -51,9 +51,9 @@
116
117 QDBusConnection m_sessionConnection;
118
119- internal::DBusPropertyCache::SPtr m_propertyCache;
120+ util::DBusPropertyCache::SPtr m_propertyCache;
121
122- internal::DBusPropertyCache::SPtr m_writePropertyCache;
123+ util::DBusPropertyCache::SPtr m_writePropertyCache;
124
125 shared_ptr<ComUbuntuConnectivity1NetworkingStatusInterface> m_readInterface;
126
127@@ -235,24 +235,24 @@
128 DBusTypes::DBUS_NAME, DBusTypes::PRIVATE_PATH,
129 d->m_sessionConnection);
130
131- d->m_writePropertyCache = make_shared<internal::DBusPropertyCache>(
132+ d->m_writePropertyCache = make_shared<util::DBusPropertyCache>(
133 DBusTypes::DBUS_NAME, DBusTypes::PRIVATE_INTERFACE,
134 DBusTypes::PRIVATE_PATH, sessionConnection);
135 connect(d->m_writePropertyCache.get(),
136- &internal::DBusPropertyCache::propertyChanged, d.get(),
137+ &util::DBusPropertyCache::propertyChanged, d.get(),
138 &Priv::propertyChanged);
139 connect(d->m_writePropertyCache.get(),
140- &internal::DBusPropertyCache::initialized, d.get(),
141+ &util::DBusPropertyCache::initialized, d.get(),
142 &Connectivity::Priv::interfaceInitialized);
143
144- d->m_propertyCache = make_shared<internal::DBusPropertyCache>(
145+ d->m_propertyCache = make_shared<util::DBusPropertyCache>(
146 DBusTypes::DBUS_NAME, DBusTypes::SERVICE_INTERFACE,
147 DBusTypes::SERVICE_PATH, sessionConnection);
148 connect(d->m_propertyCache.get(),
149- &internal::DBusPropertyCache::propertyChanged, d.get(),
150+ &util::DBusPropertyCache::propertyChanged, d.get(),
151 &Priv::propertyChanged);
152 connect(d->m_propertyCache.get(),
153- &internal::DBusPropertyCache::initialized, d.get(),
154+ &util::DBusPropertyCache::initialized, d.get(),
155 &Connectivity::Priv::interfaceInitialized);
156
157
158
159=== modified file 'src/connectivity-api/connectivity-qt/connectivityqt/internal/modems-list-model-parameters.h'
160--- src/connectivity-api/connectivity-qt/connectivityqt/internal/modems-list-model-parameters.h 2016-05-26 10:57:25 +0000
161+++ src/connectivity-api/connectivity-qt/connectivityqt/internal/modems-list-model-parameters.h 2016-10-30 18:45:06 +0000
162@@ -19,8 +19,7 @@
163
164 #pragma once
165
166-#include <connectivityqt/internal/dbus-property-cache.h>
167-
168+#include <util/dbus-property-cache.h>
169 #include <NetworkingStatusPrivateInterface.h>
170
171 #include <connectivityqt/sims-list-model.h>
172@@ -37,7 +36,7 @@
173 {
174 std::function<void(QObject*)> objectOwner;
175 std::shared_ptr<ComUbuntuConnectivity1PrivateInterface> writeInterface;
176- std::shared_ptr<internal::DBusPropertyCache> propertyCache;
177+ std::shared_ptr<util::DBusPropertyCache> propertyCache;
178 SimsListModel::SPtr sims;
179 };
180
181
182=== modified file 'src/connectivity-api/connectivity-qt/connectivityqt/internal/sims-list-model-parameters.h'
183--- src/connectivity-api/connectivity-qt/connectivityqt/internal/sims-list-model-parameters.h 2016-05-26 10:57:25 +0000
184+++ src/connectivity-api/connectivity-qt/connectivityqt/internal/sims-list-model-parameters.h 2016-10-30 18:45:06 +0000
185@@ -19,7 +19,7 @@
186
187 #pragma once
188
189-#include <connectivityqt/internal/dbus-property-cache.h>
190+#include <util/dbus-property-cache.h>
191
192 #include <NetworkingStatusPrivateInterface.h>
193
194@@ -35,7 +35,7 @@
195 {
196 std::function<void(QObject*)> objectOwner;
197 std::shared_ptr<ComUbuntuConnectivity1PrivateInterface> writeInterface;
198- std::shared_ptr<internal::DBusPropertyCache> propertyCache;
199+ std::shared_ptr<util::DBusPropertyCache> propertyCache;
200 };
201
202 }
203
204=== modified file 'src/connectivity-api/connectivity-qt/connectivityqt/internal/vpn-connection-list-model-parameters.h'
205--- src/connectivity-api/connectivity-qt/connectivityqt/internal/vpn-connection-list-model-parameters.h 2015-12-04 13:18:04 +0000
206+++ src/connectivity-api/connectivity-qt/connectivityqt/internal/vpn-connection-list-model-parameters.h 2016-10-30 18:45:06 +0000
207@@ -19,7 +19,7 @@
208
209 #pragma once
210
211-#include <connectivityqt/internal/dbus-property-cache.h>
212+#include <util/dbus-property-cache.h>
213
214 #include <NetworkingStatusPrivateInterface.h>
215
216@@ -37,7 +37,7 @@
217
218 std::shared_ptr<ComUbuntuConnectivity1PrivateInterface> writeInterface;
219
220- std::shared_ptr<internal::DBusPropertyCache> propertyCache;
221+ std::shared_ptr<util::DBusPropertyCache> propertyCache;
222 };
223
224 }
225
226=== modified file 'src/connectivity-api/connectivity-qt/connectivityqt/modem.cpp'
227--- src/connectivity-api/connectivity-qt/connectivityqt/modem.cpp 2016-06-17 11:55:15 +0000
228+++ src/connectivity-api/connectivity-qt/connectivityqt/modem.cpp 2016-10-30 18:45:06 +0000
229@@ -17,9 +17,9 @@
230 * Antti Kaijanmäki <antti.kaijanmaki@canonical.com>
231 */
232
233-#include <connectivityqt/internal/dbus-property-cache.h>
234+#include <util/dbus-property-cache.h>
235 #include <connectivityqt/modem.h>
236-#include <dbus-types.h>
237+#include <qdbus-stubs/dbus-types.h>
238
239 #include <ModemInterface.h>
240
241@@ -41,6 +41,7 @@
242 public Q_SLOTS:
243 void propertyChanged(const QString& name, const QVariant& value)
244 {
245+ Q_UNUSED(value);
246 if (name == "Sim")
247 {
248 simsUpdated();
249@@ -72,7 +73,7 @@
250
251 unique_ptr<ComUbuntuConnectivity1ModemInterface> m_modemInterface;
252
253- internal::DBusPropertyCache::UPtr m_propertyCache;
254+ util::DBusPropertyCache::UPtr m_propertyCache;
255 };
256
257 Modem::Modem(const QDBusObjectPath& path,
258@@ -87,13 +88,13 @@
259 DBusTypes::DBUS_NAME, path.path(), connection);
260
261 d->m_propertyCache =
262- make_unique<internal::DBusPropertyCache>(
263+ make_unique<util::DBusPropertyCache>(
264 DBusTypes::DBUS_NAME,
265 ComUbuntuConnectivity1ModemInterface::staticInterfaceName(),
266 path.path(), connection);
267
268 connect(d->m_propertyCache.get(),
269- &internal::DBusPropertyCache::propertyChanged, d.get(),
270+ &util::DBusPropertyCache::propertyChanged, d.get(),
271 &Priv::propertyChanged);
272
273 d->simsUpdated();
274
275=== modified file 'src/connectivity-api/connectivity-qt/connectivityqt/modems-list-model.cpp'
276--- src/connectivity-api/connectivity-qt/connectivityqt/modems-list-model.cpp 2016-06-02 13:22:54 +0000
277+++ src/connectivity-api/connectivity-qt/connectivityqt/modems-list-model.cpp 2016-10-30 18:45:06 +0000
278@@ -125,7 +125,7 @@
279 QList<Modem::SPtr> m_modems;
280
281 shared_ptr<ComUbuntuConnectivity1PrivateInterface> m_writeInterface;
282- internal::DBusPropertyCache::SPtr m_propertyCache;
283+ util::DBusPropertyCache::SPtr m_propertyCache;
284 };
285
286 ModemsListModel::ModemsListModel(const internal::ModemsListModelParameters &parameters) :
287@@ -138,7 +138,7 @@
288 d->m_propertyCache = parameters.propertyCache;
289
290 connect(d->m_propertyCache.get(),
291- &internal::DBusPropertyCache::propertyChanged, d.get(),
292+ &util::DBusPropertyCache::propertyChanged, d.get(),
293 &Priv::propertyChanged);
294
295 QList<QDBusObjectPath> tmp;
296
297=== modified file 'src/connectivity-api/connectivity-qt/connectivityqt/openvpn-connection.cpp'
298--- src/connectivity-api/connectivity-qt/connectivityqt/openvpn-connection.cpp 2015-12-04 13:18:04 +0000
299+++ src/connectivity-api/connectivity-qt/connectivityqt/openvpn-connection.cpp 2016-10-30 18:45:06 +0000
300@@ -18,7 +18,7 @@
301 */
302
303 #include <connectivityqt/openvpn-connection.h>
304-#include <connectivityqt/internal/dbus-property-cache.h>
305+#include <util/dbus-property-cache.h>
306 #include <dbus-types.h>
307
308 #include <OpenVpnConnectionInterface.h>
309@@ -142,7 +142,7 @@
310
311 unique_ptr<ComUbuntuConnectivity1VpnVpnConnectionOpenVpnInterface> m_openvpnInterface;
312
313- internal::DBusPropertyCache::UPtr m_propertyCache;
314+ util::DBusPropertyCache::UPtr m_propertyCache;
315 };
316
317 OpenvpnConnection::OpenvpnConnection(const QDBusObjectPath& path, const QDBusConnection& connection) :
318@@ -154,13 +154,13 @@
319 DBusTypes::DBUS_NAME, path.path(), connection);
320
321 d->m_propertyCache =
322- make_unique<internal::DBusPropertyCache>(
323+ make_unique<util::DBusPropertyCache>(
324 DBusTypes::DBUS_NAME,
325 ComUbuntuConnectivity1VpnVpnConnectionOpenVpnInterface::staticInterfaceName(),
326 path.path(), connection);
327
328 connect(d->m_propertyCache.get(),
329- &internal::DBusPropertyCache::propertyChanged, d.get(),
330+ &util::DBusPropertyCache::propertyChanged, d.get(),
331 &Priv::propertyChanged);
332 }
333
334
335=== modified file 'src/connectivity-api/connectivity-qt/connectivityqt/pptp-connection.cpp'
336--- src/connectivity-api/connectivity-qt/connectivityqt/pptp-connection.cpp 2016-01-14 11:40:59 +0000
337+++ src/connectivity-api/connectivity-qt/connectivityqt/pptp-connection.cpp 2016-10-30 18:45:06 +0000
338@@ -18,7 +18,7 @@
339 */
340
341 #include <connectivityqt/pptp-connection.h>
342-#include <connectivityqt/internal/dbus-property-cache.h>
343+#include <util/dbus-property-cache.h>
344 #include <dbus-types.h>
345
346 #include <PptpConnectionInterface.h>
347@@ -107,7 +107,7 @@
348
349 unique_ptr<ComUbuntuConnectivity1VpnVpnConnectionPptpInterface> m_pptpInterface;
350
351- internal::DBusPropertyCache::UPtr m_propertyCache;
352+ util::DBusPropertyCache::UPtr m_propertyCache;
353 };
354
355 PptpConnection::PptpConnection(const QDBusObjectPath& path, const QDBusConnection& connection) :
356@@ -119,13 +119,13 @@
357 DBusTypes::DBUS_NAME, path.path(), connection);
358
359 d->m_propertyCache =
360- make_unique<internal::DBusPropertyCache>(
361+ make_unique<util::DBusPropertyCache>(
362 DBusTypes::DBUS_NAME,
363 ComUbuntuConnectivity1VpnVpnConnectionPptpInterface::staticInterfaceName(),
364 path.path(), connection);
365
366 connect(d->m_propertyCache.get(),
367- &internal::DBusPropertyCache::propertyChanged, d.get(),
368+ &util::DBusPropertyCache::propertyChanged, d.get(),
369 &Priv::propertyChanged);
370 }
371
372
373=== modified file 'src/connectivity-api/connectivity-qt/connectivityqt/sim.cpp'
374--- src/connectivity-api/connectivity-qt/connectivityqt/sim.cpp 2016-07-22 13:10:24 +0000
375+++ src/connectivity-api/connectivity-qt/connectivityqt/sim.cpp 2016-10-30 18:45:06 +0000
376@@ -17,7 +17,7 @@
377 * Antti Kaijanmäki <antti.kaijanmaki@canonical.com>
378 */
379
380-#include <connectivityqt/internal/dbus-property-cache.h>
381+#include <util/dbus-property-cache.h>
382 #include <connectivityqt/sim.h>
383 #include <dbus-types.h>
384
385@@ -70,7 +70,7 @@
386
387 unique_ptr<ComUbuntuConnectivity1SimInterface> m_simInterface;
388
389- internal::DBusPropertyCache::UPtr m_propertyCache;
390+ util::DBusPropertyCache::UPtr m_propertyCache;
391 };
392
393 Sim::Sim(const QDBusObjectPath& path, const QDBusConnection& connection, QObject* parent) :
394@@ -81,13 +81,13 @@
395 DBusTypes::DBUS_NAME, path.path(), connection);
396
397 d->m_propertyCache =
398- make_unique<internal::DBusPropertyCache>(
399+ make_unique<util::DBusPropertyCache>(
400 DBusTypes::DBUS_NAME,
401 ComUbuntuConnectivity1SimInterface::staticInterfaceName(),
402 path.path(), connection);
403
404 connect(d->m_propertyCache.get(),
405- &internal::DBusPropertyCache::propertyChanged, d.get(),
406+ &util::DBusPropertyCache::propertyChanged, d.get(),
407 &Priv::propertyChanged);
408 }
409
410
411=== modified file 'src/connectivity-api/connectivity-qt/connectivityqt/sims-list-model.cpp'
412--- src/connectivity-api/connectivity-qt/connectivityqt/sims-list-model.cpp 2016-07-22 13:10:24 +0000
413+++ src/connectivity-api/connectivity-qt/connectivityqt/sims-list-model.cpp 2016-10-30 18:45:06 +0000
414@@ -168,7 +168,7 @@
415 QList<Sim::SPtr> m_sims;
416
417 shared_ptr<ComUbuntuConnectivity1PrivateInterface> m_writeInterface;
418- internal::DBusPropertyCache::SPtr m_propertyCache;
419+ util::DBusPropertyCache::SPtr m_propertyCache;
420 };
421
422 SimsListModel::SimsListModel(const internal::SimsListModelParameters &parameters) :
423@@ -180,7 +180,7 @@
424 d->m_propertyCache = parameters.propertyCache;
425
426 connect(d->m_propertyCache.get(),
427- &internal::DBusPropertyCache::propertyChanged, d.get(),
428+ &util::DBusPropertyCache::propertyChanged, d.get(),
429 &Priv::propertyChanged);
430
431 QList<QDBusObjectPath> tmp;
432
433=== modified file 'src/connectivity-api/connectivity-qt/connectivityqt/vpn-connection.cpp'
434--- src/connectivity-api/connectivity-qt/connectivityqt/vpn-connection.cpp 2016-03-02 18:26:02 +0000
435+++ src/connectivity-api/connectivity-qt/connectivityqt/vpn-connection.cpp 2016-10-30 18:45:06 +0000
436@@ -17,7 +17,7 @@
437 * Pete Woods <pete.woods@canonical.com>
438 */
439
440-#include <connectivityqt/internal/dbus-property-cache.h>
441+#include <util/dbus-property-cache.h>
442 #include <connectivityqt/vpn-connection.h>
443 #include <dbus-types.h>
444
445@@ -64,7 +64,7 @@
446
447 unique_ptr<ComUbuntuConnectivity1VpnVpnConnectionInterface> m_vpnInterface;
448
449- internal::DBusPropertyCache::UPtr m_propertyCache;
450+ util::DBusPropertyCache::UPtr m_propertyCache;
451 };
452
453 VpnConnection::VpnConnection(const QDBusObjectPath& path, const QDBusConnection& connection, QObject* parent) :
454@@ -75,13 +75,13 @@
455 DBusTypes::DBUS_NAME, path.path(), connection);
456
457 d->m_propertyCache =
458- make_unique<internal::DBusPropertyCache>(
459+ make_unique<util::DBusPropertyCache>(
460 DBusTypes::DBUS_NAME,
461 ComUbuntuConnectivity1VpnVpnConnectionInterface::staticInterfaceName(),
462 path.path(), connection);
463
464 connect(d->m_propertyCache.get(),
465- &internal::DBusPropertyCache::propertyChanged, d.get(),
466+ &util::DBusPropertyCache::propertyChanged, d.get(),
467 &Priv::propertyChanged);
468 }
469
470
471=== modified file 'src/connectivity-api/connectivity-qt/connectivityqt/vpn-connections-list-model.cpp'
472--- src/connectivity-api/connectivity-qt/connectivityqt/vpn-connections-list-model.cpp 2016-01-14 11:40:59 +0000
473+++ src/connectivity-api/connectivity-qt/connectivityqt/vpn-connections-list-model.cpp 2016-10-30 18:45:06 +0000
474@@ -220,7 +220,7 @@
475
476 shared_ptr<ComUbuntuConnectivity1PrivateInterface> m_writeInterface;
477
478- DBusPropertyCache::SPtr m_propertyCache;
479+ util::DBusPropertyCache::SPtr m_propertyCache;
480
481 QList<VpnConnection::SPtr> m_vpnConnections;
482 };
483@@ -232,7 +232,7 @@
484 d->m_writeInterface = parameters.writeInterface;
485 d->m_propertyCache = parameters.propertyCache;
486 d->updatePaths(d->m_propertyCache->get("VpnConnections"));
487- connect(d->m_propertyCache.get(), &DBusPropertyCache::propertyChanged, d.get(), &Priv::propertyChanged);
488+ connect(d->m_propertyCache.get(), &util::DBusPropertyCache::propertyChanged, d.get(), &Priv::propertyChanged);
489 }
490
491 VpnConnectionsListModel::~VpnConnectionsListModel()
492
493=== modified file 'src/indicator/CMakeLists.txt'
494--- src/indicator/CMakeLists.txt 2016-05-16 07:43:52 +0000
495+++ src/indicator/CMakeLists.txt 2016-10-30 18:45:06 +0000
496@@ -5,10 +5,6 @@
497 )
498 include_directories(${QOFONO_INCLUDE_DIRS})
499
500-include_directories("${CMAKE_SOURCE_DIR}/src")
501-include_directories("${CMAKE_BINARY_DIR}/src/qdbus-stubs")
502-include_directories("${CMAKE_SOURCE_DIR}/src/qdbus-stubs")
503-
504 # list these here to have them visible in Qt Creator
505 file(
506 GLOB_RECURSE NETWORK_SERVICE_HEADERS
507@@ -25,6 +21,7 @@
508 nmofono/kill-switch.cpp
509 nmofono/manager.cpp
510 nmofono/manager-impl.cpp
511+ nmofono/nm-device-statistics-monitor.cpp
512 nmofono/connection/active-connection.cpp
513 nmofono/connection/active-connection-manager.cpp
514 nmofono/connection/active-vpn-connection.cpp
515
516=== modified file 'src/indicator/nmofono/manager-impl.cpp'
517--- src/indicator/nmofono/manager-impl.cpp 2016-09-20 17:28:22 +0000
518+++ src/indicator/nmofono/manager-impl.cpp 2016-10-30 18:45:06 +0000
519@@ -48,6 +48,8 @@
520 #include <algorithm>
521 #include <iostream>
522
523+#include "nm-device-statistics-monitor.h"
524+
525 using namespace std;
526
527 namespace nmofono {
528@@ -72,6 +74,8 @@
529
530 bool m_modemAvailable = false;
531
532+ QList<QDBusObjectPath> m_nmDevices;
533+
534 QSet<Link::Ptr> m_nmLinks;
535 QMap<QString, wwan::Modem::Ptr> m_ofonoLinks;
536
537@@ -95,6 +99,8 @@
538
539 QTimer m_checkSimForMobileDataTimer;
540
541+ NMDeviceStatisticsMonitor::Ptr m_statisticsMonitor;
542+
543 Private(Manager& parent) :
544 p(parent)
545 {
546@@ -401,6 +407,19 @@
547 m_ofonoLinks[path] = modem;
548 connect(modem.get(), &wwan::Modem::readyToUnlock, this, &Private::modemReadyToUnlock);
549 connect(modem.get(), &wwan::Modem::ready, this, &Private::modemReady);
550+
551+ for (const auto &nmobjpath : m_nmDevices)
552+ {
553+ auto dev = make_shared<OrgFreedesktopNetworkManagerDeviceInterface>(
554+ NM_DBUS_SERVICE,
555+ nmobjpath.path(),
556+ nm->connection());
557+ if (dev->udi() == path) {
558+ modem->setNmPath(nmobjpath.path());
559+ m_statisticsMonitor->addLink(modem);
560+ break;
561+ }
562+ }
563 }
564
565 Q_EMIT p.linksUpdated();
566@@ -516,6 +535,12 @@
567 d->m_unlockDialog = make_shared<SimUnlockDialog>(notificationManager);
568 connect(d->m_unlockDialog.get(), &SimUnlockDialog::ready, d.get(), &Private::sim_unlock_ready);
569
570+ d->m_statisticsMonitor = make_shared<NMDeviceStatisticsMonitor>();
571+
572+ connect(d->m_statisticsMonitor.get(), &NMDeviceStatisticsMonitor::txChanged, this, &ManagerImpl::txChanged);
573+ connect(d->m_statisticsMonitor.get(), &NMDeviceStatisticsMonitor::rxChanged, this, &ManagerImpl::rxChanged);
574+
575+
576 d->m_ofono = make_shared<QOfonoManager>();
577
578 // Load the SIM manager before we connect to the signals
579@@ -545,7 +570,7 @@
580 connect(d->m_hotspotManager.get(), &HotspotManager::reportError, this, &Manager::reportError);
581
582 connect(d->nm.get(), &OrgFreedesktopNetworkManagerInterface::DeviceAdded, this, &ManagerImpl::device_added);
583- QList<QDBusObjectPath> devices(d->nm->GetDevices());
584+ QList<QDBusObjectPath> devices = d->nm->GetDevices();
585 for(const auto &path : devices) {
586 device_added(path);
587 }
588@@ -570,7 +595,7 @@
589 for(auto sim : d->m_sims) {
590 connect(sim.get(), &wwan::Sim::presentChanged, d.get(), &Private::startCheckSimForMobileDataTimer);
591 }
592- d->m_checkSimForMobileDataTimer.start();
593+ d->m_checkSimForMobileDataTimer.start();
594 }
595
596 bool
597@@ -690,6 +715,11 @@
598 ManagerImpl::device_removed(const QDBusObjectPath &path)
599 {
600 qDebug() << "Device Removed:" << path.path();
601+
602+ d->m_nmDevices.removeAll(path);
603+
604+ d->m_statisticsMonitor->remove(path.path());
605+
606 Link::Ptr toRemove;
607 for (auto dev : d->m_nmLinks)
608 {
609@@ -712,6 +742,9 @@
610 ManagerImpl::device_added(const QDBusObjectPath &path)
611 {
612 qDebug() << "Device Added:" << path.path();
613+
614+ d->m_nmDevices.append(path);
615+
616 for (const auto &dev : d->m_nmLinks)
617 {
618 auto wifiLink = dynamic_pointer_cast<wifi::WifiLinkImpl>(dev);
619@@ -740,6 +773,22 @@
620 link = tmp;
621 }
622 }
623+ else if (dev->deviceType() == NM_DEVICE_TYPE_MODEM)
624+ {
625+ if (dev->driver() == "ofono")
626+ {
627+ for (const auto &modem : d->m_ofonoLinks)
628+ {
629+ if (modem->ofonoPath() == dev->udi())
630+ {
631+ modem->setNmPath(path.path());
632+ d->m_statisticsMonitor->addLink(modem);
633+ break;
634+ }
635+ }
636+ }
637+ }
638+
639 } catch (const exception &e) {
640 qDebug() << ": failed to create Device proxy for "<< path.path() << ": ";
641 qDebug() << "\t" << e.what();
642@@ -750,6 +799,8 @@
643 if (link) {
644 d->m_nmLinks.insert(link);
645 Q_EMIT linksUpdated();
646+
647+ d->m_statisticsMonitor->addLink(link);
648 }
649
650 d->updateHasWifi();
651@@ -976,6 +1027,18 @@
652 return d->m_sims;
653 }
654
655+bool
656+ManagerImpl::tx() const
657+{
658+ return d->m_statisticsMonitor->tx();
659+}
660+
661+bool
662+ManagerImpl::rx() const
663+{
664+ return d->m_statisticsMonitor->rx();
665+}
666+
667
668 }
669
670
671=== modified file 'src/indicator/nmofono/manager-impl.h'
672--- src/indicator/nmofono/manager-impl.h 2016-04-27 10:34:46 +0000
673+++ src/indicator/nmofono/manager-impl.h 2016-10-30 18:45:06 +0000
674@@ -99,6 +99,10 @@
675
676 QList<wwan::Sim::Ptr> sims() const override;
677
678+ bool tx() const override;
679+
680+ bool rx() const override;
681+
682 void setHotspotEnabled(bool) override;
683
684 void setHotspotSsid(const QByteArray&) override;
685
686=== modified file 'src/indicator/nmofono/manager.h'
687--- src/indicator/nmofono/manager.h 2016-04-27 10:34:46 +0000
688+++ src/indicator/nmofono/manager.h 2016-10-30 18:45:06 +0000
689@@ -156,6 +156,12 @@
690 Q_PROPERTY(QList<wwan::Sim::Ptr> sims READ sims NOTIFY simsChanged)
691 virtual QList<wwan::Sim::Ptr> sims() const = 0;
692
693+ Q_PROPERTY(bool tx READ tx NOTIFY txChanged)
694+ virtual bool tx() const = 0;
695+
696+ Q_PROPERTY(bool rx READ rx NOTIFY rxChanged)
697+ virtual bool rx() const = 0;
698+
699
700 Q_SIGNALS:
701 void flightModeUpdated(bool);
702@@ -196,6 +202,10 @@
703
704 void simsChanged();
705
706+ void txChanged();
707+
708+ void rxChanged();
709+
710 public Q_SLOTS:
711 virtual void setWifiEnabled(bool) = 0;
712
713@@ -215,6 +225,7 @@
714
715 virtual void setSimForMobileData(wwan::Sim::Ptr) = 0;
716
717+
718 protected:
719 /**
720 * @brief The default constructor is protected.
721
722=== added file 'src/indicator/nmofono/nm-device-statistics-monitor.cpp'
723--- src/indicator/nmofono/nm-device-statistics-monitor.cpp 1970-01-01 00:00:00 +0000
724+++ src/indicator/nmofono/nm-device-statistics-monitor.cpp 2016-10-30 18:45:06 +0000
725@@ -0,0 +1,363 @@
726+/*
727+ * Copyright (C) 2016 Canonical, Ltd.
728+ *
729+ * This program is free software: you can redistribute it and/or modify it
730+ * under the terms of the GNU General Public License version 3, as published
731+ * by the Free Software Foundation.
732+ *
733+ * This program is distributed in the hope that it will be useful, but
734+ * WITHOUT ANY WARRANTY; without even the implied warranties of
735+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
736+ * PURPOSE. See the GNU General Public License for more details.
737+ *
738+ * You should have received a copy of the GNU General Public License along
739+ * with this program. If not, see <http://www.gnu.org/licenses/>.
740+ *
741+ * Authors:
742+ * Antti Kaijanmäki <antti.kaijanmaki@canonical.com>
743+ */
744+
745+#include <nmofono/nm-device-statistics-monitor.h>
746+
747+#include <NetworkManager.h>
748+
749+#include <QDBusInterface>
750+
751+#include <QMap>
752+#include <QDebug>
753+
754+#include <NetworkManagerDeviceStatisticsInterface.h>
755+
756+#include <gio/gio.h>
757+#define G_SETTINGS_ENABLE_BACKEND
758+#include <gio/gsettingsbackend.h>
759+
760+#include "wifi/wifi-link-impl.h"
761+#include "wwan/modem.h"
762+
763+using namespace std;
764+
765+namespace nmofono
766+{
767+
768+class NMDeviceStatisticsMonitor::Private : public QObject, public std::enable_shared_from_this<Private>
769+{
770+ Q_OBJECT
771+
772+ NMDeviceStatisticsMonitor& p;
773+
774+public:
775+
776+ QMap<QString, std::shared_ptr<OrgFreedesktopNetworkManagerDeviceStatisticsInterface>> m_interfaces;
777+ QTimer m_txTimer;
778+ QTimer m_rxTimer;
779+
780+ bool m_tx{false};
781+ bool m_rx{false};
782+
783+ bool m_enabled{false};
784+
785+ /***************/
786+ // This QDBusInterface magic is blatantly adapted from unity8: src/plugins/Powerd/Powerd.cpp
787+ // BTW: the service com.canonical.Unity.Screen is provided by lp:repowerd
788+ // BUGISH: no xml2qdbus goodness for us
789+ // https://bugs.launchpad.net/ubuntu/+source/repowerd/+bug/1637730
790+
791+ enum Status {
792+ Off,
793+ On,
794+ };
795+
796+ QDBusInterface m_unityScreen{QStringLiteral("com.canonical.Unity.Screen"),
797+ QStringLiteral("/com/canonical/Unity/Screen"),
798+ QStringLiteral("com.canonical.Unity.Screen"),
799+ QDBusConnection::systemBus()};
800+ Status m_status {Status::On}; // fingers crossed..
801+ // BUG: https://bugs.launchpad.net/ubuntu/+source/repowerd/+bug/1637722
802+ /***************/
803+
804+ Private(NMDeviceStatisticsMonitor& parent)
805+ : p(parent)
806+ {
807+ GSettings *settings{nullptr};
808+ if (qEnvironmentVariableIsSet("INDICATOR_NETWORK_UNDER_TESTING"))
809+ {
810+ Q_ASSERT(qEnvironmentVariableIsSet("INDICATOR_NETWOR_TESTING_GSETTINGS_INI"));
811+ Q_ASSERT(qEnvironmentVariableIsSet("GSETTINGS_SCHEMA_DIR"));
812+
813+ GSettingsBackend *backend = g_keyfile_settings_backend_new(qgetenv("INDICATOR_NETWOR_TESTING_GSETTINGS_INI"),
814+ "/com/canonical/indicator/network/",
815+ "root");
816+
817+ settings = g_settings_new_with_backend("com.canonical.indicator.network",
818+ backend);
819+ g_object_unref(backend);
820+ }
821+ else
822+ {
823+ settings = g_settings_new("com.canonical.indicator.network");
824+ }
825+ m_enabled = g_settings_get_boolean(settings,
826+ "data-usage-indication");
827+ g_object_unref(settings);
828+#ifdef INDICATOR_NETWORK_TRACE_MESSAGES
829+ qDebug() << "enabled:" << m_enabled;
830+#endif
831+
832+ m_unityScreen.connection().connect(QStringLiteral("com.canonical.Unity.Screen"),
833+ QStringLiteral("/com/canonical/Unity/Screen"),
834+ QStringLiteral("com.canonical.Unity.Screen"),
835+ QStringLiteral("DisplayPowerStateChange"),
836+ this,
837+ SLOT(handleDisplayPowerStateChange(int, int)));
838+
839+ m_txTimer.setInterval(1000);
840+ m_txTimer.setSingleShot(true);
841+ connect(&m_rxTimer, &QTimer::timeout, this, &Private::txShot);
842+
843+ m_rxTimer.setInterval(1000);
844+ m_rxTimer.setSingleShot(true);
845+ connect(&m_rxTimer, &QTimer::timeout, this, &Private::rxShot);
846+ }
847+
848+ ~Private()
849+ {
850+ for (auto path : m_interfaces.keys())
851+ {
852+ resetInterface(path);
853+ }
854+ }
855+
856+ void setTx(bool value)
857+ {
858+ if (m_tx == value)
859+ {
860+ return;
861+ }
862+
863+ m_tx = value;
864+ Q_EMIT p.txChanged();
865+ }
866+
867+ void setRx(bool value)
868+ {
869+ if (m_rx == value)
870+ {
871+ return;
872+ }
873+
874+ m_rx = value;
875+ Q_EMIT p.rxChanged();
876+ }
877+
878+
879+ void setUpInterface(const QString &path)
880+ {
881+#ifdef INDICATOR_NETWORK_TRACE_MESSAGES
882+ qDebug() << path;
883+#endif
884+
885+ if (!m_interfaces.contains(path))
886+ {
887+ return;
888+ }
889+
890+ if (!m_enabled)
891+ {
892+ return;
893+ }
894+
895+ auto iface = m_interfaces[path];
896+
897+ connect(iface.get(), &OrgFreedesktopNetworkManagerDeviceStatisticsInterface::PropertiesChanged, this, &Private::propertiesChanged);
898+ iface->setRefreshRateMs(500);
899+ }
900+
901+ void resetInterface(const QString &path)
902+ {
903+#ifdef INDICATOR_NETWORK_TRACE_MESSAGES
904+ qDebug() << path;
905+#endif
906+ if (!m_interfaces.contains(path))
907+ {
908+ return;
909+ }
910+ auto iface = m_interfaces[path];
911+ disconnect(iface.get(), &OrgFreedesktopNetworkManagerDeviceStatisticsInterface::PropertiesChanged, this, &Private::propertiesChanged);
912+ iface->setRefreshRateMs(0);
913+ }
914+
915+ void connectAllInterfaces()
916+ {
917+#ifdef INDICATOR_NETWORK_TRACE_MESSAGES
918+ qDebug() << "";
919+#endif
920+ for (auto path : m_interfaces.keys())
921+ {
922+ setUpInterface(path);
923+ }
924+ }
925+
926+ void disconnectAllInterfaces()
927+ {
928+#ifdef INDICATOR_NETWORK_TRACE_MESSAGES
929+ qDebug() << "";
930+#endif
931+ for (auto path : m_interfaces.keys())
932+ {
933+ resetInterface(path);
934+ }
935+ }
936+
937+
938+public Q_SLOTS:
939+
940+ void handleDisplayPowerStateChange(int status, int reason)
941+ {
942+ Q_UNUSED(reason)
943+#ifdef INDICATOR_NETWORK_TRACE_MESSAGES
944+ qDebug() << status;
945+#endif
946+
947+ if (m_status != (Status)status) {
948+ m_status = (Status)status;
949+ switch (m_status)
950+ {
951+ case Status::On:
952+ {
953+ connectAllInterfaces();
954+ break;
955+ }
956+ case Status::Off:
957+ disconnectAllInterfaces();
958+ break;
959+ }
960+ }
961+ }
962+
963+ void propertiesChanged(const QVariantMap &properties)
964+ {
965+ if (properties.contains("TxBytes"))
966+ {
967+#ifdef INDICATOR_NETWORK_TRACE_MESSAGES
968+ OrgFreedesktopNetworkManagerDeviceStatisticsInterface *iface = qobject_cast<OrgFreedesktopNetworkManagerDeviceStatisticsInterface*>(sender());
969+ qDebug() << "TxBytes updated on" << iface->path();
970+#endif
971+ setTx(true);
972+ m_txTimer.start();
973+ }
974+
975+ if (properties.contains("RxBytes"))\
976+ {
977+#ifdef INDICATOR_NETWORK_TRACE_MESSAGES
978+ OrgFreedesktopNetworkManagerDeviceStatisticsInterface *iface = qobject_cast<OrgFreedesktopNetworkManagerDeviceStatisticsInterface*>(sender());
979+ qDebug() << "RxBytes updated on" << iface->path();
980+#endif
981+ setRx(true);
982+ m_rxTimer.start();
983+ }
984+ }
985+
986+ void txShot()
987+ {
988+#ifdef INDICATOR_NETWORK_TRACE_MESSAGES
989+ qDebug() << "";
990+#endif
991+ setTx(false);
992+ }
993+
994+ void rxShot()
995+ {
996+#ifdef INDICATOR_NETWORK_TRACE_MESSAGES
997+ qDebug() << "";
998+#endif
999+ setRx(false);
1000+ }
1001+
1002+
1003+};
1004+
1005+
1006+NMDeviceStatisticsMonitor::NMDeviceStatisticsMonitor()
1007+ : d{new Private(*this)}
1008+{
1009+}
1010+
1011+NMDeviceStatisticsMonitor::~NMDeviceStatisticsMonitor()
1012+{
1013+
1014+}
1015+
1016+void
1017+NMDeviceStatisticsMonitor::addLink(Link::Ptr link)
1018+{
1019+#ifdef INDICATOR_NETWORK_TRACE_MESSAGES
1020+ qDebug() << "adding" << link->name();
1021+#endif
1022+
1023+ QString path;
1024+
1025+ if (std::dynamic_pointer_cast<wifi::WifiLinkImpl>(link))
1026+ {
1027+#ifdef INDICATOR_NETWORK_TRACE_MESSAGES
1028+ qDebug() << " it's a WiFi link";
1029+#endif
1030+ path = std::dynamic_pointer_cast<wifi::WifiLinkImpl>(link)->device_path().path();
1031+ }
1032+ else if (std::dynamic_pointer_cast<wwan::Modem>(link))
1033+ {
1034+#ifdef INDICATOR_NETWORK_TRACE_MESSAGES
1035+ qDebug() << " it's a modem link";
1036+#endif
1037+ path = std::dynamic_pointer_cast<wwan::Modem>(link)->nmPath();
1038+ }
1039+ else
1040+ {
1041+ qWarning() << "Unhandled link type with name:" << link->name();
1042+ }
1043+
1044+ if (path.isEmpty())
1045+ {
1046+ qWarning() << "Could not determine NMDevice path for link with name:" << link->name();
1047+ return;
1048+ }
1049+
1050+ auto dev = make_shared<OrgFreedesktopNetworkManagerDeviceStatisticsInterface>(
1051+ NM_DBUS_SERVICE,
1052+ path,
1053+ QDBusConnection::systemBus());
1054+
1055+ d->m_interfaces[path] = dev;
1056+
1057+ d->setUpInterface(path);
1058+}
1059+
1060+void
1061+NMDeviceStatisticsMonitor::remove(const QString &nmPath)
1062+{
1063+#ifdef INDICATOR_NETWORK_TRACE_MESSAGES
1064+ qDebug() << "removing" << nmPath;
1065+#endif
1066+
1067+ if (d->m_interfaces.contains(nmPath))
1068+ {
1069+ d->resetInterface(nmPath);
1070+ d->m_interfaces.remove(nmPath);
1071+ }
1072+}
1073+
1074+bool
1075+NMDeviceStatisticsMonitor::tx() const
1076+{
1077+ return d->m_tx;
1078+}
1079+
1080+bool
1081+NMDeviceStatisticsMonitor::rx() const
1082+{
1083+ return d->m_rx;
1084+}
1085+
1086+}
1087+
1088+#include "nm-device-statistics-monitor.moc"
1089
1090=== added file 'src/indicator/nmofono/nm-device-statistics-monitor.h'
1091--- src/indicator/nmofono/nm-device-statistics-monitor.h 1970-01-01 00:00:00 +0000
1092+++ src/indicator/nmofono/nm-device-statistics-monitor.h 2016-10-30 18:45:06 +0000
1093@@ -0,0 +1,62 @@
1094+/*
1095+ * Copyright (C) 2016 Canonical, Ltd.
1096+ *
1097+ * This program is free software: you can redistribute it and/or modify it
1098+ * under the terms of the GNU General Public License version 3, as published
1099+ * by the Free Software Foundation.
1100+ *
1101+ * This program is distributed in the hope that it will be useful, but
1102+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1103+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1104+ * PURPOSE. See the GNU General Public License for more details.
1105+ *
1106+ * You should have received a copy of the GNU General Public License along
1107+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1108+ *
1109+ * Authors:
1110+ * Antti Kaijanmäki <antti.kaijanmaki@canonical.com>
1111+ */
1112+
1113+#pragma once
1114+
1115+#include <QObject>
1116+
1117+#include "link.h"
1118+
1119+#include <memory>
1120+
1121+namespace nmofono
1122+{
1123+
1124+class NMDeviceStatisticsMonitor : public QObject
1125+{
1126+ Q_OBJECT
1127+
1128+ class Private;
1129+ std::shared_ptr<Private> d;
1130+
1131+public:
1132+
1133+ typedef std::shared_ptr<NMDeviceStatisticsMonitor> Ptr;
1134+ typedef std::weak_ptr<NMDeviceStatisticsMonitor> WeakPtr;
1135+
1136+ Q_PROPERTY(bool tx READ tx NOTIFY txChanged)
1137+ virtual bool tx() const;
1138+
1139+ Q_PROPERTY(bool rx READ rx NOTIFY rxChanged)
1140+ virtual bool rx() const;
1141+
1142+ NMDeviceStatisticsMonitor();
1143+ ~NMDeviceStatisticsMonitor();
1144+
1145+ void addLink(Link::Ptr link);
1146+
1147+ void remove(const QString &nmPath);
1148+
1149+Q_SIGNALS:
1150+
1151+ void txChanged();
1152+ void rxChanged();
1153+};
1154+
1155+}
1156
1157=== modified file 'src/indicator/nmofono/wifi/wifi-link-impl.cpp'
1158--- src/indicator/nmofono/wifi/wifi-link-impl.cpp 2016-05-26 13:51:39 +0000
1159+++ src/indicator/nmofono/wifi/wifi-link-impl.cpp 2016-10-30 18:45:06 +0000
1160@@ -534,7 +534,8 @@
1161 return d->m_activeAccessPoint;
1162 }
1163
1164-QDBusObjectPath WifiLinkImpl::device_path() const {
1165+QDBusObjectPath
1166+WifiLinkImpl::device_path() const {
1167 return QDBusObjectPath(d->m_dev->path());
1168 }
1169
1170
1171=== modified file 'src/indicator/nmofono/wwan/modem.cpp'
1172--- src/indicator/nmofono/wwan/modem.cpp 2016-06-16 09:16:45 +0000
1173+++ src/indicator/nmofono/wwan/modem.cpp 2016-10-30 18:45:06 +0000
1174@@ -125,6 +125,8 @@
1175
1176 bool m_shouldTriggerUnlock = false;
1177
1178+ QString m_nmPath;
1179+
1180 Private(Modem& parent, shared_ptr<QOfonoModem> ofonoModem)
1181 : p(parent), m_ofonoModem{ofonoModem}
1182 {
1183@@ -731,6 +733,19 @@
1184 return d->m_ofonoModem->modemPath();
1185 }
1186
1187+QString
1188+Modem::nmPath() const
1189+{
1190+ return d->m_nmPath;
1191+}
1192+
1193+void
1194+Modem::setNmPath(const QString& path)
1195+{
1196+ d->m_nmPath = path;
1197+}
1198+
1199+
1200 WwanLink::WwanType
1201 Modem::wwanType() const
1202 {
1203
1204=== modified file 'src/indicator/nmofono/wwan/modem.h'
1205--- src/indicator/nmofono/wwan/modem.h 2016-04-27 10:34:46 +0000
1206+++ src/indicator/nmofono/wwan/modem.h 2016-10-30 18:45:06 +0000
1207@@ -134,7 +134,10 @@
1208 QString serial() const;
1209
1210 QString name() const override;
1211+
1212 QString ofonoPath() const;
1213+ QString nmPath() const;
1214+ void setNmPath(const QString& path);
1215
1216 WwanType wwanType() const override;
1217
1218
1219=== modified file 'src/indicator/root-state.cpp'
1220--- src/indicator/root-state.cpp 2016-07-15 11:25:21 +0000
1221+++ src/indicator/root-state.cpp 2016-10-30 18:45:06 +0000
1222@@ -74,6 +74,9 @@
1223 connect(m_manager.get(), &Manager::statusUpdated, this, &Private::updateNetworkingIcon);
1224 connect(m_manager.get(), &Manager::linksUpdated, this, &Private::updateNetworkingIcon);
1225
1226+ connect(m_manager.get(), &nmofono::Manager::txChanged, this, &Private::updateNetworkingIcon);
1227+ connect(m_manager.get(), &nmofono::Manager::rxChanged, this, &Private::updateNetworkingIcon);
1228+
1229 // will also call updateRootState()
1230 updateNetworkingIcon();
1231 }
1232@@ -212,6 +215,21 @@
1233 }
1234 }
1235
1236+ if (m_manager->rx() && m_manager->tx())
1237+ {
1238+ m_networkingIcons << "transfer-progress";
1239+ }
1240+ else
1241+ {
1242+ if (m_manager->rx()){
1243+ m_networkingIcons << "transfer-progress-download";
1244+ }
1245+
1246+ if (m_manager->tx()){
1247+ m_networkingIcons << "transfer-progress-upload";
1248+ }
1249+ }
1250+
1251 // Splat WiFi icons if we are using the hotspot
1252 if (m_networkingIcons.isEmpty() || m_manager->hotspotEnabled())
1253 {
1254
1255=== modified file 'src/qdbus-stubs/CMakeLists.txt'
1256--- src/qdbus-stubs/CMakeLists.txt 2015-12-11 14:58:11 +0000
1257+++ src/qdbus-stubs/CMakeLists.txt 2016-10-30 18:45:06 +0000
1258@@ -17,6 +17,7 @@
1259
1260 set_source_files_properties(
1261 "${DATA_DIR}/nm-device.xml"
1262+ "${DATA_DIR}/nm-device-statistics.xml"
1263 "${DATA_DIR}/nm-device-wifi.xml"
1264 "${DATA_DIR}/nm-access-point.xml"
1265 "${DATA_DIR}/nm-active-connection.xml"
1266@@ -26,6 +27,7 @@
1267 "${DATA_DIR}/org.freedesktop.URfkill.Device.xml"
1268 "${DATA_DIR}/org.freedesktop.URfkill.Killswitch.xml"
1269 "${DATA_DIR}/com.canonical.powerd.xml"
1270+ "${DATA_DIR}/org.freedesktop.DBus.Properties.xml"
1271 PROPERTIES
1272 NO_NAMESPACE YES
1273 )
1274@@ -72,6 +74,12 @@
1275
1276 qt5_add_dbus_interface(
1277 CONNECTIVITY_BACKEND_SRC
1278+ "${DATA_DIR}/nm-device-statistics.xml"
1279+ NetworkManagerDeviceStatisticsInterface
1280+)
1281+
1282+qt5_add_dbus_interface(
1283+ CONNECTIVITY_BACKEND_SRC
1284 "${DATA_DIR}/nm-device-wifi.xml"
1285 NetworkManagerDeviceWirelessInterface
1286 )
1287@@ -130,6 +138,12 @@
1288 PowerdInterface
1289 )
1290
1291+qt5_add_dbus_interface(
1292+ CONNECTIVITY_BACKEND_SRC
1293+ "${DATA_DIR}/org.freedesktop.DBus.Properties.xml"
1294+ PropertiesInterface
1295+)
1296+
1297 add_library(
1298 qdbus-stubs
1299 STATIC
1300
1301=== modified file 'src/util/CMakeLists.txt'
1302--- src/util/CMakeLists.txt 2016-05-26 13:51:39 +0000
1303+++ src/util/CMakeLists.txt 2016-10-30 18:45:06 +0000
1304@@ -1,9 +1,12 @@
1305-include_directories("${CMAKE_SOURCE_DIR}/src/")
1306-
1307 set(UTIL_SOURCES
1308+ dbus-property-cache.cpp
1309 dbus-utils.cpp
1310 logging.cpp
1311 unix-signal-handler.cpp
1312 )
1313
1314 add_library(util STATIC ${UTIL_SOURCES})
1315+target_link_libraries(
1316+ util
1317+ qdbus-stubs
1318+)
1319
1320=== renamed file 'src/connectivity-api/connectivity-qt/connectivityqt/internal/dbus-property-cache.cpp' => 'src/util/dbus-property-cache.cpp'
1321--- src/connectivity-api/connectivity-qt/connectivityqt/internal/dbus-property-cache.cpp 2015-12-04 13:18:04 +0000
1322+++ src/util/dbus-property-cache.cpp 2016-10-30 18:45:06 +0000
1323@@ -17,15 +17,13 @@
1324 * Pete Woods <pete.woods@canonical.com>
1325 */
1326
1327-#include <connectivityqt/internal/dbus-property-cache.h>
1328+#include "dbus-property-cache.h"
1329
1330 #include <PropertiesInterface.h>
1331
1332 using namespace std;
1333
1334-namespace connectivityqt
1335-{
1336-namespace internal
1337+namespace util
1338 {
1339
1340 class DBusPropertyCache::Priv: public QObject
1341@@ -179,7 +177,6 @@
1342 }
1343
1344 }
1345-}
1346
1347 #include "dbus-property-cache.moc"
1348
1349
1350=== renamed file 'src/connectivity-api/connectivity-qt/connectivityqt/internal/dbus-property-cache.h' => 'src/util/dbus-property-cache.h'
1351--- src/connectivity-api/connectivity-qt/connectivityqt/internal/dbus-property-cache.h 2015-11-20 13:14:50 +0000
1352+++ src/util/dbus-property-cache.h 2016-10-30 18:45:06 +0000
1353@@ -26,9 +26,7 @@
1354
1355 #include <unity/util/DefinesPtrs.h>
1356
1357-namespace connectivityqt
1358-{
1359-namespace internal
1360+namespace util
1361 {
1362
1363 class DBusPropertyCache: public QObject
1364@@ -62,4 +60,3 @@
1365 };
1366
1367 }
1368-}
1369
1370=== modified file 'tests/data/networkmanager.py'
1371--- tests/data/networkmanager.py 2016-09-29 17:17:33 +0000
1372+++ tests/data/networkmanager.py 2016-10-30 18:45:06 +0000
1373@@ -31,6 +31,7 @@
1374 SETTINGS_OBJ = '/org/freedesktop/NetworkManager/Settings'
1375 SETTINGS_IFACE = 'org.freedesktop.NetworkManager.Settings'
1376 DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device'
1377+DEVICE_STATISTICS_IFACE = 'org.freedesktop.NetworkManager.Device.Statistics'
1378 WIRELESS_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless'
1379 ACCESS_POINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint'
1380 CSETTINGS_IFACE = 'org.freedesktop.NetworkManager.Settings.Connection'
1381@@ -323,6 +324,52 @@
1382
1383 obj = dbusmock.get_object(path)
1384 obj.AddProperties(DEVICE_IFACE, props)
1385+ obj.AddProperties(DEVICE_STATISTICS_IFACE,
1386+ {
1387+ 'RefreshRateMs': dbus.UInt32(0),
1388+ 'TxBytes': dbus.UInt64(0),
1389+ 'RxBytes': dbus.UInt64(0),
1390+ })
1391+
1392+ devices = self.Get(MAIN_IFACE, 'Devices')
1393+ devices.append(path)
1394+ self.Set(MAIN_IFACE, 'Devices', devices)
1395+
1396+ self.EmitSignal('org.freedesktop.NetworkManager', 'DeviceAdded', 'o', [path])
1397+
1398+ return path
1399+
1400+@dbus.service.method(MOCK_IFACE,
1401+ in_signature='ss', out_signature='s')
1402+def AddOfonoModemDevice(self, device_name, ofono_path):
1403+
1404+ # this is a thin skeleton..
1405+
1406+ path = '/org/freedesktop/NetworkManager/Devices/' + device_name
1407+
1408+ props = {'DeviceType': dbus.UInt32(8),
1409+ 'State': dbus.UInt32(100), # NM_DEVICE_STATE_ACTIVATED
1410+ 'Interface': ofono_path[1:],
1411+ 'ActiveConnection': dbus.ObjectPath('/'),
1412+ 'AvailableConnections': dbus.Array([], signature='o'),
1413+ 'AutoConnect': False,
1414+ 'Managed': True,
1415+ 'Driver': 'ofono',
1416+ 'Udi': ofono_path,
1417+ 'IpInterface': ''}
1418+
1419+ self.AddObject(path,
1420+ DEVICE_IFACE,
1421+ props,
1422+ [])
1423+
1424+ obj = dbusmock.get_object(path)
1425+ obj.AddProperties(DEVICE_STATISTICS_IFACE,
1426+ {
1427+ 'RefreshRateMs': dbus.UInt32(0),
1428+ 'TxBytes': dbus.UInt64(0),
1429+ 'RxBytes': dbus.UInt64(0),
1430+ })
1431
1432 devices = self.Get(MAIN_IFACE, 'Devices')
1433 devices.append(path)
1434@@ -382,6 +429,12 @@
1435 'Interface': iface_name,
1436 'IpInterface': iface_name,
1437 })
1438+ dev_obj.AddProperties(DEVICE_STATISTICS_IFACE,
1439+ {
1440+ 'RefreshRateMs': dbus.UInt32(0),
1441+ 'TxBytes': dbus.UInt64(0),
1442+ 'RxBytes': dbus.UInt64(0),
1443+ })
1444
1445 devices = self.Get(MAIN_IFACE, 'Devices')
1446 devices.append(path)
1447@@ -671,6 +724,24 @@
1448
1449 self.RemoveObject(active_connection_path)
1450
1451+@dbus.service.method(MOCK_IFACE,
1452+ in_signature='stt', out_signature='')
1453+def SetDeviceStatistics(self, device_path, tx, rx):
1454+ dev_obj = dbusmock.get_object(device_path)
1455+
1456+ old_tx = dev_obj.Get(DEVICE_STATISTICS_IFACE, 'TxBytes')
1457+ old_rx = dev_obj.Get(DEVICE_STATISTICS_IFACE, 'RxBytes')
1458+
1459+ updated = {}
1460+ if old_tx != tx:
1461+ dev_obj.Set(DEVICE_STATISTICS_IFACE, 'TxBytes', dbus.UInt64(tx))
1462+ updated["TxBytes"] = dbus.UInt64(tx)
1463+ if old_rx != rx:
1464+ dev_obj.Set(DEVICE_STATISTICS_IFACE, 'RxBytes', dbus.UInt64(rx))
1465+ updated["RxBytes"] = dbus.UInt64(rx)
1466+
1467+ if len(updated) != 0:
1468+ dev_obj.EmitSignal(DEVICE_STATISTICS_IFACE, 'PropertiesChanged', 'a{sv}', [updated])
1469
1470 @dbus.service.method(SETTINGS_IFACE,
1471 in_signature='a{sa{sv}}', out_signature='o')
1472
1473=== modified file 'tests/integration/CMakeLists.txt'
1474--- tests/integration/CMakeLists.txt 2016-05-27 09:29:33 +0000
1475+++ tests/integration/CMakeLists.txt 2016-10-30 18:45:06 +0000
1476@@ -44,3 +44,24 @@
1477 integration-tests
1478 integration-tests
1479 )
1480+
1481+set(INDICATOR_NETWORK_TESTING_GSETTINGS_SCHEMA_DIR ${CMAKE_BINARY_DIR}/data) #need this somewhere higher up in the hierarchy
1482+
1483+set(TEST_ENV_VARS
1484+ INDICATOR_NETWORK_UNDER_TESTING=1
1485+ INDICATOR_NETWOR_TESTING_GSETTINGS_INI=${CMAKE_BINARY_DIR}/data/test_gsettings.ini
1486+ GSETTINGS_SCHEMA_DIR=${INDICATOR_NETWORK_TESTING_GSETTINGS_SCHEMA_DIR}
1487+)
1488+set_tests_properties(
1489+ integration-tests
1490+ PROPERTIES
1491+ ENVIRONMENT "${TEST_ENV_VARS}"
1492+)
1493+
1494+add_custom_command(OUTPUT ${INDICATOR_NETWORK_TESTING_GSETTINGS_SCHEMA_DIR}/gschemas.compiled
1495+ COMMAND glib-compile-schemas --targetdir=${INDICATOR_NETWORK_TESTING_GSETTINGS_SCHEMA_DIR} --strict ${CMAKE_SOURCE_DIR}/data
1496+ COMMENT "Compiling GSettings Schema for tests.")
1497+
1498+add_custom_target(gschemas_compiled DEPENDS ${INDICATOR_NETWORK_TESTING_GSETTINGS_SCHEMA_DIR}/gschemas.compiled)
1499+
1500+add_dependencies(integration-tests gschemas_compiled)
1501
1502=== modified file 'tests/integration/indicator-network-test-base.cpp'
1503--- tests/integration/indicator-network-test-base.cpp 2016-09-29 17:17:33 +0000
1504+++ tests/integration/indicator-network-test-base.cpp 2016-10-30 18:45:06 +0000
1505@@ -23,6 +23,11 @@
1506 #include <NetworkManagerSettingsConnectionInterface.h>
1507 #include <NetworkManagerSettingsInterface.h>
1508
1509+#include <QDebug>
1510+
1511+#define G_SETTINGS_ENABLE_BACKEND
1512+#include <gio/gsettingsbackend.h>
1513+
1514 using namespace QtDBusTest;
1515 using namespace QtDBusMock;
1516 using namespace std;
1517@@ -44,6 +49,18 @@
1518 {
1519 qputenv("INDICATOR_NETWORK_SETTINGS_PATH", temporaryDir.path().toUtf8().constData());
1520
1521+ Q_ASSERT(qEnvironmentVariableIsSet("INDICATOR_NETWOR_TESTING_GSETTINGS_INI"));
1522+ QString inipath = qgetenv("INDICATOR_NETWOR_TESTING_GSETTINGS_INI");
1523+ if (QFile::exists(inipath))
1524+ {
1525+ QFile::remove(inipath);
1526+ }
1527+ QFile inifile(inipath);
1528+ inifile.open(QIODevice::WriteOnly | QIODevice::Text);
1529+ QTextStream out(&inifile);
1530+ out << "[root]\ndata-usage-indication=false\n";
1531+ inifile.close();
1532+
1533 if (qEnvironmentVariableIsSet("TEST_WITH_BUSTLE"))
1534 {
1535 QDir::temp().mkpath("indicator-network-tests");
1536@@ -78,6 +95,11 @@
1537 DBusTypes::POWERD_DBUS_PATH,
1538 DBusTypes::POWERD_DBUS_INTERFACE,
1539 QDBusConnection::SystemBus);
1540+ dbusMock.registerCustomMock(
1541+ "com.canonical.Unity.Screen",
1542+ "/com/canonical/Unity/Screen",
1543+ "com.canonical.Unity.Screen",
1544+ QDBusConnection::SystemBus);
1545
1546 dbusMock.registerCustomMock(
1547 DBusTypes::WPASUPPLICANT_DBUS_NAME,
1548@@ -155,6 +177,34 @@
1549 sessionConnection.registerService("org.TestIndicatorNetworkService");
1550 }
1551
1552+void IndicatorNetworkTestBase::TearDown()
1553+{
1554+ Q_ASSERT(qEnvironmentVariableIsSet("INDICATOR_NETWOR_TESTING_GSETTINGS_INI"));
1555+ QString inipath = qgetenv("INDICATOR_NETWOR_TESTING_GSETTINGS_INI");
1556+ if (QFile::exists(inipath))
1557+ {
1558+ QFile::remove(inipath);
1559+ }
1560+}
1561+
1562+void IndicatorNetworkTestBase::setDataUsageIndicationSetting(bool value)
1563+{
1564+ Q_ASSERT(qEnvironmentVariableIsSet("INDICATOR_NETWOR_TESTING_GSETTINGS_INI"));
1565+
1566+ GSettingsBackend *backend = g_keyfile_settings_backend_new(qgetenv("INDICATOR_NETWOR_TESTING_GSETTINGS_INI"),
1567+ "/com/canonical/indicator/network/",
1568+ "root");
1569+ GSettings *settings = g_settings_new_with_backend("com.canonical.indicator.network",
1570+ backend);
1571+ g_settings_set_value (settings,
1572+ "data-usage-indication",
1573+ g_variant_new_boolean(value));
1574+ g_settings_sync();
1575+ g_object_unref(settings);
1576+ g_object_unref(backend);
1577+}
1578+
1579+
1580 mh::MenuMatcher::Parameters IndicatorNetworkTestBase::phoneParameters()
1581 {
1582 return mh::MenuMatcher::Parameters(
1583@@ -213,6 +263,46 @@
1584 return reply;
1585 }
1586
1587+QString IndicatorNetworkTestBase::createOfonoModemDevice(const QString &ofonoPath, const QString& id)
1588+{
1589+ auto& networkManager(dbusMock.networkManagerInterface());
1590+ QList<QVariant> argumentList;
1591+ argumentList << QVariant(QString("modem") + id) << QVariant(ofonoPath);
1592+ QDBusPendingReply<QString> reply = networkManager.asyncCallWithArgumentList(QStringLiteral("AddOfonoModemDevice"), argumentList);
1593+ reply.waitForFinished();
1594+ if (reply.isError())
1595+ {
1596+ EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
1597+ }
1598+ return reply;
1599+}
1600+
1601+
1602+void IndicatorNetworkTestBase::setDeviceStatistics(const QString &device, quint64 tx, quint64 rx)
1603+{
1604+ auto& networkManager(dbusMock.networkManagerInterface());
1605+ QList<QVariant> argumentList;
1606+ argumentList << QVariant(device) << QVariant(tx) << QVariant(rx);
1607+ networkManager.asyncCallWithArgumentList(QStringLiteral("SetDeviceStatistics"), argumentList).waitForFinished();
1608+}
1609+
1610+quint32 IndicatorNetworkTestBase::getStatisticsRefreshRateMs(const QString &device)
1611+{
1612+ QDBusInterface iface(NM_DBUS_SERVICE,
1613+ device,
1614+ "org.freedesktop.DBus.Properties",
1615+ QDBusConnection::systemBus());
1616+
1617+ QDBusPendingReply<QVariant> reply = iface.asyncCall("Get", "org.freedesktop.NetworkManager.Device.Statistics", "RefreshRateMs");
1618+ reply.waitForFinished();
1619+ if (reply.isError())
1620+ {
1621+ EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
1622+ }
1623+ QVariant tmp = reply;
1624+ return tmp.toInt();
1625+}
1626+
1627 QString IndicatorNetworkTestBase::randomMac()
1628 {
1629 int high = 254;
1630@@ -443,6 +533,21 @@
1631 }
1632 }
1633
1634+void IndicatorNetworkTestBase::setDisplayPowerState(DisplayPowerState value)
1635+{
1636+ // com.canonical.Unity.Screen interface only supports DisplayPowerStateChange signal
1637+ // Interface does not implement proper properties - https://bugs.launchpad.net/ubuntu/+source/repowerd/+bug/1637722
1638+ auto& unityscreen = dbusMock.mockInterface(
1639+ "com.canonical.Unity.Screen",
1640+ "/com/canonical/Unity/Screen",
1641+ "com.canonical.Unity.Screen",
1642+ QDBusConnection::SystemBus);
1643+
1644+ QVariantList args;
1645+ args << QVariant((qint32)(value)) << QVariant(qint32(0));
1646+ unityscreen.EmitSignal("com.canonical.Unity.Screen", "DisplayPowerStateChange", "ii", args).waitForFinished();
1647+}
1648+
1649 OrgFreedesktopDBusMockInterface& IndicatorNetworkTestBase::notificationsMockInterface()
1650 {
1651 return dbusMock.mockInterface("org.freedesktop.Notifications",
1652
1653=== modified file 'tests/integration/indicator-network-test-base.h'
1654--- tests/integration/indicator-network-test-base.h 2016-09-30 14:15:09 +0000
1655+++ tests/integration/indicator-network-test-base.h 2016-10-30 18:45:06 +0000
1656@@ -137,6 +137,9 @@
1657
1658 protected:
1659 void SetUp() override;
1660+ void TearDown() override;
1661+
1662+ void setDataUsageIndicationSetting(bool value);
1663
1664 static unity::gmenuharness::MenuMatcher::Parameters phoneParameters();
1665
1666@@ -148,6 +151,12 @@
1667
1668 QString createWiFiDevice(int state, const QString& id = "0");
1669
1670+ QString createOfonoModemDevice(const QString &ofonoPath, const QString& id);
1671+
1672+ void setDeviceStatistics(const QString &device, quint64 tx, quint64 rx);
1673+ quint32 getStatisticsRefreshRateMs(const QString &device);
1674+
1675+
1676 static QString randomMac();
1677
1678 void enableWiFi();
1679@@ -183,6 +192,12 @@
1680
1681 void setNetworkRegistrationProperty(const QString& path, const QString& propertyName, const QVariant& value);
1682
1683+ enum DisplayPowerState {
1684+ Off,
1685+ On,
1686+ };
1687+ void setDisplayPowerState(DisplayPowerState value);
1688+
1689 OrgFreedesktopDBusMockInterface& notificationsMockInterface();
1690
1691 OrgFreedesktopDBusMockInterface& modemMockInterface(const QString& path);
1692
1693=== modified file 'tests/integration/test-indicator.cpp'
1694--- tests/integration/test-indicator.cpp 2016-09-22 21:40:51 +0000
1695+++ tests/integration/test-indicator.cpp 2016-10-30 18:45:06 +0000
1696@@ -3344,4 +3344,161 @@
1697 ).match());
1698 }
1699
1700+/*
1701+ * Disabled by default because containst sleeps and what not other horrible things.
1702+ * There are timers involved, so this will be flaky
1703+ * To manually run, do following inside ${CMAKE_BINARY_DIR}
1704+ * $ export INDICATOR_NETWORK_UNDER_TESTING=1
1705+ * $ export INDICATOR_NETWOR_TESTING_GSETTINGS_INI=./data/test_gsettings.ini
1706+ * $ export GSETTINGS_SCHEMA_DIR=./data
1707+ * $ tests/integration/integration-tests --gtest_filter=TestIndicator.DISABLED_DataUsageIndication_enabled --gtest_also_run_disabled_tests
1708+ */
1709+TEST_F(TestIndicator, DISABLED_DataUsageIndication_enabled)
1710+{
1711+ setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
1712+ auto wifi_device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
1713+ auto ap = createAccessPoint("0", "the ssid", wifi_device);
1714+ auto connection = createAccessPointConnection("0", "the ssid", wifi_device);
1715+ createActiveConnection("0", wifi_device, connection, ap);
1716+
1717+ auto modem1_device = createOfonoModemDevice("/ril_0", "0");
1718+
1719+ setDataUsageIndicationSetting(true);
1720+
1721+ ASSERT_NO_THROW(startIndicator());
1722+ usleep(1000);
1723+
1724+ // create second modem to test the other code path
1725+ createModem("ril_1");
1726+ auto modem2_device = createOfonoModemDevice("/ril_1", "1");
1727+
1728+ setDisplayPowerState(DisplayPowerState::On);
1729+ usleep(1000);
1730+
1731+ EXPECT_NE(getStatisticsRefreshRateMs(wifi_device), 0);
1732+ EXPECT_NE(getStatisticsRefreshRateMs(modem1_device), 0);
1733+ EXPECT_NE(getStatisticsRefreshRateMs(modem2_device), 0);
1734+
1735+ // verify that no transfer icon is seen
1736+ EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
1737+ .item(mh::MenuItemMatcher()
1738+ .mode(mh::MenuItemMatcher::Mode::starts_with)
1739+ .state_icons({"gsm-3g-full", "gsm-3g-full", "nm-signal-100-secure"})
1740+ ).match());
1741+
1742+
1743+ setDeviceStatistics(wifi_device, 1, 0);
1744+ usleep(1000);
1745+ // verify that Tx icon is seen
1746+ EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
1747+ .item(mh::MenuItemMatcher()
1748+ .mode(mh::MenuItemMatcher::Mode::starts_with)
1749+ .state_icons({"gsm-3g-full", "gsm-3g-full", "nm-signal-100-secure", "transfer-progress-upload"})
1750+ ).match());
1751+
1752+ setDeviceStatistics(modem1_device, 0, 1);
1753+ usleep(1000);
1754+
1755+ // verify that TxRx icon is seen
1756+ EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
1757+ .item(mh::MenuItemMatcher()
1758+ .mode(mh::MenuItemMatcher::Mode::starts_with)
1759+ .state_icons({"gsm-3g-full", "gsm-3g-full", "nm-signal-100-secure", "transfer-progress"})
1760+ ).match());
1761+
1762+ sleep(2);
1763+
1764+ // verify that no transfer icon is seen
1765+ EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
1766+ .item(mh::MenuItemMatcher()
1767+ .mode(mh::MenuItemMatcher::Mode::starts_with)
1768+ .state_icons({"gsm-3g-full", "gsm-3g-full", "nm-signal-100-secure"})
1769+ ).match());
1770+
1771+ setDeviceStatistics(modem2_device, 0, 1);
1772+ usleep(1000);
1773+ // verify that Rx icon is seen
1774+ EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
1775+ .item(mh::MenuItemMatcher()
1776+ .mode(mh::MenuItemMatcher::Mode::starts_with)
1777+ .state_icons({"gsm-3g-full", "gsm-3g-full", "nm-signal-100-secure", "transfer-progress-download"})
1778+ ).match());
1779+
1780+
1781+ setDisplayPowerState(DisplayPowerState::Off);
1782+ usleep(1000);
1783+
1784+ EXPECT_EQ(getStatisticsRefreshRateMs(wifi_device), 0);
1785+ EXPECT_EQ(getStatisticsRefreshRateMs(modem1_device), 0);
1786+ EXPECT_EQ(getStatisticsRefreshRateMs(modem2_device), 0);
1787+
1788+
1789+ setDisplayPowerState(DisplayPowerState::On);
1790+ usleep(1000);
1791+
1792+ EXPECT_NE(getStatisticsRefreshRateMs(wifi_device), 0);
1793+ EXPECT_NE(getStatisticsRefreshRateMs(modem1_device), 0);
1794+ EXPECT_NE(getStatisticsRefreshRateMs(modem2_device), 0);
1795+
1796+ sleep(2);
1797+
1798+ // verify that no transfer icon is seen
1799+ EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
1800+ .item(mh::MenuItemMatcher()
1801+ .mode(mh::MenuItemMatcher::Mode::starts_with)
1802+ .state_icons({"gsm-3g-full", "gsm-3g-full", "nm-signal-100-secure"})
1803+ ).match());
1804+}
1805+
1806+TEST_F(TestIndicator, DataUsageIndication_disabled)
1807+{
1808+ setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
1809+ auto wifi_device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
1810+ auto ap = createAccessPoint("0", "the ssid", wifi_device);
1811+ auto connection = createAccessPointConnection("0", "the ssid", wifi_device);
1812+ createActiveConnection("0", wifi_device, connection, ap);
1813+
1814+ auto modem1_device = createOfonoModemDevice("/ril_0", "0");
1815+
1816+ ASSERT_NO_THROW(startIndicator());
1817+
1818+ // create second modem to test the other code path
1819+ createModem("ril_1");
1820+ auto modem2_device = createOfonoModemDevice("/ril_1", "1");
1821+
1822+ setDisplayPowerState(DisplayPowerState::On);
1823+
1824+ EXPECT_EQ(getStatisticsRefreshRateMs(wifi_device), 0);
1825+ EXPECT_EQ(getStatisticsRefreshRateMs(modem1_device), 0);
1826+ EXPECT_EQ(getStatisticsRefreshRateMs(modem2_device), 0);
1827+
1828+ // verify that no transfer icon is seen
1829+ EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
1830+ .item(mh::MenuItemMatcher()
1831+ .mode(mh::MenuItemMatcher::Mode::starts_with)
1832+ .state_icons({"gsm-3g-full", "gsm-3g-full", "nm-signal-100-secure"})
1833+ ).match());
1834+
1835+ setDisplayPowerState(DisplayPowerState::Off);
1836+
1837+ EXPECT_EQ(getStatisticsRefreshRateMs(wifi_device), 0);
1838+ EXPECT_EQ(getStatisticsRefreshRateMs(modem1_device), 0);
1839+ EXPECT_EQ(getStatisticsRefreshRateMs(modem2_device), 0);
1840+
1841+
1842+ setDisplayPowerState(DisplayPowerState::On);
1843+
1844+ EXPECT_EQ(getStatisticsRefreshRateMs(wifi_device), 0);
1845+ EXPECT_EQ(getStatisticsRefreshRateMs(modem1_device), 0);
1846+ EXPECT_EQ(getStatisticsRefreshRateMs(modem2_device), 0);
1847+
1848+ // verify that no transfer icon is seen
1849+ EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
1850+ .item(mh::MenuItemMatcher()
1851+ .mode(mh::MenuItemMatcher::Mode::starts_with)
1852+ .state_icons({"gsm-3g-full", "gsm-3g-full", "nm-signal-100-secure"})
1853+ ).match());
1854+}
1855+
1856+
1857 } // namespace

Subscribers

People subscribed via source and target branches