public static class RadioManager.FmBandConfig extends android.hardware.radio.RadioManager.BandConfig {
method public boolean getAf();
+ method public boolean getEa();
method public boolean getRds();
method public boolean getStereo();
method public boolean getTa();
ctor public RadioManager.FmBandConfig.Builder(android.hardware.radio.RadioManager.FmBandConfig);
method public android.hardware.radio.RadioManager.FmBandConfig build();
method public android.hardware.radio.RadioManager.FmBandConfig.Builder setAf(boolean);
+ method public android.hardware.radio.RadioManager.FmBandConfig.Builder setEa(boolean);
method public android.hardware.radio.RadioManager.FmBandConfig.Builder setRds(boolean);
method public android.hardware.radio.RadioManager.FmBandConfig.Builder setStereo(boolean);
method public android.hardware.radio.RadioManager.FmBandConfig.Builder setTa(boolean);
public static class RadioManager.FmBandDescriptor extends android.hardware.radio.RadioManager.BandDescriptor {
method public boolean isAfSupported();
+ method public boolean isEaSupported();
method public boolean isRdsSupported();
method public boolean isStereoSupported();
method public boolean isTaSupported();
method public boolean containsKey(java.lang.String);
method public int describeContents();
method public android.graphics.Bitmap getBitmap(java.lang.String);
+ method public android.hardware.radio.RadioMetadata.Clock getClock(java.lang.String);
method public int getInt(java.lang.String);
method public java.lang.String getString(java.lang.String);
method public java.util.Set<java.lang.String> keySet();
field public static final java.lang.String METADATA_KEY_ALBUM = "android.hardware.radio.metadata.ALBUM";
field public static final java.lang.String METADATA_KEY_ART = "android.hardware.radio.metadata.ART";
field public static final java.lang.String METADATA_KEY_ARTIST = "android.hardware.radio.metadata.ARTIST";
+ field public static final java.lang.String METADATA_KEY_CLOCK = "android.hardware.radio.metadata.CLOCK";
field public static final java.lang.String METADATA_KEY_GENRE = "android.hardware.radio.metadata.GENRE";
field public static final java.lang.String METADATA_KEY_ICON = "android.hardware.radio.metadata.ICON";
field public static final java.lang.String METADATA_KEY_RBDS_PTY = "android.hardware.radio.metadata.RBDS_PTY";
ctor public RadioMetadata.Builder(android.hardware.radio.RadioMetadata);
method public android.hardware.radio.RadioMetadata build();
method public android.hardware.radio.RadioMetadata.Builder putBitmap(java.lang.String, android.graphics.Bitmap);
+ method public android.hardware.radio.RadioMetadata.Builder putClock(java.lang.String, long, int);
method public android.hardware.radio.RadioMetadata.Builder putInt(java.lang.String, int);
method public android.hardware.radio.RadioMetadata.Builder putString(java.lang.String, java.lang.String);
}
+ public static final class RadioMetadata.Clock implements android.os.Parcelable {
+ ctor public RadioMetadata.Clock(long, int);
+ method public int describeContents();
+ method public int getTimezoneOffsetMinutes();
+ method public long getUtcEpochSeconds();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.hardware.radio.RadioMetadata.Clock> CREATOR;
+ }
+
public abstract class RadioTuner {
ctor public RadioTuner();
method public abstract int cancel();
method public void onAntennaState(boolean);
method public void onConfigurationChanged(android.hardware.radio.RadioManager.BandConfig);
method public void onControlChanged(boolean);
+ method public void onEmergencyAnnouncement(boolean);
method public void onError(int);
method public void onMetadataChanged(android.hardware.radio.RadioMetadata);
method public void onProgramInfoChanged(android.hardware.radio.RadioManager.ProgramInfo);
private final boolean mRds;
private final boolean mTa;
private final boolean mAf;
+ private final boolean mEa;
FmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing,
- boolean stereo, boolean rds, boolean ta, boolean af) {
+ boolean stereo, boolean rds, boolean ta, boolean af, boolean ea) {
super(region, type, lowerLimit, upperLimit, spacing);
mStereo = stereo;
mRds = rds;
mTa = ta;
mAf = af;
+ mEa = ea;
}
/** Stereo is supported
return mAf;
}
+ /** Emergency Announcement is supported
+ * @return {@code true} if Emergency annoucement is supported, {@code false} otherwise.
+ */
+ public boolean isEaSupported() {
+ return mEa;
+ }
+
/* Parcelable implementation */
private FmBandDescriptor(Parcel in) {
super(in);
mRds = in.readByte() == 1;
mTa = in.readByte() == 1;
mAf = in.readByte() == 1;
+ mEa = in.readByte() == 1;
}
public static final Parcelable.Creator<FmBandDescriptor> CREATOR
dest.writeByte((byte) (mRds ? 1 : 0));
dest.writeByte((byte) (mTa ? 1 : 0));
dest.writeByte((byte) (mAf ? 1 : 0));
+ dest.writeByte((byte) (mEa ? 1 : 0));
}
@Override
@Override
public String toString() {
return "FmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo
- + ", mRds=" + mRds + ", mTa=" + mTa + ", mAf=" + mAf + "]";
+ + ", mRds=" + mRds + ", mTa=" + mTa + ", mAf=" + mAf +
+ ", mEa =" + mEa + "]";
}
@Override
result = prime * result + (mRds ? 1 : 0);
result = prime * result + (mTa ? 1 : 0);
result = prime * result + (mAf ? 1 : 0);
+ result = prime * result + (mEa ? 1 : 0);
return result;
}
return false;
if (mAf != other.isAfSupported())
return false;
+ if (mEa != other.isEaSupported())
+ return false;
return true;
}
}
private final boolean mRds;
private final boolean mTa;
private final boolean mAf;
+ private final boolean mEa;
FmBandConfig(FmBandDescriptor descriptor) {
super((BandDescriptor)descriptor);
mRds = descriptor.isRdsSupported();
mTa = descriptor.isTaSupported();
mAf = descriptor.isAfSupported();
+ mEa = descriptor.isEaSupported();
}
FmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing,
- boolean stereo, boolean rds, boolean ta, boolean af) {
+ boolean stereo, boolean rds, boolean ta, boolean af, boolean ea) {
super(region, type, lowerLimit, upperLimit, spacing);
mStereo = stereo;
mRds = rds;
mTa = ta;
mAf = af;
+ mEa = ea;
}
/** Get stereo enable state
return mAf;
}
+ /**
+ * Get Emergency announcement enable state
+ * @return the enable state.
+ */
+ public boolean getEa() {
+ return mEa;
+ }
+
private FmBandConfig(Parcel in) {
super(in);
mStereo = in.readByte() == 1;
mRds = in.readByte() == 1;
mTa = in.readByte() == 1;
mAf = in.readByte() == 1;
+ mEa = in.readByte() == 1;
}
public static final Parcelable.Creator<FmBandConfig> CREATOR
dest.writeByte((byte) (mRds ? 1 : 0));
dest.writeByte((byte) (mTa ? 1 : 0));
dest.writeByte((byte) (mAf ? 1 : 0));
+ dest.writeByte((byte) (mEa ? 1 : 0));
}
@Override
public String toString() {
return "FmBandConfig [" + super.toString()
+ ", mStereo=" + mStereo + ", mRds=" + mRds + ", mTa=" + mTa
- + ", mAf=" + mAf + "]";
+ + ", mAf=" + mAf + ", mEa =" + mEa + "]";
}
@Override
result = prime * result + (mRds ? 1 : 0);
result = prime * result + (mTa ? 1 : 0);
result = prime * result + (mAf ? 1 : 0);
+ result = prime * result + (mEa ? 1 : 0);
return result;
}
return false;
if (mAf != other.mAf)
return false;
+ if (mEa != other.mEa)
+ return false;
return true;
}
private boolean mRds;
private boolean mTa;
private boolean mAf;
+ private boolean mEa;
/**
* Constructs a new Builder with the defaults from an {@link FmBandDescriptor} .
mRds = descriptor.isRdsSupported();
mTa = descriptor.isTaSupported();
mAf = descriptor.isAfSupported();
+ mEa = descriptor.isEaSupported();
}
/**
mRds = config.getRds();
mTa = config.getTa();
mAf = config.getAf();
+ mEa = config.getEa();
}
/**
FmBandConfig config = new FmBandConfig(mDescriptor.getRegion(),
mDescriptor.getType(), mDescriptor.getLowerLimit(),
mDescriptor.getUpperLimit(), mDescriptor.getSpacing(),
- mStereo, mRds, mTa, mAf);
+ mStereo, mRds, mTa, mAf, mEa);
return config;
}
mAf = state;
return this;
}
+
+ /** Set Emergency Announcement enable state
+ * @param state The new enable state.
+ * @return the same Builder instance.
+ */
+ public Builder setEa(boolean state) {
+ mEa = state;
+ return this;
+ }
};
}
*/
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";
+
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;
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);
}
// keep in sync with: system/media/radio/include/system/radio_metadata.h
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;
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 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;
return bmp;
}
+ 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;
}
/**
+ * 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
return 0;
}
}
+
+ int putClockFromNative(int nativeKey, long utcEpochSeconds, int timezoneOffsetInMinutes) {
+ Log.d(TAG, "putClockFromNative()");
+ 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;
+ }
}
static final int EVENT_METADATA = 4;
static final int EVENT_TA = 5;
static final int EVENT_AF_SWITCH = 6;
+ static final int EVENT_EA = 7;
static final int EVENT_CONTROL = 100;
static final int EVENT_SERVER_DIED = 101;
callback.onTrafficAnnouncement(msg.arg2 == 1);
}
break;
+ case EVENT_EA:
+ if (callback != null) {
+ callback.onEmergencyAnnouncement(msg.arg2 == 1);
+ }
case EVENT_CONTROL:
if (callback != null) {
callback.onControlChanged(msg.arg2 == 1);
*/
public void onTrafficAnnouncement(boolean active) {}
/**
+ * onEmergencyAnnouncement() is called when an emergency annoucement starts and stops.
+ */
+ public void onEmergencyAnnouncement(boolean active) {}
+ /**
* onAntennaState() is called when the antenna is connected or disconnected.
*/
public void onAntennaState(boolean connected) {}
jfieldID mRds;
jfieldID mTa;
jfieldID mAf;
+ jfieldID mEa;
} gRadioFmBandConfigFields;
static const char* const kRadioAmBandConfigClassPathName =
jmethodID putIntFromNative;
jmethodID putStringFromNative;
jmethodID putBitmapFromNative;
+ jmethodID putClockFromNative;
} gRadioMetadataMethods;
static Mutex gLock;
nBandconfig->band.fm.stereo,
nBandconfig->band.fm.rds != RADIO_RDS_NONE,
nBandconfig->band.fm.ta,
- nBandconfig->band.fm.af);
+ nBandconfig->band.fm.af,
+ nBandconfig->band.fm.ea);
} else if (nBandconfig->band.type == RADIO_BAND_AM) {
*jBandDescriptor = env->NewObject(gRadioAmBandDescriptorClass, gRadioAmBandDescriptorCstor,
nBandconfig->region, nBandconfig->band.type,
nBandconfig->band.fm.stereo,
nBandconfig->band.fm.rds != RADIO_RDS_NONE,
nBandconfig->band.fm.ta,
- nBandconfig->band.fm.af);
+ nBandconfig->band.fm.af,
+ nBandconfig->band.fm.ea);
} else if (nBandconfig->band.type == RADIO_BAND_AM) {
*jBandConfig = env->NewObject(gRadioAmBandConfigClass, gRadioAmBandConfigCstor,
nBandconfig->region, nBandconfig->band.type,
}
env->DeleteLocalRef(jData);
} break;
+ case RADIO_METADATA_TYPE_CLOCK: {
+ ALOGV("%s RADIO_METADATA_TYPE_CLOCK %d", __FUNCTION__, key);
+ radio_metadata_clock_t *clock = (radio_metadata_clock_t *) value;
+ jStatus =
+ env->CallIntMethod(*jMetadata,
+ gRadioMetadataMethods.putClockFromNative,
+ key, (jint) clock->utc_seconds_since_epoch,
+ (jint) clock->timezone_offset_in_minutes);
+ if (jStatus == 0) {
+ jCount++;
+ }
+ } break;
}
}
return jCount;
nBandconfig->region);
nBandconfig->band.fm.ta = env->GetBooleanField(jBandConfig, gRadioFmBandConfigFields.mTa);
nBandconfig->band.fm.af = env->GetBooleanField(jBandConfig, gRadioFmBandConfigFields.mAf);
+ nBandconfig->band.fm.ea = env->GetBooleanField(jBandConfig, gRadioFmBandConfigFields.mEa);
} else if (env->IsInstanceOf(jBandConfig, gRadioAmBandConfigClass)) {
nBandconfig->band.am.stereo =
env->GetBooleanField(jBandConfig, gRadioAmBandConfigFields.mStereo);
break;
case RADIO_EVENT_ANTENNA:
case RADIO_EVENT_TA:
+ case RADIO_EVENT_EA:
case RADIO_EVENT_CONTROL:
jArg2 = event->on ? 1 : 0;
break;
jclass fmBandDescriptorClass = FindClassOrDie(env, kRadioFmBandDescriptorClassPathName);
gRadioFmBandDescriptorClass = MakeGlobalRefOrDie(env, fmBandDescriptorClass);
gRadioFmBandDescriptorCstor = GetMethodIDOrDie(env, fmBandDescriptorClass, "<init>",
- "(IIIIIZZZZ)V");
+ "(IIIIIZZZZZ)V");
jclass amBandDescriptorClass = FindClassOrDie(env, kRadioAmBandDescriptorClassPathName);
gRadioAmBandDescriptorClass = MakeGlobalRefOrDie(env, amBandDescriptorClass);
jclass fmBandConfigClass = FindClassOrDie(env, kRadioFmBandConfigClassPathName);
gRadioFmBandConfigClass = MakeGlobalRefOrDie(env, fmBandConfigClass);
gRadioFmBandConfigCstor = GetMethodIDOrDie(env, fmBandConfigClass, "<init>",
- "(IIIIIZZZZ)V");
+ "(IIIIIZZZZZ)V");
gRadioFmBandConfigFields.mStereo = GetFieldIDOrDie(env, fmBandConfigClass, "mStereo", "Z");
gRadioFmBandConfigFields.mRds = GetFieldIDOrDie(env, fmBandConfigClass, "mRds", "Z");
gRadioFmBandConfigFields.mTa = GetFieldIDOrDie(env, fmBandConfigClass, "mTa", "Z");
gRadioFmBandConfigFields.mAf = GetFieldIDOrDie(env, fmBandConfigClass, "mAf", "Z");
+ gRadioFmBandConfigFields.mEa =
+ GetFieldIDOrDie(env, fmBandConfigClass, "mEa", "Z");
jclass amBandConfigClass = FindClassOrDie(env, kRadioAmBandConfigClassPathName);
gRadioMetadataMethods.putBitmapFromNative = GetMethodIDOrDie(env, metadataClass,
"putBitmapFromNative",
"(I[B)I");
+ gRadioMetadataMethods.putClockFromNative = GetMethodIDOrDie(env, metadataClass,
+ "putClockFromNative",
+ "(III)I");
RegisterMethodsOrDie(env, kRadioManagerClassPathName, gMethods, NELEM(gMethods));