Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7058e4ca authored by Sanket Agarwal's avatar Sanket Agarwal Committed by Eric Laurent
Browse files

Radio features for Automotive usecase.

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)
parent 557b64ab
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -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);
+48 −5
Original line number Diff line number Diff line
@@ -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;
            }
        };
    }

+105 −0
Original line number Diff line number Diff line
@@ -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;
@@ -388,6 +460,27 @@ public final class RadioMetadata implements Parcelable {
            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.
         *
@@ -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;
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -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);
+4 −0
Original line number Diff line number Diff line
@@ -280,6 +280,10 @@ public abstract class RadioTuner {
         * onTrafficAnnouncement() is called when a traffic announcement starts and stops.
         */
        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.
         */
Loading