blob: 02ad6c71b58657ec6aa671a53fe107d0657d6174 [file] [log] [blame]
Dianne Hackbornc51cf032014-03-02 19:08:15 -08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "BatteryStatsService"
18//#define LOG_NDEBUG 0
19
Mark Salyzyn96bf5982016-09-28 16:15:30 -070020#include <errno.h>
21#include <fcntl.h>
22#include <inttypes.h>
23#include <semaphore.h>
24#include <stddef.h>
25#include <stdio.h>
26#include <string.h>
27#include <sys/stat.h>
28#include <sys/types.h>
29#include <unistd.h>
30
Ruchi Kandoi0d434042016-10-03 09:12:02 -070031#include <android/hardware/power/1.0/IPower.h>
Ahmed ElArabawyd8b44112017-05-23 21:25:02 +000032#include <android/hardware/power/1.1/IPower.h>
Dianne Hackbornc51cf032014-03-02 19:08:15 -080033#include <android_runtime/AndroidRuntime.h>
34#include <jni.h>
35
Steven Moreland2279b252017-07-19 09:50:45 -070036#include <nativehelper/ScopedLocalRef.h>
37#include <nativehelper/ScopedPrimitiveArray.h>
Dianne Hackbornc51cf032014-03-02 19:08:15 -080038
Mark Salyzyn96bf5982016-09-28 16:15:30 -070039#include <log/log.h>
Dianne Hackbornc51cf032014-03-02 19:08:15 -080040#include <utils/misc.h>
41#include <utils/Log.h>
Dianne Hackbornc51cf032014-03-02 19:08:15 -080042#include <suspend/autosuspend.h>
43
Ruchi Kandoi0d434042016-10-03 09:12:02 -070044using android::hardware::Return;
45using android::hardware::Void;
Ruchi Kandoi0d434042016-10-03 09:12:02 -070046using android::hardware::power::V1_0::PowerStatePlatformSleepState;
47using android::hardware::power::V1_0::PowerStateVoter;
48using android::hardware::power::V1_0::Status;
Ahmed ElArabawyd8b44112017-05-23 21:25:02 +000049using android::hardware::power::V1_1::PowerStateSubsystem;
50using android::hardware::power::V1_1::PowerStateSubsystemSleepState;
Ruchi Kandoi0d434042016-10-03 09:12:02 -070051using android::hardware::hidl_vec;
Wei Wang5d77c722017-11-29 12:28:00 -080052using IPowerV1_1 = android::hardware::power::V1_1::IPower;
53using IPowerV1_0 = android::hardware::power::V1_0::IPower;
Ruchi Kandoi0d434042016-10-03 09:12:02 -070054
Dianne Hackbornc51cf032014-03-02 19:08:15 -080055namespace android
56{
57
58#define LAST_RESUME_REASON "/sys/kernel/wakeup_reasons/last_resume_reason"
59#define MAX_REASON_SIZE 512
60
61static bool wakeup_init = false;
62static sem_t wakeup_sem;
Wei Wang5d77c722017-11-29 12:28:00 -080063extern sp<IPowerV1_0> getPowerHalV1_0();
64extern sp<IPowerV1_1> getPowerHalV1_1();
65extern bool processPowerHalReturn(const Return<void> &ret, const char* functionName);
Dianne Hackbornc51cf032014-03-02 19:08:15 -080066
Bookatz50df7112017-08-04 14:53:26 -070067// Java methods used in getLowPowerStats
68static jmethodID jgetAndUpdatePlatformState = NULL;
69static jmethodID jgetSubsystem = NULL;
70static jmethodID jputVoter = NULL;
71static jmethodID jputState = NULL;
72
Adam Lesinski87fd3222015-06-25 13:10:36 -070073static void wakeup_callback(bool success)
Dianne Hackbornc51cf032014-03-02 19:08:15 -080074{
Adam Lesinski87fd3222015-06-25 13:10:36 -070075 ALOGV("In wakeup_callback: %s", success ? "resumed from suspend" : "suspend aborted");
Dianne Hackbornc51cf032014-03-02 19:08:15 -080076 int ret = sem_post(&wakeup_sem);
77 if (ret < 0) {
78 char buf[80];
79 strerror_r(errno, buf, sizeof(buf));
80 ALOGE("Error posting wakeup sem: %s\n", buf);
81 }
82}
83
Adam Lesinski515702c2015-07-23 18:13:38 -070084static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobject outBuf)
Dianne Hackbornc51cf032014-03-02 19:08:15 -080085{
Adam Lesinski515702c2015-07-23 18:13:38 -070086 if (outBuf == NULL) {
Dianne Hackbornc51cf032014-03-02 19:08:15 -080087 jniThrowException(env, "java/lang/NullPointerException", "null argument");
88 return -1;
89 }
90
91 // Register our wakeup callback if not yet done.
92 if (!wakeup_init) {
93 wakeup_init = true;
94 ALOGV("Creating semaphore...");
95 int ret = sem_init(&wakeup_sem, 0, 0);
96 if (ret < 0) {
97 char buf[80];
98 strerror_r(errno, buf, sizeof(buf));
99 ALOGE("Error creating semaphore: %s\n", buf);
100 jniThrowException(env, "java/lang/IllegalStateException", buf);
101 return -1;
102 }
103 ALOGV("Registering callback...");
Steve Paik4955d6c2017-12-18 10:23:31 -0800104 autosuspend_set_wakeup_callback(&wakeup_callback);
Adam Lesinski6b0331a2015-06-05 17:08:22 -0700105 }
106
107 // Wait for wakeup.
108 ALOGV("Waiting for wakeup...");
109 int ret = sem_wait(&wakeup_sem);
110 if (ret < 0) {
111 char buf[80];
112 strerror_r(errno, buf, sizeof(buf));
113 ALOGE("Error waiting on semaphore: %s\n", buf);
114 // Return 0 here to let it continue looping but not return results.
115 return 0;
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800116 }
117
118 FILE *fp = fopen(LAST_RESUME_REASON, "r");
119 if (fp == NULL) {
120 ALOGE("Failed to open %s", LAST_RESUME_REASON);
121 return -1;
122 }
123
Adam Lesinski515702c2015-07-23 18:13:38 -0700124 char* mergedreason = (char*)env->GetDirectBufferAddress(outBuf);
125 int remainreasonlen = (int)env->GetDirectBufferCapacity(outBuf);
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800126
Adam Lesinski515702c2015-07-23 18:13:38 -0700127 ALOGV("Reading wakeup reasons");
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800128 char* mergedreasonpos = mergedreason;
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800129 char reasonline[128];
130 int i = 0;
Adam Lesinski87fd3222015-06-25 13:10:36 -0700131 while (fgets(reasonline, sizeof(reasonline), fp) != NULL) {
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800132 char* pos = reasonline;
133 char* endPos;
Adam Lesinski87fd3222015-06-25 13:10:36 -0700134 int len;
135 // First field is the index or 'Abort'.
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800136 int irq = (int)strtol(pos, &endPos, 10);
Adam Lesinski87fd3222015-06-25 13:10:36 -0700137 if (pos != endPos) {
138 // Write the irq number to the merged reason string.
139 len = snprintf(mergedreasonpos, remainreasonlen, i == 0 ? "%d" : ":%d", irq);
140 } else {
141 // The first field is not an irq, it may be the word Abort.
142 const size_t abortPrefixLen = strlen("Abort:");
143 if (strncmp(pos, "Abort:", abortPrefixLen) != 0) {
144 // Ooops.
145 ALOGE("Bad reason line: %s", reasonline);
146 continue;
147 }
148
149 // Write 'Abort' to the merged reason string.
150 len = snprintf(mergedreasonpos, remainreasonlen, i == 0 ? "Abort" : ":Abort");
151 endPos = pos + abortPrefixLen;
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800152 }
153 pos = endPos;
Adam Lesinski87fd3222015-06-25 13:10:36 -0700154
155 if (len >= 0 && len < remainreasonlen) {
156 mergedreasonpos += len;
157 remainreasonlen -= len;
158 }
159
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800160 // Skip whitespace; rest of the buffer is the reason string.
161 while (*pos == ' ') {
162 pos++;
163 }
Adam Lesinski87fd3222015-06-25 13:10:36 -0700164
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800165 // Chop newline at end.
166 char* endpos = pos;
167 while (*endpos != 0) {
168 if (*endpos == '\n') {
169 *endpos = 0;
170 break;
171 }
172 endpos++;
173 }
Adam Lesinski87fd3222015-06-25 13:10:36 -0700174
175 len = snprintf(mergedreasonpos, remainreasonlen, ":%s", pos);
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800176 if (len >= 0 && len < remainreasonlen) {
177 mergedreasonpos += len;
178 remainreasonlen -= len;
179 }
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800180 i++;
181 }
182
183 ALOGV("Got %d reasons", i);
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800184 if (i > 0) {
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800185 *mergedreasonpos = 0;
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800186 }
187
188 if (fclose(fp) != 0) {
189 ALOGE("Failed to close %s", LAST_RESUME_REASON);
190 return -1;
191 }
Adam Lesinski515702c2015-07-23 18:13:38 -0700192 return mergedreasonpos - mergedreason;
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800193}
194
Bookatz50df7112017-08-04 14:53:26 -0700195static void getLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject jrpmStats) {
196 if (jrpmStats == NULL) {
197 jniThrowException(env, "java/lang/NullPointerException",
198 "The rpmstats jni input jobject jrpmStats is null.");
199 return;
200 }
201 if (jgetAndUpdatePlatformState == NULL || jgetSubsystem == NULL
202 || jputVoter == NULL || jputState == NULL) {
203 ALOGE("A rpmstats jni jmethodID is null.");
204 return;
205 }
206
Wei Wang5d77c722017-11-29 12:28:00 -0800207 sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0();
208 if (powerHalV1_0 == nullptr) {
Bookatz50df7112017-08-04 14:53:26 -0700209 ALOGE("Power Hal not loaded");
210 return;
211 }
212
Wei Wang5d77c722017-11-29 12:28:00 -0800213 Return<void> ret = powerHalV1_0->getPlatformLowPowerStats(
Bookatz50df7112017-08-04 14:53:26 -0700214 [&env, &jrpmStats](hidl_vec<PowerStatePlatformSleepState> states, Status status) {
215
216 if (status != Status::SUCCESS) return;
217
218 for (size_t i = 0; i < states.size(); i++) {
219 const PowerStatePlatformSleepState& state = states[i];
220
221 jobject jplatformState = env->CallObjectMethod(jrpmStats,
222 jgetAndUpdatePlatformState,
223 env->NewStringUTF(state.name.c_str()),
224 state.residencyInMsecSinceBoot,
225 state.totalTransitions);
226 if (jplatformState == NULL) {
227 ALOGE("The rpmstats jni jobject jplatformState is null.");
228 return;
229 }
230
231 for (size_t j = 0; j < state.voters.size(); j++) {
232 const PowerStateVoter& voter = state.voters[j];
233 env->CallVoidMethod(jplatformState, jputVoter,
234 env->NewStringUTF(voter.name.c_str()),
235 voter.totalTimeInMsecVotedForSinceBoot,
236 voter.totalNumberOfTimesVotedSinceBoot);
237 }
238 }
239 });
Wei Wang5d77c722017-11-29 12:28:00 -0800240 if (!processPowerHalReturn(ret, "getPlatformLowPowerStats")) {
Bookatz50df7112017-08-04 14:53:26 -0700241 return;
242 }
243
Wei Wang5d77c722017-11-29 12:28:00 -0800244 // Trying to get IPower 1.1, this will succeed only for devices supporting 1.1
245 sp<IPowerV1_1> powerHal_1_1 = getPowerHalV1_1();
246 if (powerHal_1_1 == nullptr) {
247 // This device does not support IPower@1.1, exiting gracefully
Bookatz50df7112017-08-04 14:53:26 -0700248 return;
249 }
Wei Wang5d77c722017-11-29 12:28:00 -0800250 ret = powerHal_1_1->getSubsystemLowPowerStats(
Bookatz50df7112017-08-04 14:53:26 -0700251 [&env, &jrpmStats](hidl_vec<PowerStateSubsystem> subsystems, Status status) {
252
253 if (status != Status::SUCCESS) return;
254
255 if (subsystems.size() > 0) {
256 for (size_t i = 0; i < subsystems.size(); i++) {
257 const PowerStateSubsystem &subsystem = subsystems[i];
258
259 jobject jsubsystem = env->CallObjectMethod(jrpmStats, jgetSubsystem,
260 env->NewStringUTF(subsystem.name.c_str()));
261 if (jsubsystem == NULL) {
262 ALOGE("The rpmstats jni jobject jsubsystem is null.");
263 return;
264 }
265
266 for (size_t j = 0; j < subsystem.states.size(); j++) {
267 const PowerStateSubsystemSleepState& state = subsystem.states[j];
268 env->CallVoidMethod(jsubsystem, jputState,
269 env->NewStringUTF(state.name.c_str()),
270 state.residencyInMsecSinceBoot,
271 state.totalTransitions);
272 }
273 }
274 }
275 });
Wei Wang5d77c722017-11-29 12:28:00 -0800276 processPowerHalReturn(ret, "getSubsystemLowPowerStats");
Bookatz50df7112017-08-04 14:53:26 -0700277}
278
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700279static jint getPlatformLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject outBuf) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700280 char *output = (char*)env->GetDirectBufferAddress(outBuf);
281 char *offset = output;
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700282 int remaining = (int)env->GetDirectBufferCapacity(outBuf);
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700283 int total_added = -1;
284
285 if (outBuf == NULL) {
286 jniThrowException(env, "java/lang/NullPointerException", "null argument");
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700287 return -1;
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700288 }
289
Connor O'Brien578eb7f2017-02-27 16:41:35 -0800290 {
Wei Wang5d77c722017-11-29 12:28:00 -0800291 sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0();
292 if (powerHalV1_0 == nullptr) {
Connor O'Brien578eb7f2017-02-27 16:41:35 -0800293 ALOGE("Power Hal not loaded");
294 return -1;
295 }
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700296
Wei Wang5d77c722017-11-29 12:28:00 -0800297 Return<void> ret = powerHalV1_0->getPlatformLowPowerStats(
Connor O'Brien578eb7f2017-02-27 16:41:35 -0800298 [&offset, &remaining, &total_added](hidl_vec<PowerStatePlatformSleepState> states,
299 Status status) {
300 if (status != Status::SUCCESS)
301 return;
302 for (size_t i = 0; i < states.size(); i++) {
303 int added;
304 const PowerStatePlatformSleepState& state = states[i];
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700305
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700306 added = snprintf(offset, remaining,
Connor O'Brien578eb7f2017-02-27 16:41:35 -0800307 "state_%zu name=%s time=%" PRIu64 " count=%" PRIu64 " ",
308 i + 1, state.name.c_str(), state.residencyInMsecSinceBoot,
309 state.totalTransitions);
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700310 if (added < 0) {
311 break;
312 }
313 if (added > remaining) {
314 added = remaining;
315 }
316 offset += added;
317 remaining -= added;
318 total_added += added;
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700319
Connor O'Brien578eb7f2017-02-27 16:41:35 -0800320 for (size_t j = 0; j < state.voters.size(); j++) {
321 const PowerStateVoter& voter = state.voters[j];
322 added = snprintf(offset, remaining,
323 "voter_%zu name=%s time=%" PRIu64 " count=%" PRIu64 " ",
324 j + 1, voter.name.c_str(),
325 voter.totalTimeInMsecVotedForSinceBoot,
326 voter.totalNumberOfTimesVotedSinceBoot);
327 if (added < 0) {
328 break;
329 }
330 if (added > remaining) {
331 added = remaining;
332 }
333 offset += added;
334 remaining -= added;
335 total_added += added;
336 }
337
338 if (remaining <= 0) {
339 /* rewrite NULL character*/
340 offset--;
341 total_added--;
342 ALOGE("PowerHal: buffer not enough");
343 break;
344 }
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700345 }
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700346 }
Connor O'Brien578eb7f2017-02-27 16:41:35 -0800347 );
348
Wei Wang5d77c722017-11-29 12:28:00 -0800349 if (!processPowerHalReturn(ret, "getPlatformLowPowerStats")) {
Connor O'Brien578eb7f2017-02-27 16:41:35 -0800350 return -1;
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700351 }
Connor O'Brien578eb7f2017-02-27 16:41:35 -0800352 }
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700353 *offset = 0;
354 total_added += 1;
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700355 return total_added;
356}
357
Ahmed ElArabawyd8b44112017-05-23 21:25:02 +0000358static jint getSubsystemLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject outBuf) {
359 char *output = (char*)env->GetDirectBufferAddress(outBuf);
360 char *offset = output;
361 int remaining = (int)env->GetDirectBufferCapacity(outBuf);
362 int total_added = -1;
363
Wei Wang5d77c722017-11-29 12:28:00 -0800364 // This is a IPower 1.1 API
365 sp<IPowerV1_1> powerHal_1_1 = nullptr;
Ahmed ElArabawyd8b44112017-05-23 21:25:02 +0000366
367 if (outBuf == NULL) {
368 jniThrowException(env, "java/lang/NullPointerException", "null argument");
369 return -1;
370 }
371
372 {
Wei Wang5d77c722017-11-29 12:28:00 -0800373 // Trying to get 1.1, this will succeed only for devices supporting 1.1
374 powerHal_1_1 = getPowerHalV1_1();
375 if (powerHal_1_1 == nullptr) {
Ahmed ElArabawyd8b44112017-05-23 21:25:02 +0000376 //This device does not support IPower@1.1, exiting gracefully
377 return 0;
Wei Wang5d77c722017-11-29 12:28:00 -0800378 }
Ahmed ElArabawyd8b44112017-05-23 21:25:02 +0000379
Wei Wang5d77c722017-11-29 12:28:00 -0800380 Return<void> ret = powerHal_1_1->getSubsystemLowPowerStats(
Ahmed ElArabawyd8b44112017-05-23 21:25:02 +0000381 [&offset, &remaining, &total_added](hidl_vec<PowerStateSubsystem> subsystems,
382 Status status) {
383
384 if (status != Status::SUCCESS)
385 return;
386
Ahmed ElArabawy307edcd2017-07-07 17:48:13 -0700387 if (subsystems.size() > 0) {
388 int added = snprintf(offset, remaining, "SubsystemPowerState ");
Ahmed ElArabawyd8b44112017-05-23 21:25:02 +0000389 offset += added;
390 remaining -= added;
391 total_added += added;
392
Ahmed ElArabawy307edcd2017-07-07 17:48:13 -0700393 for (size_t i = 0; i < subsystems.size(); i++) {
394 const PowerStateSubsystem &subsystem = subsystems[i];
395
Ahmed ElArabawyd8b44112017-05-23 21:25:02 +0000396 added = snprintf(offset, remaining,
Ahmed ElArabawy307edcd2017-07-07 17:48:13 -0700397 "subsystem_%zu name=%s ", i + 1, subsystem.name.c_str());
Ahmed ElArabawyd8b44112017-05-23 21:25:02 +0000398 if (added < 0) {
399 break;
400 }
401
402 if (added > remaining) {
403 added = remaining;
404 }
405
406 offset += added;
407 remaining -= added;
408 total_added += added;
Ahmed ElArabawyd8b44112017-05-23 21:25:02 +0000409
Ahmed ElArabawy307edcd2017-07-07 17:48:13 -0700410 for (size_t j = 0; j < subsystem.states.size(); j++) {
411 const PowerStateSubsystemSleepState& state = subsystem.states[j];
412 added = snprintf(offset, remaining,
413 "state_%zu name=%s time=%" PRIu64 " count=%" PRIu64 " last entry=%" PRIu64 " ",
414 j + 1, state.name.c_str(), state.residencyInMsecSinceBoot,
415 state.totalTransitions, state.lastEntryTimestampMs);
416 if (added < 0) {
417 break;
418 }
419
420 if (added > remaining) {
421 added = remaining;
422 }
423
424 offset += added;
425 remaining -= added;
426 total_added += added;
427 }
428
429 if (remaining <= 0) {
430 /* rewrite NULL character*/
431 offset--;
432 total_added--;
433 ALOGE("PowerHal: buffer not enough");
434 break;
435 }
Ahmed ElArabawyd8b44112017-05-23 21:25:02 +0000436 }
437 }
438 }
439 );
440
Wei Wang5d77c722017-11-29 12:28:00 -0800441 if (!processPowerHalReturn(ret, "getSubsystemLowPowerStats")) {
Ahmed ElArabawyd8b44112017-05-23 21:25:02 +0000442 return -1;
443 }
444 }
445
446 *offset = 0;
447 total_added += 1;
448 return total_added;
449}
450
Daniel Micay76f6a862015-09-19 17:31:01 -0400451static const JNINativeMethod method_table[] = {
Adam Lesinski515702c2015-07-23 18:13:38 -0700452 { "nativeWaitWakeup", "(Ljava/nio/ByteBuffer;)I", (void*)nativeWaitWakeup },
Bookatz50df7112017-08-04 14:53:26 -0700453 { "getLowPowerStats", "(Lcom/android/internal/os/RpmStats;)V", (void*)getLowPowerStats },
Badhri Jagan Sridharan68cdf192016-04-03 21:57:15 -0700454 { "getPlatformLowPowerStats", "(Ljava/nio/ByteBuffer;)I", (void*)getPlatformLowPowerStats },
Ahmed ElArabawyd8b44112017-05-23 21:25:02 +0000455 { "getSubsystemLowPowerStats", "(Ljava/nio/ByteBuffer;)I", (void*)getSubsystemLowPowerStats },
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800456};
457
458int register_android_server_BatteryStatsService(JNIEnv *env)
459{
Bookatz50df7112017-08-04 14:53:26 -0700460 // get java classes and methods
461 jclass clsRpmStats = env->FindClass("com/android/internal/os/RpmStats");
462 jclass clsPowerStatePlatformSleepState =
463 env->FindClass("com/android/internal/os/RpmStats$PowerStatePlatformSleepState");
464 jclass clsPowerStateSubsystem =
465 env->FindClass("com/android/internal/os/RpmStats$PowerStateSubsystem");
466 if (clsRpmStats == NULL || clsPowerStatePlatformSleepState == NULL
467 || clsPowerStateSubsystem == NULL) {
468 ALOGE("A rpmstats jni jclass is null.");
469 } else {
470 jgetAndUpdatePlatformState = env->GetMethodID(clsRpmStats, "getAndUpdatePlatformState",
471 "(Ljava/lang/String;JI)Lcom/android/internal/os/RpmStats$PowerStatePlatformSleepState;");
472 jgetSubsystem = env->GetMethodID(clsRpmStats, "getSubsystem",
473 "(Ljava/lang/String;)Lcom/android/internal/os/RpmStats$PowerStateSubsystem;");
474 jputVoter = env->GetMethodID(clsPowerStatePlatformSleepState, "putVoter",
475 "(Ljava/lang/String;JI)V");
476 jputState = env->GetMethodID(clsPowerStateSubsystem, "putState",
477 "(Ljava/lang/String;JI)V");
478 }
479
Dianne Hackbornc51cf032014-03-02 19:08:15 -0800480 return jniRegisterNativeMethods(env, "com/android/server/am/BatteryStatsService",
481 method_table, NELEM(method_table));
482}
483
484};