AIDLize createEffect params

As part of the effort to convert IAudioFlinger to AIDL, converting
some of the method arguments to pure AIDL and making their
signatures more AIDL-friendly, by avoiding multiple primitive
return value.

Test: Audio-related CTS tests from CtsMediaTestCases
Change-Id: I720ff197ae5ffd50afa8d23f8fd6f19a2246e974
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 9a6bfab..56597e3 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -284,6 +284,14 @@
     return std::string(String8(legacy).c_str());
 }
 
+ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl) {
+    return String8(aidl.data(), aidl.size());
+}
+
+ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy) {
+    return std::string(legacy.c_str());
+}
+
 // The legacy enum is unnamed. Thus, we use int.
 ConversionResult<int> aidl2legacy_AudioPortConfigType(media::AudioPortConfigType aidl) {
     switch (aidl) {
@@ -1695,4 +1703,59 @@
     return aidl;
 }
 
+ConversionResult<audio_uuid_t>
+aidl2legacy_AudioUuid_audio_uuid_t(const media::AudioUuid& aidl) {
+    audio_uuid_t legacy;
+    legacy.timeLow = VALUE_OR_RETURN(convertReinterpret<uint32_t>(aidl.timeLow));
+    legacy.timeMid = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeMid));
+    legacy.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeHiAndVersion));
+    legacy.clockSeq = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.clockSeq));
+    if (aidl.node.size() != std::size(legacy.node)) {
+        return unexpected(BAD_VALUE);
+    }
+    std::copy(aidl.node.begin(), aidl.node.end(), legacy.node);
+    return legacy;
+}
+
+ConversionResult<media::AudioUuid>
+legacy2aidl_audio_uuid_t_AudioUuid(const audio_uuid_t& legacy) {
+    media::AudioUuid aidl;
+    aidl.timeLow = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.timeLow));
+    aidl.timeMid = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeMid));
+    aidl.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeHiAndVersion));
+    aidl.clockSeq = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.clockSeq));
+    std::copy(legacy.node, legacy.node + std::size(legacy.node), std::back_inserter(aidl.node));
+    return aidl;
+}
+
+ConversionResult<effect_descriptor_t>
+aidl2legacy_EffectDescriptor_effect_descriptor_t(const media::EffectDescriptor& aidl) {
+    effect_descriptor_t legacy;
+    legacy.type = VALUE_OR_RETURN(aidl2legacy_AudioUuid_audio_uuid_t(aidl.type));
+    legacy.uuid = VALUE_OR_RETURN(aidl2legacy_AudioUuid_audio_uuid_t(aidl.uuid));
+    legacy.apiVersion = VALUE_OR_RETURN(convertReinterpret<uint32_t>(aidl.apiVersion));
+    legacy.flags = VALUE_OR_RETURN(convertReinterpret<uint32_t>(aidl.flags));
+    legacy.cpuLoad = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.cpuLoad));
+    legacy.memoryUsage = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.memoryUsage));
+    RETURN_IF_ERROR(aidl2legacy_string(aidl.name, legacy.name, sizeof(legacy.name)));
+    RETURN_IF_ERROR(
+            aidl2legacy_string(aidl.implementor, legacy.implementor, sizeof(legacy.implementor)));
+    return legacy;
+}
+
+ConversionResult<media::EffectDescriptor>
+legacy2aidl_effect_descriptor_t_EffectDescriptor(const effect_descriptor_t& legacy) {
+    media::EffectDescriptor aidl;
+    aidl.type = VALUE_OR_RETURN(legacy2aidl_audio_uuid_t_AudioUuid(legacy.type));
+    aidl.uuid = VALUE_OR_RETURN(legacy2aidl_audio_uuid_t_AudioUuid(legacy.uuid));
+    aidl.apiVersion = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.apiVersion));
+    aidl.flags = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.flags));
+    aidl.cpuLoad = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.cpuLoad));
+    aidl.memoryUsage = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.memoryUsage));
+    aidl.name = VALUE_OR_RETURN(legacy2aidl_string(legacy.name, sizeof(legacy.name)));
+    aidl.implementor = VALUE_OR_RETURN(
+            legacy2aidl_string(legacy.implementor, sizeof(legacy.implementor)));
+    return aidl;
+}
+
 }  // namespace android
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 5d692e5..423d98f 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -130,12 +130,12 @@
     ],
     export_header_lib_headers: ["libaudioclient_headers"],
     export_static_lib_headers: [
-        "effect-aidl-cpp",
+        "effect-aidl-unstable-cpp",
         "shared-file-region-aidl-unstable-cpp",
     ],
 
     static_libs: [
-        "effect-aidl-cpp",
+        "effect-aidl-unstable-cpp",
         // for memory heap analysis
         "libc_malloc_debug_backtrace",
         "shared-file-region-aidl-unstable-cpp",
@@ -216,6 +216,9 @@
     name: "effect-aidl",
     unstable: true,
     local_include_dir: "aidl",
+    host_supported: true,
+    double_loadable: true,
+    vendor_available: true,
     srcs: [
         "aidl/android/media/IEffect.aidl",
         "aidl/android/media/IEffectClient.aidl",
@@ -238,6 +241,7 @@
         "aidl/android/media/AudioConfig.aidl",
         "aidl/android/media/AudioConfigBase.aidl",
         "aidl/android/media/AudioContentType.aidl",
+        "aidl/android/media/AudioDevice.aidl",
         "aidl/android/media/AudioEncapsulationMode.aidl",
         "aidl/android/media/AudioFlag.aidl",
         "aidl/android/media/AudioGainConfig.aidl",
@@ -246,6 +250,7 @@
         "aidl/android/media/AudioIoConfigEvent.aidl",
         "aidl/android/media/AudioIoDescriptor.aidl",
         "aidl/android/media/AudioIoFlags.aidl",
+        "aidl/android/media/AudioMode.aidl",
         "aidl/android/media/AudioOffloadInfo.aidl",
         "aidl/android/media/AudioOutputFlags.aidl",
         "aidl/android/media/AudioPatch.aidl",
@@ -261,7 +266,10 @@
         "aidl/android/media/AudioSourceType.aidl",
         "aidl/android/media/AudioStreamType.aidl",
         "aidl/android/media/AudioTimestampInternal.aidl",
+        "aidl/android/media/AudioUniqueIdUse.aidl",
         "aidl/android/media/AudioUsage.aidl",
+        "aidl/android/media/AudioUuid.aidl",
+        "aidl/android/media/EffectDescriptor.aidl",
     ],
     imports: [
         "audio_common-aidl",
@@ -284,6 +292,8 @@
     host_supported: true,
     vendor_available: true,
     srcs: [
+        "aidl/android/media/CreateEffectRequest.aidl",
+        "aidl/android/media/CreateEffectResponse.aidl",
         "aidl/android/media/CreateRecordRequest.aidl",
         "aidl/android/media/CreateRecordResponse.aidl",
         "aidl/android/media/CreateTrackRequest.aidl",
@@ -295,8 +305,10 @@
         "aidl/android/media/IAudioTrackCallback.aidl",
     ],
     imports: [
+        "audio_common-aidl",
         "audioclient-types-aidl",
         "av-types-aidl",
+        "effect-aidl",
         "shared-file-region-aidl",
     ],
     double_loadable: true,
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index 1282474..e5a7029 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -29,6 +29,13 @@
 #include <private/media/AudioEffectShared.h>
 #include <utils/Log.h>
 
+#define VALUE_OR_RETURN_STATUS(exp)          \
+    ({                                       \
+        auto _tmp = (exp);                   \
+        if (!_tmp.ok()) return _tmp.error(); \
+        std::move(_tmp.value());             \
+    })
+
 namespace android {
 
 using binder::Status;
@@ -101,9 +108,29 @@
     mClientPid = IPCThreadState::self()->getCallingPid();
     mClientUid = IPCThreadState::self()->getCallingUid();
 
-    iEffect = audioFlinger->createEffect((effect_descriptor_t *)&mDescriptor,
-            mIEffectClient, priority, io, mSessionId, device, mOpPackageName, mClientPid,
-            probe, &mStatus, &mId, &enabled);
+    media::CreateEffectRequest request;
+    request.desc = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_effect_descriptor_t_EffectDescriptor(mDescriptor));
+    request.client = mIEffectClient;
+    request.priority = priority;
+    request.output = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(io));
+    request.sessionId = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_session_t_int32_t(mSessionId));
+    request.device = VALUE_OR_RETURN_STATUS(legacy2aidl_AudioDeviceTypeAddress(device));
+    request.opPackageName = VALUE_OR_RETURN_STATUS(legacy2aidl_String16_string(mOpPackageName));
+    request.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(mClientPid));
+    request.probe = probe;
+
+    media::CreateEffectResponse response;
+
+    mStatus = audioFlinger->createEffect(request, &response);
+
+    if (mStatus == OK) {
+        mId = response.id;
+        enabled = response.enabled;
+        iEffect = response.effect;
+        mDescriptor = VALUE_OR_RETURN_STATUS(
+                aidl2legacy_EffectDescriptor_effect_descriptor_t(response.desc));
+    }
 
     // In probe mode, we stop here and return the status: the IEffect interface to
     // audio flinger will not be retained. initCheck() will return the creation status
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index b5c6547..4d84a07 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -792,66 +792,25 @@
         return NO_ERROR;
     }
 
