1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <hardware_legacy/power.h>
17 #include <fcntl.h>
18 #include <errno.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <errno.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <pthread.h>
27 
28 #define LOG_TAG "power"
29 #include <log/log.h>
30 
31 enum {
32     ACQUIRE_PARTIAL_WAKE_LOCK = 0,
33     RELEASE_WAKE_LOCK,
34     OUR_FD_COUNT
35 };
36 
37 const char * const OLD_PATHS[] = {
38     "/sys/android_power/acquire_partial_wake_lock",
39     "/sys/android_power/release_wake_lock",
40 };
41 
42 const char * const NEW_PATHS[] = {
43     "/sys/power/wake_lock",
44     "/sys/power/wake_unlock",
45 };
46 
47 //XXX static pthread_once_t g_initialized = THREAD_ONCE_INIT;
48 static int g_initialized = 0;
49 static int g_fds[OUR_FD_COUNT];
50 static int g_error = -1;
51 
52 static int
open_file_descriptors(const char * const paths[])53 open_file_descriptors(const char * const paths[])
54 {
55     int i;
56     for (i=0; i<OUR_FD_COUNT; i++) {
57         int fd = open(paths[i], O_RDWR | O_CLOEXEC);
58         if (fd < 0) {
59             g_error = -errno;
60             fprintf(stderr, "fatal error opening \"%s\": %s\n", paths[i],
61                 strerror(errno));
62             return -1;
63         }
64         g_fds[i] = fd;
65     }
66 
67     g_error = 0;
68     return 0;
69 }
70 
71 static inline void
initialize_fds(void)72 initialize_fds(void)
73 {
74     // XXX: should be this:
75     //pthread_once(&g_initialized, open_file_descriptors);
76     // XXX: not this:
77     if (g_initialized == 0) {
78         if(open_file_descriptors(NEW_PATHS) < 0)
79             open_file_descriptors(OLD_PATHS);
80         g_initialized = 1;
81     }
82 }
83 
84 int
acquire_wake_lock(int lock,const char * id)85 acquire_wake_lock(int lock, const char* id)
86 {
87     initialize_fds();
88 
89 //    ALOGI("acquire_wake_lock lock=%d id='%s'\n", lock, id);
90 
91     if (g_error) return g_error;
92 
93     int fd;
94     size_t len;
95     ssize_t ret;
96 
97     if (lock != PARTIAL_WAKE_LOCK) {
98         return -EINVAL;
99     }
100 
101     fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
102 
103     ret = write(fd, id, strlen(id));
104     if (ret < 0) {
105         return -errno;
106     }
107 
108     return ret;
109 }
110 
111 int
release_wake_lock(const char * id)112 release_wake_lock(const char* id)
113 {
114     initialize_fds();
115 
116 //    ALOGI("release_wake_lock id='%s'\n", id);
117 
118     if (g_error) return g_error;
119 
120     ssize_t len = write(g_fds[RELEASE_WAKE_LOCK], id, strlen(id));
121     if (len < 0) {
122         return -errno;
123     }
124     return len;
125 }
126