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
17package com.android.server.broadcastradio;
18
19import android.annotation.NonNull;
20import android.hardware.radio.ITuner;
21import android.hardware.radio.ITunerCallback;
22import android.hardware.radio.RadioManager;
23import android.hardware.radio.RadioMetadata;
24import android.hardware.radio.RadioTuner;
25import android.os.IBinder;
26import android.os.RemoteException;
27import android.util.Slog;
28
29class TunerCallback implements ITunerCallback {
30    private static final String TAG = "BroadcastRadioService.TunerCallback";
31
32    /**
33     * This field is used by native code, do not access or modify.
34     */
35    private final long mNativeContext;
36
37    @NonNull private final Tuner mTuner;
38    @NonNull private final ITunerCallback mClientCallback;
39
40    TunerCallback(@NonNull Tuner tuner, @NonNull ITunerCallback clientCallback, int halRev) {
41        mTuner = tuner;
42        mClientCallback = clientCallback;
43        mNativeContext = nativeInit(tuner, halRev);
44    }
45
46    @Override
47    protected void finalize() throws Throwable {
48        nativeFinalize(mNativeContext);
49        super.finalize();
50    }
51
52    private native long nativeInit(@NonNull Tuner tuner, int halRev);
53    private native void nativeFinalize(long nativeContext);
54    private native void nativeDetach(long nativeContext);
55
56    public void detach() {
57        nativeDetach(mNativeContext);
58    }
59
60    private interface RunnableThrowingRemoteException {
61        void run() throws RemoteException;
62    }
63
64    private void dispatch(RunnableThrowingRemoteException func) {
65        try {
66            func.run();
67        } catch (RemoteException e) {
68            Slog.e(TAG, "client died", e);
69        }
70    }
71
72    // called from native side
73    private void handleHwFailure() {
74        onError(RadioTuner.ERROR_HARDWARE_FAILURE);
75        mTuner.close();
76    }
77
78    @Override
79    public void onError(int status) {
80        dispatch(() -> mClientCallback.onError(status));
81    }
82
83    @Override
84    public void onConfigurationChanged(RadioManager.BandConfig config) {
85        dispatch(() -> mClientCallback.onConfigurationChanged(config));
86    }
87
88    @Override
89    public void onCurrentProgramInfoChanged(RadioManager.ProgramInfo info) {
90        dispatch(() -> mClientCallback.onCurrentProgramInfoChanged(info));
91    }
92
93    @Override
94    public void onTrafficAnnouncement(boolean active) {
95        dispatch(() -> mClientCallback.onTrafficAnnouncement(active));
96    }
97
98    @Override
99    public void onEmergencyAnnouncement(boolean active) {
100        dispatch(() -> mClientCallback.onEmergencyAnnouncement(active));
101    }
102
103    @Override
104    public void onAntennaState(boolean connected) {
105        dispatch(() -> mClientCallback.onAntennaState(connected));
106    }
107
108    @Override
109    public void onBackgroundScanAvailabilityChange(boolean isAvailable) {
110        dispatch(() -> mClientCallback.onBackgroundScanAvailabilityChange(isAvailable));
111    }
112
113    @Override
114    public void onBackgroundScanComplete() {
115        dispatch(() -> mClientCallback.onBackgroundScanComplete());
116    }
117
118    @Override
119    public void onProgramListChanged() {
120        dispatch(() -> mClientCallback.onProgramListChanged());
121    }
122
123    @Override
124    public IBinder asBinder() {
125        throw new RuntimeException("Not a binder");
126    }
127}
128