AudioTrack and AudioFlinger send level cleanup

Add an API to control block for getting/setting send level.
This allow us to make the mSendLevel field private.

Document the lack of barriers.

Use 0.0f to initialize floating-point values (for doc only).

Change-Id: I59f83b00adeb89eeee227e7648625d9a835be7a4
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 046d5e9..86e0682 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -85,7 +85,9 @@
                 uint16_t    bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger
 
                 uint16_t    waitTimeMs;      // Cumulated wait time
-                uint16_t    sendLevel;
+private:
+                uint16_t    mSendLevel;      // Fixed point U4.12 so 0x1000 means 1.0
+public:
     volatile    int32_t     flags;
 
                 // Cache line boundary (32 bytes)
@@ -98,6 +100,19 @@
                 uint32_t    framesAvailable_l();
                 uint32_t    framesReady();
                 bool        tryLock();
+
+                // No barriers on the following operations, so the ordering of loads/stores
+                // with respect to other parameters is UNPREDICTABLE. That's considered safe.
+
+                // for AudioTrack client only, caller must limit to 0.0 <= sendLevel <= 1.0
+                void        setSendLevel(float sendLevel) {
+                    mSendLevel = uint16_t(sendLevel * 0x1000);
+                }
+
+                // for AudioFlinger only; the return value must be validated by the caller
+                uint16_t    getSendLevel_U4_12() const {
+                    return mSendLevel;
+                }
 };
 
 
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 9c650ad..3a938dd 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -215,7 +215,7 @@
 
     mVolume[LEFT] = 1.0f;
     mVolume[RIGHT] = 1.0f;
-    mSendLevel = 0;
+    mSendLevel = 0.0f;
     mFrameCount = frameCount;
     mNotificationFramesReq = notificationFrames;
     mSessionId = sessionId;
@@ -499,14 +499,14 @@
 status_t AudioTrack::setAuxEffectSendLevel(float level)
 {
     ALOGV("setAuxEffectSendLevel(%f)", level);
-    if (level > 1.0f) {
+    if (level < 0.0f || level > 1.0f) {
         return BAD_VALUE;
     }
     AutoMutex lock(mLock);
 
     mSendLevel = level;
 
-    mCblk->sendLevel = uint16_t(level * 0x1000);
+    mCblk->setSendLevel(level);
 
     return NO_ERROR;
 }
@@ -818,7 +818,7 @@
     }
 
     mCblk->volumeLR = (uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) | uint16_t(mVolume[LEFT] * 0x1000);
-    mCblk->sendLevel = uint16_t(mSendLevel * 0x1000);
+    mCblk->setSendLevel(mSendLevel);
     mAudioTrack->attachAuxEffect(mAuxEffectId);
     mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
     mCblk->waitTimeMs = 0;
@@ -1311,7 +1311,7 @@
     : lock(Mutex::SHARED), cv(Condition::SHARED), user(0), server(0),
     userBase(0), serverBase(0), buffers(0), frameCount(0),
     loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), volumeLR(0),
-    sendLevel(0), flags(0)
+    mSendLevel(0), flags(0)
 {
 }
 
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 9fb666e..7f43100 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2183,7 +2183,13 @@
                 vl = (uint32_t)(v * cblk->volume[0]) << 12;
                 vr = (uint32_t)(v * cblk->volume[1]) << 12;
 
-                va = (uint32_t)(v * cblk->sendLevel);
+                uint16_t sendLevel = cblk->getSendLevel_U4_12();
+                // send level comes from shared memory and so may be corrupt
+                if (sendLevel >= 0x1000) {
+                    ALOGV("Track send level out of range: %04X", sendLevel);
+                    sendLevel = 0x1000;
+                }
+                va = (uint32_t)(v * sendLevel);
             }
             // Delegate volume control to effect in track effect chain if needed
             if (chain != 0 && chain->setVolume_l(&vl, &vr)) {