Home | History | Annotate | Download | only in health
      1 /*
      2  * Copyright (C) 2016 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 android.os.health;
     18 
     19 import android.os.Parcel;
     20 import android.os.Parcelable;
     21 
     22 import java.lang.annotation.Annotation;
     23 import java.lang.annotation.ElementType;
     24 import java.lang.annotation.Retention;
     25 import java.lang.annotation.RetentionPolicy;
     26 import java.lang.annotation.Target;
     27 import java.lang.reflect.Field;
     28 import java.util.Arrays;
     29 
     30 /**
     31  * Constants and stuff for the android.os.health package.
     32  *
     33  * @hide
     34  */
     35 public class HealthKeys {
     36 
     37     /**
     38      * No valid key will ever be 0.
     39      */
     40     public static final int UNKNOWN_KEY = 0;
     41 
     42     /*
     43      * Base key for each of the different classes. There is
     44      * nothing intrinsic to the operation of the value of the
     45      * keys. It's just segmented for better debugging. The
     46      * classes don't mix them anway.
     47      */
     48     public static final int BASE_UID = 10000;
     49     public static final int BASE_PID = 20000;
     50     public static final int BASE_PROCESS = 30000;
     51     public static final int BASE_PACKAGE = 40000;
     52     public static final int BASE_SERVICE = 50000;
     53 
     54     /*
     55      * The types of values supported by HealthStats.
     56      */
     57     public static final int TYPE_TIMER = 0;
     58     public static final int TYPE_MEASUREMENT = 1;
     59     public static final int TYPE_STATS = 2;
     60     public static final int TYPE_TIMERS = 3;
     61     public static final int TYPE_MEASUREMENTS = 4;
     62 
     63     public static final int TYPE_COUNT = 5;
     64 
     65     /**
     66      * Annotation to mark public static final int fields that are to be used
     67      * as field keys in HealthStats.
     68      */
     69     @Retention(RetentionPolicy.RUNTIME)
     70     @Target({ElementType.FIELD})
     71     public @interface Constant {
     72         /**
     73          * One of the TYPE_* constants above.
     74          */
     75         int type();
     76     }
     77 
     78     /**
     79      * Class to gather the constants defined in a class full of constants and
     80      * build the key indices used by HealthStatsWriter and HealthStats.
     81      *
     82      * @hide
     83      */
     84     public static class Constants {
     85         private final String mDataType;
     86         private final int[][] mKeys = new int[TYPE_COUNT][];
     87 
     88         /**
     89          * Pass in a class to gather the public static final int fields that are
     90          * tagged with the @Constant annotation.
     91          */
     92         public Constants(Class clazz) {
     93             // Save the class name for debugging
     94             mDataType = clazz.getSimpleName();
     95 
     96             // Iterate through the list of fields on this class, and build the
     97             // constant arrays for these fields.
     98             final Field[] fields = clazz.getDeclaredFields();
     99             final Class<Constant> annotationClass = Constant.class;
    100 
    101             final int N = fields.length;
    102 
    103             final SortedIntArray[] keys = new SortedIntArray[mKeys.length];
    104             for (int i=0; i<keys.length; i++) {
    105                 keys[i] = new SortedIntArray(N);
    106             }
    107 
    108             for (int i=0; i<N; i++) {
    109                 final Field field = fields[i];
    110                 final Constant constant = field.getAnnotation(annotationClass);
    111                 if (constant != null) {
    112                     final int type = constant.type();
    113                     if (type >= keys.length) {
    114                         throw new RuntimeException("Unknown Constant type " + type
    115                                 + " on " + field);
    116                     }
    117                     try {
    118                         keys[type].addValue(field.getInt(null));
    119                     } catch (IllegalAccessException ex) {
    120                         throw new RuntimeException("Can't read constant value type=" + type
    121                                 + " field=" + field, ex);
    122                     }
    123                 }
    124             }
    125 
    126             for (int i=0; i<keys.length; i++) {
    127                 mKeys[i] = keys[i].getArray();
    128             }
    129         }
    130 
    131         /**
    132          * Get a string representation of this class. Useful for debugging. It will be the
    133          * simple name of the class passed in the constructor.
    134          */
    135         public String getDataType() {
    136             return mDataType;
    137         }
    138 
    139         /**
    140          * Return how many keys there are for the given field type.
    141          *
    142          * @see TYPE_TIMER
    143          * @see TYPE_MEASUREMENT
    144          * @see TYPE_TIMERS
    145          * @see TYPE_MEASUREMENTS
    146          * @see TYPE_STATS
    147          */
    148         public int getSize(int type) {
    149             return mKeys[type].length;
    150         }
    151 
    152         /**
    153          * Return the index for the given type and key combination in the array of field
    154          * keys or values.
    155          *
    156          * @see TYPE_TIMER
    157          * @see TYPE_MEASUREMENT
    158          * @see TYPE_TIMERS
    159          * @see TYPE_MEASUREMENTS
    160          * @see TYPE_STATS
    161          */
    162         public int getIndex(int type, int key) {
    163             final int index = Arrays.binarySearch(mKeys[type], key);
    164             if (index >= 0) {
    165                 return index;
    166             } else {
    167                 throw new RuntimeException("Unknown Constant " + key + " (of type "
    168                         + type + " )");
    169             }
    170         }
    171 
    172         /**
    173          * Get the array of keys for the given field type.
    174          */
    175         public int[] getKeys(int type) {
    176             return mKeys[type];
    177         }
    178     }
    179 
    180     /**
    181      * An array of fixed size that will be sorted.
    182      */
    183     private static class SortedIntArray {
    184         int mCount;
    185         int[] mArray;
    186 
    187         /**
    188          * Construct with the maximum number of values.
    189          */
    190         SortedIntArray(int maxCount) {
    191             mArray = new int[maxCount];
    192         }
    193 
    194         /**
    195          * Add a value.
    196          */
    197         void addValue(int value) {
    198             mArray[mCount++] = value;
    199         }
    200 
    201         /**
    202          * Get the array of values that have been added, with the values in
    203          * numerically increasing order.
    204          */
    205         int[] getArray() {
    206             if (mCount == mArray.length) {
    207                 Arrays.sort(mArray);
    208                 return mArray;
    209             } else {
    210                 final int[] result = new int[mCount];
    211                 System.arraycopy(mArray, 0, result, 0, mCount);
    212                 Arrays.sort(result);
    213                 return result;
    214             }
    215         }
    216     }
    217 }
    218 
    219 
    220