/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.hardware.radio;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

/**
 * Contains meta data about a radio program such as station name, song title, artist etc...
 * @hide
 */
@SystemApi
public final class RadioMetadata implements Parcelable {
    private static final String TAG = "BroadcastRadio.metadata";

    /**
     * The RDS Program Information.
     */
    public static final String METADATA_KEY_RDS_PI = "android.hardware.radio.metadata.RDS_PI";

    /**
     * The RDS Program Service.
     */
    public static final String METADATA_KEY_RDS_PS = "android.hardware.radio.metadata.RDS_PS";

    /**
     * The RDS PTY.
     */
    public static final String METADATA_KEY_RDS_PTY = "android.hardware.radio.metadata.RDS_PTY";

    /**
     * The RBDS PTY.
     */
    public static final String METADATA_KEY_RBDS_PTY = "android.hardware.radio.metadata.RBDS_PTY";

    /**
     * The RBDS Radio Text.
     */
    public static final String METADATA_KEY_RDS_RT = "android.hardware.radio.metadata.RDS_RT";

    /**
     * The song title.
     */
    public static final String METADATA_KEY_TITLE = "android.hardware.radio.metadata.TITLE";

    /**
     * The artist name.
     */
    public static final String METADATA_KEY_ARTIST = "android.hardware.radio.metadata.ARTIST";

    /**
     * The album name.
     */
    public static final String METADATA_KEY_ALBUM = "android.hardware.radio.metadata.ALBUM";

    /**
     * The music genre.
     */
    public static final String METADATA_KEY_GENRE = "android.hardware.radio.metadata.GENRE";

    /**
     * The radio station icon {@link Bitmap}.
     */
    public static final String METADATA_KEY_ICON = "android.hardware.radio.metadata.ICON";

    /**
     * The artwork for the song/album {@link Bitmap}.
     */
    public static final String METADATA_KEY_ART = "android.hardware.radio.metadata.ART";

    /**
     * The clock.
     */
    public static final String METADATA_KEY_CLOCK = "android.hardware.radio.metadata.CLOCK";

    /**
     * Technology-independent program name (station name).
     */
    public static final String METADATA_KEY_PROGRAM_NAME =
            "android.hardware.radio.metadata.PROGRAM_NAME";

    /**
     * DAB ensemble name.
     */
    public static final String METADATA_KEY_DAB_ENSEMBLE_NAME =
            "android.hardware.radio.metadata.DAB_ENSEMBLE_NAME";

    /**
     * DAB ensemble name - short version (up to 8 characters).
     */
    public static final String METADATA_KEY_DAB_ENSEMBLE_NAME_SHORT =
            "android.hardware.radio.metadata.DAB_ENSEMBLE_NAME_SHORT";

    /**
     * DAB service name.
     */
    public static final String METADATA_KEY_DAB_SERVICE_NAME =
            "android.hardware.radio.metadata.DAB_SERVICE_NAME";

    /**
     * DAB service name - short version (up to 8 characters).
     */
    public static final String METADATA_KEY_DAB_SERVICE_NAME_SHORT =
            "android.hardware.radio.metadata.DAB_SERVICE_NAME_SHORT";

    /**
     * DAB component name.
     */
    public static final String METADATA_KEY_DAB_COMPONENT_NAME =
            "android.hardware.radio.metadata.DAB_COMPONENT_NAME";

    /**
     * DAB component name.
     */
    public static final String METADATA_KEY_DAB_COMPONENT_NAME_SHORT =
            "android.hardware.radio.metadata.DAB_COMPONENT_NAME_SHORT";


    private static final int METADATA_TYPE_INVALID = -1;
    private static final int METADATA_TYPE_INT = 0;
    private static final int METADATA_TYPE_TEXT = 1;
    private static final int METADATA_TYPE_BITMAP = 2;
    private static final int METADATA_TYPE_CLOCK = 3;

    private static final ArrayMap<String, Integer> METADATA_KEYS_TYPE;

