1035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung/*
2035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * Copyright 2017, The Android Open Source Project
3035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung *
4035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * Licensed under the Apache License, Version 2.0 (the "License");
5035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * you may not use this file except in compliance with the License.
6035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * You may obtain a copy of the License at
7035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung *
8035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung *     http://www.apache.org/licenses/LICENSE-2.0
9035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung *
10035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * Unless required by applicable law or agreed to in writing, software
11035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * distributed under the License is distributed on an "AS IS" BASIS,
12035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * See the License for the specific language governing permissions and
14035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * limitations under the License.
15035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung */
16035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
17035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung#ifndef _ANDROID_MEDIA_VOLUME_SHAPER_H_
18035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung#define _ANDROID_MEDIA_VOLUME_SHAPER_H_
19035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
20035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung#include <media/VolumeShaper.h>
21035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
22035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hungnamespace android {
23035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
24330d876a6273ca8e957933d7e63aaed577883e34Ivan Lozanousing media::VolumeShaper;
25330d876a6273ca8e957933d7e63aaed577883e34Ivan Lozano
26035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung// This entire class is inline as it is used from both core and media
27035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hungstruct VolumeShaperHelper {
28035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    struct fields_t {
29035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        // VolumeShaper.Configuration
30035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jclass    coClazz;
31035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jmethodID coConstructId;
32035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jfieldID  coTypeId;
33035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jfieldID  coIdId;
34035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jfieldID  coOptionFlagsId;
35035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jfieldID  coDurationMsId;
36d4f1e86190fbe6b280635902a3cd734d65eded52Andy Hung        jfieldID  coInterpolatorTypeId;
37035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jfieldID  coTimesId;
38035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jfieldID  coVolumesId;
39035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
40035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        // VolumeShaper.Operation
41035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jclass    opClazz;
42035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jmethodID opConstructId;
43035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jfieldID  opFlagsId;
44035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jfieldID  opReplaceIdId;
453c0f5d296e61d38e4bf4396d87cd4f59fdde32c4Andy Hung        jfieldID  opXOffsetId;
46035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
47035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        // VolumeShaper.State
48035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jclass    stClazz;
49035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jmethodID stConstructId;
50035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jfieldID  stVolumeId;
51035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jfieldID  stXOffsetId;
52035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
53035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        void init(JNIEnv *env) {
54035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            jclass lclazz = env->FindClass("android/media/VolumeShaper$Configuration");
55035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            if (lclazz == nullptr) {
56035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                return;
57035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            }
58035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            coClazz = (jclass)env->NewGlobalRef(lclazz);
59035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            if (coClazz == nullptr) {
60035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                return;
61035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            }
62d4f1e86190fbe6b280635902a3cd734d65eded52Andy Hung            coConstructId = env->GetMethodID(coClazz, "<init>", "(IIIDI[F[F)V");
63035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            coTypeId = env->GetFieldID(coClazz, "mType", "I");
64035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            coIdId = env->GetFieldID(coClazz, "mId", "I");
65035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            coOptionFlagsId = env->GetFieldID(coClazz, "mOptionFlags", "I");
66035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            coDurationMsId = env->GetFieldID(coClazz, "mDurationMs", "D");
67d4f1e86190fbe6b280635902a3cd734d65eded52Andy Hung            coInterpolatorTypeId = env->GetFieldID(coClazz, "mInterpolatorType", "I");
68035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            coTimesId = env->GetFieldID(coClazz, "mTimes", "[F");
69035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            coVolumesId = env->GetFieldID(coClazz, "mVolumes", "[F");
70035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            env->DeleteLocalRef(lclazz);
71035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
72035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            lclazz = env->FindClass("android/media/VolumeShaper$Operation");
73035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            if (lclazz == nullptr) {
74035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                return;
75035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            }
76035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            opClazz = (jclass)env->NewGlobalRef(lclazz);
77035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            if (opClazz == nullptr) {
78035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                return;
79035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            }
803c0f5d296e61d38e4bf4396d87cd4f59fdde32c4Andy Hung            opConstructId = env->GetMethodID(opClazz, "<init>", "(IIF)V");
81035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            opFlagsId = env->GetFieldID(opClazz, "mFlags", "I");
82035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            opReplaceIdId = env->GetFieldID(opClazz, "mReplaceId", "I");
833c0f5d296e61d38e4bf4396d87cd4f59fdde32c4Andy Hung            opXOffsetId = env->GetFieldID(opClazz, "mXOffset", "F");
84035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            env->DeleteLocalRef(lclazz);
85035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
86035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            lclazz = env->FindClass("android/media/VolumeShaper$State");
87035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            if (lclazz == nullptr) {
88035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                return;
89035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            }
90035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            stClazz = (jclass)env->NewGlobalRef(lclazz);
91035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            if (stClazz == nullptr) {
92035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                return;
93035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            }
94035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            stConstructId = env->GetMethodID(stClazz, "<init>", "(FF)V");
95035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            stVolumeId = env->GetFieldID(stClazz, "mVolume", "F");
96035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            stXOffsetId = env->GetFieldID(stClazz, "mXOffset", "F");
97035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            env->DeleteLocalRef(lclazz);
98035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        }
99035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
100035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        void exit(JNIEnv *env) {
101035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            env->DeleteGlobalRef(coClazz);
102035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            coClazz = nullptr;
103035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        }
104035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    };
105035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
106035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    static sp<VolumeShaper::Configuration> convertJobjectToConfiguration(
107035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            JNIEnv *env, const fields_t &fields, jobject jshaper) {
108035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        sp<VolumeShaper::Configuration> configuration = new VolumeShaper::Configuration();
109035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
110035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        configuration->setType(
111035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            (VolumeShaper::Configuration::Type)env->GetIntField(jshaper, fields.coTypeId));
112035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        configuration->setId(
113035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            (int)env->GetIntField(jshaper, fields.coIdId));
114035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        if (configuration->getType() == VolumeShaper::Configuration::TYPE_SCALE) {
115035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            configuration->setOptionFlags(
116035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                (VolumeShaper::Configuration::OptionFlag)
117035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                env->GetIntField(jshaper, fields.coOptionFlagsId));
118035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            configuration->setDurationMs(
119035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                    (double)env->GetDoubleField(jshaper, fields.coDurationMsId));
120d4f1e86190fbe6b280635902a3cd734d65eded52Andy Hung            configuration->setInterpolatorType(
121d4f1e86190fbe6b280635902a3cd734d65eded52Andy Hung                (VolumeShaper::Configuration::InterpolatorType)
122d4f1e86190fbe6b280635902a3cd734d65eded52Andy Hung                env->GetIntField(jshaper, fields.coInterpolatorTypeId));
123035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
124035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            // convert point arrays
125035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            jobject xobj = env->GetObjectField(jshaper, fields.coTimesId);
126035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            jfloatArray *xarray = reinterpret_cast<jfloatArray*>(&xobj);
127035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            jsize xlen = env->GetArrayLength(*xarray);
128035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            /* const */ float * const x =
129035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                    env->GetFloatArrayElements(*xarray, nullptr /* isCopy */);
130035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            jobject yobj = env->GetObjectField(jshaper, fields.coVolumesId);
131035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            jfloatArray *yarray = reinterpret_cast<jfloatArray*>(&yobj);
132035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            jsize ylen = env->GetArrayLength(*yarray);
133035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            /* const */ float * const y =
134035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                    env->GetFloatArrayElements(*yarray, nullptr /* isCopy */);
135035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            if (xlen != ylen) {
136035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                ALOGE("array size must match");
137035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                return nullptr;
138035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            }
139035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            for (jsize i = 0; i < xlen; ++i) {
140035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                configuration->emplace(x[i], y[i]);
141035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            }
142035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            env->ReleaseFloatArrayElements(*xarray, x, JNI_ABORT); // no need to copy back
143035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            env->ReleaseFloatArrayElements(*yarray, y, JNI_ABORT);
144035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        }
145035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        return configuration;
146035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    }
147035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
148035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    static jobject convertVolumeShaperToJobject(
149035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            JNIEnv *env, const fields_t &fields,
150035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            const sp<VolumeShaper::Configuration> &configuration) {
151035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jfloatArray xarray = nullptr;
152035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jfloatArray yarray = nullptr;
153035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        if (configuration->getType() == VolumeShaper::Configuration::TYPE_SCALE) {
154035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            // convert curve arrays
155035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            jfloatArray xarray = env->NewFloatArray(configuration->size());
156035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            jfloatArray yarray = env->NewFloatArray(configuration->size());
157035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            float * const x = env->GetFloatArrayElements(xarray, nullptr /* isCopy */);
158035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            float * const y = env->GetFloatArrayElements(yarray, nullptr /* isCopy */);
159035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            float *xptr = x, *yptr = y;
160035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            for (const auto &pt : *configuration.get()) {
161035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                *xptr++ = pt.first;
162035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung                *yptr++ = pt.second;
163035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            }
164035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            env->ReleaseFloatArrayElements(xarray, x, 0 /* mode */);
165035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            env->ReleaseFloatArrayElements(yarray, y, 0 /* mode */);
166035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        }
167035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
168035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        // prepare constructor args
169035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jvalue args[7];
170035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        args[0].i = (jint)configuration->getType();
171035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        args[1].i = (jint)configuration->getId();
172d4f1e86190fbe6b280635902a3cd734d65eded52Andy Hung        args[2].i = (jint)configuration->getOptionFlags();
173d4f1e86190fbe6b280635902a3cd734d65eded52Andy Hung        args[3].d = (jdouble)configuration->getDurationMs();
174d4f1e86190fbe6b280635902a3cd734d65eded52Andy Hung        args[4].i = (jint)configuration->getInterpolatorType();
175035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        args[5].l = xarray;
176035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        args[6].l = yarray;
177035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jobject jshaper = env->NewObjectA(fields.coClazz, fields.coConstructId, args);
178035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        return jshaper;
179035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    }
180035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
181035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    static sp<VolumeShaper::Operation> convertJobjectToOperation(
182035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            JNIEnv *env, const fields_t &fields, jobject joperation) {
183035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        VolumeShaper::Operation::Flag flags =
184035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            (VolumeShaper::Operation::Flag)env->GetIntField(joperation, fields.opFlagsId);
185035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        int replaceId = env->GetIntField(joperation, fields.opReplaceIdId);
1863c0f5d296e61d38e4bf4396d87cd4f59fdde32c4Andy Hung        float xOffset = env->GetFloatField(joperation, fields.opXOffsetId);
187035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
1883c0f5d296e61d38e4bf4396d87cd4f59fdde32c4Andy Hung        sp<VolumeShaper::Operation> operation =
1893c0f5d296e61d38e4bf4396d87cd4f59fdde32c4Andy Hung                new VolumeShaper::Operation(flags, replaceId, xOffset);
190035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        return operation;
191035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    }
192035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
193035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    static jobject convertOperationToJobject(
194035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            JNIEnv *env, const fields_t &fields, const sp<VolumeShaper::Operation> &operation) {
195035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        // prepare constructor args
1963c0f5d296e61d38e4bf4396d87cd4f59fdde32c4Andy Hung        jvalue args[3];
197035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        args[0].i = (jint)operation->getFlags();
198035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        args[1].i = (jint)operation->getReplaceId();
1993c0f5d296e61d38e4bf4396d87cd4f59fdde32c4Andy Hung        args[2].f = (jfloat)operation->getXOffset();
200035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
201035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jobject joperation = env->NewObjectA(fields.opClazz, fields.opConstructId, args);
202035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        return joperation;
203035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    }
204035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
205035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    static sp<VolumeShaper::State> convertJobjectToState(
206035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            JNIEnv *env, const fields_t &fields, jobject jstate) {
207035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        float volume = env->GetFloatField(jstate, fields.stVolumeId);
208035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        float xOffset = env->GetFloatField(jstate, fields.stXOffsetId);
209035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
210035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        sp<VolumeShaper::State> state = new VolumeShaper::State(volume, xOffset);
211035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        return state;
212035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    }
213035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
214035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    static jobject convertStateToJobject(
215035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            JNIEnv *env, const fields_t &fields, const sp<VolumeShaper::State> &state) {
216035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        // prepare constructor args
217035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jvalue args[2];
218035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        args[0].f = (jfloat)state->getVolume();
219035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        args[1].f = (jfloat)state->getXOffset();
220035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
221035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        jobject jstate = env->NewObjectA(fields.stClazz, fields.stConstructId, args);
222035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        return jstate;
223035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    }
224035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung};
225035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
226035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung}  // namespace android
227035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
228035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung#endif // _ANDROID_MEDIA_VOLUME_SHAPER_H_
229