-    virtual sp<media::IEffect> createEffect(
-                                    effect_descriptor_t *pDesc,
-                                    const sp<media::IEffectClient>& client,
-                                    int32_t priority,
-                                    audio_io_handle_t output,
-                                    audio_session_t sessionId,
-                                    const AudioDeviceTypeAddr& device,
-                                    const String16& opPackageName,
-                                    pid_t pid,
-                                    bool probe,
-                                    status_t *status,
-                                    int *id,
-                                    int *enabled)
+    virtual status_t createEffect(const media::CreateEffectRequest& request,
+                                  media::CreateEffectResponse* response)
     {
         Parcel data, reply;
         sp<media::IEffect> effect;
-        if (pDesc == NULL) {
-            if (status != NULL) {
-                *status = BAD_VALUE;
-            }
-            return nullptr;
+        if (response == nullptr) {
+            return BAD_VALUE;
         }
-
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.write(pDesc, sizeof(effect_descriptor_t));
-        data.writeStrongBinder(IInterface::asBinder(client));
-        data.writeInt32(priority);
-        data.writeInt32((int32_t) output);
-        data.writeInt32(sessionId);
-        if (data.writeParcelable(device) != NO_ERROR) {
-            if (status != NULL) {
-                *status = NO_INIT;
-            }
-            return nullptr;
-        }
-        data.writeString16(opPackageName);
-        data.writeInt32((int32_t) pid);
-        data.writeInt32(probe ? 1 : 0);
-
-        status_t lStatus = remote()->transact(CREATE_EFFECT, data, &reply);
+        status_t status;
+        status_t lStatus = data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor())
+                           ?: data.writeParcelable(request)
+                           ?: remote()->transact(CREATE_EFFECT, data, &reply)
+                           ?: reply.readInt32(&status)
+                           ?: reply.readParcelable(response)
+                           ?: status;
         if (lStatus != NO_ERROR) {
             ALOGE("createEffect error: %s", strerror(-lStatus));
-        } else {
-            lStatus = reply.readInt32();
-            int tmp = reply.readInt32();
-            if (id != NULL) {
-                *id = tmp;
-            }
-            tmp = reply.readInt32();
-            if (enabled != NULL) {
-                *enabled = tmp;
-            }
-            effect = interface_cast<media::IEffect>(reply.readStrongBinder());
-            reply.read(pDesc, sizeof(effect_descriptor_t));
         }
-        if (status != NULL) {
-            *status = lStatus;
-        }
-
-        return effect;
+        return lStatus;
     }
 
     virtual status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput,
