1 /*
2 * Copyright (C) 2021 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 #include <android/binder_parcel.h>
18 #include <android/binder_parcel_jni.h>
19 #include <android/binder_parcel_utils.h>
20 #include <android_runtime/Log.h>
21
22 #include <cstring>
23
24 #include "MultiStateCounter.h"
25 #include "core_jni_helpers.h"
26
27 namespace android {
28
29 namespace battery {
30
31 typedef battery::MultiStateCounter<int64_t> LongMultiStateCounter;
32
33 template <>
delta(const int64_t & previousValue,const int64_t & newValue,int64_t * outValue) const34 bool LongMultiStateCounter::delta(const int64_t &previousValue, const int64_t &newValue,
35 int64_t *outValue) const {
36 *outValue = newValue - previousValue;
37 return *outValue >= 0;
38 }
39
40 template <>
add(int64_t * value1,const int64_t & value2,const uint64_t numerator,const uint64_t denominator) const41 void LongMultiStateCounter::add(int64_t *value1, const int64_t &value2, const uint64_t numerator,
42 const uint64_t denominator) const {
43 if (numerator != denominator) {
44 // The caller ensures that denominator != 0
45 *value1 += value2 * numerator / denominator;
46 } else {
47 *value1 += value2;
48 }
49 }
50
51 template <>
valueToString(const int64_t & v) const52 std::string LongMultiStateCounter::valueToString(const int64_t &v) const {
53 return std::to_string(v);
54 }
55
56 } // namespace battery
57
asLongMultiStateCounter(const jlong nativePtr)58 static inline battery::LongMultiStateCounter *asLongMultiStateCounter(const jlong nativePtr) {
59 return reinterpret_cast<battery::LongMultiStateCounter *>(nativePtr);
60 }
61
native_init(jint stateCount)62 static jlong native_init(jint stateCount) {
63 battery::LongMultiStateCounter *counter = new battery::LongMultiStateCounter(stateCount, 0);
64 return reinterpret_cast<jlong>(counter);
65 }
66
native_dispose(void * nativePtr)67 static void native_dispose(void *nativePtr) {
68 delete reinterpret_cast<battery::LongMultiStateCounter *>(nativePtr);
69 }
70
native_getReleaseFunc()71 static jlong native_getReleaseFunc() {
72 return reinterpret_cast<jlong>(native_dispose);
73 }
74
native_setEnabled(jlong nativePtr,jboolean enabled,jlong timestamp)75 static void native_setEnabled(jlong nativePtr, jboolean enabled, jlong timestamp) {
76 asLongMultiStateCounter(nativePtr)->setEnabled(enabled, timestamp);
77 }
78
native_setState(jlong nativePtr,jint state,jlong timestamp)79 static void native_setState(jlong nativePtr, jint state, jlong timestamp) {
80 asLongMultiStateCounter(nativePtr)->setState(state, timestamp);
81 }
82
native_updateValue(jlong nativePtr,jlong value,jlong timestamp)83 static jlong native_updateValue(jlong nativePtr, jlong value, jlong timestamp) {
84 return (jlong)asLongMultiStateCounter(nativePtr)->updateValue((int64_t)value, timestamp);
85 }
86
native_incrementValue(jlong nativePtr,jlong count,jlong timestamp)87 static void native_incrementValue(jlong nativePtr, jlong count, jlong timestamp) {
88 asLongMultiStateCounter(nativePtr)->incrementValue(count, timestamp);
89 }
90
native_addCount(jlong nativePtr,jlong count)91 static void native_addCount(jlong nativePtr, jlong count) {
92 asLongMultiStateCounter(nativePtr)->addValue(count);
93 }
94
native_reset(jlong nativePtr)95 static void native_reset(jlong nativePtr) {
96 asLongMultiStateCounter(nativePtr)->reset();
97 }
98
native_getCount(jlong nativePtr,jint state)99 static jlong native_getCount(jlong nativePtr, jint state) {
100 return asLongMultiStateCounter(nativePtr)->getCount(state);
101 }
102
native_toString(JNIEnv * env,jobject self,jlong nativePtr)103 static jobject native_toString(JNIEnv *env, jobject self, jlong nativePtr) {
104 return env->NewStringUTF(asLongMultiStateCounter(nativePtr)->toString().c_str());
105 }
106
throwWriteRE(JNIEnv * env,binder_status_t status)107 static void throwWriteRE(JNIEnv *env, binder_status_t status) {
108 ALOGE("Could not write LongMultiStateCounter to Parcel, status = %d", status);
109 jniThrowRuntimeException(env, "Could not write LongMultiStateCounter to Parcel");
110 }
111
112 #define THROW_AND_RETURN_ON_WRITE_ERROR(expr) \
113 { \
114 binder_status_t status = expr; \
115 if (status != STATUS_OK) { \
116 throwWriteRE(env, status); \
117 return; \
118 } \
119 }
120
native_writeToParcel(JNIEnv * env,jobject self,jlong nativePtr,jobject jParcel,jint flags)121 static void native_writeToParcel(JNIEnv *env, jobject self, jlong nativePtr, jobject jParcel,
122 jint flags) {
123 battery::LongMultiStateCounter *counter = asLongMultiStateCounter(nativePtr);
124 ndk::ScopedAParcel parcel(AParcel_fromJavaParcel(env, jParcel));
125
126 uint16_t stateCount = counter->getStateCount();
127 THROW_AND_RETURN_ON_WRITE_ERROR(AParcel_writeInt32(parcel.get(), stateCount));
128
129 for (battery::state_t state = 0; state < stateCount; state++) {
130 THROW_AND_RETURN_ON_WRITE_ERROR(AParcel_writeInt64(parcel.get(), counter->getCount(state)));
131 }
132 }
133
throwReadException(JNIEnv * env,binder_status_t status)134 static void throwReadException(JNIEnv *env, binder_status_t status) {
135 ALOGE("Could not read LongMultiStateCounter from Parcel, status = %d", status);
136 jniThrowException(env, "android.os.BadParcelableException",
137 "Could not read LongMultiStateCounter from Parcel");
138 }
139
140 #define THROW_AND_RETURN_ON_READ_ERROR(expr) \
141 { \
142 binder_status_t status = expr; \
143 if (status != STATUS_OK) { \
144 throwReadException(env, status); \
145 return 0L; \
146 } \
147 }
148
native_initFromParcel(JNIEnv * env,jclass theClass,jobject jParcel)149 static jlong native_initFromParcel(JNIEnv *env, jclass theClass, jobject jParcel) {
150 ndk::ScopedAParcel parcel(AParcel_fromJavaParcel(env, jParcel));
151
152 int32_t stateCount;
153 THROW_AND_RETURN_ON_READ_ERROR(AParcel_readInt32(parcel.get(), &stateCount));
154
155 if (stateCount < 0 || stateCount > 0xEFFF) {
156 throwReadException(env, STATUS_INVALID_OPERATION);
157 return 0L;
158 }
159
160 auto counter = std::make_unique<battery::LongMultiStateCounter>(stateCount, 0);
161
162 for (battery::state_t state = 0; state < stateCount; state++) {
163 int64_t value;
164 THROW_AND_RETURN_ON_READ_ERROR(AParcel_readInt64(parcel.get(), &value));
165 counter->setValue(state, value);
166 }
167
168 return reinterpret_cast<jlong>(counter.release());
169 }
170
native_getStateCount(jlong nativePtr)171 static jint native_getStateCount(jlong nativePtr) {
172 return asLongMultiStateCounter(nativePtr)->getStateCount();
173 }
174
175 static const JNINativeMethod g_methods[] = {
176 // @CriticalNative
177 {"native_init", "(I)J", (void *)native_init},
178 // @CriticalNative
179 {"native_getReleaseFunc", "()J", (void *)native_getReleaseFunc},
180 // @CriticalNative
181 {"native_setEnabled", "(JZJ)V", (void *)native_setEnabled},
182 // @CriticalNative
183 {"native_setState", "(JIJ)V", (void *)native_setState},
184 // @CriticalNative
185 {"native_updateValue", "(JJJ)J", (void *)native_updateValue},
186 // @CriticalNative
187 {"native_incrementValue", "(JJJ)V", (void *)native_incrementValue},
188 // @CriticalNative
189 {"native_addCount", "(JJ)V", (void *)native_addCount},
190 // @CriticalNative
191 {"native_reset", "(J)V", (void *)native_reset},
192 // @CriticalNative
193 {"native_getCount", "(JI)J", (void *)native_getCount},
194 // @FastNative
195 {"native_toString", "(J)Ljava/lang/String;", (void *)native_toString},
196 // @FastNative
197 {"native_writeToParcel", "(JLandroid/os/Parcel;I)V", (void *)native_writeToParcel},
198 // @FastNative
199 {"native_initFromParcel", "(Landroid/os/Parcel;)J", (void *)native_initFromParcel},
200 // @CriticalNative
201 {"native_getStateCount", "(J)I", (void *)native_getStateCount},
202 };
203
register_com_android_internal_os_LongMultiStateCounter(JNIEnv * env)204 int register_com_android_internal_os_LongMultiStateCounter(JNIEnv *env) {
205 return RegisterMethodsOrDie(env, "com/android/internal/os/LongMultiStateCounter", g_methods,
206 NELEM(g_methods));
207 }
208
209 } // namespace android
210