Metadata.java revision 6fa41bbb56e0756d3eac15d6314007e4a450c9d3
19193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania/* 29193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania * Copyright (C) 2009 The Android Open Source Project 39193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania * 49193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania * Licensed under the Apache License, Version 2.0 (the "License"); 59193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania * you may not use this file except in compliance with the License. 69193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania * You may obtain a copy of the License at 79193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania * 89193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania * http://www.apache.org/licenses/LICENSE-2.0 99193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania * 109193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania * Unless required by applicable law or agreed to in writing, software 119193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania * distributed under the License is distributed on an "AS IS" BASIS, 129193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania * See the License for the specific language governing permissions and 149193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania * limitations under the License. 159193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania */ 169193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 179193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Cataniapackage android.media; 189193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 199193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Cataniaimport android.graphics.Bitmap; 205d55c7119820ee9bb06fc072e416fe98ba77cd28Nicolas Cataniaimport android.os.Parcel; 219193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Cataniaimport android.util.Log; 229193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 23cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Cataniaimport java.util.Calendar; 249193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Cataniaimport java.util.Collections; 259193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Cataniaimport java.util.Date; 26a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Cataniaimport java.util.HashMap; 27cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Cataniaimport java.util.Set; 28cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Cataniaimport java.util.TimeZone; 299193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 305d55c7119820ee9bb06fc072e416fe98ba77cd28Nicolas Catania 319193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania/** 329193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania Class to hold the media's metadata. Metadata are used 339193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania for human consumption and can be embedded in the media (e.g 349193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania shoutcast) or available from an external source. The source can be 359193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania local (e.g thumbnail stored in the DB) or remote (e.g caption 369193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania server). 379193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 389193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania Metadata is like a Bundle. It is sparse and each key can occur at 399193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania most once. The key is an integer and the value is the actual metadata. 409193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 419193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania The caller is expected to know the type of the metadata and call 429193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania the right get* method to fetch its value. 439193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 449193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // FIXME: unhide. 459193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania {@hide} 469193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania */ 479193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Cataniapublic class Metadata 489193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania{ 499193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // The metadata are keyed using integers rather than more heavy 509193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // weight strings. We considered using Bundle to ship the metadata 519193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // between the native layer and the java layer but dropped that 529193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // option since keeping in sync a native implementation of Bundle 539193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // and the java one would be too burdensome. Besides Bundle uses 549193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // String for its keys. 559193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // The key range [0 8192) is reserved for the system. 569193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // 579193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // We manually serialize the data in Parcels. For large memory 589193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // blob (bitmaps, raw pictures) we use MemoryFile which allow the 59a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // client to make the data purge-able once it is done with it. 609193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // 619193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 629193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int ANY = 0; // Never used for metadata returned, only for filtering. 63b2c693919be966f179080a9ec70a7a82dbf57627Nicolas Catania // Keep in sync with kAny in MediaPlayerService.cpp 649193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 659193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // TODO: Should we use numbers compatible with the metadata retriever? 669193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int TITLE = 1; // String 679193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int COMMENT = 2; // String 689193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int COPYRIGHT = 3; // String 699193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int ALBUM = 4; // String 709193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int ARTIST = 5; // String 719193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int AUTHOR = 6; // String 729193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int COMPOSER = 7; // String 739193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int GENRE = 8; // String 749193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int DATE = 9; // Date 759193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int DURATION = 10; // Integer(millisec) 769193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int CD_TRACK_NUM = 11; // Integer 1-based 779193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int CD_TRACK_MAX = 12; // Integer 789193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int RATING = 13; // String 799193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int ALBUM_ART = 14; // byte[] 809193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int VIDEO_FRAME = 15; // Bitmap 819193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int CAPTION = 16; // TimedText 829193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 839193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int BIT_RATE = 17; // Integer, Aggregate rate of 849193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // all the streams in bps. 859193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 869193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int AUDIO_BIT_RATE = 18; // Integer, bps 879193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int VIDEO_BIT_RATE = 19; // Integer, bps 889193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int AUDIO_SAMPLE_RATE = 20; // Integer, Hz 899193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int VIDEO_FRAME_RATE = 21; // Integer, Hz 909193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 919193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // See RFC2046 and RFC4281. 929193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int MIME_TYPE = 22; // String 939193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int AUDIO_CODEC = 23; // String 949193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int VIDEO_CODEC = 24; // String 959193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 969193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int VIDEO_HEIGHT = 25; // Integer 979193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int VIDEO_WIDTH = 26; // Integer 989193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int NUM_TRACKS = 27; // Integer 999193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final int DRM_CRIPPLED = 28; // Boolean 100716383a686b086f68533a51785ba77186359ce6bNicolas Catania 101716383a686b086f68533a51785ba77186359ce6bNicolas Catania // Playback capabilities. 102716383a686b086f68533a51785ba77186359ce6bNicolas Catania public static final int PAUSE_AVAILABLE = 29; // Boolean 103716383a686b086f68533a51785ba77186359ce6bNicolas Catania public static final int SEEK_BACKWARD_AVAILABLE = 30; // Boolean 104716383a686b086f68533a51785ba77186359ce6bNicolas Catania public static final int SEEK_FORWARD_AVAILABLE = 31; // Boolean 105716383a686b086f68533a51785ba77186359ce6bNicolas Catania 106716383a686b086f68533a51785ba77186359ce6bNicolas Catania private static final int LAST_SYSTEM = 31; 107a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania private static final int FIRST_CUSTOM = 8092; 1089193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 1099193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania // Shorthands to set the MediaPlayer's metadata filter. 1109193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final Set<Integer> MATCH_NONE = Collections.EMPTY_SET; 1119193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public static final Set<Integer> MATCH_ALL = Collections.singleton(ANY); 1129193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 113cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania public static final int STRING_VAL = 1; 114cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania public static final int INTEGER_VAL = 2; 115cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania public static final int BOOLEAN_VAL = 3; 116cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania public static final int LONG_VAL = 4; 117cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania public static final int DOUBLE_VAL = 5; 118cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania public static final int TIMED_TEXT_VAL = 6; 119cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania public static final int DATE_VAL = 7; 120cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania public static final int BYTE_ARRAY_VAL = 8; 121cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania // FIXME: misses a type for shared heap is missing (MemoryFile). 122cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania // FIXME: misses a type for bitmaps. 123cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania private static final int LAST_TYPE = 8; 124a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 125a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania private static final String TAG = "media.Metadata"; 1266fa41bbb56e0756d3eac15d6314007e4a450c9d3niko private static final int kInt32Size = 4; 1276fa41bbb56e0756d3eac15d6314007e4a450c9d3niko private static final int kMetaHeaderSize = 2 * kInt32Size; // size + marker 1286fa41bbb56e0756d3eac15d6314007e4a450c9d3niko private static final int kRecordHeaderSize = 3 * kInt32Size; // size + id + type 1296fa41bbb56e0756d3eac15d6314007e4a450c9d3niko 130a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania private static final int kMetaMarker = 0x4d455441; // 'M' 'E' 'T' 'A' 131a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 132a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // After a successful parsing, set the parcel with the serialized metadata. 133a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania private Parcel mParcel; 134a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 135a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // Map to associate a Metadata key (e.g TITLE) with the offset of 136a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // the record's payload in the parcel. 137a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // Used to look up if a key was present too. 138a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // Key: Metadata ID 139a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // Value: Offset of the metadata type field in the record. 140cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania private final HashMap<Integer, Integer> mKeyToPosMap = 141cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania new HashMap<Integer, Integer>(); 1425d55c7119820ee9bb06fc072e416fe98ba77cd28Nicolas Catania 1439193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania /** 144cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania * Helper class to hold a triple (time, duration, text). Can be used to 145cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania * implement caption. 1469193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania */ 1479193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public class TimedText { 1489193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania private Date mTime; 149cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania private int mDuration; // millisec 1509193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania private String mText; 151cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania 152cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania public TimedText(Date time, int duration, String text) { 1539193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania mTime = time; 154cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania mDuration = duration; 1559193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania mText = text; 1569193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania } 157cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania 1589193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public String toString() { 1599193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania StringBuilder res = new StringBuilder(80); 160cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania res.append(mTime).append("-").append(mDuration) 161cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania .append(":").append(mText); 1629193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania return res.toString(); 1639193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania } 1649193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania } 1659193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 166a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania public Metadata() { } 1679193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 168a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania /** 169a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * Go over all the records, collecting metadata keys and records' 170a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * type field offset in the Parcel. These are stored in 171a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * mKeyToPosMap for latter retrieval. 172a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * Format of a metadata record: 173a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania <pre> 174a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 1 2 3 175a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 176a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 177a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania | record size | 178a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 179a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania | metadata key | // TITLE 180a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 181a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania | metadata type | // STRING_VAL 182a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 183a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania | | 184a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania | .... metadata payload .... | 185a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania | | 186a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 187a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania </pre> 188a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * @param parcel With the serialized records. 189a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * @param bytesLeft How many bytes in the parcel should be processed. 190a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * @return false if an error occurred during parsing. 191a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania */ 192a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania private boolean scanAllRecords(Parcel parcel, int bytesLeft) { 193a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania int recCount = 0; 194a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania boolean error = false; 195a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 196a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania mKeyToPosMap.clear(); 197a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania while (bytesLeft > kRecordHeaderSize) { 198a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania final int start = parcel.dataPosition(); 199a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // Check the size. 200a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania final int size = parcel.readInt(); 201a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 202a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania if (size <= kRecordHeaderSize) { // at least 1 byte should be present. 203a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania Log.e(TAG, "Record is too short"); 204a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania error = true; 205a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania break; 206a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania } 207a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 208a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // Check the metadata key. 209a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania final int metadataId = parcel.readInt(); 210a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania if (!checkMetadataId(metadataId)) { 211a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania error = true; 212a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania break; 213a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania } 214a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 215a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // Store the record offset which points to the type 216a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // field so we can later on read/unmarshall the record 217a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // payload. 218a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania if (mKeyToPosMap.containsKey(metadataId)) { 219a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania Log.e(TAG, "Duplicate metadata ID found"); 220a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania error = true; 221a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania break; 222a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania } 223a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 224a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania mKeyToPosMap.put(metadataId, parcel.dataPosition()); 225a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 226a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // Check the metadata type. 227a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania final int metadataType = parcel.readInt(); 228a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania if (metadataType <= 0 || metadataType > LAST_TYPE) { 229a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania Log.e(TAG, "Invalid metadata type " + metadataType); 230a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania error = true; 231a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania break; 232a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania } 233a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 234a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // Skip to the next one. 235a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania parcel.setDataPosition(start + size); 236a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania bytesLeft -= size; 237a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania ++recCount; 238a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania } 239a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 240a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania if (0 != bytesLeft || error) { 241a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania Log.e(TAG, "Ran out of data or error on record " + recCount); 242a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania mKeyToPosMap.clear(); 243a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania return false; 244a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania } else { 245a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania return true; 246a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania } 2475d55c7119820ee9bb06fc072e416fe98ba77cd28Nicolas Catania } 2485d55c7119820ee9bb06fc072e416fe98ba77cd28Nicolas Catania 2499193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania /** 250a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * Check a parcel containing metadata is well formed. The header 251a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * is checked as well as the individual records format. However, the 252a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * data inside the record is not checked because we do lazy access 253a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * (we check/unmarshall only data the user asks for.) 254a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * 255a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * Format of a metadata parcel: 256a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania <pre> 257a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 1 2 3 258a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 259a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 260a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania | metadata total size | 261a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 262a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania | 'M' | 'E' | 'T' | 'A' | 263a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 264a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania | | 265a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania | .... metadata records .... | 266a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania | | 267a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 268a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania </pre> 269a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * 270a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * @param parcel With the serialized data. Metadata keeps a 271a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * reference on it to access it later on. The caller 272a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * should not modify the parcel after this call (and 273a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * not call recycle on it.) 274a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * @return false if an error occurred. 2759193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania */ 276a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania public boolean parse(Parcel parcel) { 277a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania if (parcel.dataAvail() < kMetaHeaderSize) { 278a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania Log.e(TAG, "Not enough data " + parcel.dataAvail()); 279a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania return false; 280a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania } 281a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 282a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania final int pin = parcel.dataPosition(); // to roll back in case of errors. 283a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania final int size = parcel.readInt(); 284a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 2856fa41bbb56e0756d3eac15d6314007e4a450c9d3niko // The extra kInt32Size below is to account for the int32 'size' just read. 2866fa41bbb56e0756d3eac15d6314007e4a450c9d3niko if (parcel.dataAvail() + kInt32Size < size || size < kMetaHeaderSize) { 287c39173be3237be9f39d2b57bb38249126e183c53niko Log.e(TAG, "Bad size " + size + " avail " + parcel.dataAvail() + " position " + pin); 288a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania parcel.setDataPosition(pin); 289a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania return false; 290a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania } 291a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 292a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // Checks if the 'M' 'E' 'T' 'A' marker is present. 293a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania final int kShouldBeMetaMarker = parcel.readInt(); 294a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania if (kShouldBeMetaMarker != kMetaMarker ) { 295a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania Log.e(TAG, "Marker missing " + Integer.toHexString(kShouldBeMetaMarker)); 296a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania parcel.setDataPosition(pin); 297a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania return false; 298a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania } 299a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 300a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // Scan the records to collect metadata ids and offsets. 301a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania if (!scanAllRecords(parcel, size - kMetaHeaderSize)) { 302a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania parcel.setDataPosition(pin); 303a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania return false; 304a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania } 305a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania mParcel = parcel; 306a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania return true; 3079193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania } 3089193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 3099193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania /** 310a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania * @return The set of metadata ID found. 3119193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania */ 312a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania public Set<Integer> keySet() { 313a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania return mKeyToPosMap.keySet(); 3149193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania } 3159193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 3169193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania /** 3179193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania * @return true if a value is present for the given key. 3189193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania */ 319a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania public boolean has(final int metadataId) { 320a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania if (!checkMetadataId(metadataId)) { 321a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania throw new IllegalArgumentException("Invalid key: " + metadataId); 3229193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania } 323a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania return mKeyToPosMap.containsKey(metadataId); 3249193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania } 3259193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 326cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania // Accessors. 327cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania // Caller must make sure the key is present using the {@code has} 328cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania // method otherwise a RuntimeException will occur. 329cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania 3309193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public String getString(final int key) { 331cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania checkType(key, STRING_VAL); 332cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania return mParcel.readString(); 3339193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania } 3349193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 3359193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public int getInt(final int key) { 336cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania checkType(key, INTEGER_VAL); 337cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania return mParcel.readInt(); 338cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania } 339cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania 340cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania public boolean getBoolean(final int key) { 341cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania checkType(key, BOOLEAN_VAL); 342cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania return mParcel.readInt() == 1; 3439193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania } 3449193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 3459193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public long getLong(final int key) { 346cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania checkType(key, LONG_VAL); 347cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania return mParcel.readLong(); 3489193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania } 3499193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 3509193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public double getDouble(final int key) { 351cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania checkType(key, DOUBLE_VAL); 352cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania return mParcel.readDouble(); 3539193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania } 3549193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 3559193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public byte[] getByteArray(final int key) { 356cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania checkType(key, BYTE_ARRAY_VAL); 357cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania return mParcel.createByteArray(); 3589193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania } 3599193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 3609193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public Date getDate(final int key) { 361cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania checkType(key, DATE_VAL); 362cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania final long timeSinceEpoch = mParcel.readLong(); 363cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania final String timeZone = mParcel.readString(); 364cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania 365cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania if (timeZone.length() == 0) { 366cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania return new Date(timeSinceEpoch); 367cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania } else { 368cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania TimeZone tz = TimeZone.getTimeZone(timeZone); 369cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania Calendar cal = Calendar.getInstance(tz); 370cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania 371cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania cal.setTimeInMillis(timeSinceEpoch); 372cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania return cal.getTime(); 373cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania } 3749193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania } 3759193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania 3769193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania public TimedText getTimedText(final int key) { 377cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania checkType(key, TIMED_TEXT_VAL); 378cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania final Date startTime = new Date(mParcel.readLong()); // epoch 379cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania final int duration = mParcel.readInt(); // millisec 380cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania 381cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania return new TimedText(startTime, 382cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania duration, 383cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania mParcel.readString()); 3849193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania } 385a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 386a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // @return the last available system metadata id. Ids are 387a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // 1-indexed. 388a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania public static int lastSytemId() { return LAST_SYSTEM; } 389a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 390a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // @return the first available cutom metadata id. 391a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania public static int firstCustomId() { return FIRST_CUSTOM; } 392a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 393a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // @return the last value of known type. Types are 1-indexed. 394a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania public static int lastType() { return LAST_TYPE; } 395a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania 396a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // Check val is either a system id or a custom one. 397a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // @param val Metadata key to test. 398a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania // @return true if it is in a valid range. 399a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania private boolean checkMetadataId(final int val) { 400a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania if (val <= ANY || (LAST_SYSTEM < val && val < FIRST_CUSTOM)) { 401a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania Log.e(TAG, "Invalid metadata ID " + val); 402a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania return false; 403a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania } 404a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania return true; 405a5ccb22a3ddb342fe3f7e5493095c6e6dceda60bNicolas Catania } 406cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania 407cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania // Check the type of the data match what is expected. 408cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania private void checkType(final int key, final int expectedType) { 409cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania final int pos = mKeyToPosMap.get(key); 410cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania 411cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania mParcel.setDataPosition(pos); 412cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania 413cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania final int type = mParcel.readInt(); 414cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania if (type != expectedType) { 415cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania throw new IllegalStateException("Wrong type " + expectedType + " but got " + type); 416cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania } 417cb2e00eedce99b30faf5f238136a00bc5448c5f2Nicolas Catania } 4189193e08dc1d91401fdf1846eaad4689da3911dc1Nicolas Catania} 419