@@ -1525,35 +1484,13 @@
         }
         case CREATE_EFFECT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            effect_descriptor_t desc = {};
-            if (data.read(&desc, sizeof(effect_descriptor_t)) != NO_ERROR) {
-                ALOGE("b/23905951");
-            }
-            sp<media::IEffectClient> client =
-                    interface_cast<media::IEffectClient>(data.readStrongBinder());
-            int32_t priority = data.readInt32();
-            audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
-            audio_session_t sessionId = (audio_session_t) data.readInt32();
-            AudioDeviceTypeAddr device;
-            status_t status = NO_ERROR;
-            if ((status = data.readParcelable(&device)) != NO_ERROR) {
-                return status;
-            }
-            const String16 opPackageName = data.readString16();
-            pid_t pid = (pid_t)data.readInt32();
-            bool probe = data.readInt32() == 1;
 
-            int id = 0;
-            int enabled = 0;
+            media::CreateEffectRequest request;
+            media::CreateEffectResponse response;
 
-            sp<media::IEffect> effect = createEffect(&desc, client, priority, output, sessionId,
-                    device, opPackageName, pid, probe, &status, &id, &enabled);
-            reply->writeInt32(status);
-            reply->writeInt32(id);
-            reply->writeInt32(enabled);
-            reply->writeStrongBinder(IInterface::asBinder(effect));
-            reply->write(&desc, sizeof(effect_descriptor_t));
-            return NO_ERROR;
+            return data.readParcelable(&request)
+                ?: reply->writeInt32(createEffect(request, &response))
+                ?: reply->writeParcelable(response);
         } break;
         case MOVE_EFFECTS: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
