com_android_server_am_BatteryStatsService.cpp revision c51cf03cf2458c8c137f60c7379f2cccf681d16f
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 51c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackbornstatic void wakeup_callback(void) 52c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn{ 53c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGV("In wakeup_callback"); 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 62c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackbornstatic jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jintArray outIrqs, 63c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn jobjectArray outReasons) 64c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn{ 65c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn bool first_time = false; 66c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 67c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (outIrqs == NULL || outReasons == NULL) { 68c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn jniThrowException(env, "java/lang/NullPointerException", "null argument"); 69c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn return -1; 70c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 71c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 72c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn // Register our wakeup callback if not yet done. 73c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (!wakeup_init) { 74c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn wakeup_init = true; 75c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGV("Creating semaphore..."); 76c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn int ret = sem_init(&wakeup_sem, 0, 0); 77c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (ret < 0) { 78c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char buf[80]; 79c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn strerror_r(errno, buf, sizeof(buf)); 80c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGE("Error creating semaphore: %s\n", buf); 81c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn jniThrowException(env, "java/lang/IllegalStateException", buf); 82c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn return -1; 83c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 84c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGV("Registering callback..."); 85c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn set_wakeup_callback(&wakeup_callback); 86c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn // First time through, we will just drain the current wakeup reasons. 87c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn first_time = true; 88c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } else { 89c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn // On following calls, we need to wait for wakeup. 90c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGV("Waiting for wakeup..."); 91c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn int ret = sem_wait(&wakeup_sem); 92c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (ret < 0) { 93c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char buf[80]; 94c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn strerror_r(errno, buf, sizeof(buf)); 95c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGE("Error waiting on semaphore: %s\n", buf); 96c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn // Return 0 here to let it continue looping but not return results. 97c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn return 0; 98c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 99c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 100c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 101c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn FILE *fp = fopen(LAST_RESUME_REASON, "r"); 102c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (fp == NULL) { 103c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGE("Failed to open %s", LAST_RESUME_REASON); 104c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn return -1; 105c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 106c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 107c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn int numOut = env->GetArrayLength(outIrqs); 108c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ScopedIntArrayRW irqs(env, outIrqs); 109c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 110c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGV("Reading up to %d wakeup reasons", numOut); 111c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 112c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char mergedreason[MAX_REASON_SIZE]; 113c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char* mergedreasonpos = mergedreason; 114c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn int remainreasonlen = MAX_REASON_SIZE; 115c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn int firstirq = 0; 116c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char reasonline[128]; 117c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn int i = 0; 118c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn while (fgets(reasonline, sizeof(reasonline), fp) != NULL && i < numOut) { 119c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char* pos = reasonline; 120c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char* endPos; 121c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn // First field is the index. 122c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn int irq = (int)strtol(pos, &endPos, 10); 123c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (pos == endPos) { 124c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn // Ooops. 125c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGE("Bad reason line: %s", reasonline); 126c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn continue; 127c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 128c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn pos = endPos; 129c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn // Skip whitespace; rest of the buffer is the reason string. 130c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn while (*pos == ' ') { 131c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn pos++; 132c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 133c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn // Chop newline at end. 134c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn char* endpos = pos; 135c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn while (*endpos != 0) { 136c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (*endpos == '\n') { 137c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn *endpos = 0; 138c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn break; 139c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 140c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn endpos++; 141c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 142c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (i == 0) { 143c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn firstirq = irq; 144c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } else { 145c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn int len = snprintf(mergedreasonpos, remainreasonlen, ":%d", irq); 146c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (len >= 0 && len < remainreasonlen) { 147c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn mergedreasonpos += len; 148c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn remainreasonlen -= len; 149c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 150c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 151c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn int len = snprintf(mergedreasonpos, remainreasonlen, i == 0 ? "%s" : ":%s", pos); 152c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (len >= 0 && len < remainreasonlen) { 153c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn mergedreasonpos += len; 154c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn remainreasonlen -= len; 155c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 156c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn // For now it is better to combine all of these in to one entry in the 157c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn // battery history. In the future, it might be nice to figure out a way 158c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn // to efficiently store multiple lines as a single entry in the history. 159c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn //irqs[i] = irq; 160c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn //ScopedLocalRef<jstring> reasonString(env, env->NewStringUTF(pos)); 161c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn //env->SetObjectArrayElement(outReasons, i, reasonString.get()); 162c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn //ALOGV("Wakeup reason #%d: irw %d reason %s", i, irq, pos); 163c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn i++; 164c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 165c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 166c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGV("Got %d reasons", i); 167c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (first_time) { 168c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn i = 0; 169c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 170c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (i > 0) { 171c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn irqs[0] = firstirq; 172c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn *mergedreasonpos = 0; 173c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ScopedLocalRef<jstring> reasonString(env, env->NewStringUTF(mergedreason)); 174c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn env->SetObjectArrayElement(outReasons, 0, reasonString.get()); 175c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn i = 1; 176c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 177c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 178c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn if (fclose(fp) != 0) { 179c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn ALOGE("Failed to close %s", LAST_RESUME_REASON); 180c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn return -1; 181c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn } 182c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 183c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn return first_time ? 0 : i; 184c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn} 185c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 186c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackbornstatic JNINativeMethod method_table[] = { 187c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn { "nativeWaitWakeup", "([I[Ljava/lang/String;)I", (void*)nativeWaitWakeup }, 188c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn}; 189c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 190c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackbornint register_android_server_BatteryStatsService(JNIEnv *env) 191c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn{ 192c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn return jniRegisterNativeMethods(env, "com/android/server/am/BatteryStatsService", 193c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn method_table, NELEM(method_table)); 194c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn} 195c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn 196c51cf03cf2458c8c137f60c7379f2cccf681d16fDianne Hackborn}; 197