blob: 9915c34fb58238b681a0bd1d7f50ffea8ed8c1bb [file] [log] [blame]
Tomasz Wasilczykd7c21d32017-04-17 17:02:06 -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 com.android.server.radio;
18
Tomasz Wasilczyk21348172017-04-20 14:02:42 -070019import android.annotation.NonNull;
Tomasz Wasilczykd7c21d32017-04-17 17:02:06 -070020import android.hardware.radio.ITuner;
Tomasz Wasilczyk21348172017-04-20 14:02:42 -070021import android.hardware.radio.ITunerCallback;
Tomasz Wasilczykd7c21d32017-04-17 17:02:06 -070022import android.hardware.radio.RadioManager;
23import android.util.Slog;
24
Tomasz Wasilczykd3d53f62017-05-15 12:55:28 -070025import java.util.List;
26
Tomasz Wasilczykd7c21d32017-04-17 17:02:06 -070027class Tuner extends ITuner.Stub {
28 // TODO(b/36863239): rename to RadioService.Tuner when native service goes away
29 private static final String TAG = "RadioServiceJava.Tuner";
30
31 /**
32 * This field is used by native code, do not access or modify.
33 */
Tomasz Wasilczyk21348172017-04-20 14:02:42 -070034 private final long mNativeContext;
35
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -070036 @NonNull private final TunerCallback mTunerCallback;
Tomasz Wasilczyk8b6db4f2017-05-01 09:28:36 -070037 private final Object mLock = new Object();
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -070038 private boolean mIsClosed = false;
Tomasz Wasilczyk9fa02872017-05-03 09:09:57 -070039 private boolean mIsMuted = false;
Tomasz Wasilczyk8b6db4f2017-05-01 09:28:36 -070040 private int mRegion; // TODO(b/36863239): find better solution to manage regions
Tomasz Wasilczyk9fa02872017-05-03 09:09:57 -070041 private final boolean mWithAudio;
Tomasz Wasilczyk31c8df02017-04-26 14:47:08 -070042
Tomasz Wasilczyk23837932017-05-05 08:42:10 -070043 Tuner(@NonNull ITunerCallback clientCallback, int halRev, int region, boolean withAudio) {
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -070044 mTunerCallback = new TunerCallback(this, clientCallback, halRev);
Tomasz Wasilczyk31c8df02017-04-26 14:47:08 -070045 mRegion = region;
Tomasz Wasilczyk9fa02872017-05-03 09:09:57 -070046 mWithAudio = withAudio;
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -070047 mNativeContext = nativeInit(halRev);
Tomasz Wasilczyk21348172017-04-20 14:02:42 -070048 }
Tomasz Wasilczykd7c21d32017-04-17 17:02:06 -070049
50 @Override
51 protected void finalize() throws Throwable {
52 nativeFinalize(mNativeContext);
53 super.finalize();
54 }
55
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -070056 private native long nativeInit(int halRev);
Tomasz Wasilczykd7c21d32017-04-17 17:02:06 -070057 private native void nativeFinalize(long nativeContext);
Tomasz Wasilczyk21348172017-04-20 14:02:42 -070058 private native void nativeClose(long nativeContext);
Tomasz Wasilczykd7c21d32017-04-17 17:02:06 -070059
Tomasz Wasilczyk8b6db4f2017-05-01 09:28:36 -070060 private native void nativeSetConfiguration(long nativeContext,
61 @NonNull RadioManager.BandConfig config);
62 private native RadioManager.BandConfig nativeGetConfiguration(long nativeContext, int region);
63
Tomasz Wasilczyk23837932017-05-05 08:42:10 -070064 private native void nativeStep(long nativeContext, boolean directionDown, boolean skipSubChannel);
65 private native void nativeScan(long nativeContext, boolean directionDown, boolean skipSubChannel);
66 private native void nativeTune(long nativeContext, int channel, int subChannel);
67 private native void nativeCancel(long nativeContext);
68
Tomasz Wasilczyk37d986d2017-05-08 10:41:32 -070069 private native RadioManager.ProgramInfo nativeGetProgramInformation(long nativeContext);
Tomasz Wasilczykd3d53f62017-05-15 12:55:28 -070070 private native boolean nativeStartBackgroundScan(long nativeContext);
71 private native List<RadioManager.ProgramInfo> nativeGetProgramList(long nativeContext,
72 String filter);
73
74 private native boolean nativeIsAnalogForced(long nativeContext);
75 private native void nativeSetAnalogForced(long nativeContext, boolean isForced);
Tomasz Wasilczyk37d986d2017-05-08 10:41:32 -070076
Tomasz Wasilczyk39ac2142017-05-17 14:55:17 -070077 private native boolean nativeIsAntennaConnected(long nativeContext);
78
Tomasz Wasilczykd7c21d32017-04-17 17:02:06 -070079 @Override
Tomasz Wasilczyk21348172017-04-20 14:02:42 -070080 public void close() {
Tomasz Wasilczyk8b6db4f2017-05-01 09:28:36 -070081 synchronized (mLock) {
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -070082 if (mIsClosed) return;
83 mTunerCallback.detach();
Tomasz Wasilczyk8b6db4f2017-05-01 09:28:36 -070084 nativeClose(mNativeContext);
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -070085 mIsClosed = true;
86 }
87 }
88
89 private void checkNotClosedLocked() {
90 if (mIsClosed) {
91 throw new IllegalStateException("Tuner is closed, no further operations are allowed");
Tomasz Wasilczyk8b6db4f2017-05-01 09:28:36 -070092 }
93 }
94
95 @Override
96 public void setConfiguration(RadioManager.BandConfig config) {
97 if (config == null) {
98 throw new IllegalArgumentException("The argument must not be a null pointer");
99 }
100 synchronized (mLock) {
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -0700101 checkNotClosedLocked();
Tomasz Wasilczyk8b6db4f2017-05-01 09:28:36 -0700102 nativeSetConfiguration(mNativeContext, config);
103 mRegion = config.getRegion();
104 }
105 }
106
107 @Override
108 public RadioManager.BandConfig getConfiguration() {
109 synchronized (mLock) {
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -0700110 checkNotClosedLocked();
Tomasz Wasilczyk8b6db4f2017-05-01 09:28:36 -0700111 return nativeGetConfiguration(mNativeContext, mRegion);
112 }
Tomasz Wasilczyk21348172017-04-20 14:02:42 -0700113 }
Tomasz Wasilczykd7c21d32017-04-17 17:02:06 -0700114
115 @Override
Tomasz Wasilczyk9fa02872017-05-03 09:09:57 -0700116 public void setMuted(boolean mute) {
117 if (!mWithAudio) {
118 throw new IllegalStateException("Can't operate on mute - no audio requested");
119 }
120 synchronized (mLock) {
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -0700121 checkNotClosedLocked();
Tomasz Wasilczyk9fa02872017-05-03 09:09:57 -0700122 if (mIsMuted == mute) return;
123 mIsMuted = mute;
124
125 // TODO(b/34348946): notifify audio policy manager of media activity on radio audio
126 // device. This task is pulled directly from previous implementation of native service.
127 }
128 }
129
130 @Override
131 public boolean isMuted() {
132 if (!mWithAudio) {
133 Slog.w(TAG, "Tuner did not request audio, pretending it was muted");
134 return true;
135 }
136 synchronized (mLock) {
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -0700137 checkNotClosedLocked();
Tomasz Wasilczyk9fa02872017-05-03 09:09:57 -0700138 return mIsMuted;
139 }
140 }
Tomasz Wasilczyk23837932017-05-05 08:42:10 -0700141
142 @Override
143 public void step(boolean directionDown, boolean skipSubChannel) {
144 synchronized (mLock) {
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -0700145 checkNotClosedLocked();
Tomasz Wasilczyk23837932017-05-05 08:42:10 -0700146 nativeStep(mNativeContext, directionDown, skipSubChannel);
147 }
148 }
149
150 @Override
151 public void scan(boolean directionDown, boolean skipSubChannel) {
152 synchronized (mLock) {
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -0700153 checkNotClosedLocked();
Tomasz Wasilczyk23837932017-05-05 08:42:10 -0700154 nativeScan(mNativeContext, directionDown, skipSubChannel);
155 }
156 }
157
158 @Override
159 public void tune(int channel, int subChannel) {
160 synchronized (mLock) {
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -0700161 checkNotClosedLocked();
Tomasz Wasilczyk23837932017-05-05 08:42:10 -0700162 nativeTune(mNativeContext, channel, subChannel);
163 }
164 }
165
166 @Override
167 public void cancel() {
168 synchronized (mLock) {
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -0700169 checkNotClosedLocked();
Tomasz Wasilczyk23837932017-05-05 08:42:10 -0700170 nativeCancel(mNativeContext);
171 }
172 }
Tomasz Wasilczyk37d986d2017-05-08 10:41:32 -0700173
174 @Override
175 public RadioManager.ProgramInfo getProgramInformation() {
176 synchronized (mLock) {
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -0700177 checkNotClosedLocked();
Tomasz Wasilczyk37d986d2017-05-08 10:41:32 -0700178 return nativeGetProgramInformation(mNativeContext);
179 }
180 }
Tomasz Wasilczykd3d53f62017-05-15 12:55:28 -0700181
Tomasz Wasilczyk39ac2142017-05-17 14:55:17 -0700182 @Override
Tomasz Wasilczykd3d53f62017-05-15 12:55:28 -0700183 public boolean startBackgroundScan() {
184 synchronized (mLock) {
185 checkNotClosedLocked();
186 return nativeStartBackgroundScan(mNativeContext);
187 }
188 }
189
Tomasz Wasilczyk39ac2142017-05-17 14:55:17 -0700190 @Override
Tomasz Wasilczykd3d53f62017-05-15 12:55:28 -0700191 public List<RadioManager.ProgramInfo> getProgramList(String filter) {
192 synchronized (mLock) {
193 checkNotClosedLocked();
194 List<RadioManager.ProgramInfo> list = nativeGetProgramList(mNativeContext, filter);
195 if (list == null) {
196 throw new IllegalStateException("Program list is not ready");
197 }
198 return list;
199 }
200 }
201
Tomasz Wasilczyk39ac2142017-05-17 14:55:17 -0700202 @Override
Tomasz Wasilczykd3d53f62017-05-15 12:55:28 -0700203 public boolean isAnalogForced() {
204 synchronized (mLock) {
205 checkNotClosedLocked();
206 return nativeIsAnalogForced(mNativeContext);
207 }
208 }
209
Tomasz Wasilczyk39ac2142017-05-17 14:55:17 -0700210 @Override
Tomasz Wasilczykd3d53f62017-05-15 12:55:28 -0700211 public void setAnalogForced(boolean isForced) {
212 synchronized (mLock) {
213 checkNotClosedLocked();
214 nativeSetAnalogForced(mNativeContext, isForced);
215 }
216 }
Tomasz Wasilczyk39ac2142017-05-17 14:55:17 -0700217
218 @Override
219 public boolean isAntennaConnected() {
220 synchronized (mLock) {
221 checkNotClosedLocked();
222 return nativeIsAntennaConnected(mNativeContext);
223 }
224 }
Tomasz Wasilczykd7c21d32017-04-17 17:02:06 -0700225}