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