diff --git a/media/libaudioclient/aidl/android/media/AudioDevice.aidl b/media/libaudioclient/aidl/android/media/AudioDevice.aidl
new file mode 100644
index 0000000..b200697
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioDevice.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * {@hide}
+ */
+parcelable AudioDevice {
+    /** Interpreted as audio_devices_t. */
+    int type;
+    @utf8InCpp String address;
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioMode.aidl b/media/libaudioclient/aidl/android/media/AudioMode.aidl
new file mode 100644
index 0000000..a72c397
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioMode.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media;
+
+@Backing(type="int")
+enum AudioMode {
+    INVALID = -2,
+    CURRENT = -1,
+    NORMAL = 0,
+    RINGTONE = 1,
+    IN_CALL = 2,
+    IN_COMMUNICATION = 3,
+    CALL_SCREEN = 4,
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioUniqueIdUse.aidl b/media/libaudioclient/aidl/android/media/AudioUniqueIdUse.aidl
new file mode 100644
index 0000000..052740e
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioUniqueIdUse.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media;
+
+@Backing(type="int")
+enum AudioUniqueIdUse {
+    UNSPECIFIED = 0,
+    SESSION = 1, // audio_session_t
+                 // for allocated sessions, not special AUDIO_SESSION_*
+    MODULE = 2,  // audio_module_handle_t
+    EFFECT = 3,  // audio_effect_handle_t
+    PATCH = 4,   // audio_patch_handle_t
+    OUTPUT = 5,  // audio_io_handle_t
+    INPUT = 6,   // audio_io_handle_t
+    CLIENT = 7,  // client-side players and recorders
+                 // FIXME should move to a separate namespace;
+                 // these IDs are allocated by AudioFlinger on client request,
+                 // but are never used by AudioFlinger
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioUuid.aidl b/media/libaudioclient/aidl/android/media/AudioUuid.aidl
new file mode 100644
index 0000000..5a90c31
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioUuid.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media;
+
+parcelable AudioUuid {
+    int timeLow;
+    int timeMid;
+    int timeHiAndVersion;
+    int clockSeq;
+    byte[] node;  // Length = 6
+}
diff --git a/media/libaudioclient/aidl/android/media/CreateEffectRequest.aidl b/media/libaudioclient/aidl/android/media/CreateEffectRequest.aidl
new file mode 100644
index 0000000..8368854
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/CreateEffectRequest.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.AudioDevice;
+import android.media.EffectDescriptor;
+import android.media.IEffectClient;
+
+/**
+ * Input arguments of the createEffect() method.
+ *
+ * {@hide}
+ */
+parcelable CreateEffectRequest {
+    EffectDescriptor desc;
+    @nullable IEffectClient client;
+    int priority;
+    /** Interpreted as audio_io_handle_t. */
+    int output;
+    /** Interpreted as audio_session_t. */
+    int sessionId;
+    AudioDevice device;
+    @utf8InCpp String opPackageName;
+    /** Interpreted as pid_t. */
+    int pid;
+    boolean probe;
+}
diff --git a/media/libaudioclient/aidl/android/media/CreateEffectResponse.aidl b/media/libaudioclient/aidl/android/media/CreateEffectResponse.aidl
new file mode 100644
index 0000000..0aa640a
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/CreateEffectResponse.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.EffectDescriptor;
+import android.media.IEffect;
+
+/**
+ * Output arguments of the createEffect() method.
+ *
+ * {@hide}
+ */
+parcelable CreateEffectResponse {
+    int id;
+    boolean enabled;
+    @nullable IEffect effect;
+    EffectDescriptor desc;
+}
diff --git a/media/libaudioclient/aidl/android/media/EffectDescriptor.aidl b/media/libaudioclient/aidl/android/media/EffectDescriptor.aidl
new file mode 100644
index 0000000..35a3d74
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/EffectDescriptor.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.AudioUuid;
+
+/**
+ * {@hide}
+ */
+parcelable EffectDescriptor {
+    /** UUID of to the OpenSL ES interface implemented by this effect. */
+    AudioUuid type;
+    /** UUID for this particular implementation. */
+    AudioUuid uuid;
+    /** Version of the effect control API implemented. */
+    int apiVersion;
+    /** Effect engine capabilities/requirements flags. */
+    int flags;
+    /** CPU load indication.. */
+    int cpuLoad;
+    /** Data Memory usage.. */
+    int memoryUsage;
+    /** Human readable effect name. */
+    @utf8InCpp String name;
+    /** Human readable effect implementor name. */
+    @utf8InCpp String implementor;
+}
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 62f87a5..78f9b83 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -35,13 +35,14 @@
 #include <android/media/AudioOutputFlags.h>
 #include <android/media/AudioPortConfigType.h>
 #include <android/media/AudioTimestampInternal.h>
+#include <android/media/EffectDescriptor.h>
 
 #include <android/media/SharedFileRegion.h>
-
 #include <binder/IMemory.h>
 #include <media/AudioClient.h>
 #include <media/AudioIoDescriptor.h>
 #include <media/AudioTimestamp.h>
+#include <system/audio_effect.h>
 
 namespace android {
 
@@ -132,6 +133,9 @@
 ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl);
 ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy);
 
+ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl);
+ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy);
+
 ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl);
 ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy);
 
