Merge "audio policy: remove obsolete AudioPolicyManager class members"
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
index 99e5df4..af091f4 100644
--- a/camera/CameraParameters.cpp
+++ b/camera/CameraParameters.cpp
@@ -16,7 +16,6 @@
 */
 
 #define LOG_TAG "CameraParams"
-// #define LOG_NDEBUG 0
 #include <utils/Log.h>
 
 #include <string.h>
@@ -199,8 +198,6 @@
             flattened += ";";
     }
 
-    ALOGV("%s: Flattened params = %s", __FUNCTION__, flattened.string());
-
     return flattened;
 }
 
@@ -250,9 +247,7 @@
         return;
     }
 
-    // Replacing a value updates the key's order to be the new largest order
-    ssize_t res = mMap.replaceValueFor(String8(key), String8(value));
-    LOG_ALWAYS_FATAL_IF(res < 0, "replaceValueFor(%s,%s) failed", key, value);
+    mMap.replaceValueFor(String8(key), String8(value));
 }
 
 void CameraParameters::set(const char *key, int value)
@@ -271,12 +266,10 @@
 
 const char *CameraParameters::get(const char *key) const
 {
-    ssize_t idx = mMap.indexOfKey(String8(key));
-    if (idx < 0) {
-        return NULL;
-    } else {
-        return mMap.valueAt(idx).string();
-    }
+    String8 v = mMap.valueFor(String8(key));
+    if (v.length() == 0)
+        return 0;
+    return v.string();
 }
 
 int CameraParameters::getInt(const char *key) const
@@ -294,36 +287,6 @@
     return strtof(v, 0);
 }
 
-status_t CameraParameters::compareSetOrder(const char *key1, const char *key2,
-        int *order) const {
-    if (key1 == NULL) {
-        ALOGE("%s: key1 must not be NULL", __FUNCTION__);
-        return BAD_VALUE;
-    } else if (key2 == NULL) {
-        ALOGE("%s: key2 must not be NULL", __FUNCTION__);
-        return BAD_VALUE;
-    } else if (order == NULL) {
-        ALOGE("%s: order must not be NULL", __FUNCTION__);
-        return BAD_VALUE;
-    }
-
-    ssize_t index1 = mMap.indexOfKey(String8(key1));
-    ssize_t index2 = mMap.indexOfKey(String8(key2));
-    if (index1 < 0) {
-        ALOGW("%s: Key1 (%s) was not set", __FUNCTION__, key1);
-        return NAME_NOT_FOUND;
-    } else if (index2 < 0) {
-        ALOGW("%s: Key2 (%s) was not set", __FUNCTION__, key2);
-        return NAME_NOT_FOUND;
-    }
-
-    *order = (index1 == index2) ? 0  :
-             (index1 < index2)  ? -1 :
-             1;
-
-    return OK;
-}
-
 void CameraParameters::remove(const char *key)
 {
     mMap.removeItem(String8(key));
@@ -449,12 +412,6 @@
     parse_pair(p, min_fps, max_fps, ',');
 }
 
-void CameraParameters::setPreviewFpsRange(int min_fps, int max_fps)
-{
-    String8 str = String8::format("%d,%d", min_fps, max_fps);
-    set(KEY_PREVIEW_FPS_RANGE, str.string());
-}
-
 void CameraParameters::setPreviewFormat(const char *format)
 {
     set(KEY_PREVIEW_FORMAT, format);
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index b2abc0f..0566d14 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -374,7 +374,7 @@
     }
 
     sp<IMediaPlayer> player =
-        service->create(client, 0);
+        service->create(client, AUDIO_SESSION_ALLOCATE);
 
     if (player != NULL && player->setDataSource(source) == NO_ERROR) {
         player->setVideoSurfaceTexture(surface->getIGraphicBufferProducer());
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index 833ba76..d521543 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -18,7 +18,6 @@
 #define ANDROID_HARDWARE_CAMERA_PARAMETERS_H
 
 #include <utils/KeyedVector.h>
-#include <utils/Vector.h>
 #include <utils/String8.h>
 
 namespace android {
@@ -51,26 +50,10 @@
     void set(const char *key, const char *value);
     void set(const char *key, int value);
     void setFloat(const char *key, float value);
-    // Look up string value by key.
-    // -- The string remains valid until the next set/remove of the same key,
-    //    or until the map gets cleared.
     const char *get(const char *key) const;
     int getInt(const char *key) const;
     float getFloat(const char *key) const;
 
-    // Compare the order that key1 was set vs the order that key2 was set.
-    //
-    // Sets the order parameter to an integer less than, equal to, or greater
-    // than zero if key1's set order was respectively, to be less than, to
-    // match, or to be greater than key2's set order.
-    //
-    // Error codes:
-    //  * NAME_NOT_FOUND - if either key has not been set previously
-    //  * BAD_VALUE - if any of the parameters are NULL
-    status_t compareSetOrder(const char *key1, const char *key2,
-            /*out*/
-            int *order) const;
-
     void remove(const char *key);
 
     void setPreviewSize(int width, int height);
@@ -108,7 +91,6 @@
     void setPreviewFrameRate(int fps);
     int getPreviewFrameRate() const;
     void getPreviewFpsRange(int *min_fps, int *max_fps) const;
-    void setPreviewFpsRange(int min_fps, int max_fps);
     void setPreviewFormat(const char *format);
     const char *getPreviewFormat() const;
     void setPictureSize(int width, int height);
@@ -693,91 +675,7 @@
     static const char LIGHTFX_HDR[];
 
 private:
-
-    // Quick and dirty map that maintains insertion order
-    template <typename KeyT, typename ValueT>
-    struct OrderedKeyedVector {
-
-        ssize_t add(const KeyT& key, const ValueT& value) {
-            return mList.add(Pair(key, value));
-        }
-
-        size_t size() const {
-            return mList.size();
-        }
-
-        const KeyT& keyAt(size_t idx) const {
-            return mList[idx].mKey;
-        }
-
-        const ValueT& valueAt(size_t idx) const {
-            return mList[idx].mValue;
-        }
-
-        const ValueT& valueFor(const KeyT& key) const {
-            ssize_t i = indexOfKey(key);
-            LOG_ALWAYS_FATAL_IF(i<0, "%s: key not found", __PRETTY_FUNCTION__);
-
-            return valueAt(i);
-        }
-
-        ssize_t indexOfKey(const KeyT& key) const {
-                size_t vectorIdx = 0;
-                for (; vectorIdx < mList.size(); ++vectorIdx) {
-                    if (mList[vectorIdx].mKey == key) {
-                        return (ssize_t) vectorIdx;
-                    }
-                }
-
-                return NAME_NOT_FOUND;
-        }
-
-        ssize_t removeItem(const KeyT& key) {
-            size_t vectorIdx = (size_t) indexOfKey(key);
-
-            if (vectorIdx < 0) {
-                return vectorIdx;
-            }
-
-            return mList.removeAt(vectorIdx);
-        }
-
-        void clear() {
-            mList.clear();
-        }
-
-        // Same as removing and re-adding. The key's index changes to max.
-        ssize_t replaceValueFor(const KeyT& key, const ValueT& value) {
-            removeItem(key);
-            return add(key, value);
-        }
-
-    private:
-
-        struct Pair {
-            Pair() : mKey(), mValue() {}
-            Pair(const KeyT& key, const ValueT& value) :
-                    mKey(key),
-                    mValue(value) {}
-            KeyT   mKey;
-            ValueT mValue;
-        };
-
-        Vector<Pair> mList;
-    };
-
-    /**
-     * Order matters: Keys that are set() later are stored later in the map.
-     *
-     * If two keys have meaning that conflict, then the later-set key
-     * wins.
-     *
-     * For example, preview FPS and preview FPS range conflict since only
-     * we only want to use the FPS range if that's the last thing that was set.
-     * So in that case, only use preview FPS range if it was set later than
-     * the preview FPS.
-     */
-    OrderedKeyedVector<String8,String8>    mMap;
+    DefaultKeyedVector<String8,String8>    mMap;
 };
 
 }; // namespace android
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
index f3024b7..f98002d 100644
--- a/include/media/AudioEffect.h
+++ b/include/media/AudioEffect.h
@@ -217,8 +217,9 @@
      *      higher priorities, 0 being the normal priority.
      * cbf:         optional callback function (see effect_callback_t)
      * user:        pointer to context for use by the callback receiver.
