blob: b299ffe042b2538bbfb78921b930ee8be0891240 [file] [log] [blame]
Tomasz Wasilczyk21348172017-04-20 14:02:42 -07001/**
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 android.hardware.radio;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.os.Handler;
22import android.os.Looper;
Tomasz Wasilczyk24250ef2017-07-13 15:59:08 -070023import android.util.Log;
Tomasz Wasilczyk21348172017-04-20 14:02:42 -070024
Tomasz Wasilczyk436128f2018-01-08 16:46:09 -080025import java.util.List;
Tomasz Wasilczyk8e932c62017-11-17 16:18:40 +000026import java.util.Map;
Tomasz Wasilczyk436128f2018-01-08 16:46:09 -080027import java.util.Objects;
Tomasz Wasilczyk8e932c62017-11-17 16:18:40 +000028
Tomasz Wasilczyk21348172017-04-20 14:02:42 -070029/**
30 * Implements the ITunerCallback interface by forwarding calls to RadioTuner.Callback.
31 */
32class TunerCallbackAdapter extends ITunerCallback.Stub {
Tomasz Wasilczyk6b4b6462017-07-19 10:52:28 -070033 private static final String TAG = "BroadcastRadio.TunerCallbackAdapter";
Tomasz Wasilczyk24250ef2017-07-13 15:59:08 -070034
Tomasz Wasilczyk436128f2018-01-08 16:46:09 -080035 private final Object mLock = new Object();
Tomasz Wasilczyk21348172017-04-20 14:02:42 -070036 @NonNull private final RadioTuner.Callback mCallback;
37 @NonNull private final Handler mHandler;
38
Tomasz Wasilczyk436128f2018-01-08 16:46:09 -080039 @Nullable ProgramList mProgramList;
40 @Nullable List<RadioManager.ProgramInfo> mLastCompleteList; // for legacy getProgramList call
41 private boolean mDelayedCompleteCallback = false;
42
Tomasz Wasilczyk21348172017-04-20 14:02:42 -070043 TunerCallbackAdapter(@NonNull RadioTuner.Callback callback, @Nullable Handler handler) {
44 mCallback = callback;
45 if (handler == null) {
46 mHandler = new Handler(Looper.getMainLooper());
47 } else {
48 mHandler = handler;
49 }
50 }
51
Tomasz Wasilczyk436128f2018-01-08 16:46:09 -080052 void setProgramListObserver(@Nullable ProgramList programList,
53 @NonNull ProgramList.OnCloseListener closeListener) {
54 Objects.requireNonNull(closeListener);
55 synchronized (mLock) {
56 if (mProgramList != null) {
57 Log.w(TAG, "Previous program list observer wasn't properly closed, closing it...");
58 mProgramList.close();
59 }
60 mProgramList = programList;
61 if (programList == null) return;
62 programList.setOnCloseListener(() -> {
63 synchronized (mLock) {
64 if (mProgramList != programList) return;
65 mProgramList = null;
66 mLastCompleteList = null;
67 closeListener.onClose();
68 }
69 });
70 programList.addOnCompleteListener(() -> {
71 synchronized (mLock) {
72 if (mProgramList != programList) return;
73 mLastCompleteList = programList.toList();
74 if (mDelayedCompleteCallback) {
75 Log.d(TAG, "Sending delayed onBackgroundScanComplete callback");
76 sendBackgroundScanCompleteLocked();
77 }
78 }
79 });
80 }
81 }
82
83 @Nullable List<RadioManager.ProgramInfo> getLastCompleteList() {
84 synchronized (mLock) {
85 return mLastCompleteList;
86 }
87 }
88
89 void clearLastCompleteList() {
90 synchronized (mLock) {
91 mLastCompleteList = null;
92 }
93 }
94
Tomasz Wasilczyk21348172017-04-20 14:02:42 -070095 @Override
96 public void onError(int status) {
97 mHandler.post(() -> mCallback.onError(status));
98 }
99
100 @Override
101 public void onConfigurationChanged(RadioManager.BandConfig config) {
102 mHandler.post(() -> mCallback.onConfigurationChanged(config));
103 }
Tomasz Wasilczyk23837932017-05-05 08:42:10 -0700104
105 @Override
Tomasz Wasilczyk162d14a2017-08-03 18:10:45 -0700106 public void onCurrentProgramInfoChanged(RadioManager.ProgramInfo info) {
107 if (info == null) {
108 Log.e(TAG, "ProgramInfo must not be null");
Tomasz Wasilczyk24250ef2017-07-13 15:59:08 -0700109 return;
110 }
111
112 mHandler.post(() -> {
113 mCallback.onProgramInfoChanged(info);
114
115 RadioMetadata metadata = info.getMetadata();
116 if (metadata != null) mCallback.onMetadataChanged(metadata);
117 });
Tomasz Wasilczykc9a1ac72017-05-17 21:29:28 -0700118 }
119
120 @Override
121 public void onTrafficAnnouncement(boolean active) {
122 mHandler.post(() -> mCallback.onTrafficAnnouncement(active));
123 }
124
125 @Override
126 public void onEmergencyAnnouncement(boolean active) {
127 mHandler.post(() -> mCallback.onEmergencyAnnouncement(active));
128 }
129
130 @Override
131 public void onAntennaState(boolean connected) {
132 mHandler.post(() -> mCallback.onAntennaState(connected));
133 }
134
135 @Override
136 public void onBackgroundScanAvailabilityChange(boolean isAvailable) {
137 mHandler.post(() -> mCallback.onBackgroundScanAvailabilityChange(isAvailable));
138 }
139
Tomasz Wasilczyk436128f2018-01-08 16:46:09 -0800140 private void sendBackgroundScanCompleteLocked() {
141 mDelayedCompleteCallback = false;
142 mHandler.post(() -> mCallback.onBackgroundScanComplete());
143 }
144
Tomasz Wasilczykc9a1ac72017-05-17 21:29:28 -0700145 @Override
146 public void onBackgroundScanComplete() {
Tomasz Wasilczyk436128f2018-01-08 16:46:09 -0800147 synchronized (mLock) {
148 if (mLastCompleteList == null) {
149 Log.i(TAG, "Got onBackgroundScanComplete callback, but the "
150 + "program list didn't get through yet. Delaying it...");
151 mDelayedCompleteCallback = true;
152 return;
153 }
154 sendBackgroundScanCompleteLocked();
155 }
Tomasz Wasilczykc9a1ac72017-05-17 21:29:28 -0700156 }
157
158 @Override
159 public void onProgramListChanged() {
160 mHandler.post(() -> mCallback.onProgramListChanged());
161 }
Tomasz Wasilczyk8e932c62017-11-17 16:18:40 +0000162
163 @Override
Tomasz Wasilczyk436128f2018-01-08 16:46:09 -0800164 public void onProgramListUpdated(ProgramList.Chunk chunk) {
165 synchronized (mLock) {
166 if (mProgramList == null) return;
167 mProgramList.apply(Objects.requireNonNull(chunk));
168 }
169 }
170
171 @Override
Tomasz Wasilczyk8e932c62017-11-17 16:18:40 +0000172 public void onParametersUpdated(Map parameters) {
173 mHandler.post(() -> mCallback.onParametersUpdated(parameters));
174 }
Tomasz Wasilczyk21348172017-04-20 14:02:42 -0700175}