| /* |
| * 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.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.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; |
| |
| @Override |
| public int hashCode() { |
| return mBundle.hashCode(); |
| } |
| |
| @Override |
| public boolean equals(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(); |
| } |
| |
| @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); |
| 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); |
| 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); |
| 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)); |
| return 0; |
| } |
| } |