1633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent/*
2633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent**
3633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent** Copyright 2015, The Android Open Source Project
4633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent**
5633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent** Licensed under the Apache License, Version 2.0 (the "License");
6633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent** you may not use this file except in compliance with the License.
7633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent** You may obtain a copy of the License at
8633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent**
9633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent**     http://www.apache.org/licenses/LICENSE-2.0
10633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent**
11633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent** Unless required by applicable law or agreed to in writing, software
12633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent** distributed under the License is distributed on an "AS IS" BASIS,
13633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent** See the License for the specific language governing permissions and
15633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent** limitations under the License.
16633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent*/
17633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
18633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent//#define LOG_NDEBUG 0
19633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent#define LOG_TAG "Radio-JNI"
20633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent#include <utils/Log.h>
21633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
22633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent#include "jni.h"
23633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent#include "JNIHelp.h"
24633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent#include "core_jni_helpers.h"
25633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent#include <system/radio.h>
26633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent#include <system/radio_metadata.h>
27633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent#include <radio/RadioCallback.h>
28633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent#include <radio/Radio.h>
29633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent#include <utils/RefBase.h>
30633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent#include <utils/Vector.h>
31633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent#include <binder/IMemory.h>
32633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent#include <binder/MemoryDealer.h>
33633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
34633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentusing namespace android;
35633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
36633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jclass gArrayListClass;
37633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic struct {
38633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jmethodID    add;
39633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent} gArrayListMethods;
40633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
41633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic const char* const kRadioManagerClassPathName = "android/hardware/radio/RadioManager";
42633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jclass gRadioManagerClass;
43633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
44633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic const char* const kRadioModuleClassPathName = "android/hardware/radio/RadioModule";
45633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jclass gRadioModuleClass;
46633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic struct {
47633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jfieldID    mNativeContext;
48633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jfieldID    mId;
49633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent} gModuleFields;
50633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jmethodID gPostEventFromNative;
51633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
52633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic const char* const kModulePropertiesClassPathName =
53633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                     "android/hardware/radio/RadioManager$ModuleProperties";
54633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jclass gModulePropertiesClass;
55633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jmethodID gModulePropertiesCstor;
56633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
57633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
58633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic const char* const kRadioBandDescriptorClassPathName =
59633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                             "android/hardware/radio/RadioManager$BandDescriptor";
60633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jclass gRadioBandDescriptorClass;
61633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic struct {
62633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jfieldID mRegion;
63633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jfieldID mType;
64633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jfieldID mLowerLimit;
65633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jfieldID mUpperLimit;
66633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jfieldID mSpacing;
67633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent} gRadioBandDescriptorFields;
68633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
69633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic const char* const kRadioFmBandDescriptorClassPathName =
70633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                             "android/hardware/radio/RadioManager$FmBandDescriptor";
71633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jclass gRadioFmBandDescriptorClass;
72633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jmethodID gRadioFmBandDescriptorCstor;
73633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
74633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic const char* const kRadioAmBandDescriptorClassPathName =
75633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                             "android/hardware/radio/RadioManager$AmBandDescriptor";
76633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jclass gRadioAmBandDescriptorClass;
77633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jmethodID gRadioAmBandDescriptorCstor;
78633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
79633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic const char* const kRadioBandConfigClassPathName =
80633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                             "android/hardware/radio/RadioManager$BandConfig";
81633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jclass gRadioBandConfigClass;
82633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic struct {
83633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jfieldID mDescriptor;
84633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent} gRadioBandConfigFields;
85633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
86633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
87633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic const char* const kRadioFmBandConfigClassPathName =
88633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                             "android/hardware/radio/RadioManager$FmBandConfig";
89633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jclass gRadioFmBandConfigClass;
90633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jmethodID gRadioFmBandConfigCstor;
91633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic struct {
92633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jfieldID mStereo;
93633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jfieldID mRds;
94633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jfieldID mTa;
95633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jfieldID mAf;
967058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal    jfieldID mEa;
97633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent} gRadioFmBandConfigFields;
98633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
99633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic const char* const kRadioAmBandConfigClassPathName =
100633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                             "android/hardware/radio/RadioManager$AmBandConfig";
101633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jclass gRadioAmBandConfigClass;
102633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jmethodID gRadioAmBandConfigCstor;
103633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic struct {
104633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jfieldID mStereo;
105633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent} gRadioAmBandConfigFields;
106633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
107633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
108633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic const char* const kRadioProgramInfoClassPathName =
109633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                             "android/hardware/radio/RadioManager$ProgramInfo";
110633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jclass gRadioProgramInfoClass;
111633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jmethodID gRadioProgramInfoCstor;
112633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
113633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic const char* const kRadioMetadataClassPathName =
114633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                             "android/hardware/radio/RadioMetadata";
115633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jclass gRadioMetadataClass;
116633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jmethodID gRadioMetadataCstor;
117633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic struct {
118633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jmethodID putIntFromNative;
119633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jmethodID putStringFromNative;
120633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jmethodID putBitmapFromNative;
1217058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal    jmethodID putClockFromNative;
122633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent} gRadioMetadataMethods;
123633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
124633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic Mutex gLock;
125633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
126633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentenum {
127633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    RADIO_STATUS_OK = 0,
128633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    RADIO_STATUS_ERROR = INT_MIN,
129633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    RADIO_PERMISSION_DENIED = -1,
130633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    RADIO_STATUS_NO_INIT = -19,
131633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    RADIO_STATUS_BAD_VALUE = -22,
132633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    RADIO_STATUS_DEAD_OBJECT = -32,
133633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    RADIO_STATUS_INVALID_OPERATION = -38,
134633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    RADIO_STATUS_TIMED_OUT = -110,
135633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent};
136633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
137633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
138633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent// ----------------------------------------------------------------------------
139633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
140633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic sp<Radio> getRadio(JNIEnv* env, jobject thiz)
141633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
142633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    Mutex::Autolock l(gLock);
143633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    Radio* const radio = (Radio*)env->GetLongField(thiz, gModuleFields.mNativeContext);
144633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return sp<Radio>(radio);
145633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
146633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
147633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic sp<Radio> setRadio(JNIEnv* env, jobject thiz, const sp<Radio>& module)
148633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
149633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    Mutex::Autolock l(gLock);
150633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<Radio> old = (Radio*)env->GetLongField(thiz, gModuleFields.mNativeContext);
151633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (module.get()) {
152633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        module->incStrong((void*)setRadio);
153633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
154633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (old != 0) {
155633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        old->decStrong((void*)setRadio);
156633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
157633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    env->SetLongField(thiz, gModuleFields.mNativeContext, (jlong)module.get());
158633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return old;
159633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
160633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
161633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jint convertBandDescriptorFromNative(JNIEnv *env,
162633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                           jobject *jBandDescriptor,
163633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                           const radio_band_config_t *nBandconfig)
164633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
165633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s type %d region %d", __FUNCTION__, nBandconfig->band.type, nBandconfig->region);
166633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
167633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (nBandconfig->band.type == RADIO_BAND_FM ||
168633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            nBandconfig->band.type == RADIO_BAND_FM_HD) {
169633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        *jBandDescriptor = env->NewObject(gRadioFmBandDescriptorClass, gRadioFmBandDescriptorCstor,
170633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->region, nBandconfig->band.type,
171633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.lower_limit, nBandconfig->band.upper_limit,
172633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.spacings[0],
173633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.fm.stereo,
174633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.fm.rds != RADIO_RDS_NONE,
175633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.fm.ta,
1767058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal                                      nBandconfig->band.fm.af,
1777058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal                                      nBandconfig->band.fm.ea);
178633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    } else if (nBandconfig->band.type == RADIO_BAND_AM) {
179633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        *jBandDescriptor = env->NewObject(gRadioAmBandDescriptorClass, gRadioAmBandDescriptorCstor,
180633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->region, nBandconfig->band.type,
181633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.lower_limit, nBandconfig->band.upper_limit,
182633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.spacings[0],
183633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.am.stereo);
184633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    } else {
185633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        ALOGE("%s unknown band type %d", __FUNCTION__, nBandconfig->band.type);
186633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return (jint)RADIO_STATUS_BAD_VALUE;
187633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
188633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
189633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (*jBandDescriptor == NULL) {
190633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return (jint)RADIO_STATUS_NO_INIT;
191633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
192633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
193633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return (jint)RADIO_STATUS_OK;
194633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
195633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
196633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jint convertBandConfigFromNative(JNIEnv *env,
197633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                           jobject *jBandConfig,
198633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                           const radio_band_config_t *nBandconfig)
199633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
200633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s type %d region %d", __FUNCTION__, nBandconfig->band.type, nBandconfig->region);
201633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
202633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (nBandconfig->band.type == RADIO_BAND_FM ||
203633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            nBandconfig->band.type == RADIO_BAND_FM_HD) {
204633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        *jBandConfig = env->NewObject(gRadioFmBandConfigClass, gRadioFmBandConfigCstor,
205633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->region, nBandconfig->band.type,
206633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.lower_limit, nBandconfig->band.upper_limit,
207633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.spacings[0],
208633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.fm.stereo,
209633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.fm.rds != RADIO_RDS_NONE,
210633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.fm.ta,
2117058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal                                      nBandconfig->band.fm.af,
2127058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal                                      nBandconfig->band.fm.ea);
213633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    } else if (nBandconfig->band.type == RADIO_BAND_AM) {
214633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        *jBandConfig = env->NewObject(gRadioAmBandConfigClass, gRadioAmBandConfigCstor,
215633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->region, nBandconfig->band.type,
216633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.lower_limit, nBandconfig->band.upper_limit,
217633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.spacings[0],
218633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      nBandconfig->band.am.stereo);
219633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    } else {
220633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        ALOGE("%s unknown band type %d", __FUNCTION__, nBandconfig->band.type);
221633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return (jint)RADIO_STATUS_BAD_VALUE;
222633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
223633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
224633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (*jBandConfig == NULL) {
225633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return (jint)RADIO_STATUS_NO_INIT;
226633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
227633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
228633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return (jint)RADIO_STATUS_OK;
229633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
230633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
231633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jint convertMetadataFromNative(JNIEnv *env,
232633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                           jobject *jMetadata,
233633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                           const radio_metadata_t *nMetadata)
234633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
235633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
236633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    int count = radio_metadata_get_count(nMetadata);
237633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (count <= 0) {
238633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return (jint)count;
239633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
240633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    *jMetadata = env->NewObject(gRadioMetadataClass, gRadioMetadataCstor);
241633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
242633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jint jCount = 0;
243633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jint jStatus = 0;
244633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    for (unsigned int i = 0; i < (unsigned int)count; i++) {
245633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        radio_metadata_key_t key;
246633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        radio_metadata_type_t type;
247633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        void *value;
248633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        unsigned int size;
249633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        if (radio_metadata_get_at_index(nMetadata, i , &key, &type, &value, &size) != 0) {
250633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            continue;
251633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        }
252633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        switch (type) {
253633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            case RADIO_METADATA_TYPE_INT: {
254633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                ALOGV("%s RADIO_METADATA_TYPE_INT %d", __FUNCTION__, key);
255633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                jStatus = env->CallIntMethod(*jMetadata,
256633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                   gRadioMetadataMethods.putIntFromNative,
257633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                   key, *(jint *)value);
258633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                if (jStatus == 0) {
259633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                    jCount++;
260633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                }
261633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            } break;
262633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            case RADIO_METADATA_TYPE_TEXT: {
263633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                ALOGV("%s RADIO_METADATA_TYPE_TEXT %d", __FUNCTION__, key);
264633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                jstring jText = env->NewStringUTF((char *)value);
265633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                jStatus = env->CallIntMethod(*jMetadata,
266633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                   gRadioMetadataMethods.putStringFromNative,
267633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                   key, jText);
268633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                if (jStatus == 0) {
269633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                    jCount++;
270633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                }
271633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                env->DeleteLocalRef(jText);
272633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            } break;
273633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            case RADIO_METADATA_TYPE_RAW: {
274633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                ALOGV("%s RADIO_METADATA_TYPE_RAW %d size %u", __FUNCTION__, key, size);
275633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                if (size == 0) {
276633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                    break;
277633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                }
278633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                jbyteArray jData = env->NewByteArray(size);
279633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                if (jData == NULL) {
280633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                    break;
281633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                }
282633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                env->SetByteArrayRegion(jData, 0, size, (jbyte *)value);
283633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                jStatus = env->CallIntMethod(*jMetadata,
284633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                   gRadioMetadataMethods.putBitmapFromNative,
285633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                   key, jData);
286633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                if (jStatus == 0) {
287633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                    jCount++;
288633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                }
289633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                env->DeleteLocalRef(jData);
290633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            } break;
2917058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal            case RADIO_METADATA_TYPE_CLOCK: {
2927058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal                  ALOGV("%s RADIO_METADATA_TYPE_CLOCK %d", __FUNCTION__, key);
2937058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal                  radio_metadata_clock_t *clock = (radio_metadata_clock_t *) value;
2947058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal                  jStatus =
2957058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal                      env->CallIntMethod(*jMetadata,
2967058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal                                         gRadioMetadataMethods.putClockFromNative,
2977058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal                                         key, (jint) clock->utc_seconds_since_epoch,
2987058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal                                         (jint) clock->timezone_offset_in_minutes);
2997058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal                  if (jStatus == 0) {
3007058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal                      jCount++;
3017058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal                  }
3027058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal            } break;
303633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        }
304633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
305633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return jCount;
306633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
307633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
308633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jint convertProgramInfoFromNative(JNIEnv *env,
309633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                           jobject *jProgramInfo,
310633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                           const radio_program_info_t *nProgramInfo)
311633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
312633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
313633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    int jStatus;
314633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jobject jMetadata = NULL;
315633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (nProgramInfo->metadata != NULL) {
316633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        ALOGV("%s metadata %p", __FUNCTION__, nProgramInfo->metadata);
317633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        jStatus = convertMetadataFromNative(env, &jMetadata, nProgramInfo->metadata);
318633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        if (jStatus < 0) {
319633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            return jStatus;
320633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        }
321633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
322633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
323633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s channel %d tuned %d", __FUNCTION__, nProgramInfo->channel, nProgramInfo->tuned);
324633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
325633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    *jProgramInfo = env->NewObject(gRadioProgramInfoClass, gRadioProgramInfoCstor,
326633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                  nProgramInfo->channel, nProgramInfo->sub_channel,
327633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                  nProgramInfo->tuned, nProgramInfo->stereo,
328633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                  nProgramInfo->digital, nProgramInfo->signal_strength,
329633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                  jMetadata);
330633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
331633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    env->DeleteLocalRef(jMetadata);
332633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return (jint)RADIO_STATUS_OK;
333633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
334633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
335633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
336633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jint convertBandConfigToNative(JNIEnv *env,
337633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      radio_band_config_t *nBandconfig,
338633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                      jobject jBandConfig)
339633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
340633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
341633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
342633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jobject jDescriptor = env->GetObjectField(jBandConfig, gRadioBandConfigFields.mDescriptor);
343633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
344633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (jDescriptor == NULL) {
345633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return (jint)RADIO_STATUS_NO_INIT;
346633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
347633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
348633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    nBandconfig->region =
349633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            (radio_region_t)env->GetIntField(jDescriptor, gRadioBandDescriptorFields.mRegion);
350633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    nBandconfig->band.type =
351633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            (radio_band_t)env->GetIntField(jDescriptor, gRadioBandDescriptorFields.mType);
352633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    nBandconfig->band.lower_limit =
353633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            env->GetIntField(jDescriptor, gRadioBandDescriptorFields.mLowerLimit);
354633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    nBandconfig->band.upper_limit =
355633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            env->GetIntField(jDescriptor, gRadioBandDescriptorFields.mUpperLimit);
356633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    nBandconfig->band.num_spacings = 1;
357633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    nBandconfig->band.spacings[0] =
358633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            env->GetIntField(jDescriptor, gRadioBandDescriptorFields.mSpacing);
359633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
360633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (env->IsInstanceOf(jBandConfig, gRadioFmBandConfigClass)) {
361633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        nBandconfig->band.fm.deemphasis = radio_demephasis_for_region(nBandconfig->region);
362633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        nBandconfig->band.fm.stereo =
363633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                env->GetBooleanField(jBandConfig, gRadioFmBandConfigFields.mStereo);
364633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        nBandconfig->band.fm.rds =
365633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                radio_rds_for_region(env->GetBooleanField(jBandConfig,
366633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                                          gRadioFmBandConfigFields.mRds),
367633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                     nBandconfig->region);
368633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        nBandconfig->band.fm.ta = env->GetBooleanField(jBandConfig, gRadioFmBandConfigFields.mTa);
369633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        nBandconfig->band.fm.af = env->GetBooleanField(jBandConfig, gRadioFmBandConfigFields.mAf);
3707058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal        nBandconfig->band.fm.ea = env->GetBooleanField(jBandConfig, gRadioFmBandConfigFields.mEa);
371633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    } else if (env->IsInstanceOf(jBandConfig, gRadioAmBandConfigClass)) {
372633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        nBandconfig->band.am.stereo =
373633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                env->GetBooleanField(jBandConfig, gRadioAmBandConfigFields.mStereo);
374633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    } else {
375633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return (jint)RADIO_STATUS_BAD_VALUE;
376633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
377633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
378633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return (jint)RADIO_STATUS_OK;
379633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
380633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
381633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jint
382633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentandroid_hardware_Radio_listModules(JNIEnv *env, jobject clazz,
383633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                          jobject jModules)
384633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
385633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
386633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
387633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (jModules == NULL) {
388633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        ALOGE("listModules NULL ArrayList");
389633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return RADIO_STATUS_BAD_VALUE;
390633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
391633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (!env->IsInstanceOf(jModules, gArrayListClass)) {
392633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        ALOGE("listModules not an arraylist");
393633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return RADIO_STATUS_BAD_VALUE;
394633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
395633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
396633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    unsigned int numModules = 0;
397633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    radio_properties_t *nModules = NULL;
398633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
399633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    status_t status = Radio::listModules(nModules, &numModules);
400633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (status != NO_ERROR || numModules == 0) {
401633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return (jint)status;
402633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
403633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
404633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    nModules = (radio_properties_t *)calloc(numModules, sizeof(radio_properties_t));
405633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
406633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    status = Radio::listModules(nModules, &numModules);
407633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s Radio::listModules status %d numModules %d", __FUNCTION__, status, numModules);
408633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
409633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (status != NO_ERROR) {
410633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        numModules = 0;
411633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
412633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
413633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    for (size_t i = 0; i < numModules; i++) {
414633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        if (nModules[i].num_bands == 0) {
415633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            continue;
416633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        }
417633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        ALOGV("%s module %zu id %d implementor %s product %s",
418633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent              __FUNCTION__, i, nModules[i].handle, nModules[i].implementor,
419633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent              nModules[i].product);
420633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
421633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
422633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        jobjectArray jBands = env->NewObjectArray(nModules[i].num_bands,
423633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                                  gRadioBandDescriptorClass, NULL);
424633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
425633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        for (size_t j = 0; j < nModules[i].num_bands; j++) {
426633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            jobject jBandDescriptor;
427633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            int jStatus =
428633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                    convertBandDescriptorFromNative(env, &jBandDescriptor, &nModules[i].bands[j]);
429633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            if (jStatus != RADIO_STATUS_OK) {
430633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                continue;
431633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            }
432633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            env->SetObjectArrayElement(jBands, j, jBandDescriptor);
433633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            env->DeleteLocalRef(jBandDescriptor);
434633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        }
435633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
436633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        if (env->GetArrayLength(jBands) == 0) {
437633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            continue;
438633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        }
439633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        jstring jImplementor = env->NewStringUTF(nModules[i].implementor);
440633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        jstring jProduct = env->NewStringUTF(nModules[i].product);
441633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        jstring jVersion = env->NewStringUTF(nModules[i].version);
442633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        jstring jSerial = env->NewStringUTF(nModules[i].serial);
443633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        jobject jModule = env->NewObject(gModulePropertiesClass, gModulePropertiesCstor,
444633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                               nModules[i].handle, nModules[i].class_id,
445633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                               jImplementor, jProduct, jVersion, jSerial,
446633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                               nModules[i].num_tuners,
447633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                               nModules[i].num_audio_sources,
448633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                               nModules[i].supports_capture,
449633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                               jBands);
450633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
451633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        env->DeleteLocalRef(jImplementor);
452633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        env->DeleteLocalRef(jProduct);
453633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        env->DeleteLocalRef(jVersion);
454633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        env->DeleteLocalRef(jSerial);
455633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        env->DeleteLocalRef(jBands);
456633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        if (jModule == NULL) {
457633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            continue;
458633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        }
459633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        env->CallBooleanMethod(jModules, gArrayListMethods.add, jModule);
460633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
461633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
462633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    free(nModules);
463633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return (jint) status;
464633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
465633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
466633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent// ----------------------------------------------------------------------------
467633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
468633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentclass JNIRadioCallback: public RadioCallback
469633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
470633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentpublic:
471633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    JNIRadioCallback(JNIEnv* env, jobject thiz, jobject weak_thiz);
472633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ~JNIRadioCallback();
473633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
474633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    virtual void onEvent(struct radio_event *event);
475633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
476633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentprivate:
477633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jclass      mClass;     // Reference to Radio class
478633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jobject     mObject;    // Weak ref to Radio Java object to call on
479633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent};
480633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
481633cb563f36001d6973b69291086cbdfe50612c5Eric LaurentJNIRadioCallback::JNIRadioCallback(JNIEnv* env, jobject thiz, jobject weak_thiz)
482633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
483633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
484633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    // Hold onto the RadioModule class for use in calling the static method
485633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    // that posts events to the application thread.
486633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jclass clazz = env->GetObjectClass(thiz);
487633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (clazz == NULL) {
488633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        ALOGE("Can't find class %s", kRadioModuleClassPathName);
489633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return;
490633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
491633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    mClass = (jclass)env->NewGlobalRef(clazz);
492633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
493633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    // We use a weak reference so the RadioModule object can be garbage collected.
494633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    // The reference is only used as a proxy for callbacks.
495633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    mObject  = env->NewGlobalRef(weak_thiz);
496633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
497633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
498633cb563f36001d6973b69291086cbdfe50612c5Eric LaurentJNIRadioCallback::~JNIRadioCallback()
499633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
500633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    // remove global references
501633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    JNIEnv *env = AndroidRuntime::getJNIEnv();
502633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (env == NULL) {
503633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return;
504633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
505633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    env->DeleteGlobalRef(mObject);
506633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    env->DeleteGlobalRef(mClass);
507633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
508633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
509633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentvoid JNIRadioCallback::onEvent(struct radio_event *event)
510633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
511633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    JNIEnv *env = AndroidRuntime::getJNIEnv();
512633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (env == NULL) {
513633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return;
514633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
515633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
516633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
517633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
518633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jobject jObj = NULL;
519633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jint jArg2 = 0;
520633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jint jStatus = RADIO_STATUS_OK;
521633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    switch (event->type) {
522633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        case RADIO_EVENT_CONFIG:
523633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            jStatus = convertBandConfigFromNative(env, &jObj, &event->config);
524633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            break;
525633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        case RADIO_EVENT_TUNED:
526633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        case RADIO_EVENT_AF_SWITCH:
527633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            ALOGV("%s RADIO_EVENT_TUNED channel %d", __FUNCTION__, event->info.channel);
528633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            jStatus = convertProgramInfoFromNative(env, &jObj, &event->info);
529633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            break;
530633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        case RADIO_EVENT_METADATA:
531633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            jStatus = convertMetadataFromNative(env, &jObj, event->metadata);
532633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            if (jStatus >= 0) {
533633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                jStatus = RADIO_STATUS_OK;
534633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            }
535633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            break;
536633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        case RADIO_EVENT_ANTENNA:
537633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        case RADIO_EVENT_TA:
5387058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal        case RADIO_EVENT_EA:
539633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        case RADIO_EVENT_CONTROL:
540633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            jArg2 = event->on ? 1 : 0;
541633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            break;
542633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
543633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
544633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (jStatus != RADIO_STATUS_OK) {
545633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return;
546633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
547633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
548633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                              event->type, event->status, jArg2, jObj);
549633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
550633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    env->DeleteLocalRef(jObj);
551633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (env->ExceptionCheck()) {
552633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        ALOGW("An exception occurred while notifying an event.");
553633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        env->ExceptionClear();
554633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
555633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
556633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
557633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent// ----------------------------------------------------------------------------
558633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
559633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic void
560633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentandroid_hardware_Radio_setup(JNIEnv *env, jobject thiz,
561633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                             jobject weak_this, jobject jConfig, jboolean withAudio)
562633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
563633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
564633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
565633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    setRadio(env, thiz, 0);
566633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
567633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<JNIRadioCallback> callback = new JNIRadioCallback(env, thiz, weak_this);
568633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
569633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    radio_handle_t handle = (radio_handle_t)env->GetIntField(thiz, gModuleFields.mId);
570633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
571633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    struct radio_band_config nConfig;
572633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    struct radio_band_config *configPtr = NULL;
573633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (jConfig != NULL) {
574633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        jint jStatus = convertBandConfigToNative(env, &nConfig, jConfig);
575633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        if (jStatus != RADIO_STATUS_OK) {
576633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            return;
577633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        }
578633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        configPtr = &nConfig;
579633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
580633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<Radio> module = Radio::attach(handle, configPtr, (bool)withAudio, callback);
581633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (module == 0) {
582633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return;
583633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
584633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
585633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    setRadio(env, thiz, module);
586633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
587633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
588633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic void
589633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentandroid_hardware_Radio_close(JNIEnv *env, jobject thiz)
590633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
591633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
592633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<Radio> module = setRadio(env, thiz, 0);
593633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("detach module %p", module.get());
594633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (module != 0) {
595633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        ALOGV("detach module->detach()");
596633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        module->detach();
597633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
598633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
599633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
600633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic void
601633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentandroid_hardware_Radio_finalize(JNIEnv *env, jobject thiz)
602633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
603633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
604633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<Radio> module = getRadio(env, thiz);
605633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (module != 0) {
606633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        ALOGW("Radio finalized without being detached");
607633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
608633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    android_hardware_Radio_close(env, thiz);
609633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
610633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
611633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jint
612633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentandroid_hardware_Radio_setConfiguration(JNIEnv *env, jobject thiz, jobject jConfig)
613633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
614633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
615633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<Radio> module = getRadio(env, thiz);
616633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (module == NULL) {
617633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return RADIO_STATUS_NO_INIT;
618633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
619633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
620633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (!env->IsInstanceOf(jConfig, gRadioFmBandConfigClass) &&
621633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            !env->IsInstanceOf(jConfig, gRadioAmBandConfigClass)) {
622633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return RADIO_STATUS_BAD_VALUE;
623633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
624633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
625633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    struct radio_band_config nConfig;
626633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jint jStatus = convertBandConfigToNative(env, &nConfig, jConfig);
627633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (jStatus != RADIO_STATUS_OK) {
628633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return jStatus;
629633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
630633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
631633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    status_t status = module->setConfiguration(&nConfig);
632633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return (jint)status;
633633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
634633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
635633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jint
636633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentandroid_hardware_Radio_getConfiguration(JNIEnv *env, jobject thiz, jobjectArray jConfigs)
637633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
638633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
639633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<Radio> module = getRadio(env, thiz);
640633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (module == NULL) {
641633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return RADIO_STATUS_NO_INIT;
642633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
643633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (env->GetArrayLength(jConfigs) != 1) {
644633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return (jint)RADIO_STATUS_BAD_VALUE;
645633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
646633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
647633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    struct radio_band_config nConfig;
648633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
649633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    status_t status = module->getConfiguration(&nConfig);
650633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (status != NO_ERROR) {
651633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return (jint)status;
652633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
653633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jobject jConfig;
654633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    int jStatus = convertBandConfigFromNative(env, &jConfig, &nConfig);
655633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (jStatus != RADIO_STATUS_OK) {
656633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return jStatus;
657633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
658633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    env->SetObjectArrayElement(jConfigs, 0, jConfig);
659633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    env->DeleteLocalRef(jConfig);
660633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return RADIO_STATUS_OK;
661633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
662633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
663633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jint
664633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentandroid_hardware_Radio_setMute(JNIEnv *env, jobject thiz, jboolean mute)
665633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
666633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
667633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<Radio> module = getRadio(env, thiz);
668633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (module == NULL) {
669633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return RADIO_STATUS_NO_INIT;
670633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
671633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    status_t status = module->setMute((bool)mute);
672633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return (jint)status;
673633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
674633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
675633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jboolean
676633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentandroid_hardware_Radio_getMute(JNIEnv *env, jobject thiz)
677633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
678633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
679633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<Radio> module = getRadio(env, thiz);
680633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (module == NULL) {
681633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return true;
682633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
683633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    bool mute = true;
684633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    status_t status = module->getMute(&mute);
685633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (status != NO_ERROR) {
686633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return true;
687633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
688633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return (jboolean)mute;
689633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
690633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
691633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jint
692633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentandroid_hardware_Radio_step(JNIEnv *env, jobject thiz, jint direction, jboolean skipSubChannel)
693633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
694633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
695633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<Radio> module = getRadio(env, thiz);
696633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (module == NULL) {
697633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return RADIO_STATUS_NO_INIT;
698633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
699633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    status_t status = module->step((radio_direction_t)direction, (bool)skipSubChannel);
700633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return (jint)status;
701633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
702633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
703633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jint
704633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentandroid_hardware_Radio_scan(JNIEnv *env, jobject thiz, jint direction, jboolean skipSubChannel)
705633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
706633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
707633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<Radio> module = getRadio(env, thiz);
708633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (module == NULL) {
709633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return RADIO_STATUS_NO_INIT;
710633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
711633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    status_t status = module->scan((radio_direction_t)direction, (bool)skipSubChannel);
712633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return (jint)status;
713633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
714633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
715633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jint
716633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentandroid_hardware_Radio_tune(JNIEnv *env, jobject thiz, jint channel, jint subChannel)
717633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
718633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
719633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<Radio> module = getRadio(env, thiz);
720633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (module == NULL) {
721633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return RADIO_STATUS_NO_INIT;
722633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
723633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    status_t status = module->tune((unsigned int)channel, (unsigned int)subChannel);
724633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return (jint)status;
725633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
726633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
727633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jint
728633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentandroid_hardware_Radio_cancel(JNIEnv *env, jobject thiz)
729633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
730633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
731633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<Radio> module = getRadio(env, thiz);
732633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (module == NULL) {
733633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return RADIO_STATUS_NO_INIT;
734633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
735633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    status_t status = module->cancel();
736633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return (jint)status;
737633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
738633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
739633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jint
740633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentandroid_hardware_Radio_getProgramInformation(JNIEnv *env, jobject thiz, jobjectArray jInfos)
741633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
742633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
743633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<Radio> module = getRadio(env, thiz);
744633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (module == NULL) {
745633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return RADIO_STATUS_NO_INIT;
746633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
747633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (env->GetArrayLength(jInfos) != 1) {
748633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return (jint)RADIO_STATUS_BAD_VALUE;
749633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
750633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
751633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    struct radio_program_info nInfo;
752633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    radio_metadata_allocate(&nInfo.metadata, 0, 0);
753633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jobject jInfo = NULL;
754633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    int jStatus;
755633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
756633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jStatus = (int)module->getProgramInformation(&nInfo);
757633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (jStatus != RADIO_STATUS_OK) {
758633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        goto exit;
759633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
760633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jStatus = convertProgramInfoFromNative(env, &jInfo, &nInfo);
761633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (jStatus != RADIO_STATUS_OK) {
762633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        goto exit;
763633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
764633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    env->SetObjectArrayElement(jInfos, 0, jInfo);
765633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
766633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentexit:
767633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (jInfo != NULL) {
768633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        env->DeleteLocalRef(jInfo);
769633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
770633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    radio_metadata_deallocate(nInfo.metadata);
771633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return jStatus;
772633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
773633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
774633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jboolean
775633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentandroid_hardware_Radio_isAntennaConnected(JNIEnv *env, jobject thiz)
776633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
777633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
778633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<Radio> module = getRadio(env, thiz);
779633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (module == NULL) {
780633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return false;
781633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
782633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
783633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    struct radio_band_config nConfig;
784633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
785633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    status_t status = module->getConfiguration(&nConfig);
786633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (status != NO_ERROR) {
787633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return false;
788633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
789633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
790633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return (jboolean)nConfig.band.antenna_connected;
791633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
792633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
793633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
794633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic jboolean
795633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentandroid_hardware_Radio_hasControl(JNIEnv *env, jobject thiz)
796633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
797633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGV("%s", __FUNCTION__);
798633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    sp<Radio> module = getRadio(env, thiz);
799633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (module == NULL) {
800633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return false;
801633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
802633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
803633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    bool hasControl;
804633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    status_t status = module->hasControl(&hasControl);
805633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    if (status != NO_ERROR) {
806633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        return false;
807633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    }
808633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
809633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return (jboolean)hasControl;
810633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
811633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
812633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
813633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic JNINativeMethod gMethods[] = {
814633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    {"listModules",
815633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        "(Ljava/util/List;)I",
816633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        (void *)android_hardware_Radio_listModules},
817633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent};
818633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
819633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentstatic JNINativeMethod gModuleMethods[] = {
820633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    {"native_setup",
821633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        "(Ljava/lang/Object;Landroid/hardware/radio/RadioManager$BandConfig;Z)V",
822633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        (void *)android_hardware_Radio_setup},
823633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    {"native_finalize",
824633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        "()V",
825633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        (void *)android_hardware_Radio_finalize},
826633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    {"close",
827633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        "()V",
828633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        (void *)android_hardware_Radio_close},
829633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    {"setConfiguration",
830633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        "(Landroid/hardware/radio/RadioManager$BandConfig;)I",
831633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        (void *)android_hardware_Radio_setConfiguration},
832633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    {"getConfiguration",
833633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        "([Landroid/hardware/radio/RadioManager$BandConfig;)I",
834633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        (void *)android_hardware_Radio_getConfiguration},
835633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    {"setMute",
836633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        "(Z)I",
837633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        (void *)android_hardware_Radio_setMute},
838633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    {"getMute",
839633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        "()Z",
840633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        (void *)android_hardware_Radio_getMute},
841633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    {"step",
842633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        "(IZ)I",
843633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        (void *)android_hardware_Radio_step},
844633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    {"scan",
845633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        "(IZ)I",
846633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        (void *)android_hardware_Radio_scan},
847633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    {"tune",
848633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        "(II)I",
849633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        (void *)android_hardware_Radio_tune},
850633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    {"cancel",
851633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        "()I",
852633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        (void *)android_hardware_Radio_cancel},
853633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    {"getProgramInformation",
854633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        "([Landroid/hardware/radio/RadioManager$ProgramInfo;)I",
855633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        (void *)android_hardware_Radio_getProgramInformation},
856633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    {"isAntennaConnected",
857633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        "()Z",
858633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        (void *)android_hardware_Radio_isAntennaConnected},
859633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    {"hasControl",
860633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        "()Z",
861633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent        (void *)android_hardware_Radio_hasControl},
862633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent};
863633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
864633cb563f36001d6973b69291086cbdfe50612c5Eric Laurentint register_android_hardware_Radio(JNIEnv *env)
865633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent{
866633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
867633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
868633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
869633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
870633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jclass lClass = FindClassOrDie(env, kRadioManagerClassPathName);
871633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioManagerClass = MakeGlobalRefOrDie(env, lClass);
872633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
873633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jclass moduleClass = FindClassOrDie(env, kRadioModuleClassPathName);
874633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioModuleClass = MakeGlobalRefOrDie(env, moduleClass);
875633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gPostEventFromNative = GetStaticMethodIDOrDie(env, moduleClass, "postEventFromNative",
876633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                                  "(Ljava/lang/Object;IIILjava/lang/Object;)V");
877633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gModuleFields.mNativeContext = GetFieldIDOrDie(env, moduleClass, "mNativeContext", "J");
878633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gModuleFields.mId = GetFieldIDOrDie(env, moduleClass, "mId", "I");
879633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
880633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jclass modulePropertiesClass = FindClassOrDie(env, kModulePropertiesClassPathName);
881633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gModulePropertiesClass = MakeGlobalRefOrDie(env, modulePropertiesClass);
882633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gModulePropertiesCstor = GetMethodIDOrDie(env, modulePropertiesClass, "<init>",
883633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            "(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIZ[Landroid/hardware/radio/RadioManager$BandDescriptor;)V");
884633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
885633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jclass bandDescriptorClass = FindClassOrDie(env, kRadioBandDescriptorClassPathName);
886633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioBandDescriptorClass = MakeGlobalRefOrDie(env, bandDescriptorClass);
887633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioBandDescriptorFields.mRegion = GetFieldIDOrDie(env, bandDescriptorClass, "mRegion", "I");
888633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioBandDescriptorFields.mType = GetFieldIDOrDie(env, bandDescriptorClass, "mType", "I");
889633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioBandDescriptorFields.mLowerLimit =
890633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            GetFieldIDOrDie(env, bandDescriptorClass, "mLowerLimit", "I");
891633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioBandDescriptorFields.mUpperLimit =
892633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            GetFieldIDOrDie(env, bandDescriptorClass, "mUpperLimit", "I");
893633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioBandDescriptorFields.mSpacing =
894633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            GetFieldIDOrDie(env, bandDescriptorClass, "mSpacing", "I");
895633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
896633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jclass fmBandDescriptorClass = FindClassOrDie(env, kRadioFmBandDescriptorClassPathName);
897633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioFmBandDescriptorClass = MakeGlobalRefOrDie(env, fmBandDescriptorClass);
898633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioFmBandDescriptorCstor = GetMethodIDOrDie(env, fmBandDescriptorClass, "<init>",
8997058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal            "(IIIIIZZZZZ)V");
900633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
901633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jclass amBandDescriptorClass = FindClassOrDie(env, kRadioAmBandDescriptorClassPathName);
902633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioAmBandDescriptorClass = MakeGlobalRefOrDie(env, amBandDescriptorClass);
903633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioAmBandDescriptorCstor = GetMethodIDOrDie(env, amBandDescriptorClass, "<init>",
904633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            "(IIIIIZ)V");
905633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
906633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jclass bandConfigClass = FindClassOrDie(env, kRadioBandConfigClassPathName);
907633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioBandConfigClass = MakeGlobalRefOrDie(env, bandConfigClass);
908633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioBandConfigFields.mDescriptor =
909633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            GetFieldIDOrDie(env, bandConfigClass, "mDescriptor",
910633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                            "Landroid/hardware/radio/RadioManager$BandDescriptor;");
911633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
912633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jclass fmBandConfigClass = FindClassOrDie(env, kRadioFmBandConfigClassPathName);
913633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioFmBandConfigClass = MakeGlobalRefOrDie(env, fmBandConfigClass);
914633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioFmBandConfigCstor = GetMethodIDOrDie(env, fmBandConfigClass, "<init>",
9157058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal            "(IIIIIZZZZZ)V");
916633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioFmBandConfigFields.mStereo = GetFieldIDOrDie(env, fmBandConfigClass, "mStereo", "Z");
917633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioFmBandConfigFields.mRds = GetFieldIDOrDie(env, fmBandConfigClass, "mRds", "Z");
918633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioFmBandConfigFields.mTa = GetFieldIDOrDie(env, fmBandConfigClass, "mTa", "Z");
919633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioFmBandConfigFields.mAf = GetFieldIDOrDie(env, fmBandConfigClass, "mAf", "Z");
9207058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal    gRadioFmBandConfigFields.mEa =
9217058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal        GetFieldIDOrDie(env, fmBandConfigClass, "mEa", "Z");
922633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
923633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
924633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jclass amBandConfigClass = FindClassOrDie(env, kRadioAmBandConfigClassPathName);
925633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioAmBandConfigClass = MakeGlobalRefOrDie(env, amBandConfigClass);
926633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioAmBandConfigCstor = GetMethodIDOrDie(env, amBandConfigClass, "<init>",
927633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            "(IIIIIZ)V");
928633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioAmBandConfigFields.mStereo = GetFieldIDOrDie(env, amBandConfigClass, "mStereo", "Z");
929633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
930633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jclass programInfoClass = FindClassOrDie(env, kRadioProgramInfoClassPathName);
931633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioProgramInfoClass = MakeGlobalRefOrDie(env, programInfoClass);
932633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioProgramInfoCstor = GetMethodIDOrDie(env, programInfoClass, "<init>",
933633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent            "(IIZZZILandroid/hardware/radio/RadioMetadata;)V");
934633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
935633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    jclass metadataClass = FindClassOrDie(env, kRadioMetadataClassPathName);
936633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioMetadataClass = MakeGlobalRefOrDie(env, metadataClass);
937633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioMetadataCstor = GetMethodIDOrDie(env, metadataClass, "<init>", "()V");
938633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioMetadataMethods.putIntFromNative = GetMethodIDOrDie(env, metadataClass,
939633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                                              "putIntFromNative",
940633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                                              "(II)I");
941633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioMetadataMethods.putStringFromNative = GetMethodIDOrDie(env, metadataClass,
942633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                                                 "putStringFromNative",
943633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                                                 "(ILjava/lang/String;)I");
944633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    gRadioMetadataMethods.putBitmapFromNative = GetMethodIDOrDie(env, metadataClass,
945633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                                                 "putBitmapFromNative",
946633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent                                                                 "(I[B)I");
9477058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal    gRadioMetadataMethods.putClockFromNative = GetMethodIDOrDie(env, metadataClass,
9487058e4ca585a06462a495d021d61e1fd27f85cd2Sanket Agarwal                                                                "putClockFromNative",
949a00acdd1b444d379c5f3699cd307f3a50f530194Sanket Agarwal                                                                "(IJI)I");
950633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
951633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
952633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    RegisterMethodsOrDie(env, kRadioManagerClassPathName, gMethods, NELEM(gMethods));
953633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
954633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    int ret = RegisterMethodsOrDie(env, kRadioModuleClassPathName, gModuleMethods, NELEM(gModuleMethods));
955633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
956633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    ALOGI("%s DONE", __FUNCTION__);
957633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent
958633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent    return ret;
959633cb563f36001d6973b69291086cbdfe50612c5Eric Laurent}
960