Merge lp:~thomas-voss/platform-api/hw-alarms-api into lp:platform-api

Proposed by Thomas Voß
Status: Merged
Approved by: Ricardo Salveti
Approved revision: 214
Merged at revision: 218
Proposed branch: lp:~thomas-voss/platform-api/hw-alarms-api
Merge into: lp:platform-api
Diff against target: 704 lines (+540/-8)
15 files modified
data/CMakeLists.txt (+6/-2)
data/ubuntu-platform-hardware-api.pc.in (+10/-0)
debian/control (+2/-1)
debian/libplatform-api1-hybris-tests.install (+2/-1)
debian/libplatform-hardware-api1-dev.install (+1/-1)
debian/libubuntu-platform-hardware-api1.symbols (+7/-0)
include/ubuntu/hardware/CMakeLists.txt (+2/-1)
include/ubuntu/hardware/alarm.h (+104/-0)
src/ubuntu/CMakeLists.txt (+7/-0)
src/ubuntu/hardware/CMakeLists.txt (+9/-0)
src/ubuntu/hardware/alarm.cpp (+304/-0)
src/ubuntu/hybris/CMakeLists.txt (+7/-2)
src/ubuntu/hybris/tests/CMakeLists.txt (+4/-0)
src/ubuntu/hybris/tests/test_alarms_api.cpp (+74/-0)
src/ubuntu/hybris/ubuntu_platform_hardware_api.cpp (+1/-0)
To merge this branch: bzr merge lp:~thomas-voss/platform-api/hw-alarms-api
Reviewer Review Type Date Requested Status
Ricardo Salveti (community) Approve
PS Jenkins bot continuous-integration Approve
Charles Kerr (community) Approve
Review via email: mp+210592@code.launchpad.net

Commit message

Add hw alarm api implementation for android's /dev/alarm.
Add simple test executable for hw alarm api implementation on android.
Adjust interface signatures to make sure that status of operations is reported correctly.
Add HW Alarms API interface definition.
Add Ubuntu implementation that will bridge over to the android world.

Description of the change

Add hw alarm api implementation for android's /dev/alarm.
Add simple test executable for hw alarm api implementation on android.
Adjust interface signatures to make sure that status of operations is reported correctly.
Add HW Alarms API interface definition.
Add Ubuntu implementation that will bridge over to the android world.

* Is your branch in sync with latest trunk: yes
* Did you build your software in a clean sbuild/pbuilder chroot or ppa? yes
* Did you build your software in a clean sbuild/pbuilder armhf chroot or ppa? yes
* Has a 5 minute exploratory testing run been executed on N4? yes
* If you changed the packaging (debian), did you subscribe a core-dev to this MP? N/A
* If you changed the UI, did you subscribe the design-reviewers to this MP? N/A
* What components might get impacted by your changes? Indicator-Datetime, Clock App
* Have you requested review by the teams of these owning components? Yes

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
Ricardo Salveti (rsalveti) wrote :

31 + libEGL \
32 + libGLESv2 \

Do we really need to link to EGL/GLESv2 in here?

Can you also add a simple test that can be consumed from the ubuntu side as well?

review: Needs Fixing
201. By Thomas Voß

Add test-case runnable from the Ubuntu side.
Adjust linker flags according to review.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Ricardo Salveti (rsalveti) wrote :

dh_install: usr/bin/test_hardware_alarms_api exists in debian/tmp but is not installed to anywhere

Need to add it to be installed.

review: Needs Fixing
202. By Thomas Voß

Add newly added test executable to packaging setup.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Omer Akram (om26er) wrote :

57 + * Copyright © 2013 Canonical Ltd.

maybe change that and other headers to 2014 :)

Revision history for this message
Charles Kerr (charlesk) wrote :

A couple of small points and one question:

* in include/ubuntu/hardware/CMakeLists.txt, need to add 'alarm.h' to UBUNTU_HARDWARE_HEADERS

* in UbuntuHardwareAlarm::set() if ioctl(fd, ANDROID_ALARM_SET(type), ts) fails, we should include strerror(errno) in the ALOGE call.

* in UbuntuHardwareAlarm::~UbuntuHardwareAlarm(), need to check fd is valid before closing. If open() couldn't fail, is_valid() wouldn't be needed...

* in u_hardware_alarm_set_timezone() (a) I'm unclear on the use case for this function and (b) it's got a questionable use of settimeofday(NULL, tz). settimeofday(2) says:

       Under Linux there are some peculiar "warp clock" semantics associated
       with the settimeofday() system call if on the very first call (after
       booting) that has a non-NULL tz argument, the tv argument is NULL and
       the tz_minuteswest field is nonzero. (The tz_dsttime field should be
       zero for this case.) In such a case it is assumed that the CMOS clock
       is on local time, and that it has to be incremented by this amount to
       get UTC system time. No doubt it is a bad idea to use this feature.

