diff options
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/hardware/radio/Announcement.aidl | 20 | ||||
| -rw-r--r-- | core/java/android/hardware/radio/Announcement.java | 133 | ||||
| -rw-r--r-- | core/java/android/hardware/radio/IAnnouncementListener.aidl | 24 | ||||
| -rw-r--r-- | core/java/android/hardware/radio/ICloseHandle.aidl | 22 | ||||
| -rw-r--r-- | core/java/android/hardware/radio/IRadioService.aidl | 5 | ||||
| -rw-r--r-- | core/java/android/hardware/radio/RadioManager.java | 64 | ||||
| -rw-r--r-- | core/java/android/hardware/radio/Utils.java | 11 |
7 files changed, 279 insertions, 0 deletions
diff --git a/core/java/android/hardware/radio/Announcement.aidl b/core/java/android/hardware/radio/Announcement.aidl new file mode 100644 index 000000000000..eeb5951ee782 --- /dev/null +++ b/core/java/android/hardware/radio/Announcement.aidl @@ -0,0 +1,20 @@ +/** + * Copyright (C) 2018 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; + +/** @hide */ +parcelable Announcement; diff --git a/core/java/android/hardware/radio/Announcement.java b/core/java/android/hardware/radio/Announcement.java new file mode 100644 index 000000000000..166fe6043f3d --- /dev/null +++ b/core/java/android/hardware/radio/Announcement.java @@ -0,0 +1,133 @@ +/** + * Copyright (C) 2018 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.IntDef; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Collection; +import java.util.Map; +import java.util.Objects; + +/** + * @hide + */ +@SystemApi +public final class Announcement implements Parcelable { + + /** DAB alarm, RDS emergency program type (PTY 31). */ + public static final int TYPE_EMERGENCY = 1; + /** DAB warning. */ + public static final int TYPE_WARNING = 2; + /** DAB road traffic, RDS TA, HD Radio transportation. */ + public static final int TYPE_TRAFFIC = 3; + /** Weather. */ + public static final int TYPE_WEATHER = 4; + /** News. */ + public static final int TYPE_NEWS = 5; + /** DAB event, special event. */ + public static final int TYPE_EVENT = 6; + /** DAB sport report, RDS sports. */ + public static final int TYPE_SPORT = 7; + /** All others. */ + public static final int TYPE_MISC = 8; + /** @hide */ + @IntDef(prefix = { "TYPE_" }, value = { + TYPE_EMERGENCY, + TYPE_WARNING, + TYPE_TRAFFIC, + TYPE_WEATHER, + TYPE_NEWS, + TYPE_EVENT, + TYPE_SPORT, + TYPE_MISC, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Type {} + + /** + * Listener of announcement list events. + */ + public interface OnListUpdatedListener { + /** + * An event called whenever a list of active announcements change. + * + * The entire list is sent each time a new announcement appears or any ends broadcasting. + * + * @param activeAnnouncements a full list of active announcements + */ + void onListUpdated(Collection<Announcement> activeAnnouncements); + } + + @NonNull private final ProgramSelector mSelector; + @Type private final int mType; + @NonNull private final Map<String, String> mVendorInfo; + + /** @hide */ + public Announcement(@NonNull ProgramSelector selector, @Type int type, + @NonNull Map<String, String> vendorInfo) { + mSelector = Objects.requireNonNull(selector); + mType = Objects.requireNonNull(type); + mVendorInfo = Objects.requireNonNull(vendorInfo); + } + + private Announcement(@NonNull Parcel in) { + mSelector = in.readTypedObject(ProgramSelector.CREATOR); + mType = in.readInt(); + mVendorInfo = Utils.readStringMap(in); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeTypedObject(mSelector, 0); + dest.writeInt(mType); + Utils.writeStringMap(dest, mVendorInfo); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<Announcement> CREATOR = + new Parcelable.Creator<Announcement>() { + public Announcement createFromParcel(Parcel in) { + return new Announcement(in); + } + + public Announcement[] newArray(int size) { + return new Announcement[size]; + } + }; + + public @NonNull ProgramSelector getSelector() { + return mSelector; + } + + public @Type int getType() { + return mType; + } + + public @NonNull Map<String, String> getVendorInfo() { + return mVendorInfo; + } +} diff --git a/core/java/android/hardware/radio/IAnnouncementListener.aidl b/core/java/android/hardware/radio/IAnnouncementListener.aidl new file mode 100644 index 000000000000..b4d974a37ede --- /dev/null +++ b/core/java/android/hardware/radio/IAnnouncementListener.aidl @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2018 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.hardware.radio.Announcement; + +/** {@hide} */ +oneway interface IAnnouncementListener { + void onListUpdated(in List<Announcement> activeAnnouncements); +} diff --git a/core/java/android/hardware/radio/ICloseHandle.aidl b/core/java/android/hardware/radio/ICloseHandle.aidl new file mode 100644 index 000000000000..576c03b0db84 --- /dev/null +++ b/core/java/android/hardware/radio/ICloseHandle.aidl @@ -0,0 +1,22 @@ +/** + * Copyright (C) 2018 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; + +/** {@hide} */ +interface ICloseHandle { + void close(); +} diff --git a/core/java/android/hardware/radio/IRadioService.aidl b/core/java/android/hardware/radio/IRadioService.aidl index c43fd2615e44..9349cf7d0c32 100644 --- a/core/java/android/hardware/radio/IRadioService.aidl +++ b/core/java/android/hardware/radio/IRadioService.aidl @@ -16,6 +16,8 @@ package android.hardware.radio; +import android.hardware.radio.IAnnouncementListener; +import android.hardware.radio.ICloseHandle; import android.hardware.radio.ITuner; import android.hardware.radio.ITunerCallback; import android.hardware.radio.RadioManager; @@ -30,4 +32,7 @@ interface IRadioService { ITuner openTuner(int moduleId, in RadioManager.BandConfig bandConfig, boolean withAudio, in ITunerCallback callback); + + ICloseHandle addAnnouncementListener(in int[] enabledTypes, + in IAnnouncementListener listener); } diff --git a/core/java/android/hardware/radio/RadioManager.java b/core/java/android/hardware/radio/RadioManager.java index 56668ac00527..c2197593b413 100644 --- a/core/java/android/hardware/radio/RadioManager.java +++ b/core/java/android/hardware/radio/RadioManager.java @@ -17,6 +17,7 @@ package android.hardware.radio; import android.Manifest; +import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; @@ -40,6 +41,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.concurrent.Executor; import java.util.stream.Collectors; /** @@ -1713,6 +1715,68 @@ public class RadioManager { config != null ? config.getType() : BAND_INVALID); } + private final Map<Announcement.OnListUpdatedListener, ICloseHandle> mAnnouncementListeners = + new HashMap<>(); + + /** + * Adds new announcement listener. + * + * @param enabledAnnouncementTypes a set of announcement types to listen to + * @param listener announcement listener + */ + @RequiresPermission(Manifest.permission.ACCESS_BROADCAST_RADIO) + public void addAnnouncementListener(@NonNull Set<Integer> enabledAnnouncementTypes, + @NonNull Announcement.OnListUpdatedListener listener) { + addAnnouncementListener(cmd -> cmd.run(), enabledAnnouncementTypes, listener); + } + + /** + * Adds new announcement listener with executor. + * + * @param executor the executor + * @param enabledAnnouncementTypes a set of announcement types to listen to + * @param listener announcement listener + */ + @RequiresPermission(Manifest.permission.ACCESS_BROADCAST_RADIO) + public void addAnnouncementListener(@NonNull @CallbackExecutor Executor executor, + @NonNull Set<Integer> enabledAnnouncementTypes, + @NonNull Announcement.OnListUpdatedListener listener) { + Objects.requireNonNull(executor); + Objects.requireNonNull(listener); + int[] types = enabledAnnouncementTypes.stream().mapToInt(Integer::intValue).toArray(); + IAnnouncementListener listenerIface = new IAnnouncementListener.Stub() { + public void onListUpdated(List<Announcement> activeAnnouncements) { + executor.execute(() -> listener.onListUpdated(activeAnnouncements)); + } + }; + synchronized (mAnnouncementListeners) { + ICloseHandle closeHandle = null; + try { + closeHandle = mService.addAnnouncementListener(types, listenerIface); + } catch (RemoteException ex) { + ex.rethrowFromSystemServer(); + } + Objects.requireNonNull(closeHandle); + ICloseHandle oldCloseHandle = mAnnouncementListeners.put(listener, closeHandle); + if (oldCloseHandle != null) Utils.close(oldCloseHandle); + } + } + + /** + * Removes previously registered announcement listener. + * + * @param listener announcement listener, previously registered with + * {@link addAnnouncementListener} + */ + @RequiresPermission(Manifest.permission.ACCESS_BROADCAST_RADIO) + public void removeAnnouncementListener(@NonNull Announcement.OnListUpdatedListener listener) { + Objects.requireNonNull(listener); + synchronized (mAnnouncementListeners) { + ICloseHandle closeHandle = mAnnouncementListeners.remove(listener); + if (closeHandle != null) Utils.close(closeHandle); + } + } + @NonNull private final Context mContext; @NonNull private final IRadioService mService; diff --git a/core/java/android/hardware/radio/Utils.java b/core/java/android/hardware/radio/Utils.java index 09bf8feb30c2..a80bbf208fe3 100644 --- a/core/java/android/hardware/radio/Utils.java +++ b/core/java/android/hardware/radio/Utils.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; +import android.os.RemoteException; import java.util.HashMap; import java.util.HashSet; @@ -28,6 +29,8 @@ import java.util.Objects; import java.util.Set; final class Utils { + private static final String TAG = "BroadcastRadio.utils"; + static void writeStringMap(@NonNull Parcel dest, @Nullable Map<String, String> map) { if (map == null) { dest.writeInt(0); @@ -89,4 +92,12 @@ final class Utils { } }); } + + static void close(ICloseHandle handle) { + try { + handle.close(); + } catch (RemoteException ex) { + ex.rethrowFromSystemServer(); + } + } } |