@@ -297,4 +301,14 @@
 ConversionResult<media::AudioTimestampInternal>
 legacy2aidl_AudioTimestamp(const AudioTimestamp& legacy);
 
+ConversionResult<audio_uuid_t>
+aidl2legacy_AudioUuid_audio_uuid_t(const media::AudioUuid& aidl);
+ConversionResult<media::AudioUuid>
+legacy2aidl_audio_uuid_t_AudioUuid(const audio_uuid_t& legacy);
+
+ConversionResult<effect_descriptor_t>
+aidl2legacy_EffectDescriptor_effect_descriptor_t(const media::EffectDescriptor& aidl);
+ConversionResult<media::EffectDescriptor>
+legacy2aidl_effect_descriptor_t_EffectDescriptor(const effect_descriptor_t& legacy);
+
 }  // namespace android
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 9afd416..8aa493f 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -37,6 +37,8 @@
 #include <string>
 #include <vector>
 
+#include "android/media/CreateEffectRequest.h"
+#include "android/media/CreateEffectResponse.h"
 #include "android/media/CreateRecordRequest.h"
 #include "android/media/CreateRecordResponse.h"
 #include "android/media/CreateTrackRequest.h"
@@ -278,20 +280,8 @@
                                          uint32_t preferredTypeFlag,
                                          effect_descriptor_t *pDescriptor) const = 0;
 
-    virtual sp<media::IEffect> createEffect(
-                                    effect_descriptor_t *pDesc,
-                                    const sp<media::IEffectClient>& client,
-                                    int32_t priority,
-                                    // AudioFlinger doesn't take over handle reference from client
-                                    audio_io_handle_t output,
-                                    audio_session_t sessionId,
-                                    const AudioDeviceTypeAddr& device,
-                                    const String16& callingPackage,
-                                    pid_t pid,
-                                    bool probe,
-                                    status_t *status,
-                                    int *id,
-                                    int *enabled) = 0;
+    virtual status_t createEffect(const media::CreateEffectRequest& request,
+                                  media::CreateEffectResponse* response) = 0;
 
     virtual status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput,
                                     audio_io_handle_t dstOutput) = 0;
