blob: 8c69d276fe6a9b1a59a5cf07cbf06d876909098d [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <android/binder_parcel.h>
#include <android/binder_parcel_jni.h>
#include <android/binder_parcel_utils.h>
#include <android_runtime/Log.h>
#include <cstring>
#include "MultiStateCounter.h"
#include "core_jni_helpers.h"
namespace android {
namespace battery {
typedef battery::MultiStateCounter<int64_t> LongMultiStateCounter;
template <>
bool LongMultiStateCounter::delta(const int64_t &previousValue, const int64_t &newValue,
int64_t *outValue) const {
*outValue = newValue - previousValue;
return *outValue >= 0;
}
template <>
void LongMultiStateCounter::add(int64_t *value1, const int64_t &value2, const uint64_t numerator,
const uint64_t denominator) const {
if (numerator != denominator) {
// The caller ensures that denominator != 0
*value1 += value2 * numerator / denominator;
} else {
*value1 += value2;
}
}
template <>
std::string LongMultiStateCounter::valueToString(const int64_t &v) const {
return std::to_string(v);
}
} // namespace battery
static inline battery::LongMultiStateCounter *asLongMultiStateCounter(const jlong nativePtr) {
return reinterpret_cast<battery::LongMultiStateCounter *>(nativePtr);
}
static jlong native_init(jint stateCount) {
battery::LongMultiStateCounter *counter = new battery::LongMultiStateCounter(stateCount, 0);
return reinterpret_cast<jlong>(counter);
}
static void native_dispose(void *nativePtr) {
delete reinterpret_cast<battery::LongMultiStateCounter *>(nativePtr);
}
static jlong native_getReleaseFunc() {
return reinterpret_cast<jlong>(native_dispose);
}
static void native_setEnabled(jlong nativePtr, jboolean enabled, jlong timestamp) {
asLongMultiStateCounter(nativePtr)->setEnabled(enabled, timestamp);
}
static void native_setState(jlong nativePtr, jint state, jlong timestamp) {
asLongMultiStateCounter(nativePtr)->setState(state, timestamp);
}
static jlong native_updateValue(jlong nativePtr, jlong value, jlong timestamp) {
return (jlong)asLongMultiStateCounter(nativePtr)->updateValue((int64_t)value, timestamp);
}
static void native_incrementValue(jlong nativePtr, jlong count, jlong timestamp) {
asLongMultiStateCounter(nativePtr)->incrementValue(count, timestamp);
}
static void native_addCount(jlong nativePtr, jlong count) {
asLongMultiStateCounter(nativePtr)->addValue(count);
}
static void native_reset(jlong nativePtr) {
asLongMultiStateCounter(nativePtr)->reset();
}
static jlong native_getCount(jlong nativePtr, jint state) {
return asLongMultiStateCounter(nativePtr)->getCount(state);
}
static jobject native_toString(JNIEnv *env, jobject self, jlong nativePtr) {
return env->NewStringUTF(asLongMultiStateCounter(nativePtr)->toString().c_str());
}
static void throwWriteRE(JNIEnv *env, binder_status_t status) {
ALOGE("Could not write LongMultiStateCounter to Parcel, status = %d", status);
jniThrowRuntimeException(env, "Could not write LongMultiStateCounter to Parcel");
}
#define THROW_ON_WRITE_ERROR(expr) \
{ \
binder_status_t status = expr; \
if (status != STATUS_OK) { \
throwWriteRE(env, status); \
} \
}
static void native_writeToParcel(JNIEnv *env, jobject self, jlong nativePtr, jobject jParcel,
jint flags) {
battery::LongMultiStateCounter *counter = asLongMultiStateCounter(nativePtr);
ndk::ScopedAParcel parcel(AParcel_fromJavaParcel(env, jParcel));
uint16_t stateCount = counter->getStateCount();
THROW_ON_WRITE_ERROR(AParcel_writeInt32(parcel.get(), stateCount));
for (battery::state_t state = 0; state < stateCount; state++) {
THROW_ON_WRITE_ERROR(AParcel_writeInt64(parcel.get(), counter->getCount(state)));
}
}
static void throwReadRE(JNIEnv *env, binder_status_t status) {
ALOGE("Could not read LongMultiStateCounter from Parcel, status = %d", status);
jniThrowRuntimeException(env, "Could not read LongMultiStateCounter from Parcel");
}
#define THROW_ON_READ_ERROR(expr) \
{ \
binder_status_t status = expr; \
if (status != STATUS_OK) { \
throwReadRE(env, status); \
} \
}
static jlong native_initFromParcel(JNIEnv *env, jclass theClass, jobject jParcel) {
ndk::ScopedAParcel parcel(AParcel_fromJavaParcel(env, jParcel));
int32_t stateCount;
THROW_ON_READ_ERROR(AParcel_readInt32(parcel.get(), &stateCount));
battery::LongMultiStateCounter *counter = new battery::LongMultiStateCounter(stateCount, 0);
for (battery::state_t state = 0; state < stateCount; state++) {
int64_t value;
THROW_ON_READ_ERROR(AParcel_readInt64(parcel.get(), &value));
counter->setValue(state, value);
}
return reinterpret_cast<jlong>(counter);
}
static jint native_getStateCount(jlong nativePtr) {
return asLongMultiStateCounter(nativePtr)->getStateCount();
}
static const JNINativeMethod g_methods[] = {
// @CriticalNative
{"native_init", "(I)J", (void *)native_init},
// @CriticalNative
{"native_getReleaseFunc", "()J", (void *)native_getReleaseFunc},
// @CriticalNative
{"native_setEnabled", "(JZJ)V", (void *)native_setEnabled},
// @CriticalNative
{"native_setState", "(JIJ)V", (void *)native_setState},
// @CriticalNative
{"native_updateValue", "(JJJ)J", (void *)native_updateValue},
// @CriticalNative
{"native_incrementValue", "(JJJ)V", (void *)native_incrementValue},
// @CriticalNative
{"native_addCount", "(JJ)V", (void *)native_addCount},
// @CriticalNative
{"native_reset", "(J)V", (void *)native_reset},
// @CriticalNative
{"native_getCount", "(JI)J", (void *)native_getCount},
// @FastNative
{"native_toString", "(J)Ljava/lang/String;", (void *)native_toString},
// @FastNative
{"native_writeToParcel", "(JLandroid/os/Parcel;I)V", (void *)native_writeToParcel},
// @FastNative
{"native_initFromParcel", "(Landroid/os/Parcel;)J", (void *)native_initFromParcel},
// @CriticalNative
{"native_getStateCount", "(J)I", (void *)native_getStateCount},
};
int register_com_android_internal_os_LongMultiStateCounter(JNIEnv *env) {
return RegisterMethodsOrDie(env, "com/android/internal/os/LongMultiStateCounter", g_methods,
NELEM(g_methods));
}
} // namespace android