Merge lp:~charlesk/indicator-bluetooth/lp-1236249 into lp:indicator-bluetooth/13.10

Proposed by Charles Kerr
Status: Merged
Approved by: Ted Gould
Approved revision: 73
Merged at revision: 70
Proposed branch: lp:~charlesk/indicator-bluetooth/lp-1236249
Merge into: lp:indicator-bluetooth/13.10
Diff against target: 422 lines (+133/-84)
8 files modified
src/bluetooth.vala (+8/-41)
src/bluez.vala (+108/-26)
src/desktop.vala (+2/-6)
src/killswitch.vala (+7/-0)
src/main.vala (+1/-1)
src/org-bluez.vala (+1/-1)
src/phone.vala (+1/-1)
src/profile.vala (+5/-8)
To merge this branch: bzr merge lp:~charlesk/indicator-bluetooth/lp-1236249
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+190669@code.launchpad.net

Commit message

When the user chooses to toggle bluetooth on or off, if /dev/rfkill isn't available, fall back to toggling org.bluez.Adapter's Powered property.

Description of the change

* Use org.bluez.Adapter's Powered property to toggle bluetooth on and off. Skip /dev/rfkill entirely for 13.10, there are issues there that can't be resolved in time for 13.10.

* Leave the killswitch /dev/rfkill code in the codebase, though disabled for now, because it's likely to return post-13.10

* Do a better job of monitoring the bluez Manager and Adapter for changes s.t. the indicator can update its own state appropriately.

See also https://bugs.launchpad.net/ubuntu/+source/unity8/+bug/1236249/comments/8

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ted Gould (ted) wrote :

