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