-     * sessionID:   audio session this effect is associated to. If 0, the effect will be global to
-     *      the output mix. If not 0, the effect will be applied to all players
+     * sessionID:   audio session this effect is associated to.
+     *      If equal to AUDIO_SESSION_OUTPUT_MIX, the effect will be global to
+     *      the output mix.  Otherwise, the effect will be applied to all players
      *      (AudioTrack or MediaPLayer) within the same audio session.
      * io:  HAL audio output or input stream to which this effect must be attached. Leave at 0 for
      *      automatic output selection by AudioFlinger.
@@ -229,8 +230,8 @@
                   int32_t priority = 0,
                   effect_callback_t cbf = NULL,
                   void* user = NULL,
-                  int sessionId = 0,
-                  audio_io_handle_t io = 0
+                  int sessionId = AUDIO_SESSION_OUTPUT_MIX,
+                  audio_io_handle_t io = AUDIO_IO_HANDLE_NONE
                   );
 
     /* Constructor.
@@ -241,8 +242,8 @@
                     int32_t priority = 0,
                     effect_callback_t cbf = NULL,
                     void* user = NULL,
-                    int sessionId = 0,
-                    audio_io_handle_t io = 0
+                    int sessionId = AUDIO_SESSION_OUTPUT_MIX,
+                    audio_io_handle_t io = AUDIO_IO_HANDLE_NONE
                     );
 
     /* Terminates the AudioEffect and unregisters it from AudioFlinger.
@@ -263,8 +264,8 @@
                             int32_t priority = 0,
                             effect_callback_t cbf = NULL,
                             void* user = NULL,
-                            int sessionId = 0,
-                            audio_io_handle_t io = 0
+                            int sessionId = AUDIO_SESSION_OUTPUT_MIX,
+                            audio_io_handle_t io = AUDIO_IO_HANDLE_NONE
                             );
 
     /* Result of constructing the AudioEffect. This must be checked
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 28fdfd4..402b479 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -113,7 +113,6 @@
     // returns the audio output stream latency in ms. Corresponds to
     // audio_stream_out->get_latency()
     static status_t getLatency(audio_io_handle_t output,
-                               audio_stream_type_t stream,
                                uint32_t* latency);
 
     static bool routedToA2dpOutput(audio_stream_type_t streamType);
@@ -125,8 +124,7 @@
     static status_t setVoiceVolume(float volume);
 
     // return the number of audio frames written by AudioFlinger to audio HAL and
-    // audio dsp to DAC since the output on which the specified stream is playing
-    // has exited standby.
+    // audio dsp to DAC since the specified output I/O handle has exited standby.
     // returned status (from utils/Errors.h) can be:
     // - NO_ERROR: successful operation, halFrames and dspFrames point to valid data
     // - INVALID_OPERATION: Not supported on current hardware platform
@@ -135,13 +133,18 @@
     // necessary to check returned status before using the returned values.
     static status_t getRenderPosition(audio_io_handle_t output,
                                       uint32_t *halFrames,
-                                      uint32_t *dspFrames,
-                                      audio_stream_type_t stream = AUDIO_STREAM_DEFAULT);
+                                      uint32_t *dspFrames);
 
     // return the number of input frames lost by HAL implementation, or 0 if the handle is invalid
     static uint32_t getInputFramesLost(audio_io_handle_t ioHandle);
 
+    // Allocate a new audio session ID and return that new ID.
+    // If unable to contact AudioFlinger, returns AUDIO_SESSION_ALLOCATE instead.
+    // FIXME If AudioFlinger were to ever exhaust the session ID namespace,
+    //       this method could fail by returning either AUDIO_SESSION_ALLOCATE
+    //       or an unspecified existing session ID.
     static int newAudioSessionId();
+
     static void acquireAudioSessionId(int audioSession, pid_t pid);
     static void releaseAudioSessionId(int audioSession, pid_t pid);
 
@@ -318,8 +321,6 @@
 
     static sp<IAudioPolicyService> gAudioPolicyService;
 
-    // mapping between stream types and outputs
-    static DefaultKeyedVector<audio_stream_type_t, audio_io_handle_t> gStreamOutputMap;
     // list of output descriptors containing cached parameters
     // (sampling rate, framecount, channel count...)
     static DefaultKeyedVector<audio_io_handle_t, OutputDescriptor *> gOutputs;
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 647748b..2c48bbf 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -36,11 +36,6 @@
 class AudioTrack : public RefBase
 {
 public:
-    enum channel_index {
-        MONO   = 0,
-        LEFT   = 0,
-        RIGHT  = 1
-    };
 
     /* Events used by AudioTrack callback function (callback_t).
      * Keep in sync with frameworks/base/media/java/android/media/AudioTrack.java NATIVE_EVENT_*.
@@ -82,6 +77,7 @@
                                   // (currently ignored, but will make the primary field in future)
 
         size_t      size;         // input/output in bytes == frameCount * frameSize
+                                  // on input it is unused
                                   // on output is the number of bytes actually filled
                                   // FIXME this is redundant with respect to frameCount,
                                   // and TRANSFER_OBTAIN mode is broken for 8-bit data
@@ -91,7 +87,7 @@
             void*       raw;
             short*      i16;      // signed 16-bit
             int8_t*     i8;       // unsigned 8-bit, offset by 0x80
-        };
+        };                        // input: unused, output: pointer to buffer
     };
 
     /* As a convenience, if a callback is supplied, a handler thread
@@ -455,7 +451,8 @@
      *  none.
      *
      * Returned value:
-     *  handle on audio hardware output
+     *  handle on audio hardware output, or AUDIO_IO_HANDLE_NONE if the
+     *  track needed to be re-created but that failed
      */
             audio_io_handle_t    getOutput() const;
 