review: Needs Information
Revision history for this message
Charles Kerr (charlesk) wrote :

* I blame my self for not asking sooner, since I did review the API when it was just in header form, but what are the steps for cancelling an alarm to reset it?

Consider indicator-datetime. It doesn't know when the hardware is going to sleep, so whenever there are alarms set it's going to need a thread that's blocked inside ua_hardware_alarm_wait_for_next_alarm(). Then the user edits/deletes the EDS alarm that was going to trigger next. indicator-datetime is going to need to reset the alarm and call wait again. What should happen to the first wait?

203. By Thomas Voß

Address reviewer comments.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Thomas Voß (thomas-voss) wrote :

> * I blame my self for not asking sooner, since I did review the API when it
> was just in header form, but what are the steps for cancelling an alarm to
> reset it?
>
> Consider indicator-datetime. It doesn't know when the hardware is going to
> sleep, so whenever there are alarms set it's going to need a thread that's
> blocked inside ua_hardware_alarm_wait_for_next_alarm(). Then the user
> edits/deletes the EDS alarm that was going to trigger next. indicator-datetime
> is going to need to reset the alarm and call wait again. What should happen to
> the first wait?

You only need one wait, no need to reset the blocking wait. The android alarm service takes a very similar approach when using /dev/alarm:

  * http://androidxref.com/4.4.2_r2/xref/frameworks/base/services/java/com/android/server/AlarmManagerService.java#655
  * http://androidxref.com/4.4.2_r2/xref/frameworks/base/services/java/com/android/server/AlarmManagerService.java#1155

Revision history for this message
Charles Kerr (charlesk) wrote :

LGTM.

review: Approve
204. By Thomas Voß

Add a pkgconfig file for the hardware portions of the platform api.
Install hardware/alarm.h.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
205. By Thomas Voß

Make sure that pkgconfig file for hardware abstractions is installed in debian package.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
206. By Thomas Voß

Remove exception-based error handling.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
207. By Thomas Voß

[ Gerry Boland ]
* Manually call mir's SurfacePlacementStrategy::place and
  SessionListener::surface_created methods for in process client
  Surface Mir 0.1.8 refactoring causes in-process client surfaces to
  be an implementation detail of Mir's surface stack, and prevents
  shell from getting access to its surface to position it and define
  input areas on it. To fix this,we perform the following: 1. Create
  an InProcessClientSession to represent the in-process client 2. Get
  access to Mir's SurfacePlacementStrategy object and call its place
  method explicitly, to allow shell to position its surface 3. Get
  access to Mir's SessionListener object and call its surface_created
  method explicitly, to notify shell its surface was created
[ Alan Griffiths ]
* Changes for compatibility with Mir 0.1.8
[ Ubuntu daily release ]
* New rebuild forced
[ Andreas Pokorny ]
* CMakeLists adaptation to make platform-api cross compile with a
  simple chroot setup. Note that <PKG_NAME>_LINK_LIBRARIES variables
  were removed from link_directories and respective <PKG_NAME>_LDFLAGS
  variables were instead put into target_link_libraries. Those
  informations attached to targets are transitively forwarded to the
  user of the library. link_directories only attaches the information
  to the source directory.
[ Chris Gagnon ]
* enable getting coverage in CI
[ Ubuntu daily release ]
* New rebuild forced
[ Kevin Gunn ]
* bump to mir0.1.7
[ Kevin Gunn ]
* bump debian dep to mir0.1.6
[ Łukasz 'sil2100' Zemczak ]
* Bump the build-dependency on dbus-cpp due to the ABI change

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
208. By Thomas Voß

Rename enumeration constant in alarms from _NOW to _RTC.
[ Alberto Aguirre ]
* needed for mir019
[ Ubuntu daily release ]
* New rebuild forced

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
209. By Thomas Voß

Adjust test case to account for adjusted naming of enumeration value.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
210. By Thomas Voß

Add a function for querying the time since boot from /dev/alarm.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
211. By Thomas Voß

Adjust test case on the Ubuntu side.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
212. By Thomas Voß

Add missing header.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
213. By Thomas Voß

