• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.internal.os;
18 
19 import android.annotation.CheckResult;
20 import android.annotation.Nullable;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.ravenwood.annotation.RavenwoodKeepWholeClass;
24 import android.ravenwood.annotation.RavenwoodRedirect;
25 import android.ravenwood.annotation.RavenwoodRedirectionClass;
26 import android.ravenwood.annotation.RavenwoodReplace;
27 
28 import com.android.internal.util.Preconditions;
29 
30 import dalvik.annotation.optimization.CriticalNative;
31 import dalvik.annotation.optimization.FastNative;
32 
33 import libcore.util.NativeAllocationRegistry;
34 
35 /**
36  * Performs per-state counting of multi-element values over time. The class' behavior is illustrated
37  * by this example:
38  * <pre>
39  *   // At 0 ms, the state of the tracked object is 0
40  *   counter.setState(0, 0);
41  *
42  *   // At 1000 ms, the state changes to 1
43  *   counter.setState(1, 1000);
44  *
45  *   // At 3000 ms, the tracked values are updated to {30, 300}
46  *   counter.updateValues(arrayContainer, new long[]{{30, 300}, 3000);
47  *
48  *   // The values are distributed between states 0 and 1 according to the time
49  *   // spent in those respective states. In this specific case, 1000 and 2000 ms.
50  *   counter.getCounts(array, 0);
51  *   // array now has values {10, 100}
52  *   counter.getCounts(array, 1);
53  *   // array now has values {20, 200}
54  * </pre>
55  *
56  * The tracked values are expected to increase monotonically.
57  *
58  * @hide
59  */
60 @RavenwoodKeepWholeClass
61 @RavenwoodRedirectionClass("LongArrayMultiStateCounter_ravenwood")
62 public final class LongArrayMultiStateCounter implements Parcelable {
63     private static volatile NativeAllocationRegistry sRegistry;
64     private final int mStateCount;
65     private final int mLength;
66 
67     // Visible to other objects in this package so that it can be passed to @CriticalNative
68     // methods.
69     final long mNativeObject;
70 
LongArrayMultiStateCounter(int stateCount, int arrayLength)71     public LongArrayMultiStateCounter(int stateCount, int arrayLength) {
72         Preconditions.checkArgumentPositive(stateCount, "stateCount must be greater than 0");
73         mStateCount = stateCount;
74         mLength = arrayLength;
75         mNativeObject = native_init(stateCount, arrayLength);
76         registerNativeAllocation();
77     }
78 
79     @RavenwoodReplace
registerNativeAllocation()80     private void registerNativeAllocation() {
81         if (sRegistry == null) {
82             synchronized (LongArrayMultiStateCounter.class) {
83                 if (sRegistry == null) {
84                     sRegistry = NativeAllocationRegistry.createMalloced(
85                             LongArrayMultiStateCounter.class.getClassLoader(),
86                             native_getReleaseFunc());
87                 }
88             }
89         }
90         sRegistry.registerNativeAllocation(this, mNativeObject);
91     }
92 
registerNativeAllocation$ravenwood()93     private void registerNativeAllocation$ravenwood() {
94         // No-op under ravenwood
95     }
96 
LongArrayMultiStateCounter(Parcel in)97     private LongArrayMultiStateCounter(Parcel in) {
98         mNativeObject = native_initFromParcel(in);
99         registerNativeAllocation();
100 
101         mStateCount = native_getStateCount(mNativeObject);
102         mLength = native_getArrayLength(mNativeObject);
103     }
104 
getStateCount()105     public int getStateCount() {
106         return mStateCount;
107     }
108 
getArrayLength()109     public int getArrayLength() {
110         return mLength;
111     }
112 
113     /**
114      * Enables or disables the counter.  When the counter is disabled, it does not
115      * accumulate counts supplied by the {@link #updateValues} method.
116      */
setEnabled(boolean enabled, long timestampMs)117     public void setEnabled(boolean enabled, long timestampMs) {
118         native_setEnabled(mNativeObject, enabled, timestampMs);
119     }
120 
121     /**
122      * Sets the current state to the supplied value.
123      */
setState(int state, long timestampMs)124     public void setState(int state, long timestampMs) {
125         if (state < 0 || state >= mStateCount) {
126             throw new IllegalArgumentException(
127                     "State: " + state + ", outside the range: [0-" + (mStateCount - 1) + "]");
128         }
129         native_setState(mNativeObject, state, timestampMs);
130     }
131 
132     /**
133      * Copies time-in-state and timestamps from the supplied counter.
134      */
copyStatesFrom(LongArrayMultiStateCounter counter)135     public void copyStatesFrom(LongArrayMultiStateCounter counter) {
136         if (mStateCount != counter.mStateCount) {
137             throw new IllegalArgumentException(
138                     "State count is not the same: " + mStateCount + " vs. " + counter.mStateCount);
139         }
140         native_copyStatesFrom(mNativeObject, counter.mNativeObject);
141     }
142 
143     /**
144      * Sets the new values for the given state.
145      */
setValues(int state, long[] values)146     public void setValues(int state, long[] values) {
147         if (state < 0 || state >= mStateCount) {
148             throw new IllegalArgumentException(
149                     "State: " + state + ", outside the range: [0-" + (mStateCount - 1) + "]");
150         }
151         if (values.length != mLength) {
152             throw new IllegalArgumentException(
153                     "Invalid array length: " + values.length + ", expected: " + mLength);
154         }
155         native_setValues(mNativeObject, state, values);
156     }
157 
158     /**
159      * Adds the supplied values to the current accumulated values in the counter.
160      * Null `values` parameter is interpreted as an array of zeros.
161      */
incrementValues(@ullable long[] values, long timestampMs)162     public void incrementValues(@Nullable long[] values, long timestampMs) {
163         native_incrementValues(mNativeObject, values, timestampMs);
164     }
165 
166     /**
167      * Sets the new values.  The delta between the previously set values and these values
168      * is distributed among the state according to the time the object spent in those states
169      * since the previous call to updateValues.
170      */
updateValues(long[] values, long timestampMs)171     public void updateValues(long[] values, long timestampMs) {
172         if (values.length != mLength) {
173             throw new IllegalArgumentException(
174                     "Invalid array length: " + values.length + ", expected: " + mLength);
175         }
176         native_updateValues(mNativeObject, values, timestampMs);
177     }
178 
179     /**
180      * Adds the supplied values to the current accumulated values in the counter.
181      */
addCounts(long[] counts)182     public void addCounts(long[] counts) {
183         if (counts.length != mLength) {
184             throw new IllegalArgumentException(
185                     "Invalid array length: " + counts.length + ", expected: " + mLength);
186         }
187         native_addCounts(mNativeObject, counts);
188     }
189 
190     /**
191      * Resets the accumulated counts to 0.
192      */
reset()193     public void reset() {
194         native_reset(mNativeObject);
195     }
196 
197     /**
198      * Populates the array with the accumulated counts for the specified state.
199      */
200     @CheckResult
getCounts(long[] counts, int state)201     public boolean getCounts(long[] counts, int state) {
202         if (state < 0 || state >= mStateCount) {
203             throw new IllegalArgumentException(
204                     "State: " + state + ", outside the range: [0-" + mStateCount + "]");
205         }
206         if (counts.length != mLength) {
207             throw new IllegalArgumentException(
208                     "Invalid array length: " + counts.length + ", expected: " + mLength);
209         }
210         return native_getCounts(mNativeObject, counts, state);
211     }
212 
213     @Override
toString()214     public String toString() {
215         return native_toString(mNativeObject);
216     }
217 
218     @Override
writeToParcel(Parcel dest, int flags)219     public void writeToParcel(Parcel dest, int flags) {
220         native_writeToParcel(mNativeObject, dest, flags);
221     }
222 
223     @Override
describeContents()224     public int describeContents() {
225         return 0;
226     }
227 
228     public static final Creator<LongArrayMultiStateCounter> CREATOR = new Creator<>() {
229         @Override
230         public LongArrayMultiStateCounter createFromParcel(Parcel in) {
231             return new LongArrayMultiStateCounter(in);
232         }
233 
234         @Override
235         public LongArrayMultiStateCounter[] newArray(int size) {
236             return new LongArrayMultiStateCounter[size];
237         }
238     };
239 
240 
241     @CriticalNative
242     @RavenwoodRedirect
native_init(int stateCount, int arrayLength)243     private static native long native_init(int stateCount, int arrayLength);
244 
245     @CriticalNative
246     @RavenwoodRedirect
native_getReleaseFunc()247     private static native long native_getReleaseFunc();
248 
249     @CriticalNative
250     @RavenwoodRedirect
native_setEnabled(long nativeObject, boolean enabled, long timestampMs)251     private static native void native_setEnabled(long nativeObject, boolean enabled,
252             long timestampMs);
253 
254     @CriticalNative
255     @RavenwoodRedirect
native_setState(long nativeObject, int state, long timestampMs)256     private static native void native_setState(long nativeObject, int state, long timestampMs);
257 
258     @CriticalNative
259     @RavenwoodRedirect
native_copyStatesFrom(long nativeObjectTarget, long nativeObjectSource)260     private static native void native_copyStatesFrom(long nativeObjectTarget,
261             long nativeObjectSource);
262 
263     @FastNative
264     @RavenwoodRedirect
native_setValues(long nativeObject, int state, long[] values)265     private static native void native_setValues(long nativeObject, int state, long[] values);
266 
267     @FastNative
268     @RavenwoodRedirect
native_updateValues(long nativeObject, long[] values, long timestampMs)269     private static native void native_updateValues(long nativeObject, long[] values,
270             long timestampMs);
271 
272     @FastNative
273     @RavenwoodRedirect
native_incrementValues(long nativeObject, long[] values, long timestampMs)274     private static native void native_incrementValues(long nativeObject, long[] values,
275             long timestampMs);
276 
277     @FastNative
278     @RavenwoodRedirect
native_addCounts(long nativeObject, long[] counts)279     private static native void native_addCounts(long nativeObject, long[] counts);
280 
281     @CriticalNative
282     @RavenwoodRedirect
native_reset(long nativeObject)283     private static native void native_reset(long nativeObject);
284 
285     @FastNative
286     @RavenwoodRedirect
287     @CheckResult
native_getCounts(long nativeObject, long[] counts, int state)288     private static native boolean native_getCounts(long nativeObject, long[] counts, int state);
289 
290     @FastNative
291     @RavenwoodRedirect
native_toString(long nativeObject)292     private static native String native_toString(long nativeObject);
293 
294     @FastNative
295     @RavenwoodRedirect
native_writeToParcel(long nativeObject, Parcel dest, int flags)296     private static native void native_writeToParcel(long nativeObject, Parcel dest, int flags);
297 
298     @FastNative
299     @RavenwoodRedirect
native_initFromParcel(Parcel parcel)300     private static native long native_initFromParcel(Parcel parcel);
301 
302     @CriticalNative
303     @RavenwoodRedirect
native_getStateCount(long nativeObject)304     private static native int native_getStateCount(long nativeObject);
305 
306     @CriticalNative
307     @RavenwoodRedirect
native_getArrayLength(long nativeObject)308     private static native int native_getArrayLength(long nativeObject);
309 }
310