blob: 1ae7d20fb3fea694bc32954d1412f62a1509e27f [file] [log] [blame]
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -08001/**
2 * Copyright (C) 2017 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.graphics.Bitmap;
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -080021import android.hardware.broadcastradio.V2_0.ConfigFlag;
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -080022import android.hardware.broadcastradio.V2_0.ITunerSession;
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -080023import android.hardware.broadcastradio.V2_0.Result;
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -080024import android.hardware.radio.ITuner;
Tomasz Wasilczyk436128f2018-01-08 16:46:09 -080025import android.hardware.radio.ProgramList;
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -080026import android.hardware.radio.ProgramSelector;
27import android.hardware.radio.RadioManager;
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -080028import android.media.AudioSystem;
29import android.os.RemoteException;
30import android.util.MutableBoolean;
31import android.util.MutableInt;
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -080032import android.util.Slog;
33
34import java.util.List;
35import java.util.Map;
36import java.util.Objects;
37
38class TunerSession extends ITuner.Stub {
39 private static final String TAG = "BcRadio2Srv.session";
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -080040 private static final String kAudioDeviceName = "Radio tuner source";
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -080041
42 private final Object mLock = new Object();
43
44 private final ITunerSession mHwSession;
45 private final TunerCallback mCallback;
46 private boolean mIsClosed = false;
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -080047 private boolean mIsAudioConnected = false;
48 private boolean mIsMuted = false;
49
50 // necessary only for older APIs compatibility
51 private RadioManager.BandConfig mDummyConfig = null;
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -080052
53 TunerSession(@NonNull ITunerSession hwSession, @NonNull TunerCallback callback) {
54 mHwSession = Objects.requireNonNull(hwSession);
55 mCallback = Objects.requireNonNull(callback);
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -080056 notifyAudioServiceLocked(true);
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -080057 }
58
59 @Override
60 public void close() {
61 synchronized (mLock) {
62 if (mIsClosed) return;
63 mIsClosed = true;
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -080064 notifyAudioServiceLocked(false);
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -080065 }
66 }
67
68 @Override
69 public boolean isClosed() {
70 return mIsClosed;
71 }
72
73 private void checkNotClosedLocked() {
74 if (mIsClosed) {
75 throw new IllegalStateException("Tuner is closed, no further operations are allowed");
76 }
77 }
78
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -080079 private void notifyAudioServiceLocked(boolean connected) {
80 if (mIsAudioConnected == connected) return;
81
82 Slog.d(TAG, "Notifying AudioService about new state: " + connected);
83 int ret = AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_FM_TUNER,
84 connected ? AudioSystem.DEVICE_STATE_AVAILABLE : AudioSystem.DEVICE_STATE_UNAVAILABLE,
85 null, kAudioDeviceName);
86
87 if (ret == AudioSystem.AUDIO_STATUS_OK) {
88 mIsAudioConnected = connected;
89 } else {
90 Slog.e(TAG, "Failed to notify AudioService about new state: " + connected);
91 }
92 }
93
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -080094 @Override
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -080095 public void setConfiguration(RadioManager.BandConfig config) {
96 synchronized (mLock) {
97 checkNotClosedLocked();
98 mDummyConfig = Objects.requireNonNull(config);
99 Slog.i(TAG, "Ignoring setConfiguration - not applicable for broadcastradio HAL 2.x");
100 TunerCallback.dispatch(() -> mCallback.mClientCb.onConfigurationChanged(config));
101 }
102 }
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800103
104 @Override
105 public RadioManager.BandConfig getConfiguration() {
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800106 synchronized (mLock) {
107 checkNotClosedLocked();
108 return mDummyConfig;
109 }
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800110 }
111
112 @Override
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800113 public void setMuted(boolean mute) {
114 synchronized (mLock) {
115 checkNotClosedLocked();
116 if (mIsMuted == mute) return;
117 mIsMuted = mute;
118 notifyAudioServiceLocked(!mute);
119 }
120 }
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800121
122 @Override
123 public boolean isMuted() {
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800124 synchronized (mLock) {
125 checkNotClosedLocked();
126 return mIsMuted;
127 }
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800128 }
129
130 @Override
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800131 public void step(boolean directionDown, boolean skipSubChannel) {
132 synchronized (mLock) {
133 checkNotClosedLocked();
134 }
135 }
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800136
137 @Override
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800138 public void scan(boolean directionDown, boolean skipSubChannel) {
139 synchronized (mLock) {
140 checkNotClosedLocked();
141 }
142 }
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800143
144 @Override
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800145 public void tune(ProgramSelector selector) {
146 synchronized (mLock) {
147 checkNotClosedLocked();
148 }
149 }
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800150
151 @Override
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800152 public void cancel() {
153 synchronized (mLock) {
154 checkNotClosedLocked();
155 }
156 }
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800157
158 @Override
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800159 public void cancelAnnouncement() {
160 synchronized (mLock) {
161 checkNotClosedLocked();
162 }
163 }
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800164
165 @Override
166 public RadioManager.ProgramInfo getProgramInformation() {
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800167 synchronized (mLock) {
168 checkNotClosedLocked();
169 return null;
170 }
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800171 }
172
173 @Override
174 public Bitmap getImage(int id) {
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800175 synchronized (mLock) {
176 checkNotClosedLocked();
177 return null;
178 }
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800179 }
180
181 @Override
182 public boolean startBackgroundScan() {
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800183 Slog.i(TAG, "Explicit background scan trigger is not supported with HAL 2.x");
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800184 return false;
185 }
186
187 @Override
Tomasz Wasilczyk436128f2018-01-08 16:46:09 -0800188 public void startProgramListUpdates(ProgramList.Filter filter) throws RemoteException {
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800189 synchronized (mLock) {
190 checkNotClosedLocked();
Tomasz Wasilczyk436128f2018-01-08 16:46:09 -0800191 int halResult = mHwSession.startProgramListUpdates(Convert.programFilterToHal(filter));
192 Convert.throwOnError("startProgramListUpdates", halResult);
193 }
194 }
195
196 @Override
197 public void stopProgramListUpdates() throws RemoteException {
198 synchronized (mLock) {
199 checkNotClosedLocked();
200 mHwSession.stopProgramListUpdates();
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800201 }
202 }
203
Tomasz Wasilczykce40fe92018-01-04 20:52:39 -0800204 @Override
205 public boolean isConfigFlagSupported(int flag) {
206 try {
207 isConfigFlagSet(flag);
208 return true;
209 } catch (IllegalStateException ex) {
210 return true;
211 } catch (UnsupportedOperationException ex) {
212 return false;
213 }
214 }
215
216 @Override
217 public boolean isConfigFlagSet(int flag) {
218 Slog.v(TAG, "isConfigFlagSet " + ConfigFlag.toString(flag));
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800219 synchronized (mLock) {
220 checkNotClosedLocked();
221
222 MutableInt halResult = new MutableInt(Result.UNKNOWN_ERROR);
223 MutableBoolean flagState = new MutableBoolean(false);
224 try {
Tomasz Wasilczyk3097cbf2018-01-12 14:59:13 -0800225 mHwSession.isConfigFlagSet(flag, (int result, boolean value) -> {
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800226 halResult.value = result;
227 flagState.value = value;
228 });
229 } catch (RemoteException ex) {
Tomasz Wasilczykce40fe92018-01-04 20:52:39 -0800230 throw new RuntimeException("Failed to check flag " + ConfigFlag.toString(flag), ex);
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800231 }
Tomasz Wasilczykce40fe92018-01-04 20:52:39 -0800232 Convert.throwOnError("isConfigFlagSet", halResult.value);
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800233
234 return flagState.value;
235 }
236 }
237
Tomasz Wasilczykce40fe92018-01-04 20:52:39 -0800238 @Override
Tomasz Wasilczyk436128f2018-01-08 16:46:09 -0800239 public void setConfigFlag(int flag, boolean value) throws RemoteException {
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800240 Slog.v(TAG, "setConfigFlag " + ConfigFlag.toString(flag) + " = " + value);
241 synchronized (mLock) {
242 checkNotClosedLocked();
243
Tomasz Wasilczyk436128f2018-01-08 16:46:09 -0800244 int halResult = mHwSession.setConfigFlag(flag, value);
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800245 Convert.throwOnError("setConfigFlag", halResult);
246 }
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800247 }
248
249 @Override
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800250 public Map setParameters(Map parameters) {
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800251 synchronized (mLock) {
252 checkNotClosedLocked();
253 return null;
254 }
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800255 }
256
257 @Override
258 public Map getParameters(List<String> keys) {
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800259 synchronized (mLock) {
260 checkNotClosedLocked();
261 return null;
262 }
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800263 }
264
265 @Override
266 public boolean isAntennaConnected() {
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800267 synchronized (mLock) {
268 checkNotClosedLocked();
269 return true;
270 }
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -0800271 }
272}