[ Gerry Boland ]
[Daniel d'Andrada]
* Add ua_ui_window_get_size().

[Gerry Boland]
* Bump package version to match library version.
[ Ricardo Mendoza ]
* Change sensors API to allow for GCC 4.8 building across all clients
  Ubuntu-side

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ricardo Salveti (rsalveti) wrote :

Please correct me if I'm wrong, but we don't need a hybris implementation for such feature, as it uses ioctl on a known hardware device (/dev/alarm).

Did you try executing the same abstraction natively on ubuntu? I'd prefer it to not touch the android side unless it's really needed.

review: Needs Information
214. By Thomas Voß

Refactored hw-alarms implementation to live on the Ubuntu-side.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ricardo Salveti (rsalveti) wrote :

Looks fine and test seems to be working as expected.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/CMakeLists.txt'
2--- data/CMakeLists.txt 2013-06-13 12:04:14 +0000
3+++ data/CMakeLists.txt 2014-05-21 07:20:43 +0000
4@@ -2,7 +2,11 @@
5 ubuntu-platform-api.pc.in ubuntu-platform-api.pc @ONLY
6 )
7
8+configure_file(
9+ ubuntu-platform-hardware-api.pc.in ubuntu-platform-hardware-api.pc @ONLY
10+)
11+
12 install(
13- FILES ${CMAKE_CURRENT_BINARY_DIR}/ubuntu-platform-api.pc
14+ FILES ${CMAKE_CURRENT_BINARY_DIR}/ubuntu-platform-api.pc ${CMAKE_CURRENT_BINARY_DIR}/ubuntu-platform-hardware-api.pc
15 DESTINATION lib/${CMAKE_LIBRARY_ARCHITECTURE}/pkgconfig
16-)
17\ No newline at end of file
18+)
19
20=== added file 'data/ubuntu-platform-hardware-api.pc.in'
21--- data/ubuntu-platform-hardware-api.pc.in 1970-01-01 00:00:00 +0000
22+++ data/ubuntu-platform-hardware-api.pc.in 2014-05-21 07:20:43 +0000
23@@ -0,0 +1,10 @@
24+prefix=@CMAKE_INSTALL_PREFIX@
25+exec_prefix=${prefix}
26+libdir=${prefix}/@LIB_INSTALL_DIR@
27+includedir=${exec_prefix}/include
28+
29+Name: ubuntu_platform_hardware_api
30+Description: Ubuntu's platform hardware abstraction layer.
31+Version: @UBUNTU_PLATFORM_API_VERSION_MAJOR@.@UBUNTU_PLATFORM_API_VERSION_MINOR@.@UBUNTU_PLATFORM_API_VERSION_PATCH@
32+Libs: -L${libdir} -lubuntu_platform_hardware_api
33+Cflags: -I${includedir}/ubuntu
34
35=== modified file 'debian/control'
36--- debian/control 2014-05-07 07:39:57 +0000
37+++ debian/control 2014-05-21 07:20:43 +0000
38@@ -2,7 +2,8 @@
39 Priority: optional
40 Section: devel
41 Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
42-Build-Depends: cmake,
43+Build-Depends: android-headers,
44+ cmake,
45 debhelper (>= 9),
46 doxygen,
47 graphviz,
48
49=== modified file 'debian/libplatform-api1-hybris-tests.install'
50--- debian/libplatform-api1-hybris-tests.install 2013-08-17 05:22:31 +0000
51+++ debian/libplatform-api1-hybris-tests.install 2014-05-21 07:20:43 +0000
52@@ -3,4 +3,5 @@
53 usr/bin/test_android_ubuntu_app_api
54 usr/bin/test_android_ubuntu_app_api_multiple_surfaces
55 usr/bin/test_android_ubuntu_session_api
56-usr/bin/test_ubuntu_app_api_location_service
57\ No newline at end of file
58+usr/bin/test_ubuntu_app_api_location_service
59+usr/bin/test_hardware_alarms_api
60
61=== modified file 'debian/libplatform-hardware-api1-dev.install'
62--- debian/libplatform-hardware-api1-dev.install 2013-07-08 10:39:36 +0000
63+++ debian/libplatform-hardware-api1-dev.install 2014-05-21 07:20:43 +0000
64@@ -1,2 +1,2 @@
65 usr/lib/*/libubuntu_platform_hardware_api.so
66-
67+usr/lib/*/pkgconfig/ubuntu-platform-hardware-api.pc
68
69=== modified file 'debian/libubuntu-platform-hardware-api1.symbols'
70--- debian/libubuntu-platform-hardware-api1.symbols 2013-07-17 14:29:04 +0000
71+++ debian/libubuntu-platform-hardware-api1.symbols 2014-05-21 07:20:43 +0000
72@@ -1,4 +1,11 @@
73 libubuntu_platform_hardware_api.so.1 libubuntu-platform-hardware-api1 #MINVER#
74+ u_hardware_alarm_create@Base 0replaceme
75+ u_hardware_alarm_get_elapsed_real_time@Base 0replaceme
76+ u_hardware_alarm_ref@Base 0replaceme
77+ u_hardware_alarm_set_relative_to_with_behavior@Base 0replaceme
78+ u_hardware_alarm_set_timezone@Base 0replaceme
79+ u_hardware_alarm_unref@Base 0replaceme
80+ u_hardware_alarm_wait_for_next_alarm@Base 0replaceme
81 u_hardware_gps_delete@Base 0.18.2+13.10.20130709
82 u_hardware_gps_delete_aiding_data@Base 0.18.2+13.10.20130709
83 u_hardware_gps_inject_location@Base 0.18.2+13.10.20130709
84
85=== modified file 'include/ubuntu/hardware/CMakeLists.txt'
86--- include/ubuntu/hardware/CMakeLists.txt 2013-07-18 09:08:17 +0000
87+++ include/ubuntu/hardware/CMakeLists.txt 2014-05-21 07:20:43 +0000
88@@ -1,9 +1,10 @@
89 set(
90 UBUNTU_HARDWARE_HEADERS
91+ alarm.h
92 gps.h
93 )
94
95 install(
96 FILES ${UBUNTU_HARDWARE_HEADERS}
97 DESTINATION include/ubuntu/hardware
98-)
99\ No newline at end of file
100+)
101
102=== added file 'include/ubuntu/hardware/alarm.h'
103--- include/ubuntu/hardware/alarm.h 1970-01-01 00:00:00 +0000
104+++ include/ubuntu/hardware/alarm.h 2014-05-21 07:20:43 +0000
105@@ -0,0 +1,104 @@
106+/*
107+ * Copyright © 2014 Canonical Ltd.
108+ *
109+ * This program is free software: you can redistribute it and/or modify
110+ * it under the terms of the GNU Lesser General Public License version 3 as
111+ * published by the Free Software Foundation.
112+ *
113+ * This program is distributed in the hope that it will be useful,
114+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
115+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
116+ * GNU Lesser General Public License for more details.
117+ *
118+ * You should have received a copy of the GNU Lesser General Public License
119+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
120+ *
121+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
122+ */
123+#ifndef UBUNTU_HARDWARE_ALARM_H_
124+#define UBUNTU_HARDWARE_ALARM_H_
125+
126+#include <ubuntu/status.h>
127+#include <ubuntu/visibility.h>
128+
129+#ifdef __cplusplus
130+extern "C" {
131+#endif
132+
133+/** The time reference that alarms are setup to. */
134+typedef enum
135+{
136+ U_HARDWARE_ALARM_TIME_REFERENCE_BOOT, /**< Relative to the device's boot time, including sleep. */
137+ U_HARDWARE_ALARM_TIME_REFERENCE_RTC /**< Wall clock time in UTC. */
138+} UbuntuHardwareAlarmTimeReference;
139+
140+typedef UbuntuHardwareAlarmTimeReference UHardwareAlarmTimeReference;
141+
142+/** Describes if an alarm is able to wakup the device from sleep. */
143+typedef enum
144+{
145+ /** Alarm will wakeup the device from sleep. */
146+ U_HARDWARE_ALARM_SLEEP_BEHAVIOR_WAKEUP_DEVICE,
147+ /** Alarm will not wakeup the device and will be delivered on the next wakeup of the device */
148+ U_HARDWARE_ALARM_SLEEP_BEHAVIOR_KEEP_DEVICE_ASLEEP
149+} UbuntuHardwareAlarmSleepBehavior;
150+
151+typedef UbuntuHardwareAlarmSleepBehavior UHardwareAlarmSleepBehavior;
152+
153+/** Bundles the time reference and sleep/wakeup behavior when waiting for an alarm to happen. */
154+typedef struct
155+{
156+ UHardwareAlarmTimeReference reference;
157+ UHardwareAlarmSleepBehavior sleep_behavior;
158+} UbuntuHardwareAlarmWaitResult;
159+
160+typedef UbuntuHardwareAlarmWaitResult UHardwareAlarmWaitResult;
161+
162+/** Opaque type modelling access to the kernel/hw-level alarm capabilities. */
163+typedef struct UbuntuHardwareAlarm* UHardwareAlarm;
164+
165+/** Creates an instance and/or increments its refcount. */
166+UBUNTU_DLL_PUBLIC UHardwareAlarm
167+u_hardware_alarm_create();
168+
169+/** Increments the instance's ref count. */
170+UBUNTU_DLL_PUBLIC void
171+u_hardware_alarm_ref(
172+ UHardwareAlarm alarm);
173+
174+/** Decrements the instance's ref count. */
175+UBUNTU_DLL_PUBLIC void
176+u_hardware_alarm_unref(
177+ UHardwareAlarm alarm);
178+
179+/** Query the time that elapsed since boot, including deep sleeps. */
180+UBUNTU_DLL_PUBLIC UStatus
181+u_hardware_alarm_get_elapsed_real_time(
182+ UHardwareAlarm alarm,
183+ struct timespec *tz);
184+
185+/** Reports a timezone change to kernel and HW. */
186+UBUNTU_DLL_PUBLIC UStatus
187+u_hardware_alarm_set_timezone(
188+ UHardwareAlarm alarm,
189+ const struct timezone *tz);
190+
191+/** Sets and arms a timer. */
192+UBUNTU_DLL_PUBLIC UStatus
193+u_hardware_alarm_set_relative_to_with_behavior(
194+ UHardwareAlarm alarm,
195+ UHardwareAlarmTimeReference time_reference,
196+ UHardwareAlarmSleepBehavior behavior,
197+ const struct timespec *ts);
198+
199+/** Blocks until the next alarm occurs. */
200+UBUNTU_DLL_PUBLIC UStatus
201+u_hardware_alarm_wait_for_next_alarm(
202+ UHardwareAlarm alarm,
203+ UHardwareAlarmWaitResult *result);
204+
205+#ifdef __cplusplus
206+}
207+#endif
208+
209+#endif
210
211=== modified file 'src/ubuntu/CMakeLists.txt'
212--- src/ubuntu/CMakeLists.txt 2013-12-02 17:03:45 +0000
213+++ src/ubuntu/CMakeLists.txt 2014-05-21 07:20:43 +0000
214@@ -3,6 +3,7 @@
215 )
216
217 add_subdirectory(application)
218+add_subdirectory(hardware)
219 add_subdirectory(testbackend)
220
221 set(
222@@ -12,6 +13,12 @@
223 ubuntu_application_url_dispatcher
224 )
225
226+set(
227+ UBUNTU_HARDWARE_API_LINK_LIBRARIES
228+
229+ ubuntu_hardware_alarm
230+)
231+
232 if(ENABLE_HYBRIS_IMPLEMENTATION)
233 add_subdirectory(hybris/)
234 endif()
235
236=== added directory 'src/ubuntu/hardware'
237=== added file 'src/ubuntu/hardware/CMakeLists.txt'
238--- src/ubuntu/hardware/CMakeLists.txt 1970-01-01 00:00:00 +0000
239+++ src/ubuntu/hardware/CMakeLists.txt 2014-05-21 07:20:43 +0000
240@@ -0,0 +1,9 @@
241+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -fPIC")
242+
243+include_directories(/usr/include/android)
244+
245+add_library(
246+ ubuntu_hardware_alarm
247+
248+ alarm.cpp
249+)
250\ No newline at end of file
251
252=== added file 'src/ubuntu/hardware/alarm.cpp'
253--- src/ubuntu/hardware/alarm.cpp 1970-01-01 00:00:00 +0000
254+++ src/ubuntu/hardware/alarm.cpp 2014-05-21 07:20:43 +0000
255@@ -0,0 +1,304 @@
256+/*
257+ * Copyright © 2013 Canonical Ltd.
258+ *
259+ * This program is free software: you can redistribute it and/or modify
260+ * it under the terms of the GNU Lesser General Public License version 3 as
261+ * published by the Free Software Foundation.
262+ *
263+ * This program is distributed in the hope that it will be useful,
264+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
265+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
266+ * GNU Lesser General Public License for more details.
267+ *
268+ * You should have received a copy of the GNU Lesser General Public License
269+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
270+ *
271+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
272+ */
273+
274+#include <android/linux/android_alarm.h>
275+
276+#include <ubuntu/hardware/alarm.h>
277+
278+#include <cstdio>
279+#include <cstring>
280+
281+#include <stdexcept>
282+#include <string>
283+
284+#include <unistd.h>
285+
286+#include <errno.h>
287+#include <fcntl.h>
288+
289+#include <sys/ioctl.h>
290+#include <sys/time.h>
291+#include <sys/types.h>
292+
293+namespace
294+{
295+struct HardwareAlarm
296+{
297+ HardwareAlarm() = default;
298+ virtual ~HardwareAlarm() = default;
299+
300+ // Blocks the calling thread until an alarm fires or
301+ // an error occurs. Returns an int with bool semantics.
302+ virtual int wait_for() = 0;
303+
304+ // Arms the alarm with the given properties.
305+ // Returns true if the alarm has been armed successfully, false otherwise.
306+ virtual bool set(
307+ UHardwareAlarmTimeReference time_reference,
308+ UHardwareAlarmSleepBehavior behavior,
309+ const struct timespec *ts) = 0;
310+
311+ // Queries the time since last boot including deep sleep periods.
312+ virtual bool get_elapsed_realtime(struct timespec* ts) = 0;
313+};
314+
315+// An implementation of HardwareAlarm based on Android's /dev/alarm.
316+struct DevAlarmHardwareAlarm : public HardwareAlarm
317+{
318+ int fd; // file descriptor referring to /dev/alarm
319+
320+ DevAlarmHardwareAlarm() : fd(open("/dev/alarm", O_RDWR))
321+ {
322+ if (fd == -1)
323+ {
324+ auto error = errno;
325+
326+ std::string what
327+ {
328+ "Could not open /dev/alarm: "
329+ };
330+ throw std::runtime_error
331+ {
332+ (what + strerror(error)).c_str()
333+ };
334+ }
335+ }
336+
337+ ~DevAlarmHardwareAlarm()
338+ {
339+ // No need to check if fd is valid here.
340+ // Ctor would have thrown if fd was invalid.
341+ ::close(fd);
342+ }
343+
344+ int wait_for()
345+ {
346+ int result{-1};
347+
348+ do
349+ {
350+ result = ::ioctl(fd, ANDROID_ALARM_WAIT);
351+ } while (result < 0 && errno == EINTR);
352+
353+ if (result < 0)
354+ fprintf(stderr, "Waiting for hw alarm failed with: %s\n", strerror(errno));
355+
356+ return result;
357+ }
358+
359+ bool set(UHardwareAlarmTimeReference time_reference,
360+ UHardwareAlarmSleepBehavior behavior,
361+ const struct timespec *ts)
362+ {
363+ if (not ts)
364+ return false;
365+
366+ int type = 0;
367+
368+ if (time_reference == U_HARDWARE_ALARM_TIME_REFERENCE_BOOT)
369+ switch(behavior)
370+ {
371+ case U_HARDWARE_ALARM_SLEEP_BEHAVIOR_WAKEUP_DEVICE:
372+ type = ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK;
373+ break;
374+ case U_HARDWARE_ALARM_SLEEP_BEHAVIOR_KEEP_DEVICE_ASLEEP:
375+ type = ANDROID_ALARM_ELAPSED_REALTIME_MASK;
376+ break;
377+ }
378+ else if (time_reference == U_HARDWARE_ALARM_TIME_REFERENCE_RTC)
379+ switch(behavior)
380+ {
381+ case U_HARDWARE_ALARM_SLEEP_BEHAVIOR_WAKEUP_DEVICE:
382+ type = ANDROID_ALARM_RTC_WAKEUP_MASK;
383+ break;
384+ case U_HARDWARE_ALARM_SLEEP_BEHAVIOR_KEEP_DEVICE_ASLEEP:
385+ type = ANDROID_ALARM_RTC_MASK;
386+ break;
387+ }
388+
389+ int result = ::ioctl(fd, ANDROID_ALARM_SET(type), ts);
390+
391+ if (result < 0)
392+ fprintf(stderr, "Unable to set alarm: %s\n", strerror(errno));
393+
394+ return not (result < 0);
395+ }
396+
397+ bool get_elapsed_realtime(struct timespec* ts)
398+ {
399+ if (not ts)
400+ return false;
401+
402+ int result = ::ioctl(
403+ fd,
404+ ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME),
405+ ts);
406+
407+ return result == 0;
408+ }
409+};
410+}
411+
412+class UbuntuHardwareAlarm
413+{
414+ public:
415+ static UbuntuHardwareAlarm& instance()
416+ {
417+ static UbuntuHardwareAlarm ha;
418+ return ha;
419+ }
420+
421+ int wait_for()
422+ {
423+ return impl->wait_for();
424+ }
425+
426+ bool set(UHardwareAlarmTimeReference time_reference,
427+ UHardwareAlarmSleepBehavior behavior,
428+ const struct timespec *ts)
429+ {
430+ return impl->set(time_reference, behavior, ts);
431+ }
432+
433+ bool get_elapsed_realtime(struct timespec* ts)
434+ {
435+ return impl->get_elapsed_realtime(ts);
436+ }
437+
438+ bool is_valid() const
439+ {
440+ return impl != nullptr;
441+ }
442+
443+ private:
444+ UbuntuHardwareAlarm()
445+ {
446+ try
447+ {
448+ impl = new DevAlarmHardwareAlarm();
449+ } catch(const std::runtime_error& e)
450+ {
451+ fprintf(
452+ stderr, "%s: Error creating /dev/alarm-based implementation with: %s\n",
453+ __PRETTY_FUNCTION__,
454+ e.what());
455+
456+ // TODO: Should we fallback to a timer-fd implementation here? I'm not
457+ // convinced that we should do so as a timer-fd wouldn't wakeup the device
458+ // from any sort of sleep mode.
459+ }
460+ }
461+
462+ ~UbuntuHardwareAlarm()
463+ {
464+ delete impl;
465+ }
466+
467+ HardwareAlarm* impl
468+ {
469+ nullptr
470+ };
471+};
472+
473+UHardwareAlarm
474+u_hardware_alarm_create()
475+{
476+ auto result = &UbuntuHardwareAlarm::instance();
477+
478+ if (result)
479+ if (result->is_valid())
480+ return result;
481+
482+ return NULL;
483+}
484+
485+void
486+u_hardware_alarm_ref(
487+ UHardwareAlarm alarm)
488+{
489+ // Considering a singleton pattern here, just voiding the argument.
490+ (void) alarm;
491+}
492+
493+void
494+u_hardware_alarm_unref(
495+ UHardwareAlarm alarm)
496+{
497+ // Considering a singleton pattern here, just voiding the argument.
498+ (void) alarm;
499+}
500+
501+UStatus
502+u_hardware_alarm_get_elapsed_real_time(
503+ UHardwareAlarm alarm,
504+ struct timespec* ts)
505+{
506+ return alarm->get_elapsed_realtime(ts) ? U_STATUS_SUCCESS : U_STATUS_ERROR;
507+}
508+
509+UStatus
510+u_hardware_alarm_set_timezone(
511+ UHardwareAlarm alarm,
512+ const struct timezone *tz)
513+{
514+ int result = settimeofday(NULL, tz);
515+
516+ if (result < 0)
517+ return U_STATUS_ERROR;
518+
519+ return U_STATUS_SUCCESS;
520+}
521+
522+UStatus
523+u_hardware_alarm_set_relative_to_with_behavior(
524+ UHardwareAlarm alarm,
525+ UHardwareAlarmTimeReference time_reference,
526+ UHardwareAlarmSleepBehavior behavior,
527+ const struct timespec *ts)
528+{
529+ return alarm->set(time_reference, behavior, ts) ?
530+ U_STATUS_SUCCESS :
531+ U_STATUS_ERROR;
532+
533+}
534+
535+UStatus
536+u_hardware_alarm_wait_for_next_alarm(
537+ UHardwareAlarm alarm,
538+ UHardwareAlarmWaitResult *result)
539+{
540+ int rc = alarm->wait_for();
541+
542+ if (rc < 0)
543+ return U_STATUS_ERROR;
544+
545+ if ((rc & ANDROID_ALARM_RTC_MASK) ||
546+ (rc & ANDROID_ALARM_RTC_WAKEUP_MASK))
547+ result->reference = U_HARDWARE_ALARM_TIME_REFERENCE_BOOT;
548+ else if ((rc & ANDROID_ALARM_ELAPSED_REALTIME_MASK) ||
549+ (rc & ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK))
550+ result->reference = U_HARDWARE_ALARM_TIME_REFERENCE_RTC;
551+
552+ if ((rc & ANDROID_ALARM_RTC_WAKEUP_MASK) ||
553+ (rc & ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK))
554+ result->sleep_behavior = U_HARDWARE_ALARM_SLEEP_BEHAVIOR_WAKEUP_DEVICE;
555+ else
556+ result->sleep_behavior = U_HARDWARE_ALARM_SLEEP_BEHAVIOR_KEEP_DEVICE_ASLEEP;
557+
558+ return U_STATUS_SUCCESS;
559+}
560
561=== modified file 'src/ubuntu/hybris/CMakeLists.txt'
562--- src/ubuntu/hybris/CMakeLists.txt 2014-02-12 07:35:37 +0000
563+++ src/ubuntu/hybris/CMakeLists.txt 2014-05-21 07:20:43 +0000
564@@ -20,13 +20,18 @@
565 ubuntu_application_api
566
567 "-Wl,--whole-archive"
568- ${UBUNTU_APPLICATION_API_LINK_LIBRARIES}
569+ ${UBUNTU_APPLICATION_API_LINK_LIBRARIES}
570 "-Wl,--no-whole-archive"
571 ${Hybris}
572 )
573
574 target_link_libraries(
575 ubuntu_platform_hardware_api
576+
577+ "-Wl,--whole-archive"
578+ ${UBUNTU_HARDWARE_API_LINK_LIBRARIES}
579+ "-Wl,--no-whole-archive"
580+
581 dl
582 ${Hybris}
583 )
584@@ -46,7 +51,7 @@
585 )
586
587 install(
588- TARGETS ubuntu_application_api
589+ TARGETS ubuntu_application_api
590 ${INSTALL_TARGETS_DEFAULT_ARGS}
591 )
592
593
594=== modified file 'src/ubuntu/hybris/tests/CMakeLists.txt'
595--- src/ubuntu/hybris/tests/CMakeLists.txt 2013-08-17 05:22:31 +0000
596+++ src/ubuntu/hybris/tests/CMakeLists.txt 2014-05-21 07:20:43 +0000
597@@ -18,6 +18,9 @@
598 add_executable(test_ubuntu_app_api_location_service test_location_api.cpp)
599 target_link_libraries(test_ubuntu_app_api_location_service ubuntu_application_api)
600
601+add_executable(test_hardware_alarms_api test_alarms_api.cpp)
602+target_link_libraries(test_hardware_alarms_api ubuntu_platform_hardware_api)
603+
604 install(TARGETS
605 test_android_ubuntu_app_api
606 test_android_gps_api
607@@ -25,5 +28,6 @@
608 test_android_sensors_api
609 test_android_ubuntu_session_api
610 test_ubuntu_app_api_location_service
611+ test_hardware_alarms_api
612 DESTINATION bin
613 )
614
615=== added file 'src/ubuntu/hybris/tests/test_alarms_api.cpp'
616--- src/ubuntu/hybris/tests/test_alarms_api.cpp 1970-01-01 00:00:00 +0000
617+++ src/ubuntu/hybris/tests/test_alarms_api.cpp 2014-05-21 07:20:43 +0000
618@@ -0,0 +1,74 @@
619+/*
620+ * Copyright © 2013 Canonical Ltd.
621+ *
622+ * This program is free software: you can redistribute it and/or modify
623+ * it under the terms of the GNU General Public License version 3 as
624+ * published by the Free Software Foundation.
625+ *
626+ * This program is distributed in the hope that it will be useful,
627+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
628+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
629+ * GNU General Public License for more details.
630+ *
631+ * You should have received a copy of the GNU General Public License
632+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
633+ *
634+ * Authored by: Thomas Voß <thomas.voss@canonicalcom>
635+ */
636+
637+#include <ubuntu/hardware/alarm.h>
638+
639+#include <cstdio>
640+#include <cstdlib>
641+#include <ctime>
642+
643+int main(int argc, char** argv)
644+{
645+ UHardwareAlarm alarm = u_hardware_alarm_create();
646+
647+ if (!alarm)
648+ {
649+ printf("Error creating handle to hardware alarms.\n");
650+ return 1;
651+ }
652+
653+ // Alarm in two seconds.
654+ timespec ts { 0, 0 };
655+ clock_gettime(CLOCK_REALTIME, &ts);
656+
657+ int timeout_in_seconds = 5;
658+
659+ // Let's see if a timeout has been specified on the command line
660+ if (argc > 1)
661+ {
662+ timeout_in_seconds = atoi(argv[1]);
663+ }
664+
665+ // Alarm in two seconds.
666+ ts.tv_sec += timeout_in_seconds;
667+
668+ UStatus rc = u_hardware_alarm_set_relative_to_with_behavior(
669+ alarm,
670+ U_HARDWARE_ALARM_TIME_REFERENCE_RTC,
671+ U_HARDWARE_ALARM_SLEEP_BEHAVIOR_WAKEUP_DEVICE,
672+ &ts);
673+
674+ if (rc != U_STATUS_SUCCESS)
675+ {
676+ printf("Problem setting hardware alarm.\n");
677+ return 1;
678+ }
679+
680+ UHardwareAlarmWaitResult wait_result;
681+ rc = u_hardware_alarm_wait_for_next_alarm(alarm, &wait_result);
682+
683+ if (rc != U_STATUS_SUCCESS)
684+ {
685+ printf("Problem waiting for hardware alarm to go off.\n");
686+ return 1;
687+ }
688+
689+ printf("Successfully created and waited for a hw alarm.\n");
690+
691+ return 0;
692+}
693
694=== modified file 'src/ubuntu/hybris/ubuntu_platform_hardware_api.cpp'
695--- src/ubuntu/hybris/ubuntu_platform_hardware_api.cpp 2013-06-13 08:37:52 +0000
696+++ src/ubuntu/hybris/ubuntu_platform_hardware_api.cpp 2014-05-21 07:20:43 +0000
697@@ -18,6 +18,7 @@
698 */
699
700 // C APIs
701+#include <ubuntu/hardware/alarm.h>
702 #include <ubuntu/hardware/gps.h>
703
704 #include "bridge.h"

Subscribers

People subscribed via source and target branches