@@ -533,15 +530,6 @@
                                      struct timespec *elapsed = NULL, size_t *nonContig = NULL);
 public:
 
-//EL_FIXME to be reconciled with new obtainBuffer() return codes and control block proxy
-//            enum {
-//            NO_MORE_BUFFERS = 0x80000001,   // same name in AudioFlinger.h, ok to be different value
-//            TEAR_DOWN       = 0x80000002,
-//            STOPPED = 1,
-//            STREAM_END_WAIT,
-//            STREAM_END
-//        };
-
     /* Release a filled buffer of "audioBuffer->frameCount" frames for AudioFlinger to process. */
     // FIXME make private when obtainBuffer() for TRANSFER_OBTAIN is removed
             void        releaseBuffer(Buffer* audioBuffer);
diff --git a/include/media/stagefright/FileSource.h b/include/media/stagefright/FileSource.h
index d994cb3..9838ed2 100644
--- a/include/media/stagefright/FileSource.h
+++ b/include/media/stagefright/FileSource.h
@@ -30,6 +30,7 @@
 class FileSource : public DataSource {
 public:
     FileSource(const char *filename);
+    // FileSource takes ownership and will close the fd
     FileSource(int fd, int64_t offset, int64_t length);
 
     virtual status_t initCheck() const;
diff --git a/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp b/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp
index cb4b23e..e60030e 100755
--- a/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp
+++ b/libvideoeditor/lvpp/VideoEditorAudioPlayer.cpp
@@ -534,7 +534,8 @@
         mAudioTrack = new AudioTrack(
                 AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT,
                 audio_channel_out_mask_from_count(numChannels),
-                0, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this, 0);
+                0 /*frameCount*/, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this,
+                0 /*notificationFrames*/);
 
         if ((err = mAudioTrack->initCheck()) != OK) {
             mAudioTrack.clear();
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 961b0a2..a7bf380 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -471,7 +471,7 @@
 
     audio_io_handle_t input = AudioSystem::getInput(mInputSource, mSampleRate, mFormat,
             mChannelMask, mSessionId);
-    if (input == 0) {
+    if (input == AUDIO_IO_HANDLE_NONE) {
         ALOGE("Could not get audio input for record source %d, sample rate %u, format %#x, "
               "channel mask %#x, session %d",
               mInputSource, mSampleRate, mFormat, mChannelMask, mSessionId);
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 140fb66..2f16444 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -35,9 +35,9 @@
 sp<IAudioFlinger> AudioSystem::gAudioFlinger;
 sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
 audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
-// Cached values
 
-DefaultKeyedVector<audio_io_handle_t, AudioSystem::OutputDescriptor *> AudioSystem::gOutputs(0);
+// Cached values for output handles
+DefaultKeyedVector<audio_io_handle_t, AudioSystem::OutputDescriptor *> AudioSystem::gOutputs(NULL);
 
 // Cached values for recording queries, all protected by gLock
 uint32_t AudioSystem::gPrevInSamplingRate;
@@ -196,12 +196,12 @@
 
 status_t AudioSystem::setParameters(const String8& keyValuePairs)
 {
-    return setParameters((audio_io_handle_t) 0, keyValuePairs);
+    return setParameters(AUDIO_IO_HANDLE_NONE, keyValuePairs);
 }
 
 String8 AudioSystem::getParameters(const String8& keys)
 {
-    return getParameters((audio_io_handle_t) 0, keys);
+    return getParameters(AUDIO_IO_HANDLE_NONE, keys);
 }
 
 // convert volume steps to natural log scale
@@ -284,7 +284,7 @@
     }
 
     output = getOutput(streamType);
-    if (output == 0) {
+    if (output == AUDIO_IO_HANDLE_NONE) {
         return PERMISSION_DENIED;
     }
 
@@ -329,15 +329,14 @@
     }
 
     output = getOutput(streamType);
-    if (output == 0) {
+    if (output == AUDIO_IO_HANDLE_NONE) {
         return PERMISSION_DENIED;
     }
 
-    return getLatency(output, streamType, latency);
+    return getLatency(output, latency);
 }
 
 status_t AudioSystem::getLatency(audio_io_handle_t output,
-                                 audio_stream_type_t streamType __unused,
                                  uint32_t* latency)
 {
     OutputDescriptor *outputDesc;
@@ -354,7 +353,7 @@
         gLock.unlock();
     }
 
-    ALOGV("getLatency() streamType %d, output %d, latency %d", streamType, output, *latency);
+    ALOGV("getLatency() output %d, latency %d", output, *latency);
 
     return NO_ERROR;
 }
@@ -401,19 +400,11 @@
 }
 
 status_t AudioSystem::getRenderPosition(audio_io_handle_t output, uint32_t *halFrames,
-                                        uint32_t *dspFrames, audio_stream_type_t stream)
+                                        uint32_t *dspFrames)
 {
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
 
-    if (stream == AUDIO_STREAM_DEFAULT) {
-        stream = AUDIO_STREAM_MUSIC;
-    }
-
-    if (output == 0) {
-        output = getOutput(stream);
-    }
-
     return af->getRenderPosition(halFrames, dspFrames, output);
 }
 
@@ -422,7 +413,7 @@
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     uint32_t result = 0;
     if (af == 0) return result;
-    if (ioHandle == 0) return result;
+    if (ioHandle == AUDIO_IO_HANDLE_NONE) return result;
 
     result = af->getInputFramesLost(ioHandle);
     return result;
@@ -431,7 +422,7 @@
 int AudioSystem::newAudioSessionId()
 {
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
-    if (af == 0) return 0;
+    if (af == 0) return AUDIO_SESSION_ALLOCATE;
     return af->newAudioSessionId();
 }
 
@@ -473,7 +464,7 @@
     const OutputDescriptor *desc;
     audio_stream_type_t stream;
 
