blob: c0df0f386b09f7c6a0830803a20d131de700168a [file] [log] [blame]
Eric Laurent2035ac82015-03-05 15:18:44 -08001/*
2 * Copyright (C) 2015 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
Tomasz Wasilczykd44b2ea2017-03-08 10:01:04 -080019import android.annotation.NonNull;
20import android.annotation.Nullable;
Eric Laurent2035ac82015-03-05 15:18:44 -080021import android.annotation.SystemApi;
22import android.content.Context;
23import android.content.Intent;
24import android.os.Handler;
25import android.os.Looper;
26import android.os.Message;
27import java.lang.ref.WeakReference;
Tomasz Wasilczykd44b2ea2017-03-08 10:01:04 -080028import java.util.List;
Eric Laurent2035ac82015-03-05 15:18:44 -080029import java.util.UUID;
30
31/**
32 * A RadioModule implements the RadioTuner interface for a broadcast radio tuner physically
33 * present on the device and exposed by the radio HAL.
34 *
35 * @hide
36 */
37public class RadioModule extends RadioTuner {
38 private long mNativeContext = 0;
39 private int mId;
40 private NativeEventHandlerDelegate mEventHandlerDelegate;
41
42 RadioModule(int moduleId, RadioManager.BandConfig config, boolean withAudio,
43 RadioTuner.Callback callback, Handler handler) {
44 mId = moduleId;
45 mEventHandlerDelegate = new NativeEventHandlerDelegate(callback, handler);
46 native_setup(new WeakReference<RadioModule>(this), config, withAudio);
47 }
48 private native void native_setup(Object module_this,
49 RadioManager.BandConfig config, boolean withAudio);
50
51 @Override
52 protected void finalize() {
53 native_finalize();
54 }
55 private native void native_finalize();
56
57 boolean initCheck() {
58 return mNativeContext != 0;
59 }
60
61 // RadioTuner implementation
62 public native void close();
63
64 public native int setConfiguration(RadioManager.BandConfig config);
65
66 public native int getConfiguration(RadioManager.BandConfig[] config);
67
68 public native int setMute(boolean mute);
69
70 public native boolean getMute();
71
72 public native int step(int direction, boolean skipSubChannel);
73
74 public native int scan(int direction, boolean skipSubChannel);
75
76 public native int tune(int channel, int subChannel);
77
78 public native int cancel();
79
80 public native int getProgramInformation(RadioManager.ProgramInfo[] info);
81
Tomasz Wasilczyke597ce12017-03-24 13:50:53 -070082 public native boolean startBackgroundScan();
83
Tomasz Wasilczykd44b2ea2017-03-08 10:01:04 -080084 public native @NonNull List<RadioManager.ProgramInfo> getProgramList(@Nullable String filter);
85
Tomasz Wasilczyk5f0fbae2017-03-27 14:27:44 -070086 public native boolean isAnalogForced();
87
88 public native void setAnalogForced(boolean isForced);
89
Eric Laurent2035ac82015-03-05 15:18:44 -080090 public native boolean isAntennaConnected();
91
92 public native boolean hasControl();
93
94
95 /* keep in sync with radio_event_type_t in system/core/include/system/radio.h */
96 static final int EVENT_HW_FAILURE = 0;
97 static final int EVENT_CONFIG = 1;
98 static final int EVENT_ANTENNA = 2;
99 static final int EVENT_TUNED = 3;
100 static final int EVENT_METADATA = 4;
101 static final int EVENT_TA = 5;
102 static final int EVENT_AF_SWITCH = 6;
Sanket Agarwal7058e4c2015-10-08 14:14:20 -0700103 static final int EVENT_EA = 7;
Eric Laurent2035ac82015-03-05 15:18:44 -0800104 static final int EVENT_CONTROL = 100;
105 static final int EVENT_SERVER_DIED = 101;
106
107 private class NativeEventHandlerDelegate {
108 private final Handler mHandler;
109
110 NativeEventHandlerDelegate(final RadioTuner.Callback callback,
111 Handler handler) {
112 // find the looper for our new event handler
113 Looper looper;
114 if (handler != null) {
115 looper = handler.getLooper();
116 } else {
117 looper = Looper.getMainLooper();
118 }
119
120 // construct the event handler with this looper
121 if (looper != null) {
122 // implement the event handler delegate
123 mHandler = new Handler(looper) {
124 @Override
125 public void handleMessage(Message msg) {
126 switch (msg.what) {
127 case EVENT_HW_FAILURE:
128 if (callback != null) {
129 callback.onError(RadioTuner.ERROR_HARDWARE_FAILURE);
130 }
131 break;
132 case EVENT_CONFIG: {
133 RadioManager.BandConfig config = (RadioManager.BandConfig)msg.obj;
134 switch(msg.arg1) {
135 case RadioManager.STATUS_OK:
136 if (callback != null) {
137 callback.onConfigurationChanged(config);
138 }
139 break;
140 default:
141 if (callback != null) {
142 callback.onError(RadioTuner.ERROR_CONFIG);
143 }
144 break;
145 }
146 } break;
147 case EVENT_ANTENNA:
148 if (callback != null) {
149 callback.onAntennaState(msg.arg2 == 1);
150 }
151 break;
152 case EVENT_AF_SWITCH:
153 case EVENT_TUNED: {
154 RadioManager.ProgramInfo info = (RadioManager.ProgramInfo)msg.obj;
155 switch (msg.arg1) {
156 case RadioManager.STATUS_OK:
157 if (callback != null) {
158 callback.onProgramInfoChanged(info);
159 }
160 break;
161 case RadioManager.STATUS_TIMED_OUT:
162 if (callback != null) {
163 callback.onError(RadioTuner.ERROR_SCAN_TIMEOUT);
164 }
165 break;
166 case RadioManager.STATUS_INVALID_OPERATION:
167 default:
168 if (callback != null) {
169 callback.onError(RadioTuner.ERROR_CANCELLED);
170 }
171 break;
172 }
173 } break;
174 case EVENT_METADATA: {
175 RadioMetadata metadata = (RadioMetadata)msg.obj;
176 if (callback != null) {
177 callback.onMetadataChanged(metadata);
178 }
179 } break;
180 case EVENT_TA:
181 if (callback != null) {
182 callback.onTrafficAnnouncement(msg.arg2 == 1);
183 }
184 break;
Sanket Agarwal7058e4c2015-10-08 14:14:20 -0700185 case EVENT_EA:
186 if (callback != null) {
187 callback.onEmergencyAnnouncement(msg.arg2 == 1);
188 }
Eric Laurent2035ac82015-03-05 15:18:44 -0800189 case EVENT_CONTROL:
190 if (callback != null) {
191 callback.onControlChanged(msg.arg2 == 1);
192 }
193 break;
194 case EVENT_SERVER_DIED:
195 if (callback != null) {
196 callback.onError(RadioTuner.ERROR_SERVER_DIED);
197 }
198 break;
199 default:
200 // Should not happen
201 break;
202 }
203 }
204 };
205 } else {
206 mHandler = null;
207 }
208 }
209
210 Handler handler() {
211 return mHandler;
212 }
213 }
214
215
216 @SuppressWarnings("unused")
217 private static void postEventFromNative(Object module_ref,
218 int what, int arg1, int arg2, Object obj) {
219 RadioModule module = (RadioModule)((WeakReference)module_ref).get();
220 if (module == null) {
221 return;
222 }
223
224 NativeEventHandlerDelegate delegate = module.mEventHandlerDelegate;
225 if (delegate != null) {
226 Handler handler = delegate.handler();
227 if (handler != null) {
228 Message m = handler.obtainMessage(what, arg1, arg2, obj);
229 handler.sendMessage(m);
230 }
231 }
232 }
233}
234