diff --git a/media/libaudiofoundation/Android.bp b/media/libaudiofoundation/Android.bp
index a8e6c31..efa5359 100644
--- a/media/libaudiofoundation/Android.bp
+++ b/media/libaudiofoundation/Android.bp
@@ -12,6 +12,14 @@
         "libaudio_system_headers",
         "libmedia_helper_headers",
     ],
+    static_libs: [
+        "audioclient-types-aidl-unstable-cpp",
+        "libaudioclient_aidl_conversion",
+    ],
+    export_static_lib_headers: [
+        "audioclient-types-aidl-unstable-cpp",
+        "libaudioclient_aidl_conversion",
+    ],
     host_supported: true,
     target: {
         darwin: {
@@ -35,6 +43,8 @@
     ],
 
     shared_libs: [
+        "audioclient-types-aidl-unstable-cpp",
+        "libaudioclient_aidl_conversion",
         "libaudioutils",
         "libbase",
         "libbinder",
diff --git a/media/libaudiofoundation/AudioDeviceTypeAddr.cpp b/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
index a47337b..8f1e113 100644
--- a/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
+++ b/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
@@ -155,4 +155,18 @@
     return stream.str();
 }
 
+ConversionResult<AudioDeviceTypeAddr>
+aidl2legacy_AudioDeviceTypeAddress(const media::AudioDevice& aidl) {
+    audio_devices_t type = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_devices_t(aidl.type));
+    return AudioDeviceTypeAddr(type, aidl.address);
+}
+
+ConversionResult<media::AudioDevice>
+legacy2aidl_AudioDeviceTypeAddress(const AudioDeviceTypeAddr& legacy) {
+    media::AudioDevice aidl;
+    aidl.type = VALUE_OR_RETURN(legacy2aidl_audio_devices_t_int32_t(legacy.mType));
+    aidl.address = legacy.getAddress();
+    return aidl;
+}
+
 } // namespace android
diff --git a/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h b/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h
index 7497faf..34da233 100644
--- a/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h
+++ b/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h
@@ -19,9 +19,11 @@
 #include <string>
 #include <vector>
 
+#include <android/media/AudioDevice.h>
 #include <binder/Parcelable.h>
 #include <binder/Parcel.h>
 #include <media/AudioContainers.h>
+#include <media/AidlConversion.h>
 #include <system/audio.h>
 #include <utils/Errors.h>
 
@@ -84,4 +86,10 @@
 std::string dumpAudioDeviceTypeAddrVector(const AudioDeviceTypeAddrVector& deviceTypeAddrs,
                                           bool includeSensitiveInfo=false);
 
+// Conversion routines, according to AidlConversion.h conventions.
+ConversionResult<AudioDeviceTypeAddr>
+aidl2legacy_AudioDeviceTypeAddress(const media::AudioDevice& aidl);
+ConversionResult<media::AudioDevice>
+legacy2aidl_AudioDeviceTypeAddress(const AudioDeviceTypeAddr& legacy);
+
 } // namespace android
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 7443320..87b5ff4 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -38,6 +38,7 @@
         "audioflinger-aidl-unstable-cpp",
         "audioclient-types-aidl-unstable-cpp",
         "av-types-aidl-unstable-cpp",
+        "effect-aidl-unstable-cpp",
         "libaudioclient_aidl_conversion",
         "libaudiofoundation",
         "libaudiohal",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index bc8609f..ab15388 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -3474,23 +3474,28 @@
     return status;
 }
 
