blob: 0bbaf25aaa1252454e6f0c76e30795025d6b8d78 [file] [log] [blame]
Tomasz Wasilczykf151a7b2018-01-11 16:03:46 -08001/**
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.broadcastradio.hal2;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.hardware.radio.Announcement;
22import android.hardware.radio.IAnnouncementListener;
23import android.hardware.radio.ICloseHandle;
24import android.os.IBinder;
25import android.os.RemoteException;
26import android.util.Slog;
27
28import com.android.internal.annotations.GuardedBy;
29
30import java.util.ArrayList;
31import java.util.Collection;
32import java.util.List;
33import java.util.Objects;
34
35public class AnnouncementAggregator extends ICloseHandle.Stub {
36 private static final String TAG = "BcRadio2Srv.AnnAggr";
37
38 private final Object mLock = new Object();
39 @NonNull private final IAnnouncementListener mListener;
40 private final IBinder.DeathRecipient mDeathRecipient = new DeathRecipient();
41
42 @GuardedBy("mLock")
43 private final Collection<ModuleWatcher> mModuleWatchers = new ArrayList<>();
44
45 @GuardedBy("mLock")
46 private boolean mIsClosed = false;
47
48 public AnnouncementAggregator(@NonNull IAnnouncementListener listener) {
49 mListener = Objects.requireNonNull(listener);
50 try {
51 listener.asBinder().linkToDeath(mDeathRecipient, 0);
52 } catch (RemoteException ex) {
53 ex.rethrowFromSystemServer();
54 }
55 }
56
57 private class ModuleWatcher extends IAnnouncementListener.Stub {
58 private @Nullable ICloseHandle mCloseHandle;
59 public @NonNull List<Announcement> currentList = new ArrayList<>();
60
61 public void onListUpdated(List<Announcement> active) {
62 currentList = Objects.requireNonNull(active);
63 AnnouncementAggregator.this.onListUpdated();
64 }
65
66 public void setCloseHandle(@NonNull ICloseHandle closeHandle) {
67 mCloseHandle = Objects.requireNonNull(closeHandle);
68 }
69
70 public void close() throws RemoteException {
71 if (mCloseHandle != null) mCloseHandle.close();
72 }
73 }
74
75 private class DeathRecipient implements IBinder.DeathRecipient {
76 public void binderDied() {
77 try {
78 close();
79 } catch (RemoteException ex) {}
80 }
81 }
82
83 private void onListUpdated() {
84 synchronized (mLock) {
85 if (mIsClosed) {
86 Slog.e(TAG, "Announcement aggregator is closed, it shouldn't receive callbacks");
87 return;
88 }
89 List<Announcement> combined = new ArrayList<>();
90 for (ModuleWatcher watcher : mModuleWatchers) {
91 combined.addAll(watcher.currentList);
92 }
93 TunerCallback.dispatch(() -> mListener.onListUpdated(combined));
94 }
95 }
96
97 public void watchModule(@NonNull RadioModule module, @NonNull int[] enabledTypes) {
98 synchronized (mLock) {
99 if (mIsClosed) throw new IllegalStateException();
100
101 ModuleWatcher watcher = new ModuleWatcher();
102 ICloseHandle closeHandle;
103 try {
104 closeHandle = module.addAnnouncementListener(enabledTypes, watcher);
105 } catch (RemoteException ex) {
106 Slog.e(TAG, "Failed to add announcement listener", ex);
107 return;
108 }
109 watcher.setCloseHandle(closeHandle);
110 mModuleWatchers.add(watcher);
111 }
112 }
113
114 @Override
115 public void close() throws RemoteException {
116 synchronized (mLock) {
117 if (mIsClosed) return;
118 mIsClosed = true;
119
120 mListener.asBinder().unlinkToDeath(mDeathRecipient, 0);
121
122 for (ModuleWatcher watcher : mModuleWatchers) {
123 watcher.close();
124 }
125 mModuleWatchers.clear();
126 }
127 }
128}