    static {
        METADATA_KEYS_TYPE = new ArrayMap<String, Integer>();
        METADATA_KEYS_TYPE.put(METADATA_KEY_RDS_PI, METADATA_TYPE_INT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_RDS_PS, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_RDS_PTY, METADATA_TYPE_INT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_RBDS_PTY, METADATA_TYPE_INT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_RDS_RT, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_TITLE, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_ARTIST, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_ALBUM, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_GENRE, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_ICON, METADATA_TYPE_BITMAP);
        METADATA_KEYS_TYPE.put(METADATA_KEY_ART, METADATA_TYPE_BITMAP);
        METADATA_KEYS_TYPE.put(METADATA_KEY_CLOCK, METADATA_TYPE_CLOCK);
        METADATA_KEYS_TYPE.put(METADATA_KEY_PROGRAM_NAME, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_ENSEMBLE_NAME, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_ENSEMBLE_NAME_SHORT, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_SERVICE_NAME, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_SERVICE_NAME_SHORT, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_COMPONENT_NAME, METADATA_TYPE_TEXT);
        METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_COMPONENT_NAME_SHORT, METADATA_TYPE_TEXT);
    }

    // keep in sync with: system/media/radio/include/system/radio_metadata.h
    private static final int NATIVE_KEY_INVALID     = -1;
    private static final int NATIVE_KEY_RDS_PI      = 0;
    private static final int NATIVE_KEY_RDS_PS      = 1;
    private static final int NATIVE_KEY_RDS_PTY     = 2;
    private static final int NATIVE_KEY_RBDS_PTY    = 3;
    private static final int NATIVE_KEY_RDS_RT      = 4;
    private static final int NATIVE_KEY_TITLE       = 5;
    private static final int NATIVE_KEY_ARTIST      = 6;
    private static final int NATIVE_KEY_ALBUM       = 7;
    private static final int NATIVE_KEY_GENRE       = 8;
    private static final int NATIVE_KEY_ICON        = 9;
    private static final int NATIVE_KEY_ART         = 10;
    private static final int NATIVE_KEY_CLOCK       = 11;

    private static final SparseArray<String> NATIVE_KEY_MAPPING;

    static {
        NATIVE_KEY_MAPPING = new SparseArray<String>();
        NATIVE_KEY_MAPPING.put(NATIVE_KEY_RDS_PI, METADATA_KEY_RDS_PI);
        NATIVE_KEY_MAPPING.put(NATIVE_KEY_RDS_PS, METADATA_KEY_RDS_PS);
        NATIVE_KEY_MAPPING.put(NATIVE_KEY_RDS_PTY, METADATA_KEY_RDS_PTY);
        NATIVE_KEY_MAPPING.put(NATIVE_KEY_RBDS_PTY, METADATA_KEY_RBDS_PTY);
        NATIVE_KEY_MAPPING.put(NATIVE_KEY_RDS_RT, METADATA_KEY_RDS_RT);
        NATIVE_KEY_MAPPING.put(NATIVE_KEY_TITLE, METADATA_KEY_TITLE);
        NATIVE_KEY_MAPPING.put(NATIVE_KEY_ARTIST, METADATA_KEY_ARTIST);
        NATIVE_KEY_MAPPING.put(NATIVE_KEY_ALBUM, METADATA_KEY_ALBUM);
        NATIVE_KEY_MAPPING.put(NATIVE_KEY_GENRE, METADATA_KEY_GENRE);
        NATIVE_KEY_MAPPING.put(NATIVE_KEY_ICON, METADATA_KEY_ICON);
        NATIVE_KEY_MAPPING.put(NATIVE_KEY_ART, METADATA_KEY_ART);
        NATIVE_KEY_MAPPING.put(NATIVE_KEY_CLOCK, METADATA_KEY_CLOCK);
    }

    /**
     * Provides a Clock that can be used to describe time as provided by the Radio.
     *
     * The clock is defined by the seconds since epoch at the UTC + 0 timezone
     * and timezone offset from UTC + 0 represented in number of minutes.
     *
     * @hide
     */
    @SystemApi
    public static final class Clock implements Parcelable {
        private final long mUtcEpochSeconds;
        private final int mTimezoneOffsetMinutes;

        public int describeContents() {
            return 0;
        }

        public void writeToParcel(Parcel out, int flags) {
            out.writeLong(mUtcEpochSeconds);
            out.writeInt(mTimezoneOffsetMinutes);
        }

        public static final @android.annotation.NonNull Parcelable.Creator<Clock> CREATOR
                = new Parcelable.Creator<Clock>() {
            public Clock createFromParcel(Parcel in) {
                return new Clock(in);
            }

            public Clock[] newArray(int size) {
                return new Clock[size];
            }
        };

        public Clock(long utcEpochSeconds, int timezoneOffsetMinutes) {
            mUtcEpochSeconds = utcEpochSeconds;
            mTimezoneOffsetMinutes = timezoneOffsetMinutes;
        }

        private Clock(Parcel in) {
            mUtcEpochSeconds = in.readLong();
            mTimezoneOffsetMinutes = in.readInt();
        }

        public long getUtcEpochSeconds() {
            return mUtcEpochSeconds;
        }

        public int getTimezoneOffsetMinutes() {
            return mTimezoneOffsetMinutes;
        }
    }

    private final Bundle mBundle;

    // Lazily computed hash code based upon the contents of mBundle.
    private Integer mHashCode;

    @Override
    public int hashCode() {
        if (mHashCode == null) {
            List<String> keys = new ArrayList<String>(mBundle.keySet());
            keys.sort(null);
            Object[] objs = new Object[2 * keys.size()];
            for (int i = 0; i < keys.size(); i++) {
                objs[2 * i] = keys.get(i);
                objs[2 * i + 1] = mBundle.get(keys.get(i));
            }
            mHashCode = Arrays.hashCode(objs);
        }
        return mHashCode;
    }

    @Override
    public boolean equals(@Nullable Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof RadioMetadata)) return false;
        Bundle otherBundle = ((RadioMetadata) obj).mBundle;
        if (!mBundle.keySet().equals(otherBundle.keySet())) {
            return false;
        }
        for (String key : mBundle.keySet()) {
            // This logic will return a false negative if we ever put Bundles into mBundle. As of
            // 2019-04-09, we only put ints, Strings, and Parcelables in, so it's fine for now.
            if (!mBundle.get(key).equals(otherBundle.get(key))) {
                return false;
            }
        }
        return true;
    }

    RadioMetadata() {
        mBundle = new Bundle();
    }

    private RadioMetadata(Bundle bundle) {
        mBundle = new Bundle(bundle);
    }

    private RadioMetadata(Parcel in) {
        mBundle = in.readBundle();
    }

    @NonNull
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("RadioMetadata[");

        final String removePrefix = "android.hardware.radio.metadata";

        boolean first = true;
        for (String key : mBundle.keySet()) {
            if (first) first = false;
            else sb.append(", ");

            String keyDisp = key;
            if (key.startsWith(removePrefix)) keyDisp = key.substring(removePrefix.length());

            sb.append(keyDisp);
            sb.append('=');
            sb.append(mBundle.get(key));
        }

        sb.append("]");
        return sb.toString();
    }

    /**
     * Returns {@code true} if the given key is contained in the meta data
     *
     * @param key a String key
     * @return {@code true} if the key exists in this meta data, {@code false} otherwise
     */
    public boolean containsKey(String key) {
        return mBundle.containsKey(key);
    }

    /**
     * Returns the text value associated with the given key as a String, or null
     * if the key is not found in the meta data.
     *
     * @param key The key the value is stored under
     * @return a String value, or null
     */
    public String getString(String key) {
        return mBundle.getString(key);
    }

    private static void putInt(Bundle bundle, String key, int value) {
        int type = METADATA_KEYS_TYPE.getOrDefault(key, METADATA_TYPE_INVALID);
        if (type != METADATA_TYPE_INT && type != METADATA_TYPE_BITMAP) {
            throw new IllegalArgumentException("The " + key + " key cannot be used to put an int");
        }
        bundle.putInt(key, value);
    }

    /**
     * Returns the value associated with the given key,
     * or 0 if the key is not found in the meta data.
     *
     * @param key The key the value is stored under
     * @return an int value
     */
    public int getInt(String key) {
        return mBundle.getInt(key, 0);
    }

    /**
     * Returns a {@link Bitmap} for the given key or null if the key is not found in the meta data.
     *
     * @param key The key the value is stored under
     * @return a {@link Bitmap} or null
     * @deprecated Use getBitmapId(String) instead
     */
    @Deprecated
    public Bitmap getBitmap(String key) {
        Bitmap bmp = null;
        try {
            bmp = mBundle.getParcelable(key);
        } catch (Exception e) {
            // ignore, value was not a bitmap
            Log.w(TAG, "Failed to retrieve a key as Bitmap.", e);
        }
        return bmp;
    }

    /**
     * Retrieves an identifier for a bitmap.
     *
     * The format of an identifier is opaque to the application,
     * with a special case of value 0 being invalid.
     * An identifier for a given image-tuner pair is unique, so an application
     * may cache images and determine if there is a necessity to fetch them
     * again - if identifier changes, it means the image has changed.
     *
     * Only bitmap keys may be used with this method:
     * <ul>
     * <li>{@link #METADATA_KEY_ICON}</li>
     * <li>{@link #METADATA_KEY_ART}</li>
     * </ul>
     *
     * @param key The key the value is stored under.
     * @return a bitmap identifier or 0 if it's missing.
     * @hide This API is not thoroughly elaborated yet
     */
    public int getBitmapId(@NonNull String key) {
        if (!METADATA_KEY_ICON.equals(key) && !METADATA_KEY_ART.equals(key)) return 0;
        return getInt(key);
    }

    public Clock getClock(String key) {
        Clock clock = null;
        try {
            clock = mBundle.getParcelable(key);
        } catch (Exception e) {
            // ignore, value was not a clock.
            Log.w(TAG, "Failed to retrieve a key as Clock.", e);
        }
        return clock;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeBundle(mBundle);
    }

    /**
     * Returns the number of fields in this meta data.
     *
     * @return the number of fields in the meta data.
     */
    public int size() {
        return mBundle.size();
    }

    /**
     * Returns a Set containing the Strings used as keys in this meta data.
     *
     * @return a Set of String keys
     */
    public Set<String> keySet() {
        return mBundle.keySet();
    }

    /**
     * Helper for getting the String key used by {@link RadioMetadata} from the
     * corrsponding native integer key.
     *
     * @param editorKey The key used by the editor
     * @return the key used by this class or null if no mapping exists
     * @hide
     */
    public static String getKeyFromNativeKey(int nativeKey) {
        return NATIVE_KEY_MAPPING.get(nativeKey, null);
    }

    public static final @android.annotation.NonNull Parcelable.Creator<RadioMetadata> CREATOR =
            new Parcelable.Creator<RadioMetadata>() {
                @Override
                public RadioMetadata createFromParcel(Parcel in) {
                    return new RadioMetadata(in);
                }

                @Override
                public RadioMetadata[] newArray(int size) {
                    return new RadioMetadata[size];
                }
            };

    /**
     * Use to build RadioMetadata objects.
     */
    public static final class Builder {
        private final Bundle mBundle;

        /**
         * Create an empty Builder. Any field that should be included in the
         * {@link RadioMetadata} must be added.
         */
        public Builder() {
            mBundle = new Bundle();
        }

        /**
         * Create a Builder using a {@link RadioMetadata} instance to set the
         * initial values. All fields in the source meta data will be included in
         * the new meta data. Fields can be overwritten by adding the same key.
         *
         * @param source
         */
        public Builder(RadioMetadata source) {
            mBundle = new Bundle(source.mBundle);
        }

        /**
         * Create a Builder using a {@link RadioMetadata} instance to set
         * initial values, but replace bitmaps with a scaled down copy if they
         * are larger than maxBitmapSize.
         *
         * @param source The original meta data to copy.
         * @param maxBitmapSize The maximum height/width for bitmaps contained
         *            in the meta data.
         * @hide
         */
        public Builder(RadioMetadata source, int maxBitmapSize) {
            this(source);
            for (String key : mBundle.keySet()) {
                Object value = mBundle.get(key);
                if (value != null && value instanceof Bitmap) {
                    Bitmap bmp = (Bitmap) value;
                    if (bmp.getHeight() > maxBitmapSize || bmp.getWidth() > maxBitmapSize) {
                        putBitmap(key, scaleBitmap(bmp, maxBitmapSize));
                    }
                }
            }
        }

        /**
         * Put a String value into the meta data. Custom keys may be used, but if
         * the METADATA_KEYs defined in this class are used they may only be one
         * of the following:
         * <ul>
         * <li>{@link #METADATA_KEY_RDS_PS}</li>
         * <li>{@link #METADATA_KEY_RDS_RT}</li>
         * <li>{@link #METADATA_KEY_TITLE}</li>
         * <li>{@link #METADATA_KEY_ARTIST}</li>
         * <li>{@link #METADATA_KEY_ALBUM}</li>
         * <li>{@link #METADATA_KEY_GENRE}</li>
         * </ul>
         *
         * @param key The key for referencing this value
         * @param value The String value to store
         * @return the same Builder instance
         */
        public Builder putString(String key, String value) {
            if (!METADATA_KEYS_TYPE.containsKey(key) ||
                    METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
                throw new IllegalArgumentException("The " + key
                        + " key cannot be used to put a String");
            }
            mBundle.putString(key, value);
            return this;
        }

        /**
         * Put an int value into the meta data. Custom keys may be used, but if
         * the METADATA_KEYs defined in this class are used they may only be one
         * of the following:
         * <ul>
         * <li>{@link #METADATA_KEY_RDS_PI}</li>
         * <li>{@link #METADATA_KEY_RDS_PTY}</li>
         * <li>{@link #METADATA_KEY_RBDS_PTY}</li>
         * </ul>
         * or any bitmap represented by its identifier.
         *
         * @param key The key for referencing this value
         * @param value The int value to store
         * @return the same Builder instance
         */
        public Builder putInt(String key, int value) {
            RadioMetadata.putInt(mBundle, key, value);
            return this;
        }

        /**
         * Put a {@link Bitmap} into the meta data. Custom keys may be used, but
         * if the METADATA_KEYs defined in this class are used they may only be
         * one of the following:
         * <ul>
         * <li>{@link #METADATA_KEY_ICON}</li>
         * <li>{@link #METADATA_KEY_ART}</li>
         * </ul>
         * <p>
         *
         * @param key The key for referencing this value
         * @param value The Bitmap to store
         * @return the same Builder instance
         */
        public Builder putBitmap(String key, Bitmap value) {
            if (!METADATA_KEYS_TYPE.containsKey(key) ||
                    METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_BITMAP) {
                throw new IllegalArgumentException("The " + key
                        + " key cannot be used to put a Bitmap");
            }
            mBundle.putParcelable(key, value);
            return this;
        }

        /**
         * Put a {@link RadioMetadata.Clock} into the meta data. Custom keys may be used, but if the
         * METADATA_KEYs defined in this class are used they may only be one of the following:
         * <ul>
         * <li>{@link #MEADATA_KEY_CLOCK}</li>
         * </ul>
         *
         * @param utcSecondsSinceEpoch Number of seconds since epoch for UTC + 0 timezone.
         * @param timezoneOffsetInMinutes Offset of timezone from UTC + 0 in minutes.
         * @return the same Builder instance.
         */
        public Builder putClock(String key, long utcSecondsSinceEpoch, int timezoneOffsetMinutes) {
            if (!METADATA_KEYS_TYPE.containsKey(key) ||
                    METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_CLOCK) {
                throw new IllegalArgumentException("The " + key
                    + " key cannot be used to put a RadioMetadata.Clock.");
            }
            mBundle.putParcelable(key, new Clock(utcSecondsSinceEpoch, timezoneOffsetMinutes));
            return this;
        }

        /**
         * Creates a {@link RadioMetadata} instance with the specified fields.
         *
         * @return a new {@link RadioMetadata} object
         */
        public RadioMetadata build() {
            return new RadioMetadata(mBundle);
        }

        private Bitmap scaleBitmap(Bitmap bmp, int maxSize) {
            float maxSizeF = maxSize;
            float widthScale = maxSizeF / bmp.getWidth();
            float heightScale = maxSizeF / bmp.getHeight();
            float scale = Math.min(widthScale, heightScale);
            int height = (int) (bmp.getHeight() * scale);
            int width = (int) (bmp.getWidth() * scale);
            return Bitmap.createScaledBitmap(bmp, width, height, true);
        }
    }

    int putIntFromNative(int nativeKey, int value) {
        String key = getKeyFromNativeKey(nativeKey);
        try {
            putInt(mBundle, key, value);
            // Invalidate mHashCode to force it to be recomputed.
            mHashCode = null;
            return 0;
        } catch (IllegalArgumentException ex) {
            return -1;
        }
    }

    int putStringFromNative(int nativeKey, String value) {
        String key = getKeyFromNativeKey(nativeKey);
        if (!METADATA_KEYS_TYPE.containsKey(key) ||
                METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
            return -1;
        }
        mBundle.putString(key, value);
        // Invalidate mHashCode to force it to be recomputed.
        mHashCode = null;
        return 0;
    }

    int putBitmapFromNative(int nativeKey, byte[] value) {
        String key = getKeyFromNativeKey(nativeKey);
        if (!METADATA_KEYS_TYPE.containsKey(key) ||
                METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_BITMAP) {
            return -1;
        }
        Bitmap bmp = null;
        try {
            bmp = BitmapFactory.decodeByteArray(value, 0, value.length);
            if (bmp != null) {
                mBundle.putParcelable(key, bmp);
                // Invalidate mHashCode to force it to be recomputed.
                mHashCode = null;
                return 0;
            }
        } catch (Exception e) {
        }
        return -1;
    }

    int putClockFromNative(int nativeKey, long utcEpochSeconds, int timezoneOffsetInMinutes) {
        String key = getKeyFromNativeKey(nativeKey);
        if (!METADATA_KEYS_TYPE.containsKey(key) ||
                METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_CLOCK) {
              return -1;
        }
        mBundle.putParcelable(key, new RadioMetadata.Clock(
            utcEpochSeconds, timezoneOffsetInMinutes));
        // Invalidate mHashCode to force it to be recomputed.
        mHashCode = null;
        return 0;
    }
}
