/* * Copyright (C) 2016 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. */ package android.os.health; import android.os.Parcel; import android.os.Parcelable; import android.util.ArrayMap; import java.util.Map; /** * Class to write the health stats data into a parcel, so it can then be * retrieved via a {@link HealthStats} object. * * There is an attempt to keep this class as low overhead as possible, for * example storing an int[] and a long[] instead of a TimerStat[]. * * @hide */ public class HealthStatsWriter { private final HealthKeys.Constants mConstants; // TimerStat fields private final boolean[] mTimerFields; private final int[] mTimerCounts; private final long[] mTimerTimes; // Measurement fields private final boolean[] mMeasurementFields; private final long[] mMeasurementValues; // Stats fields private final ArrayMap[] mStatsValues; // Timers fields private final ArrayMap[] mTimersValues; // Measurements fields private final ArrayMap[] mMeasurementsValues; /** * Construct a HealthStatsWriter object with the given constants. * * The "getDataType()" of the resulting HealthStats object will be the * short name of the java class that the Constants object was initalized * with. */ public HealthStatsWriter(HealthKeys.Constants constants) { mConstants = constants; // TimerStat final int timerCount = constants.getSize(HealthKeys.TYPE_TIMER); mTimerFields = new boolean[timerCount]; mTimerCounts = new int[timerCount]; mTimerTimes = new long[timerCount]; // Measurement final int measurementCount = constants.getSize(HealthKeys.TYPE_MEASUREMENT); mMeasurementFields = new boolean[measurementCount]; mMeasurementValues = new long[measurementCount]; // Stats final int statsCount = constants.getSize(HealthKeys.TYPE_STATS); mStatsValues = new ArrayMap[statsCount]; // Timers final int timersCount = constants.getSize(HealthKeys.TYPE_TIMERS); mTimersValues = new ArrayMap[timersCount]; // Measurements final int measurementsCount = constants.getSize(HealthKeys.TYPE_MEASUREMENTS); mMeasurementsValues = new ArrayMap[measurementsCount]; } /** * Add a timer for the given key. */ public void addTimer(int timerId, int count, long time) { final int index = mConstants.getIndex(HealthKeys.TYPE_TIMER, timerId); mTimerFields[index] = true; mTimerCounts[index] = count; mTimerTimes[index] = time; } /** * Add a measurement for the given key. */ public void addMeasurement(int measurementId, long value) { final int index = mConstants.getIndex(HealthKeys.TYPE_MEASUREMENT, measurementId); mMeasurementFields[index] = true; mMeasurementValues[index] = value; } /** * Add a recursive HealthStats object for the given key and string name. The value * is stored as a HealthStatsWriter until this object is written to a parcel, so * don't attempt to reuse the HealthStatsWriter. * * The value field should not be null. */ public void addStats(int key, String name, HealthStatsWriter value) { final int index = mConstants.getIndex(HealthKeys.TYPE_STATS, key); ArrayMap map = mStatsValues[index]; if (map == null) { map = mStatsValues[index] = new ArrayMap(1); } map.put(name, value); } /** * Add a TimerStat for the given key and string name. * * The value field should not be null. */ public void addTimers(int key, String name, TimerStat value) { final int index = mConstants.getIndex(HealthKeys.TYPE_TIMERS, key); ArrayMap map = mTimersValues[index]; if (map == null) { map = mTimersValues[index] = new ArrayMap(1); } map.put(name, value); } /** * Add a measurement for the given key and string name. */ public void addMeasurements(int key, String name, long value) { final int index = mConstants.getIndex(HealthKeys.TYPE_MEASUREMENTS, key); ArrayMap map = mMeasurementsValues[index]; if (map == null) { map = mMeasurementsValues[index] = new ArrayMap(1); } map.put(name, value); } /** * Flattens the data in this HealthStatsWriter to the Parcel format * that can be unparceled into a HealthStat. * @more * (Called flattenToParcel because this HealthStatsWriter itself is * not parcelable and we don't flatten all the business about the * HealthKeys.Constants, only the values that were actually supplied) */ public void flattenToParcel(Parcel out) { int[] keys; // Header fields out.writeString(mConstants.getDataType()); // TimerStat fields out.writeInt(countBooleanArray(mTimerFields)); keys = mConstants.getKeys(HealthKeys.TYPE_TIMER); for (int i=0; i int countObjectArray(T[] fields) { int count = 0; final int N = fields.length; for (int i=0; i map) { final int N = map.size(); out.writeInt(N); for (int i=0; i void writeParcelableMap(Parcel out, ArrayMap map) { final int N = map.size(); out.writeInt(N); for (int i=0; i map) { final int N = map.size(); out.writeInt(N); for (int i=0; i