/******************************************************************************* * Copyright (c) 2013 Linaro * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Linaro *******************************************************************************/ /* * alarm-dev-test.c Trivial Android Alarm-dev unit test * * By: John Stultz * * For each alarm type, gets, sets and waits for an alarm. * Then sets the RTC back 10 seconds. * * TODO: */ #include #include #include #include #include #include #include "android_alarm.h" int alarmfd; int alarm_set(int type, struct timespec *ts) { return ioctl(alarmfd, ANDROID_ALARM_SET(type), ts); } int alarm_get_time(int type, struct timespec *ts) { return ioctl(alarmfd, ANDROID_ALARM_GET_TIME(type), ts); } int alarm_set_and_wait(int type, struct timespec *ts) { return ioctl(alarmfd, ANDROID_ALARM_SET_AND_WAIT(type), ts); } int alarm_wait(void) { return ioctl(alarmfd, ANDROID_ALARM_WAIT, 0); } int alarm_clear(int type) { return ioctl(alarmfd, ANDROID_ALARM_CLEAR(type),0); } int alarm_set_rtc(struct timespec *ts) { return ioctl(alarmfd, ANDROID_ALARM_SET_RTC, ts); } #define DELAY 5 int main(void) { struct timespec target, now; int ret; int alarm_type; if (getuid()) { printf("Error: Need to run as root\n"); return -1; } alarmfd = open("/dev/alarm", O_RDWR); if (alarmfd < 1) { printf("Error opening /dev/alarm\n"); return -1; } for (alarm_type = ANDROID_ALARM_RTC_WAKEUP; alarm_type < ANDROID_ALARM_TYPE_COUNT; alarm_type++) { ret = alarm_get_time(alarm_type, &now); if (ret < 0) { perror("Error: alarm_get_time"); return -1; } printf("(%i) gettime(%i): %ld:%ld\n", ret, alarm_type, now.tv_sec, now.tv_nsec); target = now; target.tv_sec += DELAY; ret = alarm_set_and_wait(alarm_type, &target); if (ret < 0) { if (errno == EBUSY) { printf("Warning: EBUSY on alarm_set_and_wait, this is likely due to the " "Android environment using this alarm type(%d). Skipping.", alarm_type); continue; } perror("Error: alarm_set_and_wait"); return -1; } printf("(0x%x) alarm_set_and_wait(0x%x)\n", ret, alarm_type); if (!(ret & (1 << alarm_type))) { printf("Error: alarm_wait: expected bit 0x%x set, got 0x%x", 1 << alarm_type, ret); return -1; } ret = alarm_get_time(alarm_type, &now); if (ret < 0) { perror("Error: alarm_get_time"); return -1; } if (now.tv_sec < target.tv_sec) { printf("Error: Early timer return!\n"); return -1; } if (now.tv_sec > target.tv_sec + 1) { printf("Error: Late timer return!\n"); return -1; } target.tv_sec += DELAY; ret = alarm_set(alarm_type, &target); if (ret < 0) { perror("Error: alarm_set"); return -1; } printf("(%i) alarm_set(%i)\n", ret, alarm_type); ret = alarm_wait(); if (ret < 0) { perror("Error: alarm_wait"); } printf("(0x%x) alarm_wait()\n", ret); if (!(ret & (1 << alarm_type))) { printf("Error: alarm_wait: expected bit 0x%x set, got 0x%x", 1 << alarm_type, ret); return -1; } ret = alarm_get_time(alarm_type, &now); if (ret < 0) { perror("Error: alarm_get_time"); return -1; } if (now.tv_sec < target.tv_sec) { printf("Error: Early timer return!\n"); return -1; } if (now.tv_sec > target.tv_sec + 1) { printf("Error: Late timer return!\n"); return -1; } ret = alarm_clear(alarm_type); printf("(%i) alarm_clear()\n", ret); if (ret < 0) { perror("Error: alarm_clear"); return -1; } target.tv_sec += DELAY; ret = alarm_set(alarm_type, &target); printf("(%i) alarm_set(%i)\n", ret, alarm_type); if (ret < 0) { perror("Error: alarm_set"); return -1; } ret = alarm_clear(alarm_type); printf("(%i) alarm_clear()\n", ret); if (ret < 0) { perror("Error: alarm_clear"); return -1; } } ret = alarm_get_time(ANDROID_ALARM_RTC, &now); if (ret < 0) { perror("Error: alarm_get_time"); return -1; } printf("(%i) gettime(ANDROID_ALARM_RTC): %ld:%ld\n", ret, now.tv_sec, now.tv_nsec); target = now; target.tv_sec -= 10; ret = alarm_set_rtc(&target); if (ret < 0) { perror("Error: alarm_set_rtc"); return -1; } printf("(%i) setting rtc back 10 sec (%ld:%ld)\n", ret, target.tv_sec, target.tv_nsec); ret = alarm_get_time(ANDROID_ALARM_RTC, &now); if (ret < 0) { perror("Error: alarm_get_time"); return -1; } printf("(%i) gettime(ANDROID_ALARM_RTC): %ld:%ld\n", ret, now.tv_sec, now.tv_nsec); if (now.tv_sec < target.tv_sec) { printf("Error: Bad time!\n"); return -1; } printf("Pass\n"); return 0; }