OSDN Git Service

Radio features for Automotive usecase.
authorSanket Agarwal <sanketa@google.com>
Thu, 8 Oct 2015 21:14:20 +0000 (14:14 -0700)
committerEric Laurent <elaurent@google.com>
Thu, 5 Nov 2015 22:50:59 +0000 (22:50 +0000)
1. Add clock to metadata - If the CAR does not have a clock (no network
or bad clock) then Radio RDS could be used as a proxy.
2. Add support for emergency announcement - If the CAR wants to make an
emergency announcement.
    2.1 Add support for callbacks.

Bug: b/24807501
Bug: b/22701655

Change-Id: Ib3131de03a022181559fd31da6701d9d3fa8698d
(cherry picked from commit 659688a129189f2a9aa353ddf9e107d5f293c4ca)

api/system-current.txt
core/java/android/hardware/radio/RadioManager.java
core/java/android/hardware/radio/RadioMetadata.java
core/java/android/hardware/radio/RadioModule.java
core/java/android/hardware/radio/RadioTuner.java
core/jni/android_hardware_Radio.cpp

index bd674ef..64162ae 100644 (file)
@@ -14919,6 +14919,7 @@ package android.hardware.radio {
 
   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();
@@ -14930,6 +14931,7 @@ package android.hardware.radio {
     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);
@@ -14937,6 +14939,7 @@ package android.hardware.radio {
 
   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();
@@ -14976,6 +14979,7 @@ package android.hardware.radio {
     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();
@@ -14985,6 +14989,7 @@ package android.hardware.radio {
     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";
@@ -15000,10 +15005,20 @@ package android.hardware.radio {
     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();
@@ -15032,6 +15047,7 @@ package android.hardware.radio {
     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);
index 32930a7..14bb923 100644 (file)
@@ -457,14 +457,16 @@ public class RadioManager {
         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
@@ -492,6 +494,13 @@ public class RadioManager {
             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);
@@ -499,6 +508,7 @@ public class RadioManager {
             mRds = in.readByte() == 1;
             mTa = in.readByte() == 1;
             mAf = in.readByte() == 1;
+            mEa = in.readByte() == 1;
         }
 
         public static final Parcelable.Creator<FmBandDescriptor> CREATOR
@@ -519,6 +529,7 @@ public class RadioManager {
             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
@@ -529,7 +540,8 @@ public class RadioManager {
         @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
@@ -540,6 +552,7 @@ public class RadioManager {
             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;
         }
 
@@ -560,6 +573,8 @@ public class RadioManager {
                 return false;
             if (mAf != other.isAfSupported())
                 return false;
+            if (mEa != other.isEaSupported())
+                return false;
             return true;
         }
     }
@@ -754,6 +769,7 @@ public class RadioManager {
         private final boolean mRds;
         private final boolean mTa;
         private final boolean mAf;
+        private final boolean mEa;
 
         FmBandConfig(FmBandDescriptor descriptor) {
             super((BandDescriptor)descriptor);
@@ -761,15 +777,17 @@ public class RadioManager {
             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
@@ -800,12 +818,21 @@ public class RadioManager {
             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
@@ -826,6 +853,7 @@ public class RadioManager {
             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
@@ -837,7 +865,7 @@ public class RadioManager {
         public String toString() {
             return "FmBandConfig [" + super.toString()
                     + ", mStereo=" + mStereo + ", mRds=" + mRds + ", mTa=" + mTa
-                    + ", mAf=" + mAf + "]";
+                    + ", mAf=" + mAf + ", mEa =" + mEa + "]";
         }
 
         @Override
@@ -848,6 +876,7 @@ public class RadioManager {
             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;
         }
 
@@ -868,6 +897,8 @@ public class RadioManager {
                 return false;
             if (mAf != other.mAf)
                 return false;
+            if (mEa != other.mEa)
+                return false;
             return true;
         }
 
@@ -880,6 +911,7 @@ public class RadioManager {
             private boolean mRds;
             private boolean mTa;
             private boolean mAf;
+            private boolean mEa;
 
             /**
              * Constructs a new Builder with the defaults from an {@link FmBandDescriptor} .
@@ -893,6 +925,7 @@ public class RadioManager {
                 mRds = descriptor.isRdsSupported();
                 mTa = descriptor.isTaSupported();
                 mAf = descriptor.isAfSupported();
+                mEa = descriptor.isEaSupported();
             }
 
             /**
@@ -906,6 +939,7 @@ public class RadioManager {
                 mRds = config.getRds();
                 mTa = config.getTa();
                 mAf = config.getAf();
+                mEa = config.getEa();
             }
 
             /**
@@ -917,7 +951,7 @@ public class RadioManager {
                 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;
             }
 
@@ -956,6 +990,15 @@ public class RadioManager {
                 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;
+            }
         };
     }
 
index 8b1851b..b7715da 100644 (file)
@@ -95,11 +95,17 @@ public final class RadioMetadata implements Parcelable {
      */
     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;
 
@@ -116,6 +122,7 @@ public final class RadioMetadata implements Parcelable {
         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
@@ -131,6 +138,7 @@ public final class RadioMetadata implements Parcelable {
     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;
 
@@ -147,6 +155,59 @@ public final class RadioMetadata implements Parcelable {
         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;
@@ -212,6 +273,17 @@ public final class RadioMetadata implements Parcelable {
         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;
@@ -389,6 +461,27 @@ public final class RadioMetadata implements Parcelable {
         }
 
         /**
+         * 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
@@ -446,4 +539,16 @@ public final class RadioMetadata implements Parcelable {
             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;
+    }
 }
index 15916ae..fc7d0d2 100644 (file)
@@ -89,6 +89,7 @@ public class RadioModule extends RadioTuner {
     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;
 
@@ -170,6 +171,10 @@ public class RadioModule extends RadioTuner {
                                 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);
index 376900a..5c82555 100644 (file)
@@ -281,6 +281,10 @@ public abstract class RadioTuner {
          */
         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) {}
index b9dd77a..5b92a6e 100644 (file)
@@ -93,6 +93,7 @@ static struct {
     jfieldID mRds;
     jfieldID mTa;
     jfieldID mAf;
+    jfieldID mEa;
 } gRadioFmBandConfigFields;
 
 static const char* const kRadioAmBandConfigClassPathName =
@@ -117,6 +118,7 @@ static struct {
     jmethodID putIntFromNative;
     jmethodID putStringFromNative;
     jmethodID putBitmapFromNative;
+    jmethodID putClockFromNative;
 } gRadioMetadataMethods;
 
 static Mutex gLock;
@@ -171,7 +173,8 @@ static jint convertBandDescriptorFromNative(JNIEnv *env,
                                       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,
@@ -205,7 +208,8 @@ static jint convertBandConfigFromNative(JNIEnv *env,
                                       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,
@@ -284,6 +288,18 @@ static jint convertMetadataFromNative(JNIEnv *env,
                 }
                 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;
@@ -351,6 +367,7 @@ static jint convertBandConfigToNative(JNIEnv *env,
                                      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);
@@ -518,6 +535,7 @@ void JNIRadioCallback::onEvent(struct radio_event *event)
             break;
         case RADIO_EVENT_ANTENNA:
         case RADIO_EVENT_TA:
+        case RADIO_EVENT_EA:
         case RADIO_EVENT_CONTROL:
             jArg2 = event->on ? 1 : 0;
             break;
@@ -878,7 +896,7 @@ int register_android_hardware_Radio(JNIEnv *env)
     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);
@@ -894,11 +912,13 @@ int register_android_hardware_Radio(JNIEnv *env)
     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);
@@ -924,6 +944,9 @@ int register_android_hardware_Radio(JNIEnv *env)
     gRadioMetadataMethods.putBitmapFromNative = GetMethodIDOrDie(env, metadataClass,
                                                                  "putBitmapFromNative",
                                                                  "(I[B)I");
+    gRadioMetadataMethods.putClockFromNative = GetMethodIDOrDie(env, metadataClass,
+                                                                "putClockFromNative",
+                                                                "(III)I");
 
 
     RegisterMethodsOrDie(env, kRadioManagerClassPathName, gMethods, NELEM(gMethods));