14eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato/*
24eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * Copyright (C) 2013 The Android Open Source Project
34eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato *
44eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * Licensed under the Apache License, Version 2.0 (the "License");
54eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * you may not use this file except in compliance with the License.
64eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * You may obtain a copy of the License at
74eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato *
84eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato *      http://www.apache.org/licenses/LICENSE-2.0
94eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato *
104eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * Unless required by applicable law or agreed to in writing, software
114eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * distributed under the License is distributed on an "AS IS" BASIS,
124eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * See the License for the specific language governing permissions and
144eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * limitations under the License.
154eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato */
164eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
174eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onoratopackage com.android.internal.app.procstats;
184eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
194eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onoratoimport android.os.Build;
204eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onoratoimport android.os.Parcel;
214eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onoratoimport android.util.Slog;
224eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onoratoimport libcore.util.EmptyArray;
234eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
244eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onoratoimport java.util.ArrayList;
254eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onoratoimport java.util.Arrays;
264eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
274eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onoratoimport com.android.internal.util.GrowingArrayUtils;
284eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
294eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato/**
304eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * Class that contains a set of tables mapping byte ids to long values.
31146dcc026500de5ef8152ef87372d548c71a1619Joe Onorato *
324eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * This class is used to store the ProcessStats data.  This data happens to be
334eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * a set of very sparse tables, that is mostly append or overwrite, with infrequent
344eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * resets of the data.
354eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato *
364eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * Data is stored as a list of large long[] arrays containing the actual values.  There are a
374eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * set of Table objects that each contain a small array mapping the byte IDs to a position
384eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * in the larger arrays.
394eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato *
404eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * The data itself is either a single long value or a range of long values which are always
414eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * stored continguously in one of the long arrays. When the caller allocates a slot with
424eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * getOrAddKey, an int key is returned.  That key can be re-retreived with getKey without
434eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato * allocating the value.  The data can then be set or retrieved with that key.
444eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato */
454eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onoratopublic class SparseMappingTable {
464eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    private static final String TAG = "SparseMappingTable";
474eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
484eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    // How big each array is.
494eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    public static final int ARRAY_SIZE = 4096;
504eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
514eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    public static final int INVALID_KEY = 0xffffffff;
524eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
534eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    // Where the "type"/"state" part of the data appears in an offset integer.
544eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    private static final int ID_SHIFT = 0;
554eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    private static final int ID_MASK = 0xff;
564eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    // Where the "which array" part of the data appears in an offset integer.
574eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    private static final int ARRAY_SHIFT = 8;
584eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    private static final int ARRAY_MASK = 0xff;
594eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    // Where the "index into array" part of the data appears in an offset integer.
604eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    private static final int INDEX_SHIFT = 16;
614eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    private static final int INDEX_MASK = 0xffff;
62146dcc026500de5ef8152ef87372d548c71a1619Joe Onorato
634eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    private int mSequence;
644eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    private int mNextIndex;
654eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    private final ArrayList<long[]> mLongs = new ArrayList<long[]>();
66146dcc026500de5ef8152ef87372d548c71a1619Joe Onorato
674eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    /**
684eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * A table of data as stored in a SparseMappingTable.
694eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     */
704eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    public static class Table {
714eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        private SparseMappingTable mParent;
7265adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        private int mSequence = 1;
734eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        private int[] mTable;
744eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        private int mSize;
754eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
764eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public Table(SparseMappingTable parent) {
774eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            mParent = parent;
784eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            mSequence = parent.mSequence;
794eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
804eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
814eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
824eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Pulls the data from 'copyFrom' and stores it in our own longs table.
834eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *
844eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param copyFrom   The Table to copy from
854eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param valueCount The number of values to copy for each key
864eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
874eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public void copyFrom(Table copyFrom, int valueCount) {
884eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            mTable = null;
894eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            mSize = 0;
904eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
914eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            final int N = copyFrom.getKeyCount();
924eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            for (int i=0; i<N; i++) {
934eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                final int theirKey = copyFrom.getKeyAt(i);
944eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                final long[] theirLongs = copyFrom.mParent.mLongs.get(getArrayFromKey(theirKey));
954eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
964eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                final byte id = SparseMappingTable.getIdFromKey(theirKey);
974eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
984eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                final int myKey = this.getOrAddKey((byte)id, valueCount);
994eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                final long[] myLongs = mParent.mLongs.get(getArrayFromKey(myKey));
1004eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
1014eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                System.arraycopy(theirLongs, getIndexFromKey(theirKey),
1024eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                        myLongs, getIndexFromKey(myKey), valueCount);
1034eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
1044eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
1054eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
1064eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
1074eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Allocates data in the buffer, and stores that key in the mapping for this
1084eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * table.
1094eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *
1104eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param id    The id of the item (will be used in making the key)
1114eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param count The number of bytes to allocate.  Must be less than
1124eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *              SparseMappingTable.ARRAY_SIZE.
1134eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *
1144eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @return The 'key' for this data value, which contains both the id itself
1154eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *         and the location in the long arrays that the data is actually stored
1164eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *         but should be considered opaque to the caller.
1174eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
1184eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public int getOrAddKey(byte id, int count) {
1194eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            assertConsistency();
1204eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
1214eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            final int idx = binarySearch(id);
1224eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            if (idx >= 0) {
1234eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                // Found
1244eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                return mTable[idx];
1254eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            } else {
1264eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                // Not found. Need to allocate it.
1274eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
1284eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                // Get an array with enough space to store 'count' values.
1294eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                final ArrayList<long[]> list = mParent.mLongs;
1304eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                int whichArray = list.size()-1;
1314eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                long[] array = list.get(whichArray);
1324eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                if (mParent.mNextIndex + count > array.length) {
1334eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    // if it won't fit then make a new array.
1344eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    array = new long[ARRAY_SIZE];
1354eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    list.add(array);
1364eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    whichArray++;
1374eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    mParent.mNextIndex = 0;
1384eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                }
1394eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
1404eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                // The key is a combination of whichArray, which index in that array, and
1414eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                // the table value itself, which will be used for lookup
1424eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                final int key = (whichArray << ARRAY_SHIFT)
1434eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                        | (mParent.mNextIndex << INDEX_SHIFT)
1444eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                        | (((int)id) << ID_SHIFT);
1454eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
1464eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                mParent.mNextIndex += count;
1474eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
1484eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                // Store the key in the sparse lookup table for this Table object.
1494eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                mTable = GrowingArrayUtils.insert(mTable != null ? mTable : EmptyArray.INT,
1504eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                        mSize, ~idx, key);
1514eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                mSize++;
1524eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
1534eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                return key;
1544eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
1554eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
1564eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
1574eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
1584eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Looks up a key in the table.
1594eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *
1604eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @return The key from this table or INVALID_KEY if the id is not found.
1614eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
1624eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public int getKey(byte id) {
1634eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            assertConsistency();
1644eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
1654eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            final int idx = binarySearch(id);
1664eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            if (idx >= 0) {
1674eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                return mTable[idx];
1684eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            } else {
1694eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                return INVALID_KEY;
1704eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
1714eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
1724eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
1734eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
1744eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Get the value for the given key and offset from that key.
1754eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *
1764eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param key   A key as obtained from getKey or getOrAddKey.
1774eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param value The value to set.
1784eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
1794eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public long getValue(int key) {
1804eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            return getValue(key, 0);
1814eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
1824eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
1834eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
1844eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Get the value for the given key and offset from that key.
1854eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *
1864eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param key   A key as obtained from getKey or getOrAddKey.
1874eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param index The offset from that key.  Must be less than the count
1884eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *              provided to getOrAddKey when the space was allocated.
1894eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param value The value to set.
1904eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *
1914eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @return the value, or 0 in case of an error
1924eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
1934eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public long getValue(int key, int index) {
1944eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            assertConsistency();
1954eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
1964eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            try {
1974eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                final long[] array = mParent.mLongs.get(getArrayFromKey(key));
1984eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                return array[getIndexFromKey(key) + index];
1994eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            } catch (IndexOutOfBoundsException ex) {
2004eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                logOrThrow("key=0x" + Integer.toHexString(key)
2014eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                        + " index=" + index + " -- " + dumpInternalState(), ex);
2024eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                return 0;
2034eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
2044eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
2054eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
2064eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
2074eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Set the value for the given id at offset 0 from that id.
2084eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * If the id is not found, return 0 instead.
2094eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *
2104eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param id    The id of the item.
2114eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
2124eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public long getValueForId(byte id) {
2134eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            return getValueForId(id, 0);
2144eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
2154eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
2164eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
2174eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Set the value for the given id and index offset from that id.
2184eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * If the id is not found, return 0 instead.
2194eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *
2204eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param id    The id of the item.
2214eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param index The offset from that key.  Must be less than the count
2224eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *              provided to getOrAddKey when the space was allocated.
2234eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
2244eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public long getValueForId(byte id, int index) {
2254eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            assertConsistency();
2264eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
2274eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            final int idx = binarySearch(id);
2284eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            if (idx >= 0) {
2294eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                final int key = mTable[idx];
2304eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                try {
2314eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    final long[] array = mParent.mLongs.get(getArrayFromKey(key));
2324eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    return array[getIndexFromKey(key) + index];
2334eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                } catch (IndexOutOfBoundsException ex) {
2344eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    logOrThrow("id=0x" + Integer.toHexString(id) + " idx=" + idx
2354eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                            + " key=0x" + Integer.toHexString(key) + " index=" + index
2364eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                            + " -- " + dumpInternalState(), ex);
2374eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    return 0;
2384eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                }
2394eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            } else {
2404eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                return 0;
2414eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
2424eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
2434eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
2444eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
2454eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Return the raw storage long[] for the given key.
2464eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
2474eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public long[] getArrayForKey(int key) {
2484eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            assertConsistency();
2494eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
2504eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            return mParent.mLongs.get(getArrayFromKey(key));
2514eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
2524eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
2534eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
2544eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Set the value for the given key and offset from that key.
2554eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *
2564eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param key   A key as obtained from getKey or getOrAddKey.
2574eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param value The value to set.
2584eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
2594eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public void setValue(int key, long value) {
2604eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            setValue(key, 0, value);
2614eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
2624eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
2634eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
2644eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Set the value for the given key and offset from that key.
2654eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *
2664eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param key   A key as obtained from getKey or getOrAddKey.
2674eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param index The offset from that key.  Must be less than the count
2684eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *              provided to getOrAddKey when the space was allocated.
2694eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @param value The value to set.
2704eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
2714eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public void setValue(int key, int index, long value) {
2724eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            assertConsistency();
2734eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
2744eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            if (value < 0) {
2754eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                logOrThrow("can't store negative values"
2764eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                        + " key=0x" + Integer.toHexString(key)
2774eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                        + " index=" + index + " value=" + value
2784eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                        + " -- " + dumpInternalState());
2794eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                return;
2804eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
2814eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
2824eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            try {
2834eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                final long[] array = mParent.mLongs.get(getArrayFromKey(key));
2844eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                array[getIndexFromKey(key) + index] = value;
2854eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            } catch (IndexOutOfBoundsException ex) {
2864eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                logOrThrow("key=0x" + Integer.toHexString(key)
2874eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                        + " index=" + index + " value=" + value
2884eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                        + " -- " + dumpInternalState(), ex);
2894eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                return;
2904eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
2914eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
2924eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
2934eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
2944eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Clear out the table, and reset the sequence numbers so future writes
2954eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * without allocations will assert.
2964eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
2974eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public void resetTable() {
2984eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            // Clear out our table.
2994eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            mTable = null;
3004eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            mSize = 0;
3014eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
3024eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            // Reset our sequence number.  This will make all read/write calls
3034eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            // start to fail, and then when we re-allocate it will be re-synced
3044eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            // to that of mParent.
30565adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato            mSequence = mParent.mSequence;
3064eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
3074eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
3084eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
3094eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Write the keys stored in the table to the parcel. The parent must
3104eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * be separately written. Does not save the actual data.
3114eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
3124eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public void writeToParcel(Parcel out) {
3134eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            out.writeInt(mSequence);
3144eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            out.writeInt(mSize);
3154eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            for (int i=0; i<mSize; i++) {
3164eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                out.writeInt(mTable[i]);
3174eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
3184eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
3194eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
3204eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
3214eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Read the keys from the parcel. The parent (with its long array) must
3224eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * have been previously initialized.
3234eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
3244eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public boolean readFromParcel(Parcel in) {
3254eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            // Read the state
3264eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            mSequence = in.readInt();
3274eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            mSize = in.readInt();
3284eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            if (mSize != 0) {
3294eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                mTable = new int[mSize];
3304eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                for (int i=0; i<mSize; i++) {
3314eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    mTable[i] = in.readInt();
3324eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                }
3334eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            } else {
3344eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                mTable = null;
3354eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
3364eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
3374eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            // Make sure we're all healthy
3384eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            if (validateKeys(true)) {
3394eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                return true;
3404eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            } else {
3414eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                // Clear it out
3424eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                mSize = 0;
3434eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                mTable = null;
3444eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                return false;
3454eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
3464eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
3474eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
3484eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
3494eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Return the number of keys that have been added to this Table.
3504eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
3514eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public int getKeyCount() {
3524eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            return mSize;
3534eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
3544eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
3554eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
3564eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Get the key at the given index in our table.
3574eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
3584eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public int getKeyAt(int i) {
3594eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            return mTable[i];
3604eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
3614eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
3624eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
3634eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Throw an exception if one of a variety of internal consistency checks fails.
3644eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
3654eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        private void assertConsistency() {
36608274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato            // Something with this checking isn't working and is triggering
36708274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato            // more problems than it's helping to debug.
36808274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato            //   Original bug: b/27045736
36908274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato            //   New bug: b/27960286
37008274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato            if (false) {
37108274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato                // Assert that our sequence number matches mParent's.  If it isn't that means
37265adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato                // we have been reset and our.  If our sequence is UNITIALIZED_SEQUENCE, then
37365adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato                // it's possible that everything is working fine and we just haven't been
37465adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato                // written to since the last resetTable().
37508274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato                if (mSequence != mParent.mSequence) {
37608274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato                    if (mSequence < mParent.mSequence) {
37765adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato                        logOrThrow("Sequence mismatch. SparseMappingTable.reset()"
37808274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato                                + " called but not Table.resetTable() -- "
37908274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato                                + dumpInternalState());
38008274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato                        return;
38108274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato                    } else if (mSequence > mParent.mSequence) {
38208274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato                        logOrThrow("Sequence mismatch. Table.resetTable()"
38365adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato                                + " called but not SparseMappingTable.reset() -- "
38408274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato                                + dumpInternalState());
38508274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato                        return;
38608274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato                    }
38708274740cd3bf34e91e243a1c5faa7d80ecb0fc6Joe Onorato                }
3884eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
3894eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
3904eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
3914eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
3924eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Finds the 'id' inside the array of length size (physical size of the array
3934eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * is not used).
3944eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         *
3954eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * @return The index of the array, or the bitwise not (~index) of where it
3964eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * would go if you wanted to insert 'id' into the array.
3974eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
3984eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        private int binarySearch(byte id) {
3994eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            int lo = 0;
4004eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            int hi = mSize - 1;
4014eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
4024eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            while (lo <= hi) {
4034eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                int mid = (lo + hi) >>> 1;
4044eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                byte midId = (byte)((mTable[mid] >> ID_SHIFT) & ID_MASK);
4054eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
4064eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                if (midId < id) {
4074eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    lo = mid + 1;
4084eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                } else if (midId > id) {
4094eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    hi = mid - 1;
4104eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                } else {
4114eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    return mid;  // id found
4124eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                }
4134eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
4144eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            return ~lo;  // id not present
4154eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
4164eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
4174eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        /**
4184eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * Check that all the keys are valid locations in the long arrays.
419146dcc026500de5ef8152ef87372d548c71a1619Joe Onorato         *
4204eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         * If any aren't, log it and return false. Else return true.
4214eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato         */
4224eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        private boolean validateKeys(boolean log) {
4234eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            ArrayList<long[]> longs = mParent.mLongs;
4244eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            final int longsSize = longs.size();
4254eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
4264eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            final int N = mSize;
4274eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            for (int i=0; i<N; i++) {
4284eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                final int key = mTable[i];
4294eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                final int arrayIndex = getArrayFromKey(key);
4304eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                final int index = getIndexFromKey(key);
4314eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                if (arrayIndex >= longsSize || index >= longs.get(arrayIndex).length) {
4324eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    if (log) {
4334eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                        Slog.w(TAG, "Invalid stats at index " + i + " -- " + dumpInternalState());
4344eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    }
4354eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    return false;
4364eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                }
4374eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
4384eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
4394eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            return true;
4404eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
4414eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
4424eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        public String dumpInternalState() {
4434eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            StringBuilder sb = new StringBuilder();
4444eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            sb.append("SparseMappingTable.Table{mSequence=");
4454eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            sb.append(mSequence);
4464eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            sb.append(" mParent.mSequence=");
4474eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            sb.append(mParent.mSequence);
4484eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            sb.append(" mParent.mLongs.size()=");
4494eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            sb.append(mParent.mLongs.size());
4504eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            sb.append(" mSize=");
4514eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            sb.append(mSize);
4524eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            sb.append(" mTable=");
4534eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            if (mTable == null) {
4544eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                sb.append("null");
4554eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            } else {
4564eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                final int N = mTable.length;
4574eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                sb.append('[');
4584eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                for (int i=0; i<N; i++) {
4594eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    final int key = mTable[i];
4604eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    sb.append("0x");
4614eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    sb.append(Integer.toHexString((key >> ID_SHIFT) & ID_MASK));
4624eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    sb.append("/0x");
4634eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    sb.append(Integer.toHexString((key >> ARRAY_SHIFT) & ARRAY_MASK));
4644eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    sb.append("/0x");
4654eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    sb.append(Integer.toHexString((key >> INDEX_SHIFT) & INDEX_MASK));
4664eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    if (i != N-1) {
4674eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                        sb.append(", ");
4684eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                    }
4694eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                }
4704eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                sb.append(']');
4714eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
4724eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            sb.append(" clazz=");
4734eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            sb.append(getClass().getName());
4744eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            sb.append('}');
4754eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
4764eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            return sb.toString();
4774eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
4784eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    }
4794eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
48065adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato    public SparseMappingTable() {
48165adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        mLongs.add(new long[ARRAY_SIZE]);
48265adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato    }
48365adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato
4844eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    /**
4854eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * Wipe out all the data.
4864eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     */
4874eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    public void reset() {
4884eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        // Clear out mLongs, and prime it with a new array of data
4894eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        mLongs.clear();
4904eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        mLongs.add(new long[ARRAY_SIZE]);
4914eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        mNextIndex = 0;
4924eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
4934eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        // Increment out sequence counter, because all of the tables will
4944eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        // now be out of sync with the data.
4954eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        mSequence++;
4964eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    }
4974eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
4984eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    /**
4994eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * Write the data arrays to the parcel.
5004eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     */
5014eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    public void writeToParcel(Parcel out) {
5024eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        out.writeInt(mSequence);
5034eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        out.writeInt(mNextIndex);
5044eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        final int N = mLongs.size();
5054eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        out.writeInt(N);
5064eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        for (int i=0; i<N-1; i++) {
5074eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            final long[] array = mLongs.get(i);
5084eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            out.writeInt(array.length);
5094eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            writeCompactedLongArray(out, array, array.length);
5104eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
5114eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        // save less for the last one. upon re-loading they'll just start a new array.
5124eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        final long[] lastLongs = mLongs.get(N-1);
5134eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        out.writeInt(mNextIndex);
5144eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        writeCompactedLongArray(out, lastLongs, mNextIndex);
5154eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    }
5164eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
5174eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    /**
5184eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * Read the data arrays from the parcel.
5194eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     */
5204eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    public void readFromParcel(Parcel in) {
5214eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        mSequence = in.readInt();
5224eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        mNextIndex = in.readInt();
5234eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
5244eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        mLongs.clear();
5254eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        final int N = in.readInt();
5264eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        for (int i=0; i<N; i++) {
5274eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            final int size = in.readInt();
5284eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            final long[] array = new long[size];
5294eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            readCompactedLongArray(in, array, size);
5304eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            mLongs.add(array);
5314eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
5324eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    }
5334eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
5344eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    /**
53565adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato     * Return a string for debugging.
53665adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato     */
53765adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato    public String dumpInternalState(boolean includeData) {
53865adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        final StringBuilder sb = new StringBuilder();
53965adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        sb.append("SparseMappingTable{");
54065adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        sb.append("mSequence=");
54165adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        sb.append(mSequence);
54265adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        sb.append(" mNextIndex=");
54365adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        sb.append(mNextIndex);
54465adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        sb.append(" mLongs.size=");
54565adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        final int N = mLongs.size();
54665adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        sb.append(N);
54765adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        sb.append("\n");
54865adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        if (includeData) {
54965adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato            for (int i=0; i<N; i++) {
55065adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato                final long[] array = mLongs.get(i);
55165adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato                for (int j=0; j<array.length; j++) {
55265adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato                    if (i == N-1 && j == mNextIndex) {
55365adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato                        break;
55465adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato                    }
55565adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato                    sb.append(String.format(" %4d %d 0x%016x %-19d\n", i, j, array[j], array[j]));
55665adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato                }
55765adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato            }
55865adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        }
55965adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        sb.append("}");
56065adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato        return sb.toString();
56165adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato    }
56265adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato
56365adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato    /**
5644eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * Write the long array to the parcel in a compacted form.  Does not allow negative
5654eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * values in the array.
5664eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     */
5674eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    private static void writeCompactedLongArray(Parcel out, long[] array, int num) {
5684eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        for (int i=0; i<num; i++) {
5694eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            long val = array[i];
5704eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            if (val < 0) {
5714eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                Slog.w(TAG, "Time val negative: " + val);
5724eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                val = 0;
5734eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
5744eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            if (val <= Integer.MAX_VALUE) {
5754eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                out.writeInt((int)val);
5764eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            } else {
5774eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                int top = ~((int)((val>>32)&0x7fffffff));
57865adfeecd2acc4e63c00fc1f2073cc0b229f3467Joe Onorato                int bottom = (int)(val&0x0ffffffffL);
5794eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                out.writeInt(top);
5804eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                out.writeInt(bottom);
5814eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
5824eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
5834eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    }
5844eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
5854eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    /**
5864eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * Read the compacted array into the long[].
5874eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     */
5884eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    private static void readCompactedLongArray(Parcel in, long[] array, int num) {
5894eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        final int alen = array.length;
5904eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        if (num > alen) {
5914eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            logOrThrow("bad array lengths: got " + num + " array is " + alen);
5924eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            return;
5934eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
5944eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        int i;
5954eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        for (i=0; i<num; i++) {
5964eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            int val = in.readInt();
5974eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            if (val >= 0) {
5984eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                array[i] = val;
5994eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            } else {
6004eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                int bottom = in.readInt();
6014eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato                array[i] = (((long)~val)<<32) | bottom;
6024eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            }
6034eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
6044eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        while (i < alen) {
6054eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            array[i] = 0;
6064eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            i++;
6074eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
6084eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    }
609146dcc026500de5ef8152ef87372d548c71a1619Joe Onorato
6104eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    /**
6114eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * Extract the id from a key.
6124eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     */
6134eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    public static byte getIdFromKey(int key) {
6144eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        return (byte)((key >> ID_SHIFT) & ID_MASK);
6154eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    }
6164eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
6174eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    /**
6184eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * Gets the index of the array in the list of arrays.
6194eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     *
6204eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * Not to be confused with getIndexFromKey.
6214eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     */
6224eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    public static int getArrayFromKey(int key) {
6234eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        return (key >> ARRAY_SHIFT) & ARRAY_MASK;
6244eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    }
6254eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
6264eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    /**
6274eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * Gets the index of a value in a long[].
6284eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     *
6294eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * Not to be confused with getArrayFromKey.
6304eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     */
6314eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    public static int getIndexFromKey(int key) {
6324eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        return (key >> INDEX_SHIFT) & INDEX_MASK;
6334eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    }
6344eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
6354eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    /**
6364eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * Do a Slog.wtf or throw an exception (thereby crashing the system process if
6374eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * this is a debug build.)
6384eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     */
6394eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    private static void logOrThrow(String message) {
640146dcc026500de5ef8152ef87372d548c71a1619Joe Onorato        logOrThrow(message, new RuntimeException("Stack trace"));
6414eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    }
6424eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato
6434eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    /**
6444eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * Do a Slog.wtf or throw an exception (thereby crashing the system process if
6454eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     * this is an eng build.)
6464eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato     */
6474eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    private static void logOrThrow(String message, Throwable th) {
64804b70fc63a80e3df9b97a5197f1d7df022cbe92bJeff Sharkey        Slog.e(TAG, message, th);
6494eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        if (Build.TYPE.equals("eng")) {
6504eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato            throw new RuntimeException(message, th);
6514eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato        }
6524eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato    }
6534eb64fdbcf899a81d0a6a04dc3658d03d9df8247Joe Onorato}
654