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