Don't see anything objectionable (a lot of code though). Works for me on my Galaxy Nexus.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/bluetooth.vala'
2--- src/bluetooth.vala 2013-10-10 19:58:46 +0000
3+++ src/bluetooth.vala 2013-10-14 23:34:48 +0000
4@@ -27,22 +27,19 @@
5 This work as a proxy for "does this hardware support bluetooth?" */
6 public abstract bool supported { get; protected set; }
7
8- /* True if there are any bluetooth adapters powered up on the system.
9- In short, whether or not this system's bluetooth is "on". */
10- public abstract bool powered { get; protected set; }
11+ /* True if bluetooth's enabled on this system.
12+ Bluetooth can be soft-blocked by software and hard-blocked physically,
13+ eg by a laptop's network killswitch */
14+ public abstract bool enabled { get; protected set; }
15+
16+ /* Try to enable/disable bluetooth. This can fail if it's overridden
17+ by the system, eg by a laptop's network killswitch */
18+ public abstract void try_set_enabled (bool b);
19
20 /* True if our system can be seen by other bluetooth devices */
21 public abstract bool discoverable { get; protected set; }
22 public abstract void try_set_discoverable (bool discoverable);
23
24- /* True if bluetooth's blocked. This can be soft-blocked by software and
25- * hard-blocked physically, eg by a laptop's network killswitch */
26- public abstract bool blocked { get; protected set; }
27-
28- /* Try to block/unblock bluetooth. This can fail if it's overridden
29- by the system, eg by a laptop's network killswitch */
30- public abstract void try_set_blocked (bool b);
31-
32 /* Get a list of the Device structs that we know about */
33 public abstract List<unowned Device> get_devices ();
34
35@@ -53,33 +50,3 @@
36 The device_key argument comes from the Device struct */
37 public abstract void set_device_connected (uint device_key, bool connected);
38 }
39-
40-
41-
42-/**
43- * Base class for Bluetooth objects that use a killswitch to implement
44- * the 'discoverable' property.
45- */
46-public abstract class KillswitchBluetooth: Object, Bluetooth
47-{
48- private KillSwitch killswitch;
49-
50- public KillswitchBluetooth (KillSwitch killswitch)
51- {
52- // always sync our 'blocked' property with the one in killswitch
53- this.killswitch = killswitch;
54- blocked = killswitch.blocked;
55- killswitch.notify["blocked"].connect (() => blocked = killswitch.blocked );
56- }
57-
58- public bool supported { get; protected set; default = false; }
59- public bool powered { get; protected set; default = false; }
60- public bool discoverable { get; protected set; default = false; }
61- public bool blocked { get; protected set; default = true; }
62- public void try_set_blocked (bool b) { killswitch.try_set_blocked (b); }
63-
64- // empty implementations
65- public abstract void try_set_discoverable (bool b);
66- public abstract List<unowned Device> get_devices ();
67- public abstract void set_device_connected (uint device_key, bool connected);
68-}
69
70=== modified file 'src/bluez.vala'
71--- src/bluez.vala 2013-10-10 19:58:46 +0000
72+++ src/bluez.vala 2013-10-14 23:34:48 +0000
73@@ -22,12 +22,25 @@
74 /**
75 * Bluetooth implementaion which uses org.bluez on DBus
76 */
77-public class Bluez: KillswitchBluetooth
78+public class Bluez: Bluetooth, Object
79 {
80 uint next_device_id = 1;
81 org.bluez.Manager manager;
82 org.bluez.Adapter default_adapter;
83
84+ private bool _powered = false;
85+
86+ private bool powered {
87+ get { return _powered; }
88+ set { _powered = value; update_enabled(); }
89+ }
90+
91+ private KillSwitch killswitch = null;
92+
93+ private string adapter_path = null;
94+
95+ private DBusConnection bus = null;
96+
97 /* maps an org.bluez.Device's object_path to the org.bluez.Device proxy */
98 HashTable<string,org.bluez.Device> path_to_proxy;
99
100@@ -40,44 +53,87 @@
101 /* maps our arbitrary unique id to a Bluetooth.Device struct for public consumption */
102 HashTable<uint,Device> id_to_device;
103
104- public Bluez (KillSwitch killswitch)
105+ public Bluez (KillSwitch? killswitch)
106 {
107- base (killswitch);
108+ try
109+ {
110+ bus = Bus.get_sync (BusType.SYSTEM);
111+ }
112+ catch (Error e)
113+ {
114+ critical (@"$(e.message)");
115+ }
116
117- string adapter_path = null;
118+ if ((killswitch != null) && (killswitch.is_valid()))
119+ {
120+ this.killswitch = killswitch;
121+ killswitch.notify["blocked"].connect (() => update_enabled());
122+ update_enabled ();
123+ }
124
125 id_to_path = new HashTable<uint,string> (direct_hash, direct_equal);
126 id_to_device = new HashTable<uint,Device> (direct_hash, direct_equal);
127 path_to_id = new HashTable<string,uint> (str_hash, str_equal);
128 path_to_proxy = new HashTable<string,org.bluez.Device> (str_hash, str_equal);
129
130+ reset_manager ();
131+ }
132+
133+ private void reset_manager ()
134+ {
135+ string new_adapter_path = null;
136 try
137 {
138- manager = Bus.get_proxy_sync (BusType.SYSTEM, "org.bluez", "/");
139+ manager = bus.get_proxy_sync ("org.bluez", "/");
140
141- // get the current default adapter & watch for future default adapters
142- adapter_path = manager.default_adapter ();
143+ // if the default adapter changes, update our connections
144 manager.default_adapter_changed.connect ((object_path)
145 => on_default_adapter_changed (object_path));
146+
147+ // if the current adapter disappears, call clear_adapter()
148+ manager.adapter_removed.connect ((object_path) => {
149+ if (object_path == adapter_path)
150+ clear_adapter ();
151+ });
152+
153+ // get the current default adapter & watch for future default adapters
154+ new_adapter_path = manager.default_adapter ();
155 }
156 catch (Error e)
157 {
158 critical (@"$(e.message)");
159 }
160
161- on_default_adapter_changed (adapter_path);
162- }
163-
164- private void on_default_adapter_changed (string? object_path)
165- {
166- supported = object_path != null;
167+ on_default_adapter_changed (new_adapter_path);
168+ }
169+
170+ private void clear_adapter ()
171+ {
172+ if (adapter_path != null)
173+ debug (@"clearing adapter; was using $adapter_path");
174+
175+ path_to_proxy.remove_all ();
176+ path_to_id.remove_all ();
177+ id_to_path.remove_all ();
178+ id_to_device.remove_all ();
179+
180+ default_adapter = null;
181+ adapter_path = null;
182+
183+ discoverable = false;
184+ powered = false;
185+ }
186+
187+ void on_default_adapter_changed (string? object_path)
188+ {
189+ clear_adapter ();
190
191 if (object_path != null) try
192 {
193- debug (@"using default adapter at $object_path");
194+ adapter_path = object_path;
195 default_adapter = Bus.get_proxy_sync (BusType.SYSTEM,
196 "org.bluez",
197- object_path);
198+ adapter_path);
199
200 default_adapter.property_changed.connect (()
201 => on_default_adapter_properties_changed ());
202@@ -104,6 +160,8 @@
203 on_default_adapter_properties_changed ();
204 }
205
206+ /* When the default adapter's properties change,
207+ update our own properties "powered" and "discoverable" */
208 private void on_default_adapter_properties_changed ()
209 {
210 bool is_discoverable = false;
211@@ -217,7 +275,6 @@
212 private void device_connect_on_interface (DBusProxy proxy,
213 string interface_name)
214 {
215- var bus = proxy.get_connection ();
216 var object_path = proxy.get_object_path ();
217
218 debug (@"trying to connect to $object_path: $(interface_name)");
219@@ -359,11 +416,21 @@
220 devices_changed ();
221 }
222
223+ /* update the 'enabled' property by looking at the killswitch state
224+ and the 'powered' property state */
225+ void update_enabled ()
226+ {
227+ var blocked = (killswitch != null) && killswitch.blocked;
228+ debug (@"in upate_enabled, powered is $powered, blocked is $blocked");
229+ enabled = powered && !blocked;
230+ }
231+
232+
233 ////
234 //// Public API
235 ////
236
237- public override void set_device_connected (uint id, bool connected)
238+ public void set_device_connected (uint id, bool connected)
239 {
240 var device = id_to_device.lookup (id);
241 var path = id_to_path.lookup (id);
242@@ -380,20 +447,35 @@
243 }
244 }
245
246- public override void try_set_discoverable (bool b)
247+ public void try_set_discoverable (bool b)
248 {
249- if (discoverable != b) try
250- {
251- default_adapter.set_property ("Discoverable", new Variant.boolean (b));
252- }
253- catch (Error e)
254- {
255- critical (@"$(e.message)");
256+ if (discoverable != b)
257+ {
258+ default_adapter.set_property.begin ("Discoverable", new Variant.boolean (b));
259 }
260 }
261
262- public override List<unowned Device> get_devices ()
263+ public List<unowned Device> get_devices ()
264 {
265 return id_to_device.get_values();
266 }
267+
268+ public bool supported { get; protected set; default = false; }
269+ public bool discoverable { get; protected set; default = false; }
270+ public bool enabled { get; protected set; default = false; }
271+
272+ public void try_set_enabled (bool b)
273+ {
274+ if (killswitch != null)
275+ {
276+ debug (@"setting killswitch blocked to $(!b)");
277+ killswitch.try_set_blocked (!b);
278+ }
279+ else if (default_adapter != null)
280+ {
281+ debug (@"setting bluez Adapter's Powered property to $b");
282+ default_adapter.set_property.begin ("Powered", new Variant.boolean (b));
283+ powered = b;
284+ }
285+ }
286 }
287
288=== modified file 'src/desktop.vala'
289--- src/desktop.vala 2013-10-10 19:58:46 +0000
290+++ src/desktop.vala 2013-10-14 23:34:48 +0000
291@@ -66,7 +66,7 @@
292
293 // know when to show the indicator & when to hide it
294 settings.changed["visible"].connect (()=> update_visibility());
295- bluetooth.notify.connect (() => update_visibility());
296+ bluetooth.notify["enabled"].connect (() => update_visibility());
297 update_visibility ();
298
299 // when devices change, rebuild our device section
300@@ -82,7 +82,7 @@
301
302 void update_visibility ()
303 {
304- visible = bluetooth.powered && !bluetooth.blocked && settings.get_boolean("visible");
305+ visible = bluetooth.enabled && settings.get_boolean("visible");
306 }
307
308 ///
309@@ -229,10 +229,6 @@
310 bluetooth.notify["discoverable"].connect (()
311 => action.set_state (bluetooth.discoverable));
312
313- action.set_enabled (bluetooth.powered);
314- bluetooth.notify["powered"].connect (()
315- => action.set_enabled (bluetooth.powered));
316-
317 return action;
318 }
319
320
321=== modified file 'src/killswitch.vala'
322--- src/killswitch.vala 2013-08-06 20:33:26 +0000
323+++ src/killswitch.vala 2013-10-14 23:34:48 +0000
324@@ -26,6 +26,8 @@
325 */
326 public interface KillSwitch: Object
327 {
328+ public abstract bool is_valid ();
329+
330 public abstract bool blocked { get; protected set; }
331
332 /* Try to block/unblock bluetooth.
333@@ -109,6 +111,11 @@
334 }
335 }
336
337+ public bool is_valid ()
338+ {
339+ return fd != -1;
340+ }
341+
342 private bool on_channel_event (IOChannel source, IOCondition condition)
343 {
344 read_event ();
345
346=== modified file 'src/main.vala'
347--- src/main.vala 2013-08-06 00:43:18 +0000
348+++ src/main.vala 2013-10-14 23:34:48 +0000
349@@ -26,7 +26,7 @@
350 Intl.textdomain (Config.GETTEXT_PACKAGE);
351
352 // create the backend
353- var bluetooth = new Bluez (new RfKillSwitch ());
354+ var bluetooth = new Bluez (null);
355
356 // start the service
357 var service = new Service (bluetooth);
358
359=== modified file 'src/org-bluez.vala'
360--- src/org-bluez.vala 2013-08-01 23:21:05 +0000
361+++ src/org-bluez.vala 2013-10-14 23:34:48 +0000
362@@ -69,7 +69,7 @@
363 public abstract GLib.HashTable<string, GLib.Variant> get_properties() throws DBusError, IOError;
364
365 [DBus (name = "SetProperty")]
366- public abstract void set_property(string name, GLib.Variant value) throws DBusError, IOError;
367+ public abstract async void set_property(string name, GLib.Variant value) throws DBusError, IOError;
368
369 [DBus (name = "RequestSession")]
370 public abstract void request_session() throws DBusError, IOError;
371
372=== modified file 'src/phone.vala'
373--- src/phone.vala 2013-10-10 19:58:46 +0000
374+++ src/phone.vala 2013-10-14 23:34:48 +0000
375@@ -53,7 +53,7 @@
376
377 void update_visibility ()
378 {
379- visible = bluetooth.powered && !bluetooth.blocked;
380+ visible = bluetooth.enabled;
381 }
382
383 ///
384
385=== modified file 'src/profile.vala'
386--- src/profile.vala 2013-10-10 19:58:46 +0000
387+++ src/profile.vala 2013-10-14 23:34:48 +0000
388@@ -123,16 +123,16 @@
389 {
390 var action = new SimpleAction.stateful ("bluetooth-enabled",
391 null,
392- !bluetooth.blocked);
393+ bluetooth.enabled);
394
395 action.activate.connect (()
396 => action.change_state (!action.get_state().get_boolean()));
397
398 action.change_state.connect ((action, requestedValue)
399- => bluetooth.try_set_blocked (!requestedValue.get_boolean()));
400+ => bluetooth.try_set_enabled (requestedValue.get_boolean()));
401
402- bluetooth.notify["blocked"].connect (()
403- => action.set_state (!bluetooth.blocked));
404+ bluetooth.notify["enabled"].connect (()
405+ => action.set_state (bluetooth.enabled));
406
407 return action;
408 }
409@@ -144,12 +144,9 @@
410
411 protected Variant action_state_for_root ()
412 {
413- var blocked = bluetooth.blocked;
414- var powered = bluetooth.powered;
415-
416 string a11y;
417 string icon_name;
418- if (powered && !blocked)
419+ if (bluetooth.enabled)
420 {
421 a11y = "Bluetooth (on)";
422 icon_name = "bluetooth-active";

Subscribers

People subscribed via source and target branches