com_android_server_am_BatteryStatsService.cpp revision 87fd322ecb5cd7582f449e5b4721a1e4dea062e6
1c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn/* 2c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn * Copyright (C) 2014 The Android Open Source Project 3c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn * 4c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 5c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn * you may not use this file except in compliance with the License. 6c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn * You may obtain a copy of the License at 7c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn * 8c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 9c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn * 10c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn * Unless required by applicable law or agreed to in writing, software 11c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 12c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn * See the License for the specific language governing permissions and 14c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn * limitations under the License. 15c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn */ 16c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 17c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#define LOG_TAG "BatteryStatsService" 18c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn//#define LOG_NDEBUG 0 19c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 20c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <android_runtime/AndroidRuntime.h> 21c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <jni.h> 22c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 23c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <ScopedLocalRef.h> 24c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <ScopedPrimitiveArray.h> 25c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 26c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <cutils/log.h> 27c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <utils/misc.h> 28c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <utils/Log.h> 29c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <hardware/hardware.h> 30c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <suspend/autosuspend.h> 31c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 32c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <stdio.h> 33c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <errno.h> 34c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <fcntl.h> 35c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <semaphore.h> 36c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <stddef.h> 37c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <string.h> 38c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <sys/stat.h> 39c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <sys/types.h> 40c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#include <unistd.h> 41c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 42c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackbornnamespace android 43c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn{ 44c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 45c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#define LAST_RESUME_REASON "/sys/kernel/wakeup_reasons/last_resume_reason" 46c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn#define MAX_REASON_SIZE 512 47c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 48c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackbornstatic bool wakeup_init = false; 49c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackbornstatic sem_t wakeup_sem; 50c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 5187fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinskistatic void wakeup_callback(bool success) 52c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn{ 5387fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski ALOGV("In wakeup_callback: %s", success ? "resumed from suspend" : "suspend aborted"); 54c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn int ret = sem_post(&wakeup_sem); 55c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (ret < 0) { 56c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char buf[80]; 57c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn strerror_r(errno, buf, sizeof(buf)); 58c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGE("Error posting wakeup sem: %s\n", buf); 59c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 60c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn} 61c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 6287fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinskistatic jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobjectArray outReasons) 63c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn{ 6487fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski if (outReasons == NULL) { 65c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn jniThrowException(env, "java/lang/NullPointerException", "null argument"); 66c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn return -1; 67c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 68c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 69c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn // Register our wakeup callback if not yet done. 70c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (!wakeup_init) { 71c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn wakeup_init = true; 72c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGV("Creating semaphore..."); 73c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn int ret = sem_init(&wakeup_sem, 0, 0); 74c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (ret < 0) { 75c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char buf[80]; 76c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn strerror_r(errno, buf, sizeof(buf)); 77c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGE("Error creating semaphore: %s\n", buf); 78c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn jniThrowException(env, "java/lang/IllegalStateException", buf); 79c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn return -1; 80c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 81c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGV("Registering callback..."); 82c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn set_wakeup_callback(&wakeup_callback); 836b0331a03025f2ea8c966bf9406dd5788ffa176eAdam Lesinski } 846b0331a03025f2ea8c966bf9406dd5788ffa176eAdam Lesinski 856b0331a03025f2ea8c966bf9406dd5788ffa176eAdam Lesinski // Wait for wakeup. 866b0331a03025f2ea8c966bf9406dd5788ffa176eAdam Lesinski ALOGV("Waiting for wakeup..."); 876b0331a03025f2ea8c966bf9406dd5788ffa176eAdam Lesinski int ret = sem_wait(&wakeup_sem); 886b0331a03025f2ea8c966bf9406dd5788ffa176eAdam Lesinski if (ret < 0) { 896b0331a03025f2ea8c966bf9406dd5788ffa176eAdam Lesinski char buf[80]; 906b0331a03025f2ea8c966bf9406dd5788ffa176eAdam Lesinski strerror_r(errno, buf, sizeof(buf)); 916b0331a03025f2ea8c966bf9406dd5788ffa176eAdam Lesinski ALOGE("Error waiting on semaphore: %s\n", buf); 926b0331a03025f2ea8c966bf9406dd5788ffa176eAdam Lesinski // Return 0 here to let it continue looping but not return results. 936b0331a03025f2ea8c966bf9406dd5788ffa176eAdam Lesinski return 0; 94c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 95c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 96c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn FILE *fp = fopen(LAST_RESUME_REASON, "r"); 97c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (fp == NULL) { 98c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGE("Failed to open %s", LAST_RESUME_REASON); 99c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn return -1; 100c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 101c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 10287fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski ALOGV("Reading wakeup reasons"); 103c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 104c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char mergedreason[MAX_REASON_SIZE]; 105c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char* mergedreasonpos = mergedreason; 106c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn int remainreasonlen = MAX_REASON_SIZE; 107c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char reasonline[128]; 108c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn int i = 0; 10987fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski while (fgets(reasonline, sizeof(reasonline), fp) != NULL) { 110c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char* pos = reasonline; 111c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char* endPos; 11287fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski int len; 11387fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski // First field is the index or 'Abort'. 114c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn int irq = (int)strtol(pos, &endPos, 10); 11587fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski if (pos != endPos) { 11687fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski // Write the irq number to the merged reason string. 11787fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski len = snprintf(mergedreasonpos, remainreasonlen, i == 0 ? "%d" : ":%d", irq); 11887fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski } else { 11987fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski // The first field is not an irq, it may be the word Abort. 12087fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski const size_t abortPrefixLen = strlen("Abort:"); 12187fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski if (strncmp(pos, "Abort:", abortPrefixLen) != 0) { 12287fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski // Ooops. 12387fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski ALOGE("Bad reason line: %s", reasonline); 12487fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski continue; 12587fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski } 12687fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski 12787fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski // Write 'Abort' to the merged reason string. 12887fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski len = snprintf(mergedreasonpos, remainreasonlen, i == 0 ? "Abort" : ":Abort"); 12987fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski endPos = pos + abortPrefixLen; 130c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 131c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn pos = endPos; 13287fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski 13387fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski if (len >= 0 && len < remainreasonlen) { 13487fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski mergedreasonpos += len; 13587fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski remainreasonlen -= len; 13687fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski } 13787fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski 138c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn // Skip whitespace; rest of the buffer is the reason string. 139c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn while (*pos == ' ') { 140c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn pos++; 141c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 14287fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski 143c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn // Chop newline at end. 144c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char* endpos = pos; 145c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn while (*endpos != 0) { 146c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (*endpos == '\n') { 147c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn *endpos = 0; 148c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn break; 149c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 150c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn endpos++; 151c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 15287fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski 15387fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski len = snprintf(mergedreasonpos, remainreasonlen, ":%s", pos); 154c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (len >= 0 && len < remainreasonlen) { 155c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn mergedreasonpos += len; 156c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn remainreasonlen -= len; 157c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 158c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn i++; 159c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 160c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 161c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGV("Got %d reasons", i); 162c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (i > 0) { 163c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn *mergedreasonpos = 0; 164c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ScopedLocalRef<jstring> reasonString(env, env->NewStringUTF(mergedreason)); 165c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn env->SetObjectArrayElement(outReasons, 0, reasonString.get()); 166c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn i = 1; 167c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 168c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 169c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (fclose(fp) != 0) { 170c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGE("Failed to close %s", LAST_RESUME_REASON); 171c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn return -1; 172c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 173c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 1746b0331a03025f2ea8c966bf9406dd5788ffa176eAdam Lesinski return i; 175c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn} 176c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 177c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackbornstatic JNINativeMethod method_table[] = { 17887fd322ecb5cd7582f449e5b4721a1e4dea062e6Adam Lesinski { "nativeWaitWakeup", "([Ljava/lang/String;)I", (void*)nativeWaitWakeup }, 179c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn}; 180c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 181c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackbornint register_android_server_BatteryStatsService(JNIEnv *env) 182c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn{ 183c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn return jniRegisterNativeMethods(env, "com/android/server/am/BatteryStatsService", 184c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn method_table, NELEM(method_table)); 185c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn} 186c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 187c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn}; 188