• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
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 
17 package com.android.server.broadcastradio.hal1;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.hardware.radio.ITunerCallback;
22 import android.hardware.radio.ProgramList;
23 import android.hardware.radio.ProgramSelector;
24 import android.hardware.radio.RadioManager;
25 import android.hardware.radio.RadioTuner;
26 import android.os.IBinder;
27 import android.os.RemoteException;
28 import android.util.Slog;
29 
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.concurrent.atomic.AtomicReference;
34 import java.util.stream.Collectors;
35 
36 class TunerCallback implements ITunerCallback {
37     private static final String TAG = "BroadcastRadioService.TunerCallback";
38 
39     /**
40      * This field is used by native code, do not access or modify.
41      */
42     private final long mNativeContext;
43 
44     @NonNull private final Tuner mTuner;
45     @NonNull private final ITunerCallback mClientCallback;
46 
47     private final AtomicReference<ProgramList.Filter> mProgramListFilter = new AtomicReference<>();
48     private boolean mInitialConfigurationDone = false;
49 
TunerCallback(@onNull Tuner tuner, @NonNull ITunerCallback clientCallback, int halRev)50     TunerCallback(@NonNull Tuner tuner, @NonNull ITunerCallback clientCallback, int halRev) {
51         mTuner = tuner;
52         mClientCallback = clientCallback;
53         mNativeContext = nativeInit(tuner, halRev);
54     }
55 
56     @Override
finalize()57     protected void finalize() throws Throwable {
58         nativeFinalize(mNativeContext);
59         super.finalize();
60     }
61 
nativeInit(@onNull Tuner tuner, int halRev)62     private native long nativeInit(@NonNull Tuner tuner, int halRev);
nativeFinalize(long nativeContext)63     private native void nativeFinalize(long nativeContext);
nativeDetach(long nativeContext)64     private native void nativeDetach(long nativeContext);
65 
detach()66     public void detach() {
67         nativeDetach(mNativeContext);
68     }
69 
70     private interface RunnableThrowingRemoteException {
run()71         void run() throws RemoteException;
72     }
73 
dispatch(RunnableThrowingRemoteException func)74     private void dispatch(RunnableThrowingRemoteException func) {
75         try {
76             func.run();
77         } catch (RemoteException e) {
78             Slog.e(TAG, "client died", e);
79         }
80     }
81 
82     // called from native side
handleHwFailure()83     private void handleHwFailure() {
84         onError(RadioTuner.ERROR_HARDWARE_FAILURE);
85         mTuner.close();
86     }
87 
startProgramListUpdates(@ullable ProgramList.Filter filter)88     void startProgramListUpdates(@Nullable ProgramList.Filter filter) {
89         if (filter == null) filter = new ProgramList.Filter();
90         mProgramListFilter.set(filter);
91         sendProgramListUpdate();
92     }
93 
stopProgramListUpdates()94     void stopProgramListUpdates() {
95         mProgramListFilter.set(null);
96     }
97 
isInitialConfigurationDone()98     boolean isInitialConfigurationDone() {
99         return mInitialConfigurationDone;
100     }
101 
102     @Override
onError(int status)103     public void onError(int status) {
104         dispatch(() -> mClientCallback.onError(status));
105     }
106 
107     @Override
onTuneFailed(int result, ProgramSelector selector)108     public void onTuneFailed(int result, ProgramSelector selector) {
109         Slog.e(TAG, "Not applicable for HAL 1.x");
110     }
111 
112     @Override
onConfigurationChanged(RadioManager.BandConfig config)113     public void onConfigurationChanged(RadioManager.BandConfig config) {
114         mInitialConfigurationDone = true;
115         dispatch(() -> mClientCallback.onConfigurationChanged(config));
116     }
117 
118     @Override
onCurrentProgramInfoChanged(RadioManager.ProgramInfo info)119     public void onCurrentProgramInfoChanged(RadioManager.ProgramInfo info) {
120         dispatch(() -> mClientCallback.onCurrentProgramInfoChanged(info));
121     }
122 
123     @Override
onTrafficAnnouncement(boolean active)124     public void onTrafficAnnouncement(boolean active) {
125         dispatch(() -> mClientCallback.onTrafficAnnouncement(active));
126     }
127 
128     @Override
onEmergencyAnnouncement(boolean active)129     public void onEmergencyAnnouncement(boolean active) {
130         dispatch(() -> mClientCallback.onEmergencyAnnouncement(active));
131     }
132 
133     @Override
onAntennaState(boolean connected)134     public void onAntennaState(boolean connected) {
135         dispatch(() -> mClientCallback.onAntennaState(connected));
136     }
137 
138     @Override
onBackgroundScanAvailabilityChange(boolean isAvailable)139     public void onBackgroundScanAvailabilityChange(boolean isAvailable) {
140         dispatch(() -> mClientCallback.onBackgroundScanAvailabilityChange(isAvailable));
141     }
142 
143     @Override
onBackgroundScanComplete()144     public void onBackgroundScanComplete() {
145         dispatch(() -> mClientCallback.onBackgroundScanComplete());
146     }
147 
148     @Override
onProgramListChanged()149     public void onProgramListChanged() {
150         dispatch(() -> mClientCallback.onProgramListChanged());
151         sendProgramListUpdate();
152     }
153 
sendProgramListUpdate()154     private void sendProgramListUpdate() {
155         ProgramList.Filter filter = mProgramListFilter.get();
156         if (filter == null) return;
157 
158         List<RadioManager.ProgramInfo> modified;
159         try {
160             modified = mTuner.getProgramList(filter.getVendorFilter());
161         } catch (IllegalStateException ex) {
162             Slog.d(TAG, "Program list not ready yet");
163             return;
164         }
165         Set<RadioManager.ProgramInfo> modifiedSet = modified.stream().collect(Collectors.toSet());
166         ProgramList.Chunk chunk = new ProgramList.Chunk(true, true, modifiedSet, null);
167         dispatch(() -> mClientCallback.onProgramListUpdated(chunk));
168     }
169 
170     @Override
onProgramListUpdated(ProgramList.Chunk chunk)171     public void onProgramListUpdated(ProgramList.Chunk chunk) {
172         dispatch(() -> mClientCallback.onProgramListUpdated(chunk));
173     }
174 
175     @Override
onParametersUpdated(Map<String, String> parameters)176     public void onParametersUpdated(Map<String, String> parameters) {
177         Slog.e(TAG, "Not applicable for HAL 1.x");
178     }
179 
180     @Override
asBinder()181     public IBinder asBinder() {
182         throw new RuntimeException("Not a binder");
183     }
184 }
185