| #include <pthread.h> |
| #include <sys/epoll.h> |
| #include <sys/timerfd.h> |
| |
| #include "mbtk_sleep.h" |
| #include "mbtk_log.h" |
| #include "mbtk_utils.h" |
| |
| static bool autosleep_enable = FALSE; |
| |
| static mbtk_lock_name_s mbtk_lock_name[LOCK_MAX_SIZE]={0}; |
| |
| int g_mEpollFd = -1; |
| mbtk_sleep_callback_func g_sleep_timer_cb; |
| int g_sleep_timer_fd = 0; |
| pthread_t g_timer_thread_id; |
| |
| int mbtk_powerrind_get() |
| { |
| char buffer[4]; |
| int ret = 0; |
| |
| int fd = open(MTBK_POWERIND, O_RDWR | O_SYNC, 0662); |
| if (fd != -1) |
| { |
| mbtk_read(fd, buffer, strlen(buffer)+1); |
| close(fd); |
| } |
| |
| ret = atoi(buffer); |
| |
| return ret; |
| } |
| |
| |
| int mbtk_autosuspend_enable(char enable) |
| { |
| if((enable == 1) || enable == '1') |
| { |
| if(!access("/sys/power/autosleep", W_OK)) |
| { |
| mbtk_system("echo mem > /sys/power/autosleep"); |
| autosleep_enable = TRUE; |
| return 0; |
| } |
| else |
| { |
| LOGE("/sys/power/autosleep can not write."); |
| return -1; |
| } |
| } |
| else if((enable == 0) || enable == '0') |
| { |
| if(!access("/sys/power/autosleep", W_OK)) |
| { |
| mbtk_system("echo off > /sys/power/autosleep"); |
| autosleep_enable = FALSE; |
| return 0; |
| } |
| else |
| { |
| LOGE("/sys/power/autosleep can not write."); |
| return -1; |
| } |
| } |
| else |
| { |
| LOGE("qser_autosuspend_enablecan enable err."); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| int mbtk_wakelock_create(const char* name , size_t len) |
| { |
| int len_t; |
| |
| len_t = strlen(name); |
| |
| if((name != NULL) && (len < 33) && (len_t < 33)) |
| { |
| int i; |
| for(i=1 ;i<LOCK_MAX_SIZE;i++) |
| { |
| if(strcmp(mbtk_lock_name[i].name, name) == 0) |
| { |
| LOGE("Repeated names."); |
| return -1; |
| } |
| } |
| |
| for(i=1 ;i<LOCK_MAX_SIZE;i++) |
| { |
| if(mbtk_lock_name[i].fd == 0) |
| break; |
| } |
| |
| if (i >= LOCK_MAX_SIZE) |
| { |
| LOGE("Fd is full."); |
| return -1; |
| } |
| |
| memcpy(mbtk_lock_name[i].name, name, strlen(name)+1); |
| mbtk_lock_name[i].fd = i; |
| return mbtk_lock_name[i].fd -1;//Starting from scratch |
| } |
| else |
| return -1; |
| |
| return -1; |
| } |
| |
| int mbtk_wakelock_lock(int fd) |
| { |
| int i; |
| for(i=1;i<LOCK_MAX_SIZE;i++) |
| { |
| if(mbtk_lock_name[i].fd -1 == fd) |
| break; |
| } |
| if(i == LOCK_MAX_SIZE) |
| { |
| LOGE("LOCK_MAX_SIZE is full\n"); |
| return -1; |
| } |
| |
| if(!access("/sys/power/wake_lock", W_OK)) |
| { |
| char cmd[128]={0}; |
| sprintf(cmd, "echo %s > /sys/power/wake_lock", mbtk_lock_name[i].name); |
| mbtk_system(cmd); |
| return 0; |
| } |
| else |
| { |
| LOGE("/sys/power/wake_lock can not write."); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| int mbtk_wakelock_unlock(int fd) |
| { |
| int i; |
| for(i=1;i<LOCK_MAX_SIZE;i++) |
| { |
| if(mbtk_lock_name[i].fd -1 == fd) |
| break; |
| } |
| if(i == LOCK_MAX_SIZE) |
| { |
| LOGE("LOCK_MAX_SIZE is full\n"); |
| return -1; |
| } |
| |
| if(!access("/sys/power/wake_unlock", W_OK)) |
| { |
| char cmd[128]={0}; |
| sprintf(cmd, "echo %s > /sys/power/wake_unlock", mbtk_lock_name[i].name); |
| mbtk_system(cmd); |
| return 0; |
| } |
| else |
| { |
| LOGE("/sys/power/wake_unlock can not write."); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| int mbtk_wakelock_destroy(int fd) |
| { |
| int i; |
| for(i=1;i<LOCK_MAX_SIZE;i++) |
| { |
| if(mbtk_lock_name[i].fd -1 == fd) |
| break; |
| } |
| |
| if(i == LOCK_MAX_SIZE) |
| { |
| LOGE("LOCK_MAX_SIZE is full\n"); |
| return -1; |
| } |
| else |
| { |
| mbtk_lock_name[i].fd = 0; |
| memset(mbtk_lock_name[i].name, 0, 64); |
| return 0; |
| } |
| |
| return 0; |
| } |
| |
| static void* suspend_timer_thread_run(void* arg) |
| { |
| struct epoll_event eventItems[EPOLL_SIZE_HINT]; |
| int eventCount = epoll_wait(g_mEpollFd, eventItems, EPOLL_SIZE_HINT, -1); |
| |
| int timerFd = -1; |
| int eventIndex = 0; |
| uint64_t readCounter; |
| |
| if (eventCount < 0) { |
| LOGE("Poll failed with an unexpected error: %s\n", strerror(errno)); |
| return (void*)-1; |
| } |
| |
| for (; eventIndex < eventCount; ++eventIndex) |
| { |
| timerFd = eventItems[eventIndex].data.fd; |
| |
| int retRead = read(timerFd, &readCounter, sizeof(uint64_t)); |
| |
| |
| if (retRead < 0) |
| { |
| LOGE("read %d failed...\n", timerFd); |
| continue; |
| } |
| else |
| { |
| mbtk_autosuspend_enable(0); |
| g_sleep_timer_cb(NULL, 0); |
| g_sleep_timer_fd = 0; |
| LOGI("suspend_timer_success, retRead:%d\n", retRead); |
| } |
| |
| } |
| |
| return 0; |
| } |
| |
| |
| |
| static int suspend_timer_timer_init(void) |
| { |
| pthread_attr_t thread_attr; |
| pthread_attr_init(&thread_attr); |
| if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED)) |
| { |
| LOGE("[suspend] pthread_attr_setdetachstate() fail."); |
| return -1; |
| } |
| |
| if(pthread_create(&g_timer_thread_id, &thread_attr, suspend_timer_thread_run, NULL)) |
| { |
| LOGE("[suspend] pthread_create() fail."); |
| return -1; |
| } |
| |
| pthread_attr_destroy(&thread_attr); |
| return 0; |
| } |
| |
| |
| |
| |
| int mbtk_suspend_timer_set(int time, mbtk_sleep_callback_func cb) |
| { |
| struct itimerspec timerSet; |
| struct epoll_event eventItem; |
| int result = 0; |
| |
| if(0 < g_sleep_timer_fd) |
| { |
| LOGE("suspend timer has been init, restart"); |
| if(timerfd_settime(g_sleep_timer_fd, TFD_TIMER_CANCEL_ON_SET, &timerSet, NULL) != 0) |
| { |
| LOGE("suspend timer cancel fail"); |
| } |
| |
| pthread_detach(g_timer_thread_id); |
| |
| pthread_cancel(g_timer_thread_id); |
| |
| result = epoll_ctl(g_mEpollFd, EPOLL_CTL_DEL, g_sleep_timer_fd, &eventItem); |
| if (result != 0) |
| { |
| LOGE("Could not del timer fd(%d) to epoll instance: %s\n", g_sleep_timer_fd, strerror(errno)); |
| } |
| |
| close(g_sleep_timer_fd); |
| } |
| |
| g_mEpollFd = epoll_create(EPOLL_SIZE_HINT); |
| |
| g_sleep_timer_fd = timerfd_create(CLOCK_BOOTTIME_ALARM, 0); |
| if (g_sleep_timer_fd < 0) { |
| LOGE("Could not create timer fd: %s\n", strerror(errno)); |
| return 0; |
| } |
| |
| timerSet.it_interval.tv_sec = 0; |
| timerSet.it_interval.tv_nsec = 0; |
| timerSet.it_value.tv_sec = time; |
| timerSet.it_value.tv_nsec = 0; |
| if (timerfd_settime(g_sleep_timer_fd, 0, &timerSet, NULL) != 0) { |
| LOGE("timerfd_settime failed: %s\n", strerror(errno)); |
| close(g_sleep_timer_fd); |
| return 0; |
| } |
| |
| |
| memset(&eventItem, 0, sizeof(eventItem)); |
| eventItem.events = EPOLLIN | EPOLLET; |
| eventItem.data.fd = g_sleep_timer_fd; |
| result = epoll_ctl(g_mEpollFd, EPOLL_CTL_ADD, g_sleep_timer_fd, &eventItem); |
| if (result != 0) { |
| LOGE("Could not add timer fd(%d) to epoll instance: %s\n", g_sleep_timer_fd, strerror(errno)); |
| } |
| |
| mbtk_autosuspend_enable(1); |
| g_sleep_timer_cb = cb; |
| suspend_timer_timer_init(); |
| |
| |
| return 0; |
| } |
| |
| int mbtk_suspend_timer_cancel(void) |
| { |
| int ret = -1; |
| struct itimerspec timerSet; |
| |
| if(0 < g_sleep_timer_fd) |
| { |
| LOGD("[%s] suspend timer deinit", __func__); |
| memset(&timerSet, 0x0, sizeof(struct itimerspec)); |
| if(timerfd_settime(g_sleep_timer_fd, TFD_TIMER_CANCEL_ON_SET, &timerSet, NULL) != 0) |
| { |
| LOGE("[%s] timerfd_settime fail", __func__); |
| return -1; |
| } |
| } |
| |
| if(0 < g_mEpollFd) |
| { |
| ret = epoll_ctl(g_mEpollFd, EPOLL_CTL_DEL, g_sleep_timer_fd, NULL); |
| if (ret != 0) |
| { |
| LOGE("[%s] epoll_ctl[%d] del g_sleep_timer_fd[%d] fail. [%s]\n", g_mEpollFd, g_sleep_timer_fd, strerror(errno)); |
| return -1; |
| } |
| } |
| |
| pthread_detach(g_timer_thread_id); |
| pthread_cancel(g_timer_thread_id); |
| |
| g_timer_thread_id = 0; |
| if(0 < g_sleep_timer_fd) |
| { |
| close(g_sleep_timer_fd); |
| g_sleep_timer_fd = -1; |
| } |
| |
| if(0 < g_mEpollFd) |
| { |
| close(g_mEpollFd); |
| g_mEpollFd = -1; |
| } |
| |
| return 0; |
| } |
| |