VolumeShaper: Initial implementation

The VolumeShaper is used to apply a volume
envelope to an AudioTrack or a MediaPlayer.

Test: CTS
Bug: 30920125
Bug: 31015569
Change-Id: I42e2f13bd6879299dc780e60d143c2d465483a44
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 0de3559..d35cfe3 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -184,6 +184,7 @@
       mPreviousSchedulingGroup(SP_DEFAULT),
       mPausedPosition(0),
       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
+      mVolumeShaperId(VolumeShaper::kSystemIdMax),
       mPortId(AUDIO_PORT_HANDLE_NONE)
 {
     mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
@@ -556,7 +557,7 @@
     mFramesWritten = 0;
     mFramesWrittenServerOffset = 0;
     mFramesWrittenAtRestore = -1; // -1 is a unique initializer.
-
+    mVolumeHandler = new VolumeHandler(mSampleRate);
     return NO_ERROR;
 }
 
@@ -2310,6 +2311,40 @@
     return mAudioTrack->setParameters(keyValuePairs);
 }
 
+VolumeShaper::Status AudioTrack::applyVolumeShaper(
+        const sp<VolumeShaper::Configuration>& configuration,
+        const sp<VolumeShaper::Operation>& operation)
+{
+    AutoMutex lock(mLock);
+    if (configuration->getType() == VolumeShaper::Configuration::TYPE_SCALE) {
+        const int id = configuration->getId();
+        LOG_ALWAYS_FATAL_IF(id >= VolumeShaper::kSystemIdMax || id < -1,
+                "id must be -1 or a system id (less than kSystemIdMax)");
+        if (id == -1) {
+            // if not a system id, reassign to a unique id
+            configuration->setId(mVolumeShaperId);
+            ALOGD("setting id to %d", mVolumeShaperId);
+            // increment and avoid signed overflow.
+            if (mVolumeShaperId == INT32_MAX) {
+                mVolumeShaperId = VolumeShaper::kSystemIdMax;
+            } else {
+                ++mVolumeShaperId;
+            }
+        }
+    }
+    VolumeShaper::Status status = mAudioTrack->applyVolumeShaper(configuration, operation);
+    // TODO: For restoration purposes, record successful creation and termination.
+    return status;
+}
+
+sp<VolumeShaper::State> AudioTrack::getVolumeShaperState(int id)
+{
+    // TODO: To properly restore the AudioTrack
+    // we will need to save the last state in AudioTrackShared.
+    AutoMutex lock(mLock);
+    return mAudioTrack->getVolumeShaperState(id);
+}
+
 status_t AudioTrack::getTimestamp(ExtendedTimestamp *timestamp)
 {
     if (timestamp == nullptr) {