-sp<media::IEffect> AudioFlinger::createEffect(
-        effect_descriptor_t *pDesc,
-        const sp<IEffectClient>& effectClient,
-        int32_t priority,
-        audio_io_handle_t io,
-        audio_session_t sessionId,
-        const AudioDeviceTypeAddr& device,
-        const String16& opPackageName,
-        pid_t pid,
-        bool probe,
-        status_t *status,
-        int *id,
-        int *enabled)
-{
-    status_t lStatus = NO_ERROR;
+status_t AudioFlinger::createEffect(const media::CreateEffectRequest& request,
+                                    media::CreateEffectResponse* response) {
+    const sp<IEffectClient>& effectClient = request.client;
+    const int32_t priority = request.priority;
+    const AudioDeviceTypeAddr device = VALUE_OR_EXIT(
+            aidl2legacy_AudioDeviceTypeAddress(request.device));
+    const String16 opPackageName = VALUE_OR_EXIT(
+            aidl2legacy_string_view_String16(request.opPackageName));
+    pid_t pid = VALUE_OR_EXIT(aidl2legacy_int32_t_pid_t(request.pid));
+    const audio_session_t sessionId = VALUE_OR_EXIT(
+            aidl2legacy_int32_t_audio_session_t(request.sessionId));
+    audio_io_handle_t io = VALUE_OR_EXIT(aidl2legacy_int32_t_audio_io_handle_t(request.output));
+    const effect_descriptor_t descIn = VALUE_OR_EXIT(
+            aidl2legacy_EffectDescriptor_effect_descriptor_t(request.desc));
+    const bool probe = request.probe;
+
     sp<EffectHandle> handle;
-    effect_descriptor_t desc;
+    effect_descriptor_t descOut;
+    int enabledOut = 0;
+    int idOut = -1;
+
+    status_t lStatus = NO_ERROR;
 
     const uid_t callingUid = IPCThreadState::self()->getCallingUid();
     if (pid == -1 || !isAudioServerOrMediaServerUid(callingUid)) {
@@ -3502,12 +3507,7 @@
     }
 
     ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d, factory %p",
-            pid, effectClient.get(), priority, sessionId, io, mEffectsFactoryHal.get());
-
-    if (pDesc == NULL) {
-        lStatus = BAD_VALUE;
-        goto Exit;
-    }
+          pid, effectClient.get(), priority, sessionId, io, mEffectsFactoryHal.get());
 
     if (mEffectsFactoryHal == 0) {
         ALOGE("%s: no effects factory hal", __func__);
@@ -3564,7 +3564,7 @@
         // otherwise no preference.
         uint32_t preferredType = (sessionId == AUDIO_SESSION_OUTPUT_MIX ?
                                   EFFECT_FLAG_TYPE_AUXILIARY : EFFECT_FLAG_TYPE_MASK);
-        lStatus = getEffectDescriptor(&pDesc->uuid, &pDesc->type, preferredType, &desc);
+        lStatus = getEffectDescriptor(&descIn.uuid, &descIn.type, preferredType, &descOut);
         if (lStatus < 0) {
             ALOGW("createEffect() error %d from getEffectDescriptor", lStatus);
             goto Exit;
@@ -3572,20 +3572,20 @@
 
         // Do not allow auxiliary effects on a session different from 0 (output mix)
         if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
-             (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+             (descOut.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
             lStatus = INVALID_OPERATION;
             goto Exit;
         }
 
         // check recording permission for visualizer
-        if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
+        if ((memcmp(&descOut.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
             // TODO: Do we need to start/stop op - i.e. is there recording being performed?
             !recordingAllowed(opPackageName, pid, callingUid)) {
             lStatus = PERMISSION_DENIED;
             goto Exit;
         }
 
-        const bool hapticPlaybackRequired = EffectModule::isHapticGenerator(&desc.type);
+        const bool hapticPlaybackRequired = EffectModule::isHapticGenerator(&descOut.type);
         if (hapticPlaybackRequired
                 && (sessionId == AUDIO_SESSION_DEVICE
                         || sessionId == AUDIO_SESSION_OUTPUT_MIX
@@ -3595,13 +3595,11 @@
             goto Exit;
         }
 
-        // return effect descriptor
-        *pDesc = desc;
         if (io == AUDIO_IO_HANDLE_NONE && sessionId == AUDIO_SESSION_OUTPUT_MIX) {
             // if the output returned by getOutputForEffect() is removed before we lock the
             // mutex below, the call to checkPlaybackThread_l(io) below will detect it
             // and we will exit safely
-            io = AudioSystem::getOutputForEffect(&desc);
+            io = AudioSystem::getOutputForEffect(&descOut);
             ALOGV("createEffect got output %d", io);
         }
 
@@ -3611,15 +3609,15 @@
             sp<Client> client = registerPid(pid);
             ALOGV("%s device type %#x address %s", __func__, device.mType, device.getAddress());
             handle = mDeviceEffectManager.createEffect_l(
-                    &desc, device, client, effectClient, mPatchPanel.patches_l(),
-                    enabled, &lStatus, probe);
+                    &descOut, device, client, effectClient, mPatchPanel.patches_l(),
+                    &enabledOut, &lStatus, probe);
             if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
                 // remove local strong reference to Client with mClientLock held
                 Mutex::Autolock _cl(mClientLock);
                 client.clear();
             } else {
                 // handle must be valid here, but check again to be safe.
-                if (handle.get() != nullptr && id != nullptr) *id = handle->id();
+                if (handle.get() != nullptr) idOut = handle->id();
             }
             goto Register;
         }
@@ -3649,8 +3647,8 @@
             // Detect if the effect is created after an AudioRecord is destroyed.
             if (getOrphanEffectChain_l(sessionId).get() != nullptr) {
                 ALOGE("%s: effect %s with no specified io handle is denied because the AudioRecord"
-                        " for session %d no longer exists",
-                         __func__, desc.name, sessionId);
+                      " for session %d no longer exists",
+                      __func__, descOut.name, sessionId);
                 lStatus = PERMISSION_DENIED;
                 goto Exit;
             }
@@ -3664,7 +3662,7 @@
             if (io == AUDIO_IO_HANDLE_NONE && mPlaybackThreads.size() > 0) {
                 io = mPlaybackThreads.keyAt(0);
             }
-            ALOGV("createEffect() got io %d for effect %s", io, desc.name);
+            ALOGV("createEffect() got io %d for effect %s", io, descOut.name);
         } else if (checkPlaybackThread_l(io) != nullptr) {
             // allow only one effect chain per sessionId on mPlaybackThreads.
             for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
@@ -3684,7 +3682,7 @@
                         mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId);
                 if ((sessionType & ThreadBase::EFFECT_SESSION) != 0) {
                     ALOGE("%s: effect %s io %d denied because session %d effect exists on io %d",
-                            __func__, desc.name, (int)io, (int)sessionId, (int)checkIo);
+                          __func__, descOut.name, (int) io, (int) sessionId, (int) checkIo);
                     android_errorWriteLog(0x534e4554, "123237974");
                     lStatus = BAD_VALUE;
                     goto Exit;
@@ -3731,14 +3729,14 @@
             }
         }
         handle = thread->createEffect_l(client, effectClient, priority, sessionId,
-                &desc, enabled, &lStatus, pinned, probe);
+                                        &descOut, &enabledOut, &lStatus, pinned, probe);
         if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
             // remove local strong reference to Client with mClientLock held
             Mutex::Autolock _cl(mClientLock);
             client.clear();
         } else {
             // handle must be valid here, but check again to be safe.
-            if (handle.get() != nullptr && id != nullptr) *id = handle->id();
+            if (handle.get() != nullptr) idOut = handle->id();
             // Invalidate audio session when haptic playback is created.
             if (hapticPlaybackRequired && oriThread != nullptr) {
                 // invalidateTracksForAudioSession will trigger locking the thread.
@@ -3761,9 +3759,13 @@
         handle.clear();
     }
 
+    response->id = idOut;
+    response->enabled = enabledOut != 0;
+    response->effect = handle;
+    response->desc = VALUE_OR_EXIT(legacy2aidl_effect_descriptor_t_EffectDescriptor(descOut));
+
 Exit:
-    *status = lStatus;
-    return handle;
+    return lStatus;
 }
 
 status_t AudioFlinger::moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 42b5c99..ad07332 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -231,19 +231,8 @@
                                          uint32_t preferredTypeFlag,
                                          effect_descriptor_t *descriptor) const;
 
-    virtual sp<media::IEffect> createEffect(
-                        effect_descriptor_t *pDesc,
-                        const sp<media::IEffectClient>& effectClient,
-                        int32_t priority,
-                        audio_io_handle_t io,
-                        audio_session_t sessionId,
-                        const AudioDeviceTypeAddr& device,
-                        const String16& opPackageName,
-                        pid_t pid,
-                        bool probe,
-                        status_t *status /*non-NULL*/,
-                        int *id,
-                        int *enabled);
+    virtual status_t createEffect(const media::CreateEffectRequest& request,
+                                  media::CreateEffectResponse* response);
 
     virtual status_t moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
                         audio_io_handle_t dstOutput);