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