-    if (ioHandle == 0) return;
+    if (ioHandle == AUDIO_IO_HANDLE_NONE) return;
 
     Mutex::Autolock _l(AudioSystem::gLock);
 
@@ -739,7 +730,7 @@
 audio_devices_t AudioSystem::getDevicesForStream(audio_stream_type_t stream)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
-    if (aps == 0) return (audio_devices_t)0;
+    if (aps == 0) return AUDIO_DEVICE_NONE;
     return aps->getDevicesForStream(stream);
 }
 
@@ -747,7 +738,7 @@
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     // FIXME change return type to status_t, and return PERMISSION_DENIED here
-    if (aps == 0) return 0;
+    if (aps == 0) return AUDIO_IO_HANDLE_NONE;
     return aps->getOutputForEffect(desc);
 }
 
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 20c1cdb..fbfd3da 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -333,8 +333,8 @@
         mOffloadInfo = NULL;
     }
 
-    mVolume[LEFT] = 1.0f;
-    mVolume[RIGHT] = 1.0f;
+    mVolume[AUDIO_INTERLEAVE_LEFT] = 1.0f;
+    mVolume[AUDIO_INTERLEAVE_RIGHT] = 1.0f;
     mSendLevel = 0.0f;
     // mFrameCount is initialized in createTrack_l
     mReqFrameCount = frameCount;
@@ -371,16 +371,6 @@
             mAudioTrackThread->requestExitAndWait();
             mAudioTrackThread.clear();
         }
-        // Use of direct and offloaded output streams is ref counted by audio policy manager.
-#if 0   // FIXME This should no longer be needed
-        //Use of direct and offloaded output streams is ref counted by audio policy manager.
-        // As getOutput was called above and resulted in an output stream to be opened,
-        // we need to release it.
-        if (mOutput != 0) {
-            AudioSystem::releaseOutput(mOutput);
-            mOutput = 0;
-        }
-#endif
         return status;
     }
 
@@ -556,7 +546,7 @@
     mAudioTrack->pause();
 
     if (isOffloaded_l()) {
-        if (mOutput != 0) {
+        if (mOutput != AUDIO_IO_HANDLE_NONE) {
             uint32_t halFrames;
             // OffloadThread sends HAL pause in its threadLoop.. time saved
             // here can be slightly off
@@ -573,8 +563,8 @@
     }
 
     AutoMutex lock(mLock);
-    mVolume[LEFT] = left;
-    mVolume[RIGHT] = right;
+    mVolume[AUDIO_INTERLEAVE_LEFT] = left;
+    mVolume[AUDIO_INTERLEAVE_RIGHT] = right;
 
     mProxy->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000));
 
