You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
4.8 KiB
178 lines
4.8 KiB
#include <errno.h> |
|
#include <fcntl.h> |
|
#include <pthread.h> |
|
#include <semaphore.h> |
|
#include <stddef.h> |
|
#include <string.h> |
|
#include <sys/stat.h> |
|
#include <sys/types.h> |
|
#include <unistd.h> |
|
#include <stdlib.h> |
|
|
|
#include "autosuspend_ops.h" |
|
|
|
#define LOG_TAG "libsuspend" |
|
#include <cutils/log.h> |
|
|
|
#define SYS_KERNEL_WAKEUP_SOURCES "/sys/kernel/debug/wakeup_sources" |
|
|
|
static FILE *wakeup_sources_fd = NULL; |
|
static pthread_t debugger_thread; |
|
static sem_t debugger_lockout; |
|
|
|
static void *debugger_thread_func(void *arg __attribute__((unused))) |
|
{ |
|
int ret; |
|
char buf[512]; |
|
|
|
while (1) { |
|
ALOGV("%s: wait\n", __func__); |
|
ret = sem_wait(&debugger_lockout); |
|
if (ret < 0) { |
|
strerror_r(errno, buf, sizeof(buf)); |
|
ALOGE("Error waiting on semaphore: %s\n", buf); |
|
continue; |
|
} |
|
|
|
ALOGV("%s: read wakeup_sources\n", __func__); |
|
fseek(wakeup_sources_fd, 0, SEEK_SET); |
|
while (fgets(buf, sizeof(buf), wakeup_sources_fd) != NULL) { |
|
int active_since_index = 5; |
|
int current_index = 0; |
|
|
|
int active_count = 0; |
|
int event_count = 0; |
|
int wakeup_count = 0; |
|
int expire_count = 0; |
|
int active_since = 0; |
|
|
|
char *token = strtok(buf,"\t"); |
|
char *wakeup_source_name = token; |
|
|
|
int i; |
|
for (i = strlen(wakeup_source_name) - 1; i >= 0 ; i--) { |
|
if (wakeup_source_name[i] != ' ') { |
|
wakeup_source_name[i + 1] = '\0'; |
|
break; |
|
} |
|
} |
|
|
|
while (token != NULL) { |
|
switch(current_index) { |
|
case 1: |
|
active_count = atoi(token); |
|
break; |
|
case 2: |
|
event_count = atoi(token); |
|
break; |
|
case 3: |
|
wakeup_count = atoi(token); |
|
break; |
|
case 4: |
|
expire_count = atoi(token); |
|
break; |
|
case 5: |
|
active_since = atoi(token); |
|
break; |
|
default: |
|
break; |
|
} |
|
if (current_index == active_since_index && active_since > 0) { |
|
ALOGI("ws name: %s, act_since: %d, act_cnt: %d, ev_cnt: %d, wakeup_cnt: %d\n", |
|
wakeup_source_name, active_since, active_count, event_count, wakeup_count); |
|
} |
|
current_index++; |
|
token = strtok(NULL, "\t"); |
|
} |
|
} |
|
|
|
ALOGV("%s: release sem\n", __func__); |
|
ret = sem_post(&debugger_lockout); |
|
if (ret < 0) { |
|
strerror_r(errno, buf, sizeof(buf)); |
|
ALOGE("Error releasing semaphore: %s\n", buf); |
|
} |
|
|
|
usleep(15000000); // 15s |
|
} |
|
return NULL; |
|
} |
|
|
|
static int autosuspend_debugger_enable(void) |
|
{ |
|
char buf[80]; |
|
int ret; |
|
|
|
ALOGI("autosuspend_debugger_enable\n"); |
|
|
|
ret = sem_post(&debugger_lockout); |
|
|
|
if (ret < 0) { |
|
strerror_r(errno, buf, sizeof(buf)); |
|
ALOGE("Error changing semaphore: %s\n", buf); |
|
} |
|
|
|
ALOGI("autosuspend_debugger_enable done\n"); |
|
|
|
return ret; |
|
} |
|
|
|
static int autosuspend_debugger_disable(void) |
|
{ |
|
char buf[80]; |
|
int ret; |
|
|
|
ALOGI("autosuspend_debugger_disable\n"); |
|
|
|
ret = sem_wait(&debugger_lockout); |
|
|
|
if (ret < 0) { |
|
strerror_r(errno, buf, sizeof(buf)); |
|
ALOGE("Error changing semaphore: %s\n", buf); |
|
} |
|
|
|
ALOGI("autosuspend_debugger_disable done\n"); |
|
|
|
return ret; |
|
} |
|
|
|
struct autosuspend_ops autosuspend_debugger_ops = { |
|
.enable = autosuspend_debugger_enable, |
|
.disable = autosuspend_debugger_disable, |
|
}; |
|
|
|
struct autosuspend_ops *autosuspend_debugger_init(void) |
|
{ |
|
int ret; |
|
char buf[80]; |
|
|
|
wakeup_sources_fd = fopen(SYS_KERNEL_WAKEUP_SOURCES, "r"); |
|
if (wakeup_sources_fd == NULL) { |
|
strerror_r(errno, buf, sizeof(buf)); |
|
ALOGE("Error opening %s: %s\n", SYS_KERNEL_WAKEUP_SOURCES, buf); |
|
goto err_open_wakeup_sources; |
|
} |
|
ret = sem_init(&debugger_lockout, 0, 0); |
|
if (ret < 0) { |
|
strerror_r(errno, buf, sizeof(buf)); |
|
ALOGE("Error creating semaphore: %s\n", buf); |
|
goto err_debugger_sem_init; |
|
} |
|
ret = pthread_create(&debugger_thread, NULL, debugger_thread_func, NULL); |
|
if (ret) { |
|
strerror_r(ret, buf, sizeof(buf)); |
|
ALOGE("Error creating thread: %s\n", buf); |
|
goto err_debugger_pthread_create; |
|
} |
|
|
|
ALOGI("Selected wakeup source debugger\n"); |
|
return &autosuspend_debugger_ops; |
|
|
|
err_debugger_pthread_create: |
|
sem_destroy(&debugger_lockout); |
|
err_debugger_sem_init: |
|
fclose(wakeup_sources_fd); |
|
err_open_wakeup_sources: |
|
return NULL; |
|
} |
|
|
|
|