summaryrefslogtreecommitdiffstats
path: root/services/jni/com_android_server_AlarmManagerService.cpp
blob: 1d66fb11958f3caed5c6ac87e278850e5f2222b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* //device/libs/android_runtime/android_server_AlarmManagerService.cpp
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License"); 
** you may not use this file except in compliance with the License. 
** You may obtain a copy of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** Unless required by applicable law or agreed to in writing, software 
** distributed under the License is distributed on an "AS IS" BASIS, 
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
** See the License for the specific language governing permissions and 
** limitations under the License.
*/

#define LOG_TAG "AlarmManagerService"

#include "JNIHelp.h"
#include "jni.h"
#include "utils/Log.h"
#include "utils/misc.h"

#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>

#if HAVE_ANDROID_OS
#include <linux/ioctl.h>
#include <linux/android_alarm.h>
#endif

#define ONE_NANOSECOND 1000000000LL
#define NANOSECONDS_TO_SECONDS(x) (x / ONE_NANOSECOND)
#define SECONDS_TO_NANOSECONDS(x) (x * ONE_NANOSECOND)

namespace android {

static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv* env, jobject obj, jint fd, jint minswest)
{
#if HAVE_ANDROID_OS
    struct timezone tz;

    tz.tz_minuteswest = minswest;
    tz.tz_dsttime = 0;

    int result = settimeofday(NULL, &tz);
    if (result < 0) {
        LOGE("Unable to set kernel timezone to %d: %s\n", minswest, strerror(errno));
        return -1;
    } else {
        LOGD("Kernel timezone updated to %d minutes west of GMT\n", minswest);
    }

    return 0;
#else
    return -ENOSYS;
#endif
}

static jint android_server_AlarmManagerService_init(JNIEnv* env, jobject obj)
{
#if HAVE_ANDROID_OS
    return open("/dev/alarm", O_RDWR);
#else
	return -1;
#endif
}

static void android_server_AlarmManagerService_close(JNIEnv* env, jobject obj, jint fd)
{
#if HAVE_ANDROID_OS
	close(fd);
#endif
}

static void android_server_AlarmManagerService_set(JNIEnv* env, jobject obj, jint fd, jint type, jlong nanoseconds)
{
#if HAVE_ANDROID_OS
    struct timespec ts;
    ts.tv_sec = NANOSECONDS_TO_SECONDS(nanoseconds);
    ts.tv_nsec = nanoseconds - SECONDS_TO_NANOSECONDS(ts.tv_sec);
    
	int result = ioctl(fd, ANDROID_ALARM_SET(type), &ts);
	if (result < 0)
	{
        LOGE("Unable to set alarm to %lld: %s\n", nanoseconds, strerror(errno));
    }
#endif
}

static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv* env, jobject obj, jint fd)
{
#if HAVE_ANDROID_OS
	int result = 0;
	
	do
	{
		result = ioctl(fd, ANDROID_ALARM_WAIT);
	} while (result < 0 && errno == EINTR);
	
	if (result < 0)
	{
        LOGE("Unable to wait on alarm: %s\n", strerror(errno));
        return 0;
    }
    
    return result;
#endif
}

static JNINativeMethod sMethods[] = {
     /* name, signature, funcPtr */
	{"init", "()I", (void*)android_server_AlarmManagerService_init},
	{"close", "(I)V", (void*)android_server_AlarmManagerService_close},
	{"set", "(IIJ)V", (void*)android_server_AlarmManagerService_set},
    {"waitForAlarm", "(I)I", (void*)android_server_AlarmManagerService_waitForAlarm},
    {"setKernelTimezone", "(II)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
};

int register_android_server_AlarmManagerService(JNIEnv* env)
{
    jclass clazz = env->FindClass("com/android/server/AlarmManagerService");

    if (clazz == NULL)
	{
        LOGE("Can't find com/android/server/AlarmManagerService");
        return -1;
    }

    return jniRegisterNativeMethods(env, "com/android/server/AlarmManagerService",
                                    sMethods, NELEM(sMethods));
}

} /* namespace android */