1347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk/**
2347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk * Copyright (C) 2017 The Android Open Source Project
3347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk *
4347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk * Licensed under the Apache License, Version 2.0 (the "License");
5347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk * you may not use this file except in compliance with the License.
6347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk * You may obtain a copy of the License at
7347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk *
8347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk *      http://www.apache.org/licenses/LICENSE-2.0
9347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk *
10347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk * Unless required by applicable law or agreed to in writing, software
11347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk * distributed under the License is distributed on an "AS IS" BASIS,
12347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk * See the License for the specific language governing permissions and
14347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk * limitations under the License.
15347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk */
16347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
17347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczykpackage android.hardware.radio;
18347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
19347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczykimport android.annotation.NonNull;
20347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczykimport android.annotation.Nullable;
214482b1413656b9c0c5937b4d7a73235f872a6678Tomasz Wasilczykimport android.graphics.Bitmap;
22347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczykimport android.os.RemoteException;
23347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczykimport android.util.Log;
24347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
25347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczykimport java.util.List;
260f1776d08b43f5f71a9f89b6a4f1838df4d3d744Tomasz Wasilczykimport java.util.Map;
278e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczykimport java.util.Objects;
28347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
29347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk/**
30347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk * Implements the RadioTuner interface by forwarding calls to radio service.
31347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk */
32347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczykclass TunerAdapter extends RadioTuner {
336b4b646d9c0fa42973a429dbe78c8919a2772961Tomasz Wasilczyk    private static final String TAG = "BroadcastRadio.TunerAdapter";
34347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
35347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @NonNull private final ITuner mTuner;
36436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk    @NonNull private final TunerCallbackAdapter mCallback;
37d7c21d3cbfe8e1016a92234f89d6fe8c110144d1Tomasz Wasilczyk    private boolean mIsClosed = false;
38347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
398cfb0e81fdd91b7fe1c02287394ac068287281d5Tomasz Wasilczyk    private @RadioManager.Band int mBand;
408cfb0e81fdd91b7fe1c02287394ac068287281d5Tomasz Wasilczyk
41436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk    private ProgramList mLegacyListProxy;
42436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk    private Map<String, String> mLegacyListFilter;
43436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk
44436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk    TunerAdapter(@NonNull ITuner tuner, @NonNull TunerCallbackAdapter callback,
45436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            @RadioManager.Band int band) {
46436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk        mTuner = Objects.requireNonNull(tuner);
47436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk        mCallback = Objects.requireNonNull(callback);
488cfb0e81fdd91b7fe1c02287394ac068287281d5Tomasz Wasilczyk        mBand = band;
49347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
50347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
51347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
52347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    public void close() {
53d7c21d3cbfe8e1016a92234f89d6fe8c110144d1Tomasz Wasilczyk        synchronized (mTuner) {
54d7c21d3cbfe8e1016a92234f89d6fe8c110144d1Tomasz Wasilczyk            if (mIsClosed) {
5514752375d74908632195a875f32a2b5fd1e719efTomasz Wasilczyk                Log.v(TAG, "Tuner is already closed");
56d7c21d3cbfe8e1016a92234f89d6fe8c110144d1Tomasz Wasilczyk                return;
57d7c21d3cbfe8e1016a92234f89d6fe8c110144d1Tomasz Wasilczyk            }
58d7c21d3cbfe8e1016a92234f89d6fe8c110144d1Tomasz Wasilczyk            mIsClosed = true;
59436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            if (mLegacyListProxy != null) {
60436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                mLegacyListProxy.close();
61436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                mLegacyListProxy = null;
62436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            }
63d0c78f9f28599ac97dbca06c1634238f9b25be40Tomasz Wasilczyk            mCallback.close();
64d7c21d3cbfe8e1016a92234f89d6fe8c110144d1Tomasz Wasilczyk        }
65d7c21d3cbfe8e1016a92234f89d6fe8c110144d1Tomasz Wasilczyk        try {
66d7c21d3cbfe8e1016a92234f89d6fe8c110144d1Tomasz Wasilczyk            mTuner.close();
67d7c21d3cbfe8e1016a92234f89d6fe8c110144d1Tomasz Wasilczyk        } catch (RemoteException e) {
68d7c21d3cbfe8e1016a92234f89d6fe8c110144d1Tomasz Wasilczyk            Log.e(TAG, "Exception trying to close tuner", e);
69d7c21d3cbfe8e1016a92234f89d6fe8c110144d1Tomasz Wasilczyk        }
70347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
71347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
72347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
73347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    public int setConfiguration(RadioManager.BandConfig config) {
74ca98cde254fef6c31634d8a3069a0d7b76ecf908Tomasz Wasilczyk        if (config == null) return RadioManager.STATUS_BAD_VALUE;
758b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk        try {
768b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk            mTuner.setConfiguration(config);
778cfb0e81fdd91b7fe1c02287394ac068287281d5Tomasz Wasilczyk            mBand = config.getType();
788b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk            return RadioManager.STATUS_OK;
798b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk        } catch (IllegalArgumentException e) {
808b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk            Log.e(TAG, "Can't set configuration", e);
818b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk            return RadioManager.STATUS_BAD_VALUE;
828b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk        } catch (RemoteException e) {
839fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk            Log.e(TAG, "service died", e);
849fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk            return RadioManager.STATUS_DEAD_OBJECT;
858b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk        }
86347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
87347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
88347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
89347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    public int getConfiguration(RadioManager.BandConfig[] config) {
908b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk        if (config == null || config.length != 1) {
918b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk            throw new IllegalArgumentException("The argument must be an array of length 1");
928b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk        }
938b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk        try {
948b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk            config[0] = mTuner.getConfiguration();
958b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk            return RadioManager.STATUS_OK;
968b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk        } catch (RemoteException e) {
979fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk            Log.e(TAG, "service died", e);
989fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk            return RadioManager.STATUS_DEAD_OBJECT;
998b6db4f2eb02f231dd8006debbc1e1be1181178aTomasz Wasilczyk        }
100347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
101347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
102347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
103347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    public int setMute(boolean mute) {
1049fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk        try {
1059fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk            mTuner.setMuted(mute);
1069fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk        } catch (IllegalStateException e) {
1079fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk            Log.e(TAG, "Can't set muted", e);
1089fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk            return RadioManager.STATUS_ERROR;
1099fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk        } catch (RemoteException e) {
1109fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk            Log.e(TAG, "service died", e);
1119fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk            return RadioManager.STATUS_DEAD_OBJECT;
1129fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk        }
1139fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk        return RadioManager.STATUS_OK;
114347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
115347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
116347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
117347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    public boolean getMute() {
1189fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk        try {
1199fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk            return mTuner.isMuted();
1209fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk        } catch (RemoteException e) {
1219fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk            Log.e(TAG, "service died", e);
1229fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk            return true;
1239fa0287c1802df074d4039489dcfad712c19bcbaTomasz Wasilczyk        }
124347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
125347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
126347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
127347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    public int step(int direction, boolean skipSubChannel) {
1282383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk        try {
1292383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk            mTuner.step(direction == RadioTuner.DIRECTION_DOWN, skipSubChannel);
1302383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk        } catch (IllegalStateException e) {
1312383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk            Log.e(TAG, "Can't step", e);
1322383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk            return RadioManager.STATUS_INVALID_OPERATION;
1332383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk        } catch (RemoteException e) {
1342383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk            Log.e(TAG, "service died", e);
1352383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk            return RadioManager.STATUS_DEAD_OBJECT;
1362383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk        }
1372383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk        return RadioManager.STATUS_OK;
138347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
139347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
140347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
141347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    public int scan(int direction, boolean skipSubChannel) {
1422383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk        try {
1432383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk            mTuner.scan(direction == RadioTuner.DIRECTION_DOWN, skipSubChannel);
1442383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk        } catch (IllegalStateException e) {
1452383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk            Log.e(TAG, "Can't scan", e);
1462383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk            return RadioManager.STATUS_INVALID_OPERATION;
1472383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk        } catch (RemoteException e) {
1482383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk            Log.e(TAG, "service died", e);
1492383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk            return RadioManager.STATUS_DEAD_OBJECT;
1502383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk        }
1512383793eaee223546985ee12c2f35a3445e34b1cTomasz Wasilczyk        return RadioManager.STATUS_OK;
152347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
153347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
154347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
155347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    public int tune(int channel, int subChannel) {
15637d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk        try {
1578cfb0e81fdd91b7fe1c02287394ac068287281d5Tomasz Wasilczyk            mTuner.tune(ProgramSelector.createAmFmSelector(mBand, channel, subChannel));
15837d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk        } catch (IllegalStateException e) {
15937d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk            Log.e(TAG, "Can't tune", e);
16037d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk            return RadioManager.STATUS_INVALID_OPERATION;
16137d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk        } catch (IllegalArgumentException e) {
16237d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk            Log.e(TAG, "Can't tune", e);
16337d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk            return RadioManager.STATUS_BAD_VALUE;
16437d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk        } catch (RemoteException e) {
16537d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk            Log.e(TAG, "service died", e);
16637d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk            return RadioManager.STATUS_DEAD_OBJECT;
16737d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk        }
16837d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk        return RadioManager.STATUS_OK;
169347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
170347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
171347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
1728cfb0e81fdd91b7fe1c02287394ac068287281d5Tomasz Wasilczyk    public void tune(@NonNull ProgramSelector selector) {
1738cfb0e81fdd91b7fe1c02287394ac068287281d5Tomasz Wasilczyk        try {
1748cfb0e81fdd91b7fe1c02287394ac068287281d5Tomasz Wasilczyk            mTuner.tune(selector);
1758cfb0e81fdd91b7fe1c02287394ac068287281d5Tomasz Wasilczyk        } catch (RemoteException e) {
1768cfb0e81fdd91b7fe1c02287394ac068287281d5Tomasz Wasilczyk            throw new RuntimeException("service died", e);
1778cfb0e81fdd91b7fe1c02287394ac068287281d5Tomasz Wasilczyk        }
1788cfb0e81fdd91b7fe1c02287394ac068287281d5Tomasz Wasilczyk    }
1798cfb0e81fdd91b7fe1c02287394ac068287281d5Tomasz Wasilczyk
1808cfb0e81fdd91b7fe1c02287394ac068287281d5Tomasz Wasilczyk    @Override
181347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    public int cancel() {
18237d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk        try {
18337d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk            mTuner.cancel();
18437d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk        } catch (IllegalStateException e) {
18537d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk            Log.e(TAG, "Can't cancel", e);
18637d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk            return RadioManager.STATUS_INVALID_OPERATION;
18737d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk        } catch (RemoteException e) {
18837d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk            Log.e(TAG, "service died", e);
18937d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk            return RadioManager.STATUS_DEAD_OBJECT;
19037d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk        }
19137d986d17d0210706be907ce9119b711eeaca235Tomasz Wasilczyk        return RadioManager.STATUS_OK;
192347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
193347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
194347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
195c4cd823a2e4ce62d3a1c6ee6c71bb406c564608cTomasz Wasilczyk    public void cancelAnnouncement() {
196c4cd823a2e4ce62d3a1c6ee6c71bb406c564608cTomasz Wasilczyk        try {
197c4cd823a2e4ce62d3a1c6ee6c71bb406c564608cTomasz Wasilczyk            mTuner.cancelAnnouncement();
198c4cd823a2e4ce62d3a1c6ee6c71bb406c564608cTomasz Wasilczyk        } catch (RemoteException e) {
199c4cd823a2e4ce62d3a1c6ee6c71bb406c564608cTomasz Wasilczyk            throw new RuntimeException("service died", e);
200c4cd823a2e4ce62d3a1c6ee6c71bb406c564608cTomasz Wasilczyk        }
201c4cd823a2e4ce62d3a1c6ee6c71bb406c564608cTomasz Wasilczyk    }
202c4cd823a2e4ce62d3a1c6ee6c71bb406c564608cTomasz Wasilczyk
203c4cd823a2e4ce62d3a1c6ee6c71bb406c564608cTomasz Wasilczyk    @Override
204347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    public int getProgramInformation(RadioManager.ProgramInfo[] info) {
205347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk        if (info == null || info.length != 1) {
2063b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk            Log.e(TAG, "The argument must be an array of length 1");
2073b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk            return RadioManager.STATUS_BAD_VALUE;
208347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk        }
2093b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk
2103b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk        RadioManager.ProgramInfo current = mCallback.getCurrentProgramInformation();
2113b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk        if (current == null) {
2123b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk            Log.w(TAG, "Didn't get program info yet");
2133b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk            return RadioManager.STATUS_INVALID_OPERATION;
214347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk        }
2153b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk        info[0] = current;
2163b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk        return RadioManager.STATUS_OK;
217347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
218347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
219347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
2204482b1413656b9c0c5937b4d7a73235f872a6678Tomasz Wasilczyk    public @Nullable Bitmap getMetadataImage(int id) {
2214482b1413656b9c0c5937b4d7a73235f872a6678Tomasz Wasilczyk        try {
2224482b1413656b9c0c5937b4d7a73235f872a6678Tomasz Wasilczyk            return mTuner.getImage(id);
2234482b1413656b9c0c5937b4d7a73235f872a6678Tomasz Wasilczyk        } catch (RemoteException e) {
2244482b1413656b9c0c5937b4d7a73235f872a6678Tomasz Wasilczyk            throw new RuntimeException("service died", e);
2254482b1413656b9c0c5937b4d7a73235f872a6678Tomasz Wasilczyk        }
2264482b1413656b9c0c5937b4d7a73235f872a6678Tomasz Wasilczyk    }
2274482b1413656b9c0c5937b4d7a73235f872a6678Tomasz Wasilczyk
2284482b1413656b9c0c5937b4d7a73235f872a6678Tomasz Wasilczyk    @Override
229347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    public boolean startBackgroundScan() {
230d3d53f669268fe8dd15f16abbd0504f7b9e38405Tomasz Wasilczyk        try {
231d3d53f669268fe8dd15f16abbd0504f7b9e38405Tomasz Wasilczyk            return mTuner.startBackgroundScan();
232d3d53f669268fe8dd15f16abbd0504f7b9e38405Tomasz Wasilczyk        } catch (RemoteException e) {
233d3d53f669268fe8dd15f16abbd0504f7b9e38405Tomasz Wasilczyk            throw new RuntimeException("service died", e);
234d3d53f669268fe8dd15f16abbd0504f7b9e38405Tomasz Wasilczyk        }
235347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
236347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
237347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
2380f1776d08b43f5f71a9f89b6a4f1838df4d3d744Tomasz Wasilczyk    public @NonNull List<RadioManager.ProgramInfo>
2390f1776d08b43f5f71a9f89b6a4f1838df4d3d744Tomasz Wasilczyk            getProgramList(@Nullable Map<String, String> vendorFilter) {
240436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk        synchronized (mTuner) {
241436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            if (mLegacyListProxy == null || !Objects.equals(mLegacyListFilter, vendorFilter)) {
242436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                Log.i(TAG, "Program list filter has changed, requesting new list");
243436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                mLegacyListProxy = new ProgramList();
244436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                mLegacyListFilter = vendorFilter;
245436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk
246436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                mCallback.clearLastCompleteList();
247436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                mCallback.setProgramListObserver(mLegacyListProxy, () -> { });
248436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                try {
249436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                    mTuner.startProgramListUpdates(new ProgramList.Filter(vendorFilter));
250436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                } catch (RemoteException ex) {
251436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                    throw new RuntimeException("service died", ex);
252436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                }
253436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            }
254436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk
255436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            List<RadioManager.ProgramInfo> list = mCallback.getLastCompleteList();
256436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            if (list == null) throw new IllegalStateException("Program list is not ready yet");
257436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            return list;
258436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk        }
259436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk    }
260436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk
261436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk    @Override
262436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk    public @Nullable ProgramList getDynamicProgramList(@Nullable ProgramList.Filter filter) {
263436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk        synchronized (mTuner) {
264436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            if (mLegacyListProxy != null) {
265436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                mLegacyListProxy.close();
266436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                mLegacyListProxy = null;
267436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            }
268436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            mLegacyListFilter = null;
269436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk
270436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            ProgramList list = new ProgramList();
271436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            mCallback.setProgramListObserver(list, () -> {
272436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                try {
273436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                    mTuner.stopProgramListUpdates();
274436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                } catch (RemoteException ex) {
275436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                    Log.e(TAG, "Couldn't stop program list updates", ex);
276436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                }
277436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            });
278436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk
279436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            try {
280436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                mTuner.startProgramListUpdates(filter);
281436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            } catch (UnsupportedOperationException ex) {
282d0c78f9f28599ac97dbca06c1634238f9b25be40Tomasz Wasilczyk                Log.i(TAG, "Program list is not supported with this hardware");
283436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                return null;
284436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            } catch (RemoteException ex) {
285436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                mCallback.setProgramListObserver(null, () -> { });
286436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk                throw new RuntimeException("service died", ex);
287436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            }
288436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk
289436128f23ae4efc52bbfa3cdde666a139b4bedc4Tomasz Wasilczyk            return list;
290d3d53f669268fe8dd15f16abbd0504f7b9e38405Tomasz Wasilczyk        }
291347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
292347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
293347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
294347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    public boolean isAnalogForced() {
2953b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk        try {
2963b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk            return isConfigFlagSet(RadioManager.CONFIG_FORCE_ANALOG);
2973b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk        } catch (UnsupportedOperationException ex) {
2983b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk            throw new IllegalStateException(ex);
2993b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk        }
300ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk    }
301ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk
302ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk    @Override
303ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk    public void setAnalogForced(boolean isForced) {
3043b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk        try {
3053b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk            setConfigFlag(RadioManager.CONFIG_FORCE_ANALOG, isForced);
3063b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk        } catch (UnsupportedOperationException ex) {
3073b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk            throw new IllegalStateException(ex);
3083b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk        }
309ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk    }
310ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk
311ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk    @Override
312ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk    public boolean isConfigFlagSupported(@RadioManager.ConfigFlag int flag) {
313d3d53f669268fe8dd15f16abbd0504f7b9e38405Tomasz Wasilczyk        try {
314ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk            return mTuner.isConfigFlagSupported(flag);
315d3d53f669268fe8dd15f16abbd0504f7b9e38405Tomasz Wasilczyk        } catch (RemoteException e) {
316d3d53f669268fe8dd15f16abbd0504f7b9e38405Tomasz Wasilczyk            throw new RuntimeException("service died", e);
317d3d53f669268fe8dd15f16abbd0504f7b9e38405Tomasz Wasilczyk        }
318347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
319347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
320347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
321ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk    public boolean isConfigFlagSet(@RadioManager.ConfigFlag int flag) {
322ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk        try {
323ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk            return mTuner.isConfigFlagSet(flag);
324ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk        } catch (RemoteException e) {
325ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk            throw new RuntimeException("service died", e);
326ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk        }
327ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk    }
328ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk
329ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk    @Override
330ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk    public void setConfigFlag(@RadioManager.ConfigFlag int flag, boolean value) {
331d3d53f669268fe8dd15f16abbd0504f7b9e38405Tomasz Wasilczyk        try {
332ce40fe9b1b15221eb91d8b82322b695161664932Tomasz Wasilczyk            mTuner.setConfigFlag(flag, value);
333d3d53f669268fe8dd15f16abbd0504f7b9e38405Tomasz Wasilczyk        } catch (RemoteException e) {
334d3d53f669268fe8dd15f16abbd0504f7b9e38405Tomasz Wasilczyk            throw new RuntimeException("service died", e);
335d3d53f669268fe8dd15f16abbd0504f7b9e38405Tomasz Wasilczyk        }
336347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
337347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
338347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
3398e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk    public @NonNull Map<String, String> setParameters(@NonNull Map<String, String> parameters) {
3408e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk        try {
3418e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk            return mTuner.setParameters(Objects.requireNonNull(parameters));
3428e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk        } catch (RemoteException e) {
3438e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk            throw new RuntimeException("service died", e);
3448e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk        }
3458e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk    }
3468e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk
3478e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk    @Override
3488e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk    public @NonNull Map<String, String> getParameters(@NonNull List<String> keys) {
3498e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk        try {
3508e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk            return mTuner.getParameters(Objects.requireNonNull(keys));
3518e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk        } catch (RemoteException e) {
3528e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk            throw new RuntimeException("service died", e);
3538e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk        }
3548e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk    }
3558e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk
3568e932c61db78e7a04f6a98e070089f10abdccf1aTomasz Wasilczyk    @Override
357347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    public boolean isAntennaConnected() {
3583b4465e65688f899f2eecf5701cda044a3104523Tomasz Wasilczyk        return mCallback.isAntennaConnected();
359347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
360347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk
361347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    @Override
362347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    public boolean hasControl() {
363468a53b71025a42dde24922e0255ab3251e63fbeTomasz Wasilczyk        try {
364468a53b71025a42dde24922e0255ab3251e63fbeTomasz Wasilczyk            // don't rely on mIsClosed, as tuner might get closed internally
365468a53b71025a42dde24922e0255ab3251e63fbeTomasz Wasilczyk            return !mTuner.isClosed();
366468a53b71025a42dde24922e0255ab3251e63fbeTomasz Wasilczyk        } catch (RemoteException e) {
367468a53b71025a42dde24922e0255ab3251e63fbeTomasz Wasilczyk            return false;
368468a53b71025a42dde24922e0255ab3251e63fbeTomasz Wasilczyk        }
369347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk    }
370347192e0da1f39347e7ab7b58b002f166b4afaa7Tomasz Wasilczyk}
371