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