@@ -643,7 +633,7 @@
     // query the HAL and update if needed.
 // FIXME use Proxy return channel to update the rate from server and avoid polling here
     if (isOffloaded_l()) {
-        if (mOutput != 0) {
+        if (mOutput != AUDIO_IO_HANDLE_NONE) {
             uint32_t sampleRate = 0;
             status_t status = AudioSystem::getSamplingRate(mOutput, mStreamType, &sampleRate);
             if (status == NO_ERROR) {
@@ -789,7 +779,7 @@
             return NO_ERROR;
         }
 
-        if (mOutput != 0) {
+        if (mOutput != AUDIO_IO_HANDLE_NONE) {
             uint32_t halFrames;
             AudioSystem::getRenderPosition(mOutput, &halFrames, &dspFrames);
         }
@@ -865,7 +855,7 @@
 
     audio_io_handle_t output = AudioSystem::getOutput(mStreamType, mSampleRate, mFormat,
             mChannelMask, mFlags, mOffloadInfo);
-    if (output == 0) {
+    if (output == AUDIO_IO_HANDLE_NONE) {
         ALOGE("Could not get audio output for stream type %d, sample rate %u, format %#x, "
               "channel mask %#x, flags %#x",
               mStreamType, mSampleRate, mFormat, mChannelMask, mFlags);
@@ -878,7 +868,7 @@
     // Not all of these values are needed under all conditions, but it is easier to get them all
 
     uint32_t afLatency;
-    status = AudioSystem::getLatency(output, mStreamType, &afLatency);
+    status = AudioSystem::getLatency(output, &afLatency);
     if (status != NO_ERROR) {
         ALOGE("getLatency(%d) failed status %d", output, status);
         goto release;
@@ -1134,8 +1124,8 @@
         mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, frameCount, mFrameSizeAF);
         mProxy = mStaticProxy;
     }
-    mProxy->setVolumeLR((uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) |
-            uint16_t(mVolume[LEFT] * 0x1000));
+    mProxy->setVolumeLR((uint32_t(uint16_t(mVolume[AUDIO_INTERLEAVE_RIGHT] * 0x1000)) << 16) |
+            uint16_t(mVolume[AUDIO_INTERLEAVE_LEFT] * 0x1000));
     mProxy->setSendLevel(mSendLevel);
     mProxy->setSampleRate(mSampleRate);
     mProxy->setEpoch(epoch);
@@ -1775,16 +1765,6 @@
         }
     }
     if (result != NO_ERROR) {
-        // Use of direct and offloaded output streams is ref counted by audio policy manager.
-#if 0   // FIXME This should no longer be needed
-        //Use of direct and offloaded output streams is ref counted by audio policy manager.
-        // As getOutput was called above and resulted in an output stream to be opened,
-        // we need to release it.
-        if (mOutput != 0) {
-            AudioSystem::releaseOutput(mOutput);
-            mOutput = 0;
-        }
-#endif
         ALOGW("restoreTrack_l() failed status %d", result);
         mState = STATE_STOPPED;
     }
@@ -1818,7 +1798,7 @@
 String8 AudioTrack::getParameters(const String8& keys)
 {
     audio_io_handle_t output = getOutput();
-    if (output != 0) {
+    if (output != AUDIO_IO_HANDLE_NONE) {
         return AudioSystem::getParameters(output, keys);
     } else {
         return String8::empty();
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index fdd1a12..58c9fc1 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -200,7 +200,7 @@
             ts = &remaining;
             break;
         default:
-            LOG_FATAL("obtainBuffer() timeout=%d", timeout);
+            LOG_ALWAYS_FATAL("obtainBuffer() timeout=%d", timeout);
             ts = NULL;
             break;
         }
@@ -429,7 +429,7 @@
             ts = &remaining;
             break;
         default:
-            LOG_FATAL("waitStreamEndDone() timeout=%d", timeout);
+            LOG_ALWAYS_FATAL("waitStreamEndDone() timeout=%d", timeout);
             ts = NULL;
             break;
         }
@@ -470,7 +470,7 @@
 
 void StaticAudioTrackClientProxy::flush()
 {
-    LOG_FATAL("static flush");
+    LOG_ALWAYS_FATAL("static flush");
 }
 
 void StaticAudioTrackClientProxy::setLoop(size_t loopStart, size_t loopEnd, int loopCount)
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 762681e..eb813bd 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -109,6 +109,7 @@
         data.writeInt32(frameCount);
         track_flags_t lFlags = flags != NULL ? *flags : (track_flags_t) TRACK_DEFAULT;
         data.writeInt32(lFlags);
+        // haveSharedBuffer
         if (sharedBuffer != 0) {
             data.writeInt32(true);
             data.writeStrongBinder(sharedBuffer->asBinder());
@@ -410,7 +411,7 @@
                                          const audio_offload_info_t *offloadInfo)
     {
         Parcel data, reply;
-        audio_devices_t devices = pDevices != NULL ? *pDevices : (audio_devices_t)0;
+        audio_devices_t devices = pDevices != NULL ? *pDevices : AUDIO_DEVICE_NONE;
         uint32_t samplingRate = pSamplingRate != NULL ? *pSamplingRate : 0;
         audio_format_t format = pFormat != NULL ? *pFormat : AUDIO_FORMAT_DEFAULT;
         audio_channel_mask_t channelMask = pChannelMask != NULL ?
@@ -424,6 +425,7 @@
         data.writeInt32(channelMask);
         data.writeInt32(latency);
         data.writeInt32((int32_t) flags);
+        // hasOffloadInfo
         if (offloadInfo == NULL) {
             data.writeInt32(0);
         } else {
@@ -501,7 +503,7 @@
                                         audio_channel_mask_t *pChannelMask)
     {
         Parcel data, reply;
-        audio_devices_t devices = pDevices != NULL ? *pDevices : (audio_devices_t)0;
+        audio_devices_t devices = pDevices != NULL ? *pDevices : AUDIO_DEVICE_NONE;
         uint32_t samplingRate = pSamplingRate != NULL ? *pSamplingRate : 0;
         audio_format_t format = pFormat != NULL ? *pFormat : AUDIO_FORMAT_DEFAULT;
         audio_channel_mask_t channelMask = pChannelMask != NULL ?
@@ -599,7 +601,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
         status_t status = remote()->transact(NEW_AUDIO_SESSION_ID, data, &reply);
-        int id = 0;
+        int id = AUDIO_SESSION_ALLOCATE;
         if (status == NO_ERROR) {
             id = reply.readInt32();
         }
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 1a027a6..9bb4a49 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -137,6 +137,7 @@
         data.writeInt32(static_cast <uint32_t>(format));
         data.writeInt32(channelMask);
         data.writeInt32(static_cast <uint32_t>(flags));
+        // hasOffloadInfo
         if (offloadInfo == NULL) {
             data.writeInt32(0);
         } else {
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index adef3be..61b6d36 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -1057,7 +1057,7 @@
                       0,    // notificationFrames
                       0,    // sharedBuffer
                       mThreadCanCallJava,
-                      0,    // sessionId
+                      AUDIO_SESSION_ALLOCATE,
                       AudioTrack::TRANSFER_CALLBACK);
 
     if (mpAudioTrack->initCheck() != NO_ERROR) {
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 200c561..778eb9a 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1679,7 +1679,7 @@
 
 ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size)
 {
-    LOG_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
+    LOG_ALWAYS_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
 
     //ALOGV("write(%p, %u)", buffer, size);
     if (mTrack != 0) {
diff --git a/media/libnbaio/MonoPipe.cpp b/media/libnbaio/MonoPipe.cpp
index 9c8461c..4adf018 100644
--- a/media/libnbaio/MonoPipe.cpp
+++ b/media/libnbaio/MonoPipe.cpp
@@ -30,6 +30,23 @@
 
 namespace android {
 
+static uint64_t cacheN; // output of CCHelper::getLocalFreq()
+static bool cacheValid; // whether cacheN is valid
+static pthread_once_t cacheOnceControl = PTHREAD_ONCE_INIT;
+
+static void cacheOnceInit()
+{
+    CCHelper tmpHelper;
+    status_t res;
+    if (OK != (res = tmpHelper.getLocalFreq(&cacheN))) {
+        ALOGE("Failed to fetch local time frequency when constructing a"
+              " MonoPipe (res = %d).  getNextWriteTimestamp calls will be"
+              " non-functional", res);
+        return;
+    }
+    cacheValid = true;
+}
+
 MonoPipe::MonoPipe(size_t reqFrames, const NBAIO_Format& format, bool writeCanBlock) :
         NBAIO_Sink(format),
         mUpdateSeq(0),
@@ -47,8 +64,6 @@
         mTimestampMutator(&mTimestampShared),
         mTimestampObserver(&mTimestampShared)
 {
-    CCHelper tmpHelper;
-    status_t res;
     uint64_t N, D;
 
     mNextRdPTS = AudioBufferProvider::kInvalidPTS;
@@ -59,12 +74,13 @@
     mSamplesToLocalTime.a_to_b_denom = 0;
 
     D = Format_sampleRate(format);
-    if (OK != (res = tmpHelper.getLocalFreq(&N))) {
-        ALOGE("Failed to fetch local time frequency when constructing a"
-              " MonoPipe (res = %d).  getNextWriteTimestamp calls will be"
-              " non-functional", res);
+
+    (void) pthread_once(&cacheOnceControl, cacheOnceInit);
+    if (!cacheValid) {
+        // log has already been done
         return;
     }
+    N = cacheN;
 
     LinearTransform::reduce(&N, &D);
     static const uint64_t kSignedHiBitsMask   = ~(0x7FFFFFFFull);
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index 8623100..2669849 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -221,7 +221,8 @@
 
         mAudioTrack = new AudioTrack(
                 AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT, audioMask,
-                0, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this, 0);
+                0 /*frameCount*/, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this,
+                0 /*notificationFrames*/);
 
         if ((err = mAudioTrack->initCheck()) != OK) {
             mAudioTrack.clear();
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 50179c5..123202a 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -159,6 +159,7 @@
 AudioFlinger::AudioFlinger()
     : BnAudioFlinger(),
       mPrimaryHardwareDev(NULL),
+      mAudioHwDevs(NULL),
       mHardwareStatus(AUDIO_HW_IDLE),
       mMasterVolume(1.0f),
       mMasterMute(false),
@@ -876,7 +877,7 @@
 
     AutoMutex lock(mLock);
     PlaybackThread *thread = NULL;
-    if (output) {
+    if (output != AUDIO_IO_HANDLE_NONE) {
         thread = checkPlaybackThread_l(output);
         if (thread == NULL) {
             return BAD_VALUE;
@@ -925,7 +926,7 @@
 
     AutoMutex lock(mLock);
     float volume;
-    if (output) {
+    if (output != AUDIO_IO_HANDLE_NONE) {
         PlaybackThread *thread = checkPlaybackThread_l(output);
         if (thread == NULL) {
             return 0.0f;
@@ -958,8 +959,8 @@
         return PERMISSION_DENIED;
     }
 
-    // ioHandle == 0 means the parameters are global to the audio hardware interface
-    if (ioHandle == 0) {
+    // AUDIO_IO_HANDLE_NONE means the parameters are global to the audio hardware interface
+    if (ioHandle == AUDIO_IO_HANDLE_NONE) {
         Mutex::Autolock _l(mLock);
         status_t final_result = NO_ERROR;
         {
@@ -1041,7 +1042,7 @@
 
     Mutex::Autolock _l(mLock);
 
-    if (ioHandle == 0) {
+    if (ioHandle == AUDIO_IO_HANDLE_NONE) {
         String8 out_s8;
 
         for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
@@ -1561,15 +1562,15 @@
     ALOGV("openOutput(), offloadInfo %p version 0x%04x",
           offloadInfo, offloadInfo == NULL ? -1 : offloadInfo->version);
 
-    if (pDevices == NULL || *pDevices == 0) {
-        return 0;
+    if (pDevices == NULL || *pDevices == AUDIO_DEVICE_NONE) {
+        return AUDIO_IO_HANDLE_NONE;
     }
 
     Mutex::Autolock _l(mLock);
 
     AudioHwDevice *outHwDev = findSuitableHwDev_l(module, *pDevices);
     if (outHwDev == NULL) {
-        return 0;
+        return AUDIO_IO_HANDLE_NONE;
     }
 
     audio_hw_device_t *hwDevHal = outHwDev->hwDevice();
@@ -1641,7 +1642,7 @@
         return id;
     }
 
-    return 0;
+    return AUDIO_IO_HANDLE_NONE;
 }
 
 audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
@@ -1654,7 +1655,7 @@
     if (thread1 == NULL || thread2 == NULL) {
         ALOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1,
                 output2);
-        return 0;
+        return AUDIO_IO_HANDLE_NONE;
     }
 
     audio_io_handle_t id = nextUniqueId();
@@ -1775,7 +1776,7 @@
     audio_format_t reqFormat = config.format;
     audio_channel_mask_t reqChannelMask = config.channel_mask;
 
-    if (pDevices == NULL || *pDevices == 0) {
+    if (pDevices == NULL || *pDevices == AUDIO_DEVICE_NONE) {
         return 0;
     }
 
@@ -2089,7 +2090,7 @@
 
 uint32_t AudioFlinger::nextUniqueId()
 {
-    return android_atomic_inc(&mNextUniqueId);
+    return (uint32_t) android_atomic_inc(&mNextUniqueId);
 }
 
 AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
@@ -2281,7 +2282,7 @@
 
         // return effect descriptor
         *pDesc = desc;
-        if (io == 0 && sessionId == AUDIO_SESSION_OUTPUT_MIX) {
+        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
@@ -2296,7 +2297,7 @@
         // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
         // because of code checking output when entering the function.
         // Note: io is never 0 when creating an effect on an input
-        if (io == 0) {
+        if (io == AUDIO_IO_HANDLE_NONE) {
             if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
                 // output must be specified by AudioPolicyManager when using session
                 // AUDIO_SESSION_OUTPUT_STAGE
@@ -2321,7 +2322,7 @@
             // If no output thread contains the requested session ID, default to
             // first output. The effect chain will be moved to the correct output
             // thread when a track with the same session ID is created
-            if (io == 0 && mPlaybackThreads.size()) {
+            if (io == AUDIO_IO_HANDLE_NONE && mPlaybackThreads.size() > 0) {
                 io = mPlaybackThreads.keyAt(0);
             }
             ALOGV("createEffect() got io %d for effect %s", io, desc.name);
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 2367d7d..ec32edd 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -454,7 +454,14 @@
                                 { return mStreamTypes[stream].volume; }
               void audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2);
 
-              // allocate an audio_io_handle_t, session ID, or effect ID
+              // Allocate an audio_io_handle_t, session ID, effect ID, or audio_module_handle_t.
+              // They all share the same ID space, but the namespaces are actually independent
+              // because there are separate KeyedVectors for each kind of ID.
+              // The return value is uint32_t, but is cast to signed for some IDs.
+              // FIXME This API does not handle rollover to zero (for unsigned IDs),
+              //       or from positive to negative (for signed IDs).
+              //       Thus it may fail by returning an ID of the wrong sign,
+              //       or by returning a non-unique ID.
               uint32_t nextUniqueId();
 
               status_t moveEffectChain_l(int sessionId,
@@ -590,7 +597,11 @@
                 DefaultKeyedVector< audio_io_handle_t, sp<RecordThread> >    mRecordThreads;
 
                 DefaultKeyedVector< pid_t, sp<NotificationClient> >    mNotificationClients;
+
                 volatile int32_t                    mNextUniqueId;  // updated by android_atomic_inc
+                // nextUniqueId() returns uint32_t, but this is declared int32_t
+                // because the atomic operations require an int32_t
+
                 audio_mode_t                        mMode;
                 bool                                mBtNrecIsOff;
 
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 3ac5da9..a1783fe 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -449,7 +449,7 @@
             }
             } break;
         default:
-            LOG_FATAL("bad param");
+            LOG_ALWAYS_FATAL("setParameter track: bad param %d", param);
         }
         break;
 
@@ -474,7 +474,7 @@
             invalidateState(1 << name);
             break;
         default:
-            LOG_FATAL("bad param");
+            LOG_ALWAYS_FATAL("setParameter resample: bad param %d", param);
         }
         break;
 
@@ -522,12 +522,12 @@
             }
             break;
         default:
-            LOG_FATAL("bad param");
+            LOG_ALWAYS_FATAL("setParameter volume: bad param %d", param);
         }
         break;
 
     default:
-        LOG_FATAL("bad target");
+        LOG_ALWAYS_FATAL("setParameter: bad target %d", target);
     }
 }
 
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 90122e0..adb4aca 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -212,7 +212,7 @@
         case FastMixerState::MIX_WRITE:
             break;
         default:
-            LOG_FATAL("bad command %d", command);
+            LOG_ALWAYS_FATAL("bad command %d", command);
         }
 
         // there is a non-idle state available to us; did the state change?
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index e046e03..7700780 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1133,7 +1133,7 @@
 
     // mStreamTypes[AUDIO_STREAM_CNT] is initialized by stream_type_t default constructor
     // There is no AUDIO_STREAM_MIN, and ++ operator does not compile
-    for (audio_stream_type_t stream = (audio_stream_type_t) 0; stream < AUDIO_STREAM_CNT;
+    for (audio_stream_type_t stream = AUDIO_STREAM_MIN; stream < AUDIO_STREAM_CNT;
             stream = (audio_stream_type_t) (stream + 1)) {
         mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream);
         mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
@@ -1711,24 +1711,24 @@
 
 void AudioFlinger::PlaybackThread::readOutputParameters_l()
 {
-    // unfortunately we have no way of recovering from errors here, hence the LOG_FATAL
+    // unfortunately we have no way of recovering from errors here, hence the LOG_ALWAYS_FATAL
     mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common);
     mChannelMask = mOutput->stream->common.get_channels(&mOutput->stream->common);
     if (!audio_is_output_channel(mChannelMask)) {
-        LOG_FATAL("HAL channel mask %#x not valid for output", mChannelMask);
+        LOG_ALWAYS_FATAL("HAL channel mask %#x not valid for output", mChannelMask);
     }
     if ((mType == MIXER || mType == DUPLICATING) && mChannelMask != AUDIO_CHANNEL_OUT_STEREO) {
-        LOG_FATAL("HAL channel mask %#x not supported for mixed output; "
+        LOG_ALWAYS_FATAL("HAL channel mask %#x not supported for mixed output; "
                 "must be AUDIO_CHANNEL_OUT_STEREO", mChannelMask);
     }
     mChannelCount = popcount(mChannelMask);
     mFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
     if (!audio_is_valid_format(mFormat)) {
-        LOG_FATAL("HAL format %#x not valid for output", mFormat);
+        LOG_ALWAYS_FATAL("HAL format %#x not valid for output", mFormat);
     }
     if ((mType == MIXER || mType == DUPLICATING) && mFormat != AUDIO_FORMAT_PCM_16_BIT) {
-        LOG_FATAL("HAL format %#x not supported for mixed output; must be AUDIO_FORMAT_PCM_16_BIT",
-                mFormat);
+        LOG_ALWAYS_FATAL("HAL format %#x not supported for mixed output; "
+                "must be AUDIO_FORMAT_PCM_16_BIT", mFormat);
     }
     mFrameSize = audio_stream_frame_size(&mOutput->stream->common);
     mBufferSize = mOutput->stream->common.get_buffer_size(&mOutput->stream->common);
@@ -3118,7 +3118,7 @@
                 break;
             case TrackBase::IDLE:
             default:
-                LOG_FATAL("unexpected track state %d", track->mState);
+                LOG_ALWAYS_FATAL("unexpected track state %d", track->mState);
             }
 
             if (isActive) {
@@ -3149,7 +3149,7 @@
                     // because we're about to decrement the last sp<> on those tracks.
                     block = FastMixerStateQueue::BLOCK_UNTIL_ACKED;
                 } else {
-                    LOG_FATAL("fast track %d should have been active", j);
+                    LOG_ALWAYS_FATAL("fast track %d should have been active", j);
                 }
                 tracksToRemove->add(track);
                 // Avoids a misleading display in dumpsys
@@ -4765,7 +4765,7 @@
                     continue;
 
                 default:
-                    LOG_FATAL("Unexpected activeTrackState %d", activeTrackState);
+                    LOG_ALWAYS_FATAL("Unexpected activeTrackState %d", activeTrackState);
                 }
 
                 activeTracks.add(activeTrack);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 9fe459b..2cf10e2 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1525,7 +1525,7 @@
             mTrimQueueHeadOnRelease = false;
         }
     } else {
-        LOG_FATAL("TimedTrack::releaseBuffer of non-silence buffer with no"
+        LOG_ALWAYS_FATAL("TimedTrack::releaseBuffer of non-silence buffer with no"
                   " buffers in the timed buffer queue");
     }
 
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index d5be58c..5bfb969 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -16,7 +16,7 @@
 
 #define LOG_TAG "Camera2-Parameters"
 #define ATRACE_TAG ATRACE_TAG_CAMERA
-// #define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 
 #include <utils/Log.h>
 #include <utils/Trace.h>
@@ -92,6 +92,26 @@
         staticInfo(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, 2);
     if (!availableFpsRanges.count) return NO_INIT;
 
+    previewFpsRange[0] = availableFpsRanges.data.i32[0];
+    previewFpsRange[1] = availableFpsRanges.data.i32[1];
+
+    params.set(CameraParameters::KEY_PREVIEW_FPS_RANGE,
+            String8::format("%d,%d",
+                    previewFpsRange[0] * kFpsToApiScale,
+                    previewFpsRange[1] * kFpsToApiScale));
+
+    {
+        String8 supportedPreviewFpsRange;
+        for (size_t i=0; i < availableFpsRanges.count; i += 2) {
+            if (i != 0) supportedPreviewFpsRange += ",";
+            supportedPreviewFpsRange += String8::format("(%d,%d)",
+                    availableFpsRanges.data.i32[i] * kFpsToApiScale,
+                    availableFpsRanges.data.i32[i+1] * kFpsToApiScale);
+        }
+        params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE,
+                supportedPreviewFpsRange);
+    }
+
     previewFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP;
     params.set(CameraParameters::KEY_PREVIEW_FORMAT,
             formatEnumToString(previewFormat)); // NV21
@@ -159,9 +179,6 @@
                 supportedPreviewFormats);
     }
 
-    previewFpsRange[0] = availableFpsRanges.data.i32[0];
-    previewFpsRange[1] = availableFpsRanges.data.i32[1];
-
     // PREVIEW_FRAME_RATE / SUPPORTED_PREVIEW_FRAME_RATES are deprecated, but
     // still have to do something sane for them
 
@@ -170,27 +187,6 @@
     params.set(CameraParameters::KEY_PREVIEW_FRAME_RATE,
             previewFps);
 
-    // PREVIEW_FPS_RANGE
-    // -- Order matters. Set range after single value to so that a roundtrip
-    //    of setParameters(getParameters()) would keep the FPS range in higher
-    //    order.
-    params.set(CameraParameters::KEY_PREVIEW_FPS_RANGE,
-            String8::format("%d,%d",
-                    previewFpsRange[0] * kFpsToApiScale,
-                    previewFpsRange[1] * kFpsToApiScale));
-
-    {
-        String8 supportedPreviewFpsRange;
-        for (size_t i=0; i < availableFpsRanges.count; i += 2) {
-            if (i != 0) supportedPreviewFpsRange += ",";
-            supportedPreviewFpsRange += String8::format("(%d,%d)",
-                    availableFpsRanges.data.i32[i] * kFpsToApiScale,
-                    availableFpsRanges.data.i32[i+1] * kFpsToApiScale);
-        }
-        params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE,
-                supportedPreviewFpsRange);
-    }
-
     {
         SortedVector<int32_t> sortedPreviewFrameRates;
 
@@ -1131,72 +1127,29 @@
     // RECORDING_HINT (always supported)
     validatedParams.recordingHint = boolFromString(
         newParams.get(CameraParameters::KEY_RECORDING_HINT) );
-    IF_ALOGV() { // Avoid unused variable warning
-        bool recordingHintChanged =
-                validatedParams.recordingHint != recordingHint;
-        if (recordingHintChanged) {
-            ALOGV("%s: Recording hint changed to %d",
-                  __FUNCTION__, validatedParams.recordingHint);
-        }
-    }
+    bool recordingHintChanged = validatedParams.recordingHint != recordingHint;
+    ALOGV_IF(recordingHintChanged, "%s: Recording hint changed to %d",
+            __FUNCTION__, recordingHintChanged);
 
     // PREVIEW_FPS_RANGE
+    bool fpsRangeChanged = false;
+    int32_t lastSetFpsRange[2];
 
-    /**
-     * Use the single FPS value if it was set later than the range.
-     * Otherwise, use the range value.
-     */
-    bool fpsUseSingleValue;
-    {
-        const char *fpsRange, *fpsSingle;
+    params.getPreviewFpsRange(&lastSetFpsRange[0], &lastSetFpsRange[1]);
+    lastSetFpsRange[0] /= kFpsToApiScale;
+    lastSetFpsRange[1] /= kFpsToApiScale;
 
-        fpsRange = params.get(CameraParameters::KEY_PREVIEW_FRAME_RATE);
-        fpsSingle = params.get(CameraParameters::KEY_PREVIEW_FPS_RANGE);
-
-        /**
-         * Pick either the range or the single key if only one was set.
-         *
-         * If both are set, pick the one that has greater set order.
-         */
-        if (fpsRange == NULL && fpsSingle == NULL) {
-            ALOGE("%s: FPS was not set. One of %s or %s must be set.",
-                  __FUNCTION__, CameraParameters::KEY_PREVIEW_FRAME_RATE,
-                  CameraParameters::KEY_PREVIEW_FPS_RANGE);
-            return BAD_VALUE;
-        } else if (fpsRange == NULL) {
-            fpsUseSingleValue = true;
-            ALOGV("%s: FPS range not set, using FPS single value",
-                  __FUNCTION__);
-        } else if (fpsSingle == NULL) {
-            fpsUseSingleValue = false;
-            ALOGV("%s: FPS single not set, using FPS range value",
-                  __FUNCTION__);
-        } else {
-            int fpsKeyOrder;
-            res = params.compareSetOrder(
-                    CameraParameters::KEY_PREVIEW_FRAME_RATE,
-                    CameraParameters::KEY_PREVIEW_FPS_RANGE,
-                    &fpsKeyOrder);
-            LOG_ALWAYS_FATAL_IF(res != OK, "Impossibly bad FPS keys");
-
-            fpsUseSingleValue = (fpsKeyOrder > 0);
-
-        }
-
-        ALOGV("%s: Preview FPS value is used from '%s'",
-              __FUNCTION__, fpsUseSingleValue ? "single" : "range");
-    }
     newParams.getPreviewFpsRange(&validatedParams.previewFpsRange[0],
             &validatedParams.previewFpsRange[1]);
     validatedParams.previewFpsRange[0] /= kFpsToApiScale;
     validatedParams.previewFpsRange[1] /= kFpsToApiScale;
 
-    // Ignore the FPS range if the FPS single has higher precedence
-    if (!fpsUseSingleValue) {
-        ALOGV("%s: Preview FPS range (%d, %d)", __FUNCTION__,
-                validatedParams.previewFpsRange[0],
-                validatedParams.previewFpsRange[1]);
+    // Compare the FPS range value from the last set() to the current set()
+    // to determine if the client has changed it
+    if (validatedParams.previewFpsRange[0] != lastSetFpsRange[0] ||
+            validatedParams.previewFpsRange[1] != lastSetFpsRange[1]) {
 
+        fpsRangeChanged = true;
         camera_metadata_ro_entry_t availablePreviewFpsRanges =
             staticInfo(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, 2);
         for (i = 0; i < availablePreviewFpsRanges.count; i += 2) {
@@ -1247,13 +1200,14 @@
         }
     }
 
-    // PREVIEW_FRAME_RATE Deprecated
-    // - Use only if the single FPS value was set later than the FPS range
-    if (fpsUseSingleValue) {
+    // PREVIEW_FRAME_RATE Deprecated, only use if the preview fps range is
+    // unchanged this time.  The single-value FPS is the same as the minimum of
+    // the range.  To detect whether the application has changed the value of
+    // previewFps, compare against their last-set preview FPS.
+    if (!fpsRangeChanged) {
         int previewFps = newParams.getPreviewFrameRate();
-        ALOGV("%s: Preview FPS single value requested: %d",
-              __FUNCTION__, previewFps);
-        {
+        int lastSetPreviewFps = params.getPreviewFrameRate();
+        if (previewFps != lastSetPreviewFps || recordingHintChanged) {
             camera_metadata_ro_entry_t availableFrameRates =
                 staticInfo(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
             /**
@@ -1322,35 +1276,6 @@
         }
     }
 
-    /**
-     * Update Preview FPS and Preview FPS ranges based on
-     * what we actually set.
-     *
-     * This updates the API-visible (Camera.Parameters#getParameters) values of
-     * the FPS fields, not only the internal versions.
-     *
-     * Order matters: The value that was set last takes precedence.
-     * - If the client does a setParameters(getParameters()) we retain
-     *   the same order for preview FPS.
-     */
-    if (!fpsUseSingleValue) {
-        // Set fps single, then fps range (range wins)
-        validatedParams.params.setPreviewFrameRate(
-                fpsFromRange(/*min*/validatedParams.previewFpsRange[0],
-                             /*max*/validatedParams.previewFpsRange[1]));
-        validatedParams.params.setPreviewFpsRange(
-                validatedParams.previewFpsRange[0],
-                validatedParams.previewFpsRange[1]);
-    } else {
-        // Set fps range, then fps single (single wins)
-        validatedParams.params.setPreviewFpsRange(
-                validatedParams.previewFpsRange[0],
-                validatedParams.previewFpsRange[1]);
-        validatedParams.params.setPreviewFrameRate(
-                fpsFromRange(/*min*/validatedParams.previewFpsRange[0],
-                             /*max*/validatedParams.previewFpsRange[1]));
-    }
-
     // PICTURE_SIZE
     newParams.getPictureSize(&validatedParams.pictureWidth,
             &validatedParams.pictureHeight);