• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef _ANDROID_MEDIA_VOLUME_SHAPER_H_
18 #define _ANDROID_MEDIA_VOLUME_SHAPER_H_
19 
20 #include <media/VolumeShaper.h>
21 
22 namespace android {
23 
24 // This entire class is inline as it is used from both core and media
25 struct VolumeShaperHelper {
26     struct fields_t {
27         // VolumeShaper.Configuration
28         jclass    coClazz;
29         jmethodID coConstructId;
30         jfieldID  coTypeId;
31         jfieldID  coIdId;
32         jfieldID  coOptionFlagsId;
33         jfieldID  coDurationMsId;
34         jfieldID  coInterpolatorTypeId;
35         jfieldID  coTimesId;
36         jfieldID  coVolumesId;
37 
38         // VolumeShaper.Operation
39         jclass    opClazz;
40         jmethodID opConstructId;
41         jfieldID  opFlagsId;
42         jfieldID  opReplaceIdId;
43         jfieldID  opXOffsetId;
44 
45         // VolumeShaper.State
46         jclass    stClazz;
47         jmethodID stConstructId;
48         jfieldID  stVolumeId;
49         jfieldID  stXOffsetId;
50 
initVolumeShaperHelper::fields_t51         void init(JNIEnv *env) {
52             jclass lclazz = env->FindClass("android/media/VolumeShaper$Configuration");
53             if (lclazz == nullptr) {
54                 return;
55             }
56             coClazz = (jclass)env->NewGlobalRef(lclazz);
57             if (coClazz == nullptr) {
58                 return;
59             }
60             coConstructId = env->GetMethodID(coClazz, "<init>", "(IIIDI[F[F)V");
61             coTypeId = env->GetFieldID(coClazz, "mType", "I");
62             coIdId = env->GetFieldID(coClazz, "mId", "I");
63             coOptionFlagsId = env->GetFieldID(coClazz, "mOptionFlags", "I");
64             coDurationMsId = env->GetFieldID(coClazz, "mDurationMs", "D");
65             coInterpolatorTypeId = env->GetFieldID(coClazz, "mInterpolatorType", "I");
66             coTimesId = env->GetFieldID(coClazz, "mTimes", "[F");
67             coVolumesId = env->GetFieldID(coClazz, "mVolumes", "[F");
68             env->DeleteLocalRef(lclazz);
69 
70             lclazz = env->FindClass("android/media/VolumeShaper$Operation");
71             if (lclazz == nullptr) {
72                 return;
73             }
74             opClazz = (jclass)env->NewGlobalRef(lclazz);
75             if (opClazz == nullptr) {
76                 return;
77             }
78             opConstructId = env->GetMethodID(opClazz, "<init>", "(IIF)V");
79             opFlagsId = env->GetFieldID(opClazz, "mFlags", "I");
80             opReplaceIdId = env->GetFieldID(opClazz, "mReplaceId", "I");
81             opXOffsetId = env->GetFieldID(opClazz, "mXOffset", "F");
82             env->DeleteLocalRef(lclazz);
83 
84             lclazz = env->FindClass("android/media/VolumeShaper$State");
85             if (lclazz == nullptr) {
86                 return;
87             }
88             stClazz = (jclass)env->NewGlobalRef(lclazz);
89             if (stClazz == nullptr) {
90                 return;
91             }
92             stConstructId = env->GetMethodID(stClazz, "<init>", "(FF)V");
93             stVolumeId = env->GetFieldID(stClazz, "mVolume", "F");
94             stXOffsetId = env->GetFieldID(stClazz, "mXOffset", "F");
95             env->DeleteLocalRef(lclazz);
96         }
97 
exitVolumeShaperHelper::fields_t98         void exit(JNIEnv *env) {
99             env->DeleteGlobalRef(coClazz);
100             coClazz = nullptr;
101         }
102     };
103 
convertJobjectToConfigurationVolumeShaperHelper104     static sp<VolumeShaper::Configuration> convertJobjectToConfiguration(
105             JNIEnv *env, const fields_t &fields, jobject jshaper) {
106         sp<VolumeShaper::Configuration> configuration = new VolumeShaper::Configuration();
107 
108         configuration->setType(
109             (VolumeShaper::Configuration::Type)env->GetIntField(jshaper, fields.coTypeId));
110         configuration->setId(
111             (int)env->GetIntField(jshaper, fields.coIdId));
112         if (configuration->getType() == VolumeShaper::Configuration::TYPE_SCALE) {
113             configuration->setOptionFlags(
114                 (VolumeShaper::Configuration::OptionFlag)
115                 env->GetIntField(jshaper, fields.coOptionFlagsId));
116             configuration->setDurationMs(
117                     (double)env->GetDoubleField(jshaper, fields.coDurationMsId));
118             configuration->setInterpolatorType(
119                 (VolumeShaper::Configuration::InterpolatorType)
120                 env->GetIntField(jshaper, fields.coInterpolatorTypeId));
121 
122             // convert point arrays
123             jobject xobj = env->GetObjectField(jshaper, fields.coTimesId);
124             jfloatArray *xarray = reinterpret_cast<jfloatArray*>(&xobj);
125             jsize xlen = env->GetArrayLength(*xarray);
126             /* const */ float * const x =
127                     env->GetFloatArrayElements(*xarray, nullptr /* isCopy */);
128             jobject yobj = env->GetObjectField(jshaper, fields.coVolumesId);
129             jfloatArray *yarray = reinterpret_cast<jfloatArray*>(&yobj);
130             jsize ylen = env->GetArrayLength(*yarray);
131             /* const */ float * const y =
132                     env->GetFloatArrayElements(*yarray, nullptr /* isCopy */);
133             if (xlen != ylen) {
134                 ALOGE("array size must match");
135                 return nullptr;
136             }
137             for (jsize i = 0; i < xlen; ++i) {
138                 configuration->emplace(x[i], y[i]);
139             }
140             env->ReleaseFloatArrayElements(*xarray, x, JNI_ABORT); // no need to copy back
141             env->ReleaseFloatArrayElements(*yarray, y, JNI_ABORT);
142         }
143         return configuration;
144     }
145 
convertVolumeShaperToJobjectVolumeShaperHelper146     static jobject convertVolumeShaperToJobject(
147             JNIEnv *env, const fields_t &fields,
148             const sp<VolumeShaper::Configuration> &configuration) {
149         jfloatArray xarray = nullptr;
150         jfloatArray yarray = nullptr;
151         if (configuration->getType() == VolumeShaper::Configuration::TYPE_SCALE) {
152             // convert curve arrays
153             jfloatArray xarray = env->NewFloatArray(configuration->size());
154             jfloatArray yarray = env->NewFloatArray(configuration->size());
155             float * const x = env->GetFloatArrayElements(xarray, nullptr /* isCopy */);
156             float * const y = env->GetFloatArrayElements(yarray, nullptr /* isCopy */);
157             float *xptr = x, *yptr = y;
158             for (const auto &pt : *configuration.get()) {
159                 *xptr++ = pt.first;
160                 *yptr++ = pt.second;
161             }
162             env->ReleaseFloatArrayElements(xarray, x, 0 /* mode */);
163             env->ReleaseFloatArrayElements(yarray, y, 0 /* mode */);
164         }
165 
166         // prepare constructor args
167         jvalue args[7];
168         args[0].i = (jint)configuration->getType();
169         args[1].i = (jint)configuration->getId();
170         args[2].i = (jint)configuration->getOptionFlags();
171         args[3].d = (jdouble)configuration->getDurationMs();
172         args[4].i = (jint)configuration->getInterpolatorType();
173         args[5].l = xarray;
174         args[6].l = yarray;
175         jobject jshaper = env->NewObjectA(fields.coClazz, fields.coConstructId, args);
176         return jshaper;
177     }
178 
convertJobjectToOperationVolumeShaperHelper179     static sp<VolumeShaper::Operation> convertJobjectToOperation(
180             JNIEnv *env, const fields_t &fields, jobject joperation) {
181         VolumeShaper::Operation::Flag flags =
182             (VolumeShaper::Operation::Flag)env->GetIntField(joperation, fields.opFlagsId);
183         int replaceId = env->GetIntField(joperation, fields.opReplaceIdId);
184         float xOffset = env->GetFloatField(joperation, fields.opXOffsetId);
185 
186         sp<VolumeShaper::Operation> operation =
187                 new VolumeShaper::Operation(flags, replaceId, xOffset);
188         return operation;
189     }
190 
convertOperationToJobjectVolumeShaperHelper191     static jobject convertOperationToJobject(
192             JNIEnv *env, const fields_t &fields, const sp<VolumeShaper::Operation> &operation) {
193         // prepare constructor args
194         jvalue args[3];
195         args[0].i = (jint)operation->getFlags();
196         args[1].i = (jint)operation->getReplaceId();
197         args[2].f = (jfloat)operation->getXOffset();
198 
199         jobject joperation = env->NewObjectA(fields.opClazz, fields.opConstructId, args);
200         return joperation;
201     }
202 
convertJobjectToStateVolumeShaperHelper203     static sp<VolumeShaper::State> convertJobjectToState(
204             JNIEnv *env, const fields_t &fields, jobject jstate) {
205         float volume = env->GetFloatField(jstate, fields.stVolumeId);
206         float xOffset = env->GetFloatField(jstate, fields.stXOffsetId);
207 
208         sp<VolumeShaper::State> state = new VolumeShaper::State(volume, xOffset);
209         return state;
210     }
211 
convertStateToJobjectVolumeShaperHelper212     static jobject convertStateToJobject(
213             JNIEnv *env, const fields_t &fields, const sp<VolumeShaper::State> &state) {
214         // prepare constructor args
215         jvalue args[2];
216         args[0].f = (jfloat)state->getVolume();
217         args[1].f = (jfloat)state->getXOffset();
218 
219         jobject jstate = env->NewObjectA(fields.stClazz, fields.stConstructId, args);
220         return jstate;
221     }
222 };
223 
224 }  // namespace android
225 
226 #endif // _ANDROID_MEDIA_VOLUME_SHAPER_H_
227