Merge "DO NOT MERGE Bring Metrics summarizers over from master" into oc-dev
diff --git a/camera/include/camera/ndk/NdkCameraMetadataTags.h b/camera/include/camera/ndk/NdkCameraMetadataTags.h
index 25d364e..8b76cdf 100644
--- a/camera/include/camera/ndk/NdkCameraMetadataTags.h
+++ b/camera/include/camera/ndk/NdkCameraMetadataTags.h
@@ -1547,6 +1547,7 @@
      * <code>false</code> if present.</p>
      * <p>For applications targeting SDK versions older than O, the value of enableZsl in all
      * capture templates is always <code>false</code> if present.</p>
+     * <p>For application-operated ZSL, use CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG template.</p>
      *
      * @see ACAMERA_CONTROL_CAPTURE_INTENT
      * @see ACAMERA_SENSOR_TIMESTAMP
diff --git a/include/media/Interpolator.h b/include/media/Interpolator.h
index 120a074..45a0585 100644
--- a/include/media/Interpolator.h
+++ b/include/media/Interpolator.h
@@ -152,8 +152,8 @@
                         : mLastSlope;
             } else {
                 // finite difference spline
-                m0 = (sec0 + sec) * 0.5;
-                m1 = (sec1 + sec) * 0.5;
+                m0 = (sec0 + sec) * 0.5f;
+                m1 = (sec1 + sec) * 0.5f;
             }
 
             if (monotonic) {
@@ -294,12 +294,21 @@
 
     std::string toString() const {
         std::stringstream ss;
-        ss << "mInterpolatorType: " << mInterpolatorType << std::endl;
-        ss << "mFirstSlope: " << mFirstSlope << std::endl;
-        ss << "mLastSlope: " << mLastSlope << std::endl;
+        ss << "Interpolator{mInterpolatorType=" << static_cast<int32_t>(mInterpolatorType);
+        ss << ", mFirstSlope=" << mFirstSlope;
+        ss << ", mLastSlope=" << mLastSlope;
+        ss << ", {";
+        bool first = true;
         for (const auto &pt : *this) {
-            ss << pt.first << " " << pt.second << std::endl;
+            if (first) {
+                first = false;
+                ss << "{";
+            } else {
+                ss << ", {";
+            }
+            ss << pt.first << ", " << pt.second << "}";
         }
+        ss << "}}";
         return ss.str();
     }
 
@@ -324,7 +333,7 @@
 
     // spline cubic polynomial coefficient cache
     std::unordered_map<S, std::tuple<S /* c1 */, S /* c2 */, S /* c3 */>> mMemo;
-};
+}; // Interpolator
 
 } // namespace android
 
diff --git a/include/media/VolumeShaper.h b/include/media/VolumeShaper.h
index 1282124..e4c0b5b 100644
--- a/include/media/VolumeShaper.h
+++ b/include/media/VolumeShaper.h
@@ -51,31 +51,68 @@
 
 class VolumeShaper {
 public:
-    using S = float;
-    using T = float;
+    // S and T are like template typenames (matching the Interpolator<S, T>)
+    using S = float; // time type
+    using T = float; // volume type
 
-    static const int kSystemIdMax = 16;
+// Curve and dimension information
+// TODO: member static const or constexpr float initialization not permitted in C++11
+#define MIN_CURVE_TIME    0.f  // type S: start of VolumeShaper curve (normalized)
+#define MAX_CURVE_TIME    1.f  // type S: end of VolumeShaper curve (normalized)
+#define MIN_LINEAR_VOLUME 0.f  // type T: silence / mute audio
+#define MAX_LINEAR_VOLUME 1.f  // type T: max volume, unity gain
+#define MAX_LOG_VOLUME    0.f  // type T: max volume, unity gain in dBFS
 
-    // VolumeShaper::Status is equivalent to status_t if negative
-    // but if non-negative represents the id operated on.
-    // It must be expressible as an int32_t for binder purposes.
+    /* kSystemVolumeShapersMax is the maximum number of system VolumeShapers.
+     * Each system VolumeShapers has a predefined Id, which ranges from 0
+     * to kSystemVolumeShapersMax - 1 and is unique for its usage.
+     *
+     * "1" is reserved for system ducking.
+     */
+    static const int kSystemVolumeShapersMax = 16;
+
+    /* kUserVolumeShapersMax is the maximum number of application
+     * VolumeShapers for a player/track.  Application VolumeShapers are
+     * assigned on creation by the client, and have Ids ranging
+     * from kSystemVolumeShapersMax to INT32_MAX.
+     *
+     * The number of user/application volume shapers is independent to the
+     * system volume shapers. If an application tries to create more than
+     * kUserVolumeShapersMax to a player, then the apply() will fail.
+     * This prevents exhausting server side resources by a potentially malicious
+     * application.
+     */
+    static const int kUserVolumeShapersMax = 16;
+
+    /* VolumeShaper::Status is equivalent to status_t if negative
+     * but if non-negative represents the id operated on.
+     * It must be expressible as an int32_t for binder purposes.
+     */
     using Status = status_t;
 
+    // Local definition for clamp as std::clamp is included in C++17 only.
+    // TODO: use the std::clamp version when Android build uses C++17.
+    template<typename R>
+    static constexpr const R &clamp(const R &v, const R &lo, const R &hi) {
+        return (v < lo) ? lo : (hi < v) ? hi : v;
+    }
+
+    /* VolumeShaper.Configuration derives from the Interpolator class and adds
+     * parameters relating to the volume shape.
+     *
+     * This parallels the Java implementation and the enums must match.
+     * See "frameworks/base/media/java/android/media/VolumeShaper.java" for
+     * details on the Java implementation.
+     */
     class Configuration : public Interpolator<S, T>, public RefBase {
     public:
-        /* VolumeShaper.Configuration derives from the Interpolator class and adds
-         * parameters relating to the volume shape.
-         */
-
-        // TODO document as per VolumeShaper.java flags.
-
-        // must match with VolumeShaper.java in frameworks/base
+        // Must match with VolumeShaper.java in frameworks/base.
         enum Type : int32_t {
             TYPE_ID,
             TYPE_SCALE,
         };
 
-        // must match with VolumeShaper.java in frameworks/base
+        // Must match with VolumeShaper.java in frameworks/base.
         enum OptionFlag : int32_t {
             OPTION_FLAG_NONE           = 0,
             OPTION_FLAG_VOLUME_IN_DBFS = (1 << 0),
@@ -84,11 +121,12 @@
             OPTION_FLAG_ALL            = (OPTION_FLAG_VOLUME_IN_DBFS | OPTION_FLAG_CLOCK_TIME),
         };
 
-        // bring to derived class; must match with VolumeShaper.java in frameworks/base
+        // Bring from base class; must match with VolumeShaper.java in frameworks/base.
         using InterpolatorType = Interpolator<S, T>::InterpolatorType;
 
         Configuration()
             : Interpolator<S, T>()
+            , RefBase()
             , mType(TYPE_SCALE)
             , mOptionFlags(OPTION_FLAG_NONE)
             , mDurationMs(1000.)
@@ -97,6 +135,7 @@
 
         explicit Configuration(const Configuration &configuration)
             : Interpolator<S, T>(*static_cast<const Interpolator<S, T> *>(&configuration))
+            , RefBase()
             , mType(configuration.mType)
             , mOptionFlags(configuration.mOptionFlags)
             , mDurationMs(configuration.mDurationMs)
@@ -136,8 +175,13 @@
             return mDurationMs;
         }
 
-        void setDurationMs(double durationMs) {
-            mDurationMs = durationMs;
+        status_t setDurationMs(double durationMs) {
+            if (durationMs > 0.) {
+                mDurationMs = durationMs;
+                return NO_ERROR;
+            }
+            // zero, negative, or nan. These values not possible from Java.
+            return BAD_VALUE;
         }
 
         int32_t getId() const {
@@ -145,45 +189,46 @@
         }
 
         void setId(int32_t id) {
+            // We permit a negative id here (representing invalid).
             mId = id;
         }
 
+        /* Adjust the volume to be in linear range from MIN_LINEAR_VOLUME to MAX_LINEAR_VOLUME
+         * and compensate for log dbFS volume as needed.
+         */
         T adjustVolume(T volume) const {
             if ((getOptionFlags() & OPTION_FLAG_VOLUME_IN_DBFS) != 0) {
-                const T out = powf(10.f, volume / 10.);
+                const T out = powf(10.f, volume / 10.f);
                 VS_LOG("in: %f  out: %f", volume, out);
                 volume = out;
             }
-            // clamp
-            if (volume < 0.f) {
-                volume = 0.f;
-            } else if (volume > 1.f) {
-                volume = 1.f;
-            }
-            return volume;
+            return clamp(volume, MIN_LINEAR_VOLUME /* lo */, MAX_LINEAR_VOLUME /* hi */);
         }
 
-        status_t checkCurve() {
+        /* Check if the existing curve is valid.
+         */
+        status_t checkCurve() const {
             if (mType == TYPE_ID) return NO_ERROR;
             if (this->size() < 2) {
                 ALOGE("curve must have at least 2 points");
                 return BAD_VALUE;
             }
-            if (first().first != 0.f || last().first != 1.f) {
-                ALOGE("curve must start at 0.f and end at 1.f");
+            if (first().first != MIN_CURVE_TIME || last().first != MAX_CURVE_TIME) {
+                ALOGE("curve must start at MIN_CURVE_TIME and end at MAX_CURVE_TIME");
                 return BAD_VALUE;
             }
             if ((getOptionFlags() & OPTION_FLAG_VOLUME_IN_DBFS) != 0) {
                 for (const auto &pt : *this) {
-                    if (!(pt.second <= 0.f) /* handle nan */) {
+                    if (!(pt.second <= MAX_LOG_VOLUME) /* handle nan */) {
                         ALOGE("positive volume dbFS");
                         return BAD_VALUE;
                     }
                 }
             } else {
                 for (const auto &pt : *this) {
-                    if (!(pt.second >= 0.f) || !(pt.second <= 1.f) /* handle nan */) {
-                        ALOGE("volume < 0.f or > 1.f");
+                    if (!(pt.second >= MIN_LINEAR_VOLUME)
+                            || !(pt.second <= MAX_LINEAR_VOLUME) /* handle nan */) {
+                        ALOGE("volume < MIN_LINEAR_VOLUME or > MAX_LINEAR_VOLUME");
                         return BAD_VALUE;
                     }
                 }
@@ -191,19 +236,22 @@
             return NO_ERROR;
         }
 
+        /* Clamps the volume curve in the configuration to
+         * the valid range for log or linear scale.
+         */
         void clampVolume() {
             if ((mOptionFlags & OPTION_FLAG_VOLUME_IN_DBFS) != 0) {
                 for (auto it = this->begin(); it != this->end(); ++it) {
-                    if (!(it->second <= 0.f) /* handle nan */) {
-                        it->second = 0.f;
+                    if (!(it->second <= MAX_LOG_VOLUME) /* handle nan */) {
+                        it->second = MAX_LOG_VOLUME;
                     }
                 }
             } else {
                 for (auto it = this->begin(); it != this->end(); ++it) {
-                    if (!(it->second >= 0.f) /* handle nan */) {
-                        it->second = 0.f;
-                    } else if (!(it->second <= 1.f)) {
-                        it->second = 1.f;
+                    if (!(it->second >= MIN_LINEAR_VOLUME) /* handle nan */) {
+                        it->second = MIN_LINEAR_VOLUME;
+                    } else if (!(it->second <= MAX_LINEAR_VOLUME)) {
+                        it->second = MAX_LINEAR_VOLUME;
                     }
                 }
             }
@@ -224,8 +272,9 @@
             if (endVolume == startVolume) {
                 // match with linear ramp
                 const T offset = volume - startVolume;
+                static const T scale =  1.f / (MAX_CURVE_TIME - MIN_CURVE_TIME); // nominally 1.f
                 for (auto it = this->begin(); it != this->end(); ++it) {
-                    it->second = it->second + offset * (1.f - it->first);
+                    it->second = it->second + offset * (MAX_CURVE_TIME - it->first) * scale;
                 }
             } else {
                 const T  scale = (volume - endVolume) / (startVolume - endVolume);
@@ -262,32 +311,40 @@
                             ?: checkCurve();
         }
 
+        // Returns a string for debug printing.
         std::string toString() const {
             std::stringstream ss;
-            ss << "mType: " << mType << std::endl;
-            ss << "mId: " << mId << std::endl;
+            ss << "VolumeShaper::Configuration{mType=" << static_cast<int32_t>(mType);
+            ss << ", mId=" << mId;
             if (mType != TYPE_ID) {
-                ss << "mOptionFlags: " << mOptionFlags << std::endl;
-                ss << "mDurationMs: " << mDurationMs << std::endl;
-                ss << Interpolator<S, T>::toString().c_str();
+                ss << ", mOptionFlags=" << static_cast<int32_t>(mOptionFlags);
+                ss << ", mDurationMs=" << mDurationMs;
+                ss << ", " << Interpolator<S, T>::toString().c_str();
             }
+            ss << "}";
             return ss.str();
         }
 
     private:
-        Type mType;
-        int32_t mId;
-        OptionFlag mOptionFlags;
-        double mDurationMs;
+        Type mType;              // type of configuration
+        int32_t mId;             // A valid id is >= 0.
+        OptionFlag mOptionFlags; // option flags for the configuration.
+        double mDurationMs;      // duration, must be > 0; default is 1000 ms.
     }; // Configuration
 
-    // must match with VolumeShaper.java in frameworks/base
-    // TODO document per VolumeShaper.java flags.
+    /* VolumeShaper::Operation expresses an operation to perform on the
+     * configuration (either explicitly specified or an id).
+     *
+     * This parallels the Java implementation and the enums must match.
+     * See "frameworks/base/media/java/android/media/VolumeShaper.java" for
+     * details on the Java implementation.
+     */
     class Operation : public RefBase {
     public:
+        // Must match with VolumeShaper.java.
         enum Flag : int32_t {
             FLAG_NONE      = 0,
-            FLAG_REVERSE   = (1 << 0),
+            FLAG_REVERSE   = (1 << 0), // the absence of this indicates "play"
             FLAG_TERMINATE = (1 << 1),
             FLAG_JOIN      = (1 << 2),
             FLAG_DELAY     = (1 << 3),
@@ -332,13 +389,29 @@
         }
 
         void setXOffset(S xOffset) {
-            mXOffset = xOffset;
+            mXOffset = clamp(xOffset, MIN_CURVE_TIME /* lo */, MAX_CURVE_TIME /* hi */);
         }
 
         Flag getFlags() const {
             return mFlags;
         }
 
+        /* xOffset is the position on the volume curve and may go backwards
+         * if you are in reverse mode. This must be in the range from
+         * [MIN_CURVE_TIME, MAX_CURVE_TIME].
+         *
+         * normalizedTime always increases as time or framecount increases.
+         * normalizedTime is nominally from MIN_CURVE_TIME to MAX_CURVE_TIME when
+         * running through the curve, but could be outside this range afterwards.
+         * If you are reversing, this means the position on the curve, or xOffset,
+         * is computed as MAX_CURVE_TIME - normalizedTime, clamped to
+         * [MIN_CURVE_TIME, MAX_CURVE_TIME].
+         */
+        void setNormalizedTime(S normalizedTime) {
+            setXOffset((mFlags & FLAG_REVERSE) != 0
+                    ? MAX_CURVE_TIME - normalizedTime : normalizedTime);
+        }
+
         status_t setFlags(Flag flags) {
             if ((flags & ~FLAG_ALL) != 0) {
                 ALOGE("flags has invalid bits: %#x", flags);
@@ -365,19 +438,26 @@
 
         std::string toString() const {
             std::stringstream ss;
-            ss << "mFlags: " << mFlags << std::endl;
-            ss << "mReplaceId: " << mReplaceId << std::endl;
-            ss << "mXOffset: " << mXOffset << std::endl;
+            ss << "VolumeShaper::Operation{mFlags=" << static_cast<int32_t>(mFlags) ;
+            ss << ", mReplaceId=" << mReplaceId;
+            ss << ", mXOffset=" << mXOffset;
+            ss << "}";
             return ss.str();
         }
 
     private:
-        Flag mFlags;
-        int32_t mReplaceId;
-        S mXOffset;
+        Flag mFlags;        // operation to do
+        int32_t mReplaceId; // if >= 0 the id to remove in a replace operation.
+        S mXOffset;         // position in the curve to set if a valid number (not nan)
     }; // Operation
 
-    // must match with VolumeShaper.java in frameworks/base
+    /* VolumeShaper.State is returned when requesting the last
+     * state of the VolumeShaper.
+     *
+     * This parallels the Java implementation.
+     * See "frameworks/base/media/java/android/media/VolumeShaper.java" for
+     * details on the Java implementation.
+     */
     class State : public RefBase {
     public:
         State(T volume, S xOffset)
@@ -386,7 +466,7 @@
         }
 
         State()
-            : State(-1.f, -1.f) { }
+            : State(NAN, NAN) { }
 
         T getVolume() const {
             return mVolume;
@@ -417,16 +497,18 @@
 
         std::string toString() const {
             std::stringstream ss;
-            ss << "mVolume: " << mVolume << std::endl;
-            ss << "mXOffset: " << mXOffset << std::endl;
+            ss << "VolumeShaper::State{mVolume=" << mVolume;
+            ss << ", mXOffset=" << mXOffset;
+            ss << "}";
             return ss.str();
         }
 
     private:
-        T mVolume;
-        S mXOffset;
+        T mVolume;   // linear volume in the range MIN_LINEAR_VOLUME to MAX_LINEAR_VOLUME
+        S mXOffset;  // position on curve expressed from MIN_CURVE_TIME to MAX_CURVE_TIME
     }; // State
 
+    // Internal helper class to do an affine transform for time and amplitude scaling.
     template <typename R>
     class Translate {
     public:
@@ -457,8 +539,9 @@
 
         std::string toString() const {
             std::stringstream ss;
-            ss << "mOffset: " << mOffset << std::endl;
-            ss << "mScale: " << mScale << std::endl;
+            ss << "VolumeShaper::Translate{mOffset=" << mOffset;
+            ss << ", mScale=" << mScale;
+            ss << "}";
             return ss.str();
         }
 
@@ -482,9 +565,14 @@
         return convertTimespecToUs(tv);
     }
 
-    // TODO: Since we pass configuration and operation as shared pointers
-    // there is a potential risk that the caller may modify these after
-    // delivery.  Currently, we don't require copies made here.
+    /* Native implementation of VolumeShaper.  This is NOT mirrored
+     * on the Java side, so we don't need to mimic Java side layout
+     * and data; furthermore, this isn't refcounted as a "RefBase" object.
+     *
+     * Since we pass configuration and operation as shared pointers (like
+     * Java) there is a potential risk that the caller may modify
+     * these after delivery.
+     */
     VolumeShaper(
             const sp<VolumeShaper::Configuration> &configuration,
             const sp<VolumeShaper::Operation> &operation)
@@ -492,53 +580,58 @@
         , mOperation(operation)         // ditto
         , mStartFrame(-1)
         , mLastVolume(T(1))
-        , mLastXOffset(0.f)
-        , mDelayXOffset(std::numeric_limits<S>::quiet_NaN()) {
+        , mLastXOffset(MIN_CURVE_TIME)
+        , mDelayXOffset(MIN_CURVE_TIME) {
         if (configuration.get() != nullptr
                 && (getFlags() & VolumeShaper::Operation::FLAG_DELAY) == 0) {
             mLastVolume = configuration->first().second;
         }
     }
 
-    void updatePosition(int64_t startFrame, double sampleRate) {
-        double scale = (mConfiguration->last().first - mConfiguration->first().first)
-                        / (mConfiguration->getDurationMs() * 0.001 * sampleRate);
-        const double minScale = 1. / INT64_MAX;
-        scale = std::max(scale, minScale);
-        const S xOffset = std::isnan(mDelayXOffset) ? mConfiguration->first().first : mDelayXOffset;
-        VS_LOG("update position: scale %lf  frameCount:%lld, sampleRate:%lf, xOffset:%f",
-                scale, (long long) startFrame, sampleRate, xOffset);
-
-        mXTranslate.setOffset(startFrame - xOffset / scale);
-        mXTranslate.setScale(scale);
-        VS_LOG("translate: %s", mXTranslate.toString().c_str());
-    }
-
     // We allow a null operation here, though VolumeHandler always provides one.
     VolumeShaper::Operation::Flag getFlags() const {
         return mOperation == nullptr
-                ? VolumeShaper::Operation::FLAG_NONE :mOperation->getFlags();
+                ? VolumeShaper::Operation::FLAG_NONE : mOperation->getFlags();
     }
 
+    /* Returns the last volume and xoffset reported to the AudioFlinger.
+     * If the VolumeShaper has not been started, compute what the volume
+     * should be based on the initial offset specified.
+     */
     sp<VolumeShaper::State> getState() const {
-        return new VolumeShaper::State(mLastVolume, mLastXOffset);
+        if (!isStarted()) {
+            const T volume = computeVolumeFromXOffset(mDelayXOffset);
+            VS_LOG("delayed VolumeShaper, using cached offset:%f for volume:%f",
+                    mDelayXOffset, volume);
+            return new VolumeShaper::State(volume, mDelayXOffset);
+        } else {
+            return new VolumeShaper::State(mLastVolume, mLastXOffset);
+        }
+    }
+
+    S getDelayXOffset() const {
+        return mDelayXOffset;
     }
 
     void setDelayXOffset(S xOffset) {
-        mDelayXOffset = xOffset;
+        mDelayXOffset = clamp(xOffset, MIN_CURVE_TIME /* lo */, MAX_CURVE_TIME /* hi */);
     }
 
     bool isStarted() const {
         return mStartFrame >= 0;
     }
 
+    /* getVolume() updates the last volume/xoffset state so it is not
+     * const, even though logically it may be viewed as const.
+     */
     std::pair<T /* volume */, bool /* active */> getVolume(
             int64_t trackFrameCount, double trackSampleRate) {
         if ((getFlags() & VolumeShaper::Operation::FLAG_DELAY) != 0) {
-            VS_LOG("delayed VolumeShaper, ignoring");
-            mLastVolume = T(1);
-            mLastXOffset = 0.;
-            return std::make_pair(T(1), false);
+            // We haven't had PLAY called yet, so just return the value
+            // as if PLAY were called just now.
+            VS_LOG("delayed VolumeShaper, using cached offset %f", mDelayXOffset);
+            const T volume = computeVolumeFromXOffset(mDelayXOffset);
+            return std::make_pair(volume, false);
         }
         const bool clockTime = (mConfiguration->getOptionFlags()
                 & VolumeShaper::Configuration::OPTION_FLAG_CLOCK_TIME) != 0;
@@ -546,84 +639,110 @@
         const double sampleRate = clockTime ? 1000000 : trackSampleRate;
 
         if (mStartFrame < 0) {
-            updatePosition(frameCount, sampleRate);
+            updatePosition(frameCount, sampleRate, mDelayXOffset);
             mStartFrame = frameCount;
         }
         VS_LOG("frameCount: %lld", (long long)frameCount);
-        S x = mXTranslate((T)frameCount);
-        VS_LOG("translation: %f", x);
+        const S x = mXTranslate((T)frameCount);
+        VS_LOG("translation to normalized time: %f", x);
 
-        // handle reversal of position
-        if (getFlags() & VolumeShaper::Operation::FLAG_REVERSE) {
-            x = 1.f - x;
-            VS_LOG("reversing to %f", x);
-            if (x < mConfiguration->first().first) {
-                mLastXOffset = 1.f;
-                const T volume = mConfiguration->adjustVolume(
-                        mConfiguration->first().second);  // persist last value
-                VS_LOG("persisting volume %f", volume);
-                mLastVolume = volume;
-                return std::make_pair(volume, false);
-            }
-            if (x > mConfiguration->last().first) {
-                mLastXOffset = 0.f;
-                mLastVolume = 1.f;
-                return std::make_pair(T(1), true); // too early
-            }
-        } else {
-            if (x < mConfiguration->first().first) {
-                mLastXOffset = 0.f;
-                mLastVolume = 1.f;
-                return std::make_pair(T(1), true); // too early
-            }
-            if (x > mConfiguration->last().first) {
-                mLastXOffset = 1.f;
-                const T volume = mConfiguration->adjustVolume(
-                        mConfiguration->last().second);  // persist last value
-                VS_LOG("persisting volume %f", volume);
-                mLastVolume = volume;
-                return std::make_pair(volume, false);
-            }
-        }
-        mLastXOffset = x;
-        // x contains the location on the volume curve to use.
-        const T unscaledVolume = mConfiguration->findY(x);
-        const T volume = mConfiguration->adjustVolume(unscaledVolume); // handle log scale
-        VS_LOG("volume: %f  unscaled: %f", volume, unscaledVolume);
-        mLastVolume = volume;
-        return std::make_pair(volume, true);
+        std::tuple<T /* volume */, S /* position */, bool /* active */> vt =
+                computeStateFromNormalizedTime(x);
+
+        mLastVolume = std::get<0>(vt);
+        mLastXOffset = std::get<1>(vt);
+        const bool active = std::get<2>(vt);
+        VS_LOG("rescaled time:%f  volume:%f  xOffset:%f  active:%s",
+                x, mLastVolume, mLastXOffset, active ? "true" : "false");
+        return std::make_pair(mLastVolume, active);
     }
 
     std::string toString() const {
         std::stringstream ss;
-        ss << "StartFrame: " << mStartFrame << std::endl;
-        ss << mXTranslate.toString().c_str();
-        if (mConfiguration.get() == nullptr) {
-            ss << "VolumeShaper::Configuration: nullptr" << std::endl;
-        } else {
-            ss << "VolumeShaper::Configuration:" << std::endl;
-            ss << mConfiguration->toString().c_str();
-        }
-        if (mOperation.get() == nullptr) {
-            ss << "VolumeShaper::Operation: nullptr" << std::endl;
-        } else {
-            ss << "VolumeShaper::Operation:" << std::endl;
-            ss << mOperation->toString().c_str();
-        }
+        ss << "VolumeShaper{mStartFrame=" << mStartFrame;
+        ss << ", mXTranslate=" << mXTranslate.toString().c_str();
+        ss << ", mConfiguration=" <<
+                (mConfiguration.get() == nullptr
+                        ? "nullptr" : mConfiguration->toString().c_str());
+        ss << ", mOperation=" <<
+                (mOperation.get() == nullptr
+                        ? "nullptr" :  mOperation->toString().c_str());
+        ss << "}";
         return ss.str();
     }
 
-    Translate<S> mXTranslate; // x axis translation from frames (in usec for clock time)
+    Translate<S> mXTranslate; // translation from frames (usec for clock time) to normalized time.
     sp<VolumeShaper::Configuration> mConfiguration;
     sp<VolumeShaper::Operation> mOperation;
+
+private:
     int64_t mStartFrame; // starting frame, non-negative when started (in usec for clock time)
     T mLastVolume;       // last computed interpolated volume (y-axis)
     S mLastXOffset;      // last computed interpolated xOffset/time (x-axis)
-    S mDelayXOffset;     // delay xOffset on first volumeshaper start.
+    S mDelayXOffset;     // xOffset to use for first invocation of VolumeShaper.
+
+    // Called internally to adjust mXTranslate for first time start.
+    void updatePosition(int64_t startFrame, double sampleRate, S xOffset) {
+        double scale = (mConfiguration->last().first - mConfiguration->first().first)
+                        / (mConfiguration->getDurationMs() * 0.001 * sampleRate);
+        const double minScale = 1. / static_cast<double>(INT64_MAX);
+        scale = std::max(scale, minScale);
+        VS_LOG("update position: scale %lf  frameCount:%lld, sampleRate:%lf, xOffset:%f",
+                scale, (long long) startFrame, sampleRate, xOffset);
+
+        S normalizedTime = (getFlags() & VolumeShaper::Operation::FLAG_REVERSE) != 0 ?
+                MAX_CURVE_TIME - xOffset : xOffset;
+        mXTranslate.setOffset(static_cast<float>(static_cast<double>(startFrame)
+                                                 - static_cast<double>(normalizedTime) / scale));
+        mXTranslate.setScale(static_cast<float>(scale));
+        VS_LOG("translate: %s", mXTranslate.toString().c_str());
+    }
+
+    T computeVolumeFromXOffset(S xOffset) const {
+        const T unscaledVolume = mConfiguration->findY(xOffset);
+        const T volume = mConfiguration->adjustVolume(unscaledVolume); // handle log scale
+        VS_LOG("computeVolumeFromXOffset %f -> %f -> %f", xOffset, unscaledVolume, volume);
+        return volume;
+    }
+
+    std::tuple<T /* volume */, S /* position */, bool /* active */>
+    computeStateFromNormalizedTime(S x) const {
+        bool active = true;
+        // handle reversal of position
+        if (getFlags() & VolumeShaper::Operation::FLAG_REVERSE) {
+            x = MAX_CURVE_TIME - x;
+            VS_LOG("reversing to %f", x);
+            if (x < MIN_CURVE_TIME) {
+                x = MIN_CURVE_TIME;
+                active = false; // at the end
+            } else if (x > MAX_CURVE_TIME) {
+                x = MAX_CURVE_TIME; //early
+            }
+        } else {
+            if (x < MIN_CURVE_TIME) {
+                x = MIN_CURVE_TIME; // early
+            } else if (x > MAX_CURVE_TIME) {
+                x = MAX_CURVE_TIME;
+                active = false; // at end
+            }
+        }
+        const S xOffset = x;
+        const T volume = computeVolumeFromXOffset(xOffset);
+        return std::make_tuple(volume, xOffset, active);
+    }
 }; // VolumeShaper
 
-// VolumeHandler combines the volume factors of multiple VolumeShapers and handles
-// multiple thread access by synchronizing all public methods.
+/* VolumeHandler combines the volume factors of multiple VolumeShapers associated
+ * with a player.  It is thread safe by synchronizing all public methods.
+ *
+ * This is a native-only implementation.
+ *
+ * The server side VolumeHandler is used to maintain a list of volume handlers,
+ * keep state, and obtain volume.
+ *
+ * The client side VolumeHandler is used to maintain a list of volume handlers,
+ * keep some partial state, and restore if the server dies.
+ */
 class VolumeHandler : public RefBase {
 public:
     using S = float;
@@ -637,13 +756,15 @@
     explicit VolumeHandler(uint32_t sampleRate)
         : mSampleRate((double)sampleRate)
         , mLastFrame(0)
-        , mVolumeShaperIdCounter(VolumeShaper::kSystemIdMax)
+        , mVolumeShaperIdCounter(VolumeShaper::kSystemVolumeShapersMax)
         , mLastVolume(1.f, false) {
     }
 
     VolumeShaper::Status applyVolumeShaper(
             const sp<VolumeShaper::Configuration> &configuration,
-            const sp<VolumeShaper::Operation> &operation) {
+            const sp<VolumeShaper::Operation> &operation_in) {
+        // make a local copy of operation, as we modify it.
+        sp<VolumeShaper::Operation> operation(new VolumeShaper::Operation(operation_in));
         VS_LOG("applyVolumeShaper:configuration: %s", configuration->toString().c_str());
         VS_LOG("applyVolumeShaper:operation: %s", operation->toString().c_str());
         AutoMutex _l(mLock);
@@ -666,14 +787,16 @@
         case VolumeShaper::Configuration::TYPE_SCALE: {
             const int replaceId = operation->getReplaceId();
             if (replaceId >= 0) {
+                VS_LOG("replacing %d", replaceId);
                 auto replaceIt = findId_l(replaceId);
                 if (replaceIt == mVolumeShapers.end()) {
                     ALOGW("cannot find replace id: %d", replaceId);
                 } else {
-                    if ((replaceIt->getFlags() & VolumeShaper::Operation::FLAG_JOIN) != 0) {
+                    if ((operation->getFlags() & VolumeShaper::Operation::FLAG_JOIN) != 0) {
                         // For join, we scale the start volume of the current configuration
                         // to match the last-used volume of the replacing VolumeShaper.
                         auto state = replaceIt->getState();
+                        ALOGD("join: state:%s", state->toString().c_str());
                         if (state->getXOffset() >= 0) { // valid
                             const T volume = state->getVolume();
                             ALOGD("join: scaling start volume to %f", volume);
@@ -695,8 +818,22 @@
                 ALOGW("duplicate id, removing old %d", id);
                 (void)mVolumeShapers.erase(oldIt);
             }
-            // create new VolumeShaper
-            mVolumeShapers.emplace_back(configuration, operation);
+
+            /* Check if too many application VolumeShapers (with id >= kSystemVolumeShapersMax).
+             * We check on the server side to ensure synchronization and robustness.
+             *
+             * This shouldn't fail on a replace command unless the replaced id is
+             * already invalid (which *should* be checked in the Java layer).
+             */
+            if (id >= VolumeShaper::kSystemVolumeShapersMax
+                    && numberOfUserVolumeShapers_l() >= VolumeShaper::kUserVolumeShapersMax) {
+                ALOGW("Too many app VolumeShapers, cannot add to VolumeHandler");
+                return VolumeShaper::Status(INVALID_OPERATION);
+            }
+
+            // create new VolumeShaper with default behavior.
+            mVolumeShapers.emplace_back(configuration, new VolumeShaper::Operation());
+            VS_LOG("after adding, number of volumeShapers:%zu", mVolumeShapers.size());
         }
         // fall through to handle the operation
         HANDLE_TYPE_ID:
@@ -707,7 +844,7 @@
                 VS_LOG("couldn't find id: %d", id);
                 return VolumeShaper::Status(INVALID_OPERATION);
             }
-            if ((it->getFlags() & VolumeShaper::Operation::FLAG_TERMINATE) != 0) {
+            if ((operation->getFlags() & VolumeShaper::Operation::FLAG_TERMINATE) != 0) {
                 VS_LOG("terminate id: %d", id);
                 mVolumeShapers.erase(it);
                 break;
@@ -716,29 +853,37 @@
                     & VolumeShaper::Configuration::OPTION_FLAG_CLOCK_TIME) != 0;
             if ((it->getFlags() & VolumeShaper::Operation::FLAG_REVERSE) !=
                     (operation->getFlags() & VolumeShaper::Operation::FLAG_REVERSE)) {
-                const int64_t frameCount = clockTime ? VolumeShaper::getNowUs() : mLastFrame;
-                const S x = it->mXTranslate((T)frameCount);
-                VS_LOG("reverse translation: %f", x);
-                // reflect position
-                S target = 1.f - x;
-                if (target < it->mConfiguration->first().first) {
-                    VS_LOG("clamp to start - begin immediately");
-                    target = 0.;
+                if (it->isStarted()) {
+                    const int64_t frameCount = clockTime ? VolumeShaper::getNowUs() : mLastFrame;
+                    const S x = it->mXTranslate((T)frameCount);
+                    VS_LOG("reverse normalizedTime: %f", x);
+                    // reflect position
+                    S target = MAX_CURVE_TIME - x;
+                    if (target < MIN_CURVE_TIME) {
+                        VS_LOG("clamp to start - begin immediately");
+                        target = MIN_CURVE_TIME;
+                    }
+                    VS_LOG("reverse normalizedTime target: %f", target);
+                    it->mXTranslate.setOffset(it->mXTranslate.getOffset()
+                            + (x - target) / it->mXTranslate.getScale());
                 }
-                VS_LOG("target reverse: %f", target);
-                it->mXTranslate.setOffset(it->mXTranslate.getOffset()
-                        + (x - target) / it->mXTranslate.getScale());
+                // if not started, the delay offset doesn't change.
             }
             const S xOffset = operation->getXOffset();
             if (!std::isnan(xOffset)) {
-                const int64_t frameCount = clockTime ? VolumeShaper::getNowUs() : mLastFrame;
-                const S x = it->mXTranslate((T)frameCount);
-                VS_LOG("xOffset translation: %f", x);
-                const S target = xOffset; // offset
-                VS_LOG("xOffset target x offset: %f", target);
-                it->mXTranslate.setOffset(it->mXTranslate.getOffset()
-                        + (x - target) / it->mXTranslate.getScale());
-                it->setDelayXOffset(xOffset);
+                if (it->isStarted()) {
+                    const int64_t frameCount = clockTime ? VolumeShaper::getNowUs() : mLastFrame;
+                    const S x = it->mXTranslate((T)frameCount);
+                    VS_LOG("normalizedTime translation: %f", x);
+                    const S target =
+                            (operation->getFlags() & VolumeShaper::Operation::FLAG_REVERSE) != 0 ?
+                                    MAX_CURVE_TIME - xOffset : xOffset;
+                    VS_LOG("normalizedTime target x offset: %f", target);
+                    it->mXTranslate.setOffset(it->mXTranslate.getOffset()
+                            + (x - target) / it->mXTranslate.getScale());
+                } else {
+                    it->setDelayXOffset(xOffset);
+                }
             }
             it->mOperation = operation; // replace the operation
         } break;
@@ -756,28 +901,31 @@
         return it->getState();
     }
 
-    // getVolume() is not const, as it updates internal state.
-    // Once called, any VolumeShapers not already started begin running.
+    /* getVolume() is not const, as it updates internal state.
+     * Once called, any VolumeShapers not already started begin running.
+     */
     std::pair<T /* volume */, bool /* active */> getVolume(int64_t trackFrameCount) {
         AutoMutex _l(mLock);
         mLastFrame = trackFrameCount;
         T volume(1);
         size_t activeCount = 0;
         for (auto it = mVolumeShapers.begin(); it != mVolumeShapers.end();) {
-            std::pair<T, bool> shaperVolume =
+            const std::pair<T, bool> shaperVolume =
                     it->getVolume(trackFrameCount, mSampleRate);
             volume *= shaperVolume.first;
             activeCount += shaperVolume.second;
             ++it;
         }
         mLastVolume = std::make_pair(volume, activeCount != 0);
+        VS_LOG("getVolume: <%f, %s>", mLastVolume.first, mLastVolume.second ? "true" : "false");
         return mLastVolume;
     }
 
-    // Used by a client side VolumeHandler to ensure all the VolumeShapers
-    // indicate that they have been started.  Upon a change in audioserver
-    // output sink, this information is used for restoration of the server side
-    // VolumeHandler.
+    /* Used by a client side VolumeHandler to ensure all the VolumeShapers
+     * indicate that they have been started.  Upon a change in audioserver
+     * output sink, this information is used for restoration of the server side
+     * VolumeHandler.
+     */
     void setStarted() {
         (void)getVolume(mLastFrame);  // getVolume() will start the individual VolumeShapers.
     }
@@ -790,11 +938,19 @@
     std::string toString() const {
         AutoMutex _l(mLock);
         std::stringstream ss;
-        ss << "mSampleRate: " << mSampleRate << std::endl;
-        ss << "mLastFrame: " << mLastFrame << std::endl;
+        ss << "VolumeHandler{mSampleRate=" << mSampleRate;
+        ss << ", mLastFrame=" << mLastFrame;
+        ss << ", mVolumeShapers={";
+        bool first = true;
         for (const auto &shaper : mVolumeShapers) {
+            if (first) {
+                first = false;
+            } else {
+                ss << ", ";
+            }
             ss << shaper.toString().c_str();
         }
+        ss << "}}";
         return ss.str();
     }
 
@@ -814,8 +970,9 @@
         // keep mVolumeShaperIdCounter as is.
     }
 
-    // Sets the configuration id if necessary - This is based on the counter
-    // internal to the VolumeHandler.
+    /* Sets the configuration id if necessary - This is based on the counter
+     * internal to the VolumeHandler.
+     */
     void setIdIfNecessary(const sp<VolumeShaper::Configuration> &configuration) {
         if (configuration->getType() == VolumeShaper::Configuration::TYPE_SCALE) {
             const int id = configuration->getId();
@@ -824,7 +981,7 @@
                 AutoMutex _l(mLock);
                 while (true) {
                     if (mVolumeShaperIdCounter == INT32_MAX) {
-                        mVolumeShaperIdCounter = VolumeShaper::kSystemIdMax;
+                        mVolumeShaperIdCounter = VolumeShaper::kSystemVolumeShapersMax;
                     } else {
                         ++mVolumeShaperIdCounter;
                     }
@@ -850,6 +1007,14 @@
         return it;
     }
 
+    size_t numberOfUserVolumeShapers_l() const {
+        size_t count = 0;
+        for (const auto &shaper : mVolumeShapers) {
+            count += (shaper.mConfiguration->getId() >= VolumeShaper::kSystemVolumeShapersMax);
+        }
+        return count;
+    }
+
     mutable Mutex mLock;
     double mSampleRate; // in samples (frames) per second
     int64_t mLastFrame; // logging purpose only, 0 on start
diff --git a/media/libaaudio/examples/input_monitor/src/input_monitor_callback.cpp b/media/libaaudio/examples/input_monitor/src/input_monitor_callback.cpp
index b482e93..7c34252 100644
--- a/media/libaaudio/examples/input_monitor/src/input_monitor_callback.cpp
+++ b/media/libaaudio/examples/input_monitor/src/input_monitor_callback.cpp
@@ -24,7 +24,7 @@
 #include <time.h>
 #include <aaudio/AAudio.h>
 
-#define NUM_SECONDS           10
+#define NUM_SECONDS           5
 #define NANOS_PER_MICROSECOND ((int64_t)1000)
 #define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
 #define NANOS_PER_SECOND      (NANOS_PER_MILLISECOND * 1000)
@@ -33,13 +33,13 @@
 #define SHARING_MODE  AAUDIO_SHARING_MODE_SHARED
 
 /**
- * Simple wrapper for AAudio that opens a default stream and then calls
- * a callback function to fill the output buffers.
+ * Simple wrapper for AAudio that opens an input stream and then calls
+ * a callback function to process the input data.
  */
-class SimpleAAudioPlayer {
+class SimpleAAudioRecorder {
 public:
-    SimpleAAudioPlayer() {}
-    ~SimpleAAudioPlayer() {
+    SimpleAAudioRecorder() {}
+    ~SimpleAAudioRecorder() {
         close();
     };
 
@@ -71,6 +71,15 @@
         }
         return AAudioStream_getSamplesPerFrame(mStream);;
     }
+    /**
+     * Only call this after open() has been called.
+     */
+    int64_t getFramesRead() {
+        if (mStream == nullptr) {
+            return AAUDIO_ERROR_INVALID_STATE;
+        }
+        return AAudioStream_getFramesRead(mStream);;
+    }
 
     /**
      * Open a stream
@@ -85,7 +94,7 @@
         AAudioStreamBuilder_setDirection(mBuilder, AAUDIO_DIRECTION_INPUT);
         AAudioStreamBuilder_setSharingMode(mBuilder, mRequestedSharingMode);
         AAudioStreamBuilder_setDataCallback(mBuilder, proc, userContext);
-        AAudioStreamBuilder_setFormat(mBuilder, AAUDIO_FORMAT_PCM_I16);
+        AAudioStreamBuilder_setFormat(mBuilder, AAUDIO_FORMAT_PCM_FLOAT);
 
         // Open an AAudioStream using the Builder.
         result = AAudioStreamBuilder_openStream(mBuilder, &mStream);
@@ -121,11 +130,10 @@
     }
 
     // Write zero data to fill up the buffer and prevent underruns.
-    // Assume format is PCM_I16. TODO use floats.
     aaudio_result_t prime() {
         int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(mStream);
         const int numFrames = 32; // arbitrary
-        int16_t zeros[numFrames * samplesPerFrame];
+        float zeros[numFrames * samplesPerFrame];
         memset(zeros, 0, sizeof(zeros));
         aaudio_result_t result = numFrames;
         while (result == numFrames) {
@@ -151,8 +159,16 @@
             fprintf(stderr, "ERROR - AAudioStream_requestStop() returned %d %s\n",
                     result, AAudio_convertResultToText(result));
         }
-        int32_t xRunCount = AAudioStream_getXRunCount(mStream);
-        printf("AAudioStream_getXRunCount %d\n", xRunCount);
+        return result;
+    }
+
+    // Pause the stream. AAudio will stop calling your callback function.
+    aaudio_result_t pause() {
+        aaudio_result_t result = AAudioStream_requestPause(mStream);
+        if (result != AAUDIO_OK) {
+            fprintf(stderr, "ERROR - AAudioStream_requestPause() returned %d %s\n",
+                    result, AAudio_convertResultToText(result));
+        }
         return result;
     }
 
@@ -227,7 +243,7 @@
 int main(int argc, char **argv)
 {
     (void)argc; // unused
-    SimpleAAudioPlayer player;
+    SimpleAAudioRecorder recorder;
     PeakTrackerData_t myData = {0.0};
     aaudio_result_t result;
     const int displayRateHz = 20; // arbitrary
@@ -238,37 +254,60 @@
     setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
     printf("%s - Display audio input using an AAudio callback\n", argv[0]);
 
-    player.setSharingMode(SHARING_MODE);
+    recorder.setSharingMode(SHARING_MODE);
 
-    result = player.open(MyDataCallbackProc, &myData);
+    result = recorder.open(MyDataCallbackProc, &myData);
     if (result != AAUDIO_OK) {
-        fprintf(stderr, "ERROR -  player.open() returned %d\n", result);
+        fprintf(stderr, "ERROR -  recorder.open() returned %d\n", result);
         goto error;
     }
-    printf("player.getFramesPerSecond() = %d\n", player.getFramesPerSecond());
-    printf("player.getSamplesPerFrame() = %d\n", player.getSamplesPerFrame());
+    printf("recorder.getFramesPerSecond() = %d\n", recorder.getFramesPerSecond());
+    printf("recorder.getSamplesPerFrame() = %d\n", recorder.getSamplesPerFrame());
 
-    result = player.start();
+    result = recorder.start();
     if (result != AAUDIO_OK) {
-        fprintf(stderr, "ERROR -  player.start() returned %d\n", result);
+        fprintf(stderr, "ERROR -  recorder.start() returned %d\n", result);
         goto error;
     }
 
-    printf("Sleep for %d seconds while audio plays in a callback thread.\n", NUM_SECONDS);
-   for (int i = 0; i < loopsNeeded; i++)
+    printf("Sleep for %d seconds while audio record in a callback thread.\n", NUM_SECONDS);
+    for (int i = 0; i < loopsNeeded; i++)
     {
         const struct timespec request = { .tv_sec = 0,
                 .tv_nsec = NANOS_PER_SECOND / displayRateHz };
         (void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/);
+        printf("%08d: ", (int)recorder.getFramesRead());
+        displayPeakLevel(myData.peakLevel);
+    }
+    printf("Woke up. Stop for a moment.\n");
+
+    result = recorder.stop();
+    if (result != AAUDIO_OK) {
+        goto error;
+    }
+    sleep(1);
+    result = recorder.start();
+    if (result != AAUDIO_OK) {
+        fprintf(stderr, "ERROR -  recorder.start() returned %d\n", result);
+        goto error;
+    }
+
+    printf("Sleep for %d seconds while audio records in a callback thread.\n", NUM_SECONDS);
+    for (int i = 0; i < loopsNeeded; i++)
+    {
+        const struct timespec request = { .tv_sec = 0,
+                .tv_nsec = NANOS_PER_SECOND / displayRateHz };
+        (void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/);
+        printf("%08d: ", (int)recorder.getFramesRead());
         displayPeakLevel(myData.peakLevel);
     }
     printf("Woke up now.\n");
 
-    result = player.stop();
+    result = recorder.stop();
     if (result != AAUDIO_OK) {
         goto error;
     }
-    result = player.close();
+    result = recorder.close();
     if (result != AAUDIO_OK) {
         goto error;
     }
@@ -276,7 +315,7 @@
     printf("SUCCESS\n");
     return EXIT_SUCCESS;
 error:
-    player.close();
+    recorder.close();
     printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result));
     return EXIT_FAILURE;
 }
diff --git a/media/libaaudio/examples/write_sine/src/write_sine.cpp b/media/libaaudio/examples/write_sine/src/write_sine.cpp
index 9107a7c..57a5273 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine.cpp
@@ -23,7 +23,7 @@
 #include "SineGenerator.h"
 
 #define SAMPLE_RATE           48000
-#define NUM_SECONDS           15
+#define NUM_SECONDS           5
 #define NANOS_PER_MICROSECOND ((int64_t)1000)
 #define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
 #define NANOS_PER_SECOND      (NANOS_PER_MILLISECOND * 1000)
@@ -104,6 +104,10 @@
     AAudioStreamBuilder_setFormat(aaudioBuilder, REQUESTED_FORMAT);
     AAudioStreamBuilder_setSharingMode(aaudioBuilder, REQUESTED_SHARING_MODE);
 
+    AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_NONE);
+    //AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+    //AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_POWER_SAVING);
+
     // Create an AAudioStream using the Builder.
     result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
     if (result != AAUDIO_OK) {
@@ -132,7 +136,6 @@
     // This is the number of frames that are read in one chunk by a DMA controller
     // or a DSP or a mixer.
     framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
-    printf("Buffer: framesPerBurst = %d\n",framesPerBurst);
     printf("Buffer: bufferSize = %d\n", AAudioStream_getBufferSizeInFrames(aaudioStream));
     bufferCapacity = AAudioStream_getBufferCapacityInFrames(aaudioStream);
     printf("Buffer: bufferCapacity = %d, remainder = %d\n",
@@ -144,12 +147,15 @@
     while (framesPerWrite < 48) {
         framesPerWrite *= 2;
     }
-    printf("DataFormat: framesPerWrite = %d\n",framesPerWrite);
+    printf("Buffer: framesPerBurst = %d\n",framesPerBurst);
+    printf("Buffer: framesPerWrite = %d\n",framesPerWrite);
 
     actualDataFormat = AAudioStream_getFormat(aaudioStream);
     printf("DataFormat: requested = %d, actual = %d\n", REQUESTED_FORMAT, actualDataFormat);
     // TODO handle other data formats
 
+    printf("PerformanceMode: %d\n", AAudioStream_getPerformanceMode(aaudioStream));
+
     // Allocate a buffer for the audio data.
     if (actualDataFormat == AAUDIO_FORMAT_PCM_FLOAT) {
         floatData = new float[framesPerWrite * actualChannelCount];
diff --git a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
index cc0c3a4..1a66f35 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
@@ -26,7 +26,7 @@
 #include <aaudio/AAudio.h>
 #include "SineGenerator.h"
 
-#define NUM_SECONDS              15
+#define NUM_SECONDS              5
 
 //#define SHARING_MODE  AAUDIO_SHARING_MODE_EXCLUSIVE
 #define SHARING_MODE  AAUDIO_SHARING_MODE_SHARED
@@ -88,6 +88,10 @@
  //       AAudioStreamBuilder_setFramesPerDataCallback(mBuilder, CALLBACK_SIZE_FRAMES);
         AAudioStreamBuilder_setBufferCapacityInFrames(mBuilder, 48 * 8);
 
+        //AAudioStreamBuilder_setPerformanceMode(mBuilder, AAUDIO_PERFORMANCE_MODE_NONE);
+        AAudioStreamBuilder_setPerformanceMode(mBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+        //AAudioStreamBuilder_setPerformanceMode(mBuilder, AAUDIO_PERFORMANCE_MODE_POWER_SAVING);
+
         // Open an AAudioStream using the Builder.
         result = AAudioStreamBuilder_openStream(mBuilder, &mStream);
         if (result != AAUDIO_OK) goto finish1;
@@ -98,7 +102,6 @@
                AAudioStream_getBufferSizeInFrames(mStream));
         printf("AAudioStream_getBufferCapacityInFrames() = %d\n",
                AAudioStream_getBufferCapacityInFrames(mStream));
-        return result;
 
      finish1:
         AAudioStreamBuilder_delete(mBuilder);
@@ -227,7 +230,7 @@
     // Make printf print immediately so that debug info is not stuck
     // in a buffer if we hang or crash.
     setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
-    printf("%s - Play a sine sweep using an AAudio callback, Z1\n", argv[0]);
+    printf("%s - Play a sine sweep using an AAudio callback\n", argv[0]);
 
     player.setSharingMode(SHARING_MODE);
 
@@ -278,6 +281,7 @@
             printf("Stream state is %d %s!\n", state, AAudio_convertStreamStateToText(state));
             break;
         }
+        printf("framesWritten = %d\n", (int) AAudioStream_getFramesWritten(player.getStream()));
     }
     printf("Woke up now.\n");
 
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 532c372..c21caa4 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -125,6 +125,25 @@
 };
 typedef int32_t aaudio_sharing_mode_t;
 
+
+enum {
+    /**
+     * No particular performance needs. Default.
+     */
+            AAUDIO_PERFORMANCE_MODE_NONE = 10,
+
+    /**
+     * Extending battery life is most important.
+     */
+            AAUDIO_PERFORMANCE_MODE_POWER_SAVING,
+
+    /**
+     * Reducing latency is most important.
+     */
+            AAUDIO_PERFORMANCE_MODE_LOW_LATENCY
+};
+typedef int32_t aaudio_performance_mode_t;
+
 typedef struct AAudioStreamStruct         AAudioStream;
 typedef struct AAudioStreamBuilderStruct  AAudioStreamBuilder;
 
@@ -279,6 +298,18 @@
  */
 AAUDIO_API void AAudioStreamBuilder_setBufferCapacityInFrames(AAudioStreamBuilder* builder,
                                                                  int32_t numFrames);
+
+/**
+ * Set the requested performance mode.
+ *
+ * The default, if you do not call this function, is AAUDIO_PERFORMANCE_MODE_NONE.
+ *
+ * @param builder reference provided by AAudio_createStreamBuilder()
+ * @param mode the desired performance mode, eg. AAUDIO_PERFORMANCE_MODE_LOW_LATENCY
+ */
+AAUDIO_API void AAudioStreamBuilder_setPerformanceMode(AAudioStreamBuilder* builder,
+                                                aaudio_performance_mode_t mode);
+
 /**
  * Return one of these values from the data callback function.
  */
@@ -476,6 +507,9 @@
  * Use AAudioStream_Start() to resume playback after a pause.
  * After this call the state will be in AAUDIO_STREAM_STATE_PAUSING or AAUDIO_STREAM_STATE_PAUSED.
  *
+ * This will return AAUDIO_ERROR_UNIMPLEMENTED for input streams.
+ * For input streams use AAudioStream_requestStop().
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return AAUDIO_OK or a negative error.
  */
@@ -488,6 +522,8 @@
  * Frame counters are not reset by a flush. They may be advanced.
  * After this call the state will be in AAUDIO_STREAM_STATE_FLUSHING or AAUDIO_STREAM_STATE_FLUSHED.
  *
+ * This will return AAUDIO_ERROR_UNIMPLEMENTED for input streams.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return AAUDIO_OK or a negative error.
  */
@@ -673,6 +709,9 @@
  *
  * An underrun or overrun can cause an audible "pop" or "glitch".
  *
+ * Note that some INPUT devices may not support this function.
+ * In that case a 0 will always be returned.
+ *
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return the underrun or overrun count
  */
@@ -722,6 +761,13 @@
 AAUDIO_API aaudio_sharing_mode_t AAudioStream_getSharingMode(AAudioStream* stream);
 
 /**
+ * Get the performance mode used by the stream.
+ *
+ * @param stream reference provided by AAudioStreamBuilder_openStream()
+ */
+AAUDIO_API aaudio_performance_mode_t AAudioStream_getPerformanceMode(AAudioStream* stream);
+
+/**
  * @param stream reference provided by AAudioStreamBuilder_openStream()
  * @return direction
  */
diff --git a/media/libaaudio/libaaudio.map.txt b/media/libaaudio/libaaudio.map.txt
index efd92ae..8f74800 100644
--- a/media/libaaudio/libaaudio.map.txt
+++ b/media/libaaudio/libaaudio.map.txt
@@ -3,6 +3,7 @@
     AAudio_convertResultToText;
     AAudio_convertStreamStateToText;
     AAudio_createStreamBuilder;
+    AAudioStreamBuilder_setPerformanceMode;
     AAudioStreamBuilder_setDeviceId;
     AAudioStreamBuilder_setDataCallback;
     AAudioStreamBuilder_setErrorCallback;
@@ -34,6 +35,7 @@
     AAudioStream_getSampleRate;
     AAudioStream_getSamplesPerFrame;
     AAudioStream_getChannelCount;
+    AAudioStream_getPerformanceMode;
     AAudioStream_getDeviceId;
     AAudioStream_getFormat;
     AAudioStream_getSharingMode;
diff --git a/media/libaaudio/src/binding/AAudioBinderClient.h b/media/libaaudio/src/binding/AAudioBinderClient.h
index f7f2808..ca2da29 100644
--- a/media/libaaudio/src/binding/AAudioBinderClient.h
+++ b/media/libaaudio/src/binding/AAudioBinderClient.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef AAUDIO_AAUDIO_BINDER_CLIENT_H
-#define AAUDIO_AAUDIO_BINDER_CLIENT_H
+#ifndef ANDROID_AAUDIO_AAUDIO_BINDER_CLIENT_H
+#define ANDROID_AAUDIO_AAUDIO_BINDER_CLIENT_H
 
 #include <aaudio/AAudio.h>
 #include "AAudioServiceDefinitions.h"
@@ -91,4 +91,4 @@
 
 } /* namespace aaudio */
 
-#endif //AAUDIO_AAUDIO_BINDER_CLIENT_H
+#endif //ANDROID_AAUDIO_AAUDIO_BINDER_CLIENT_H
diff --git a/media/libaaudio/src/binding/AAudioServiceInterface.h b/media/libaaudio/src/binding/AAudioServiceInterface.h
index b565499..824e5bc 100644
--- a/media/libaaudio/src/binding/AAudioServiceInterface.h
+++ b/media/libaaudio/src/binding/AAudioServiceInterface.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef AAUDIO_BINDING_AAUDIO_SERVICE_INTERFACE_H
-#define AAUDIO_BINDING_AAUDIO_SERVICE_INTERFACE_H
+#ifndef ANDROID_AAUDIO_BINDING_AAUDIO_SERVICE_INTERFACE_H
+#define ANDROID_AAUDIO_BINDING_AAUDIO_SERVICE_INTERFACE_H
 
 #include "binding/AAudioServiceDefinitions.h"
 #include "binding/AAudioStreamRequest.h"
@@ -87,4 +87,4 @@
 
 } /* namespace aaudio */
 
-#endif //AAUDIO_BINDING_AAUDIO_SERVICE_INTERFACE_H
+#endif //ANDROID_AAUDIO_BINDING_AAUDIO_SERVICE_INTERFACE_H
diff --git a/media/libaaudio/src/binding/AAudioServiceMessage.h b/media/libaaudio/src/binding/AAudioServiceMessage.h
index d75aa32..b4377fb 100644
--- a/media/libaaudio/src/binding/AAudioServiceMessage.h
+++ b/media/libaaudio/src/binding/AAudioServiceMessage.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef AAUDIO_AAUDIO_SERVICE_MESSAGE_H
-#define AAUDIO_AAUDIO_SERVICE_MESSAGE_H
+#ifndef ANDROID_AAUDIO_AAUDIO_SERVICE_MESSAGE_H
+#define ANDROID_AAUDIO_AAUDIO_SERVICE_MESSAGE_H
 
 #include <stdint.h>
 
@@ -64,4 +64,4 @@
 
 } /* namespace aaudio */
 
-#endif //AAUDIO_AAUDIO_SERVICE_MESSAGE_H
+#endif //ANDROID_AAUDIO_AAUDIO_SERVICE_MESSAGE_H
diff --git a/media/libaaudio/src/binding/AAudioStreamConfiguration.h b/media/libaaudio/src/binding/AAudioStreamConfiguration.h
index 78c4983..b1e4a7d 100644
--- a/media/libaaudio/src/binding/AAudioStreamConfiguration.h
+++ b/media/libaaudio/src/binding/AAudioStreamConfiguration.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef BINDING_AAUDIO_STREAM_CONFIGURATION_H
-#define BINDING_AAUDIO_STREAM_CONFIGURATION_H
+#ifndef ANDROID_BINDING_AAUDIO_STREAM_CONFIGURATION_H
+#define ANDROID_BINDING_AAUDIO_STREAM_CONFIGURATION_H
 
 #include <stdint.h>
 
@@ -101,4 +101,4 @@
 
 } /* namespace aaudio */
 
-#endif //BINDING_AAUDIO_STREAM_CONFIGURATION_H
+#endif //ANDROID_BINDING_AAUDIO_STREAM_CONFIGURATION_H
diff --git a/media/libaaudio/src/binding/AAudioStreamRequest.h b/media/libaaudio/src/binding/AAudioStreamRequest.h
index d4bfbe1..77138da 100644
--- a/media/libaaudio/src/binding/AAudioStreamRequest.h
+++ b/media/libaaudio/src/binding/AAudioStreamRequest.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef BINDING_AAUDIO_STREAM_REQUEST_H
-#define BINDING_AAUDIO_STREAM_REQUEST_H
+#ifndef ANDROID_BINDING_AAUDIO_STREAM_REQUEST_H
+#define ANDROID_BINDING_AAUDIO_STREAM_REQUEST_H
 
 #include <stdint.h>
 
@@ -95,4 +95,4 @@
 
 } /* namespace aaudio */
 
-#endif //BINDING_AAUDIO_STREAM_REQUEST_H
+#endif //ANDROID_BINDING_AAUDIO_STREAM_REQUEST_H
diff --git a/media/libaaudio/src/binding/AudioEndpointParcelable.h b/media/libaaudio/src/binding/AudioEndpointParcelable.h
index 4a1cb72..993075c 100644
--- a/media/libaaudio/src/binding/AudioEndpointParcelable.h
+++ b/media/libaaudio/src/binding/AudioEndpointParcelable.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef BINDING_AUDIOENDPOINTPARCELABLE_H
-#define BINDING_AUDIOENDPOINTPARCELABLE_H
+#ifndef ANDROID_BINDING_AUDIO_ENDPOINT_PARCELABLE_H
+#define ANDROID_BINDING_AUDIO_ENDPOINT_PARCELABLE_H
 
 #include <stdint.h>
 
@@ -75,4 +75,4 @@
 
 } /* namespace aaudio */
 
-#endif //BINDING_AUDIOENDPOINTPARCELABLE_H
+#endif //ANDROID_BINDING_AUDIO_ENDPOINT_PARCELABLE_H
diff --git a/media/libaaudio/src/binding/IAAudioService.h b/media/libaaudio/src/binding/IAAudioService.h
index 2cee651..44a5e12 100644
--- a/media/libaaudio/src/binding/IAAudioService.h
+++ b/media/libaaudio/src/binding/IAAudioService.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef BINDING_IAAUDIOSERVICE_H
-#define BINDING_IAAUDIOSERVICE_H
+#ifndef ANDROID_AAUDIO_IAAUDIO_SERVICE_H
+#define ANDROID_AAUDIO_IAAUDIO_SERVICE_H
 
 #include <stdint.h>
 #include <utils/RefBase.h>
@@ -103,4 +103,4 @@
 
 } /* namespace android */
 
-#endif //BINDING_IAAUDIOSERVICE_H
+#endif //ANDROID_AAUDIO_IAAUDIO_SERVICE_H
diff --git a/media/libaaudio/src/binding/RingBufferParcelable.cpp b/media/libaaudio/src/binding/RingBufferParcelable.cpp
index 05451f9..6b74b21 100644
--- a/media/libaaudio/src/binding/RingBufferParcelable.cpp
+++ b/media/libaaudio/src/binding/RingBufferParcelable.cpp
@@ -79,29 +79,49 @@
  * The read and write must be symmetric.
  */
 status_t RingBufferParcelable::writeToParcel(Parcel* parcel) const {
-    parcel->writeInt32(mCapacityInFrames);
+    status_t status = parcel->writeInt32(mCapacityInFrames);
+    if (status != NO_ERROR) goto error;
     if (mCapacityInFrames > 0) {
-        parcel->writeInt32(mBytesPerFrame);
-        parcel->writeInt32(mFramesPerBurst);
-        parcel->writeInt32(mFlags);
-        mReadCounterParcelable.writeToParcel(parcel);
-        mWriteCounterParcelable.writeToParcel(parcel);
-        mDataParcelable.writeToParcel(parcel);
+        status = parcel->writeInt32(mBytesPerFrame);
+        if (status != NO_ERROR) goto error;
+        status = parcel->writeInt32(mFramesPerBurst);
+        if (status != NO_ERROR) goto error;
+        status = parcel->writeInt32(mFlags);
+        if (status != NO_ERROR) goto error;
+        status = mReadCounterParcelable.writeToParcel(parcel);
+        if (status != NO_ERROR) goto error;
+        status = mWriteCounterParcelable.writeToParcel(parcel);
+        if (status != NO_ERROR) goto error;
+        status = mDataParcelable.writeToParcel(parcel);
+        if (status != NO_ERROR) goto error;
     }
-    return NO_ERROR; // TODO check for errors above
+    return NO_ERROR;
+error:
+    ALOGE("RingBufferParcelable::writeToParcel() error = %d", status);
+    return status;
 }
 
 status_t RingBufferParcelable::readFromParcel(const Parcel* parcel) {
-    parcel->readInt32(&mCapacityInFrames);
+    status_t status = parcel->readInt32(&mCapacityInFrames);
+    if (status != NO_ERROR) goto error;
     if (mCapacityInFrames > 0) {
-        parcel->readInt32(&mBytesPerFrame);
-        parcel->readInt32(&mFramesPerBurst);
-        parcel->readInt32((int32_t *)&mFlags);
-        mReadCounterParcelable.readFromParcel(parcel);
-        mWriteCounterParcelable.readFromParcel(parcel);
-        mDataParcelable.readFromParcel(parcel);
+        status = parcel->readInt32(&mBytesPerFrame);
+        if (status != NO_ERROR) goto error;
+        status = parcel->readInt32(&mFramesPerBurst);
+        if (status != NO_ERROR) goto error;
+        status = parcel->readInt32((int32_t *)&mFlags);
+        if (status != NO_ERROR) goto error;
+        status = mReadCounterParcelable.readFromParcel(parcel);
+        if (status != NO_ERROR) goto error;
+        status = mWriteCounterParcelable.readFromParcel(parcel);
+        if (status != NO_ERROR) goto error;
+        status = mDataParcelable.readFromParcel(parcel);
+        if (status != NO_ERROR) goto error;
     }
-    return NO_ERROR; // TODO check for errors above
+    return NO_ERROR;
+error:
+    ALOGE("RingBufferParcelable::readFromParcel() error = %d", status);
+    return status;
 }
 
 aaudio_result_t RingBufferParcelable::resolve(SharedMemoryParcelable *memoryParcels, RingBufferDescriptor *descriptor) {
@@ -141,7 +161,7 @@
         ALOGE("RingBufferParcelable invalid mBytesPerFrame = %d", mBytesPerFrame);
         return AAUDIO_ERROR_INTERNAL;
     }
-    if (mFramesPerBurst < 0 || mFramesPerBurst >= 1024) {
+    if (mFramesPerBurst < 0 || mFramesPerBurst >= 16 * 1024) {
         ALOGE("RingBufferParcelable invalid mFramesPerBurst = %d", mFramesPerBurst);
         return AAUDIO_ERROR_INTERNAL;
     }
diff --git a/media/libaaudio/src/binding/RingBufferParcelable.h b/media/libaaudio/src/binding/RingBufferParcelable.h
index 5fc5d00..bd562f2 100644
--- a/media/libaaudio/src/binding/RingBufferParcelable.h
+++ b/media/libaaudio/src/binding/RingBufferParcelable.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef BINDING_RINGBUFFER_PARCELABLE_H
-#define BINDING_RINGBUFFER_PARCELABLE_H
+#ifndef ANDROID_AAUDIO_RINGBUFFER_PARCELABLE_H
+#define ANDROID_AAUDIO_RINGBUFFER_PARCELABLE_H
 
 #include <stdint.h>
 
@@ -82,4 +82,4 @@
 
 } /* namespace aaudio */
 
-#endif //BINDING_RINGBUFFER_PARCELABLE_H
+#endif //ANDROID_AAUDIO_RINGBUFFER_PARCELABLE_H
diff --git a/media/libaaudio/src/binding/SharedMemoryParcelable.cpp b/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
index 7e77ca0..1094d9e 100644
--- a/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
+++ b/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
@@ -50,7 +50,8 @@
     if (status != NO_ERROR) return status;
     if (mSizeInBytes > 0) {
         status = parcel->writeDupFileDescriptor(mFd);
-        ALOGE_IF(status != NO_ERROR, "SharedMemoryParcelable writeDupFileDescriptor failed : %d", status);
+        ALOGE_IF(status != NO_ERROR, "SharedMemoryParcelable writeDupFileDescriptor failed : %d",
+                 status);
     }
     return status;
 }
@@ -61,11 +62,13 @@
         return status;
     }
     if (mSizeInBytes > 0) {
-        int originalFD = parcel->readFileDescriptor();
-        mFd = fcntl(originalFD, F_DUPFD_CLOEXEC, 0);
+        mOriginalFd = parcel->readFileDescriptor();
+        ALOGV("SharedMemoryParcelable::readFromParcel() LEAK? mOriginalFd = %d\n", mOriginalFd);
+        mFd = fcntl(mOriginalFd, F_DUPFD_CLOEXEC, 0);
+        ALOGV("SharedMemoryParcelable::readFromParcel() LEAK? mFd = %d\n", mFd);
         if (mFd == -1) {
             status = -errno;
-            ALOGE("SharedMemoryParcelable readFileDescriptor fcntl() failed : %d", status);
+            ALOGE("SharedMemoryParcelable readFromParcel fcntl() failed : %d", status);
         }
     }
     return status;
@@ -81,9 +84,15 @@
         mResolvedAddress = MMAP_UNRESOLVED_ADDRESS;
     }
     if (mFd != -1) {
+        ALOGV("SharedMemoryParcelable::close() LEAK? mFd = %d\n", mFd);
         ::close(mFd);
         mFd = -1;
     }
+    if (mOriginalFd != -1) {
+        ALOGV("SharedMemoryParcelable::close() LEAK? mOriginalFd = %d\n", mOriginalFd);
+        ::close(mOriginalFd);
+        mOriginalFd = -1;
+    }
     return AAUDIO_OK;
 }
 
diff --git a/media/libaaudio/src/binding/SharedMemoryParcelable.h b/media/libaaudio/src/binding/SharedMemoryParcelable.h
index c4feb48..4b94b46 100644
--- a/media/libaaudio/src/binding/SharedMemoryParcelable.h
+++ b/media/libaaudio/src/binding/SharedMemoryParcelable.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef BINDING_SHAREDMEMORYPARCELABLE_H
-#define BINDING_SHAREDMEMORYPARCELABLE_H
+#ifndef ANDROID_AAUDIO_SHARED_MEMORY_PARCELABLE_H
+#define ANDROID_AAUDIO_SHARED_MEMORY_PARCELABLE_H
 
 #include <stdint.h>
 
@@ -67,11 +67,12 @@
 
 #define MMAP_UNRESOLVED_ADDRESS    reinterpret_cast<uint8_t*>(MAP_FAILED)
 
-    int mFd = -1;
-    int32_t mSizeInBytes = 0;
+    int      mFd = -1;
+    int      mOriginalFd = -1;
+    int32_t  mSizeInBytes = 0;
     uint8_t *mResolvedAddress = MMAP_UNRESOLVED_ADDRESS;
 };
 
 } /* namespace aaudio */
 
-#endif //BINDING_SHAREDMEMORYPARCELABLE_H
+#endif //ANDROID_AAUDIO_SHARED_MEMORY_PARCELABLE_H
diff --git a/media/libaaudio/src/binding/SharedRegionParcelable.h b/media/libaaudio/src/binding/SharedRegionParcelable.h
index e9f5785..f6babfd 100644
--- a/media/libaaudio/src/binding/SharedRegionParcelable.h
+++ b/media/libaaudio/src/binding/SharedRegionParcelable.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef BINDING_SHAREDREGIONPARCELABLE_H
-#define BINDING_SHAREDREGIONPARCELABLE_H
+#ifndef ANDROID_AAUDIO_SHARED_REGION_PARCELABLE_H
+#define ANDROID_AAUDIO_SHARED_REGION_PARCELABLE_H
 
 #include <stdint.h>
 
@@ -59,4 +59,4 @@
 
 } /* namespace aaudio */
 
-#endif //BINDING_SHAREDREGIONPARCELABLE_H
+#endif //ANDROID_AAUDIO_SHARED_REGION_PARCELABLE_H
diff --git a/media/libaaudio/src/client/AudioEndpoint.cpp b/media/libaaudio/src/client/AudioEndpoint.cpp
index 6f87df6..027d66d 100644
--- a/media/libaaudio/src/client/AudioEndpoint.cpp
+++ b/media/libaaudio/src/client/AudioEndpoint.cpp
@@ -28,6 +28,9 @@
 using namespace android;
 using namespace aaudio;
 
+#define RIDICULOUSLY_LARGE_BUFFER_CAPACITY   (256 * 1024)
+#define RIDICULOUSLY_LARGE_FRAME_SIZE        4096
+
 AudioEndpoint::AudioEndpoint()
     : mOutputFreeRunning(false)
     , mDataReadCounter(0)
@@ -45,16 +48,22 @@
         ALOGE("AudioEndpoint_validateQueueDescriptor() NULL descriptor");
         return AAUDIO_ERROR_NULL;
     }
-    if (descriptor->capacityInFrames <= 0) {
+
+    if (descriptor->capacityInFrames < 1
+        || descriptor->capacityInFrames > RIDICULOUSLY_LARGE_BUFFER_CAPACITY) {
         ALOGE("AudioEndpoint_validateQueueDescriptor() bad capacityInFrames = %d",
               descriptor->capacityInFrames);
         return AAUDIO_ERROR_OUT_OF_RANGE;
     }
-    if (descriptor->bytesPerFrame <= 1) {
+
+    // Reject extreme values to catch bugs and prevent numeric overflows.
+    if (descriptor->bytesPerFrame < 1
+        || descriptor->bytesPerFrame > RIDICULOUSLY_LARGE_FRAME_SIZE) {
         ALOGE("AudioEndpoint_validateQueueDescriptor() bad bytesPerFrame = %d",
               descriptor->bytesPerFrame);
         return AAUDIO_ERROR_OUT_OF_RANGE;
     }
+
     if (descriptor->dataAddress == nullptr) {
         ALOGE("AudioEndpoint_validateQueueDescriptor() NULL dataAddress");
         return AAUDIO_ERROR_NULL;
@@ -82,6 +91,7 @@
         *descriptor->readCounterAddress = counter;
         ALOGV("AudioEndpoint_validateQueueDescriptor() wrote readCounterAddress successfully");
     }
+
     if (descriptor->writeCounterAddress) {
         fifo_counter_t counter = *descriptor->writeCounterAddress;
         ALOGV("AudioEndpoint_validateQueueDescriptor() *writeCounterAddress = %d, now write",
@@ -89,6 +99,7 @@
         *descriptor->writeCounterAddress = counter;
         ALOGV("AudioEndpoint_validateQueueDescriptor() wrote writeCounterAddress successfully");
     }
+
     return AAUDIO_OK;
 }
 
@@ -104,7 +115,6 @@
 
 aaudio_result_t AudioEndpoint::configure(const EndpointDescriptor *pEndpointDescriptor)
 {
-    // TODO maybe remove after debugging
     aaudio_result_t result = AudioEndpoint_validateDescriptor(pEndpointDescriptor);
     if (result != AAUDIO_OK) {
         ALOGE("AudioEndpoint_validateQueueDescriptor returned %d %s",
@@ -112,10 +122,19 @@
         return result;
     }
 
+    // ============================ up message queue =============================
     const RingBufferDescriptor *descriptor = &pEndpointDescriptor->upMessageQueueDescriptor;
-    assert(descriptor->bytesPerFrame == sizeof(AAudioServiceMessage));
-    assert(descriptor->readCounterAddress != nullptr);
-    assert(descriptor->writeCounterAddress != nullptr);
+    if(descriptor->bytesPerFrame != sizeof(AAudioServiceMessage)) {
+        ALOGE("AudioEndpoint::configure() bytesPerFrame != sizeof(AAudioServiceMessage) = %d",
+              descriptor->bytesPerFrame);
+        return AAUDIO_ERROR_INTERNAL;
+    }
+
+    if(descriptor->readCounterAddress == nullptr || descriptor->writeCounterAddress == nullptr) {
+        ALOGE("AudioEndpoint_validateQueueDescriptor() NULL counter address");
+        return AAUDIO_ERROR_NULL;
+    }
+
     mUpCommandQueue = new FifoBuffer(
             descriptor->bytesPerFrame,
             descriptor->capacityInFrames,
@@ -123,25 +142,9 @@
             descriptor->writeCounterAddress,
             descriptor->dataAddress
     );
-    /* TODO mDownCommandQueue
-    if (descriptor->capacityInFrames > 0) {
-        descriptor = &pEndpointDescriptor->downMessageQueueDescriptor;
-        mDownCommandQueue = new FifoBuffer(
-                descriptor->capacityInFrames,
-                descriptor->bytesPerFrame,
-                descriptor->readCounterAddress,
-                descriptor->writeCounterAddress,
-                descriptor->dataAddress
-        );
-    }
-     */
+
+    // ============================ down data queue =============================
     descriptor = &pEndpointDescriptor->downDataQueueDescriptor;
-    assert(descriptor->capacityInFrames > 0);
-    assert(descriptor->bytesPerFrame > 1);
-    assert(descriptor->bytesPerFrame < 4 * 16); // FIXME just for initial debugging
-    assert(descriptor->framesPerBurst > 0);
-    assert(descriptor->framesPerBurst < 8 * 1024); // FIXME just for initial debugging
-    assert(descriptor->dataAddress != nullptr);
     ALOGV("AudioEndpoint::configure() data framesPerBurst = %d", descriptor->framesPerBurst);
     ALOGV("AudioEndpoint::configure() data readCounterAddress = %p", descriptor->readCounterAddress);
     mOutputFreeRunning = descriptor->readCounterAddress == nullptr;
@@ -172,8 +175,6 @@
 
 aaudio_result_t AudioEndpoint::writeDataNow(const void *buffer, int32_t numFrames)
 {
-    // TODO Make it easier for the AAudioStreamInternal to scale floats and write shorts
-    // TODO Similar to block adapter write through technique. Add a DataConverter.
     return mDownDataQueue->write(buffer, numFrames);
 }
 
diff --git a/media/libaaudio/src/client/AudioEndpoint.h b/media/libaaudio/src/client/AudioEndpoint.h
index a24a705..46a3fc5 100644
--- a/media/libaaudio/src/client/AudioEndpoint.h
+++ b/media/libaaudio/src/client/AudioEndpoint.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef AAUDIO_AUDIO_ENDPOINT_H
-#define AAUDIO_AUDIO_ENDPOINT_H
+#ifndef ANDROID_AAUDIO_AUDIO_ENDPOINT_H
+#define ANDROID_AAUDIO_AUDIO_ENDPOINT_H
 
 #include <aaudio/AAudio.h>
 
@@ -93,4 +93,4 @@
 
 } // namespace aaudio
 
-#endif //AAUDIO_AUDIO_ENDPOINT_H
+#endif //ANDROID_AAUDIO_AUDIO_ENDPOINT_H
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 810751a..eee860e 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -244,7 +244,7 @@
 
     ALOGD("AudioStreamInternal(): callbackLoop() exiting, result = %d, isPlaying() = %d",
           result, (int) isPlaying());
-    return NULL; // TODO review
+    return NULL;
 }
 
 static void *aaudio_callback_thread_proc(void *context)
@@ -402,7 +402,7 @@
 aaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId,
                            int64_t *framePosition,
                            int64_t *timeNanoseconds) {
-    // TODO implement using real HAL
+    // TODO Generate in server and pass to client. Return latest.
     int64_t time = AudioClock::getNanoseconds();
     *framePosition = mClockModel.convertTimeToPosition(time);
     *timeNanoseconds = time + (10 * AAUDIO_NANOS_PER_MILLISECOND); // Fake hardware delay
@@ -574,12 +574,9 @@
 // Write as much data as we can without blocking.
 aaudio_result_t AudioStreamInternal::writeNow(const void *buffer, int32_t numFrames,
                                          int64_t currentNanoTime, int64_t *wakeTimePtr) {
-
-    {
-        aaudio_result_t result = processCommands();
-        if (result != AAUDIO_OK) {
-            return result;
-        }
+    aaudio_result_t result = processCommands();
+    if (result != AAUDIO_OK) {
+        return result;
     }
 
     if (mAudioEndpoint.isOutputFreeRunning()) {
@@ -791,4 +788,10 @@
     return framesRead;
 }
 
-// TODO implement getTimestamp
+int64_t AudioStreamInternal::getFramesWritten()
+{
+    int64_t getFramesWritten = mAudioEndpoint.getDownDataWriteCounter()
+            + mFramesOffsetFromService;
+    ALOGD_IF(MYLOG_CONDITION, "AudioStreamInternal::getFramesWritten() returns %lld", (long long)getFramesWritten);
+    return getFramesWritten;
+}
diff --git a/media/libaaudio/src/client/AudioStreamInternal.h b/media/libaaudio/src/client/AudioStreamInternal.h
index e550ba3..ee602c1 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.h
+++ b/media/libaaudio/src/client/AudioStreamInternal.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef AAUDIO_AUDIOSTREAMINTERNAL_H
-#define AAUDIO_AUDIOSTREAMINTERNAL_H
+#ifndef ANDROID_AAUDIO_AUDIO_STREAM_INTERNAL_H
+#define ANDROID_AAUDIO_AUDIO_STREAM_INTERNAL_H
 
 #include <stdint.h>
 #include <aaudio/AAudio.h>
@@ -49,15 +49,11 @@
 
     aaudio_result_t requestStop() override;
 
-    // TODO use aaudio_clockid_t all the way down to AudioClock
     aaudio_result_t getTimestamp(clockid_t clockId,
                                        int64_t *framePosition,
                                        int64_t *timeNanoseconds) override;
 
-
-
     virtual aaudio_result_t updateStateWhileWaiting() override;
-
     // =========== End ABSTRACT methods ===========================
 
     aaudio_result_t open(const AudioStreamBuilder &builder) override;
@@ -77,6 +73,7 @@
     int32_t getFramesPerBurst() const override;
 
     int64_t getFramesRead() override;
+    int64_t getFramesWritten() override;
 
     int32_t getXRunCount() const override {
         return mXRunCount;
@@ -89,6 +86,11 @@
     // Called internally from 'C'
     void *callbackLoop();
 
+
+    bool isMMap() override {
+        return true;
+    }
+
 protected:
 
     aaudio_result_t processCommands();
@@ -164,4 +166,4 @@
 
 } /* namespace aaudio */
 
-#endif //AAUDIO_AUDIOSTREAMINTERNAL_H
+#endif //ANDROID_AAUDIO_AUDIO_STREAM_INTERNAL_H
diff --git a/media/libaaudio/src/client/IsochronousClockModel.h b/media/libaaudio/src/client/IsochronousClockModel.h
index 205c341..0314f55 100644
--- a/media/libaaudio/src/client/IsochronousClockModel.h
+++ b/media/libaaudio/src/client/IsochronousClockModel.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef AAUDIO_ISOCHRONOUS_CLOCK_MODEL_H
-#define AAUDIO_ISOCHRONOUS_CLOCK_MODEL_H
+#ifndef ANDROID_AAUDIO_ISOCHRONOUS_CLOCK_MODEL_H
+#define ANDROID_AAUDIO_ISOCHRONOUS_CLOCK_MODEL_H
 
 #include <stdint.h>
 
@@ -106,4 +106,4 @@
 
 } /* namespace aaudio */
 
-#endif //AAUDIO_ISOCHRONOUS_CLOCK_MODEL_H
+#endif //ANDROID_AAUDIO_ISOCHRONOUS_CLOCK_MODEL_H
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 462ecb3..59032d5 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -114,8 +114,15 @@
     return AAUDIO_OK;
 }
 
+AAUDIO_API void AAudioStreamBuilder_setPerformanceMode(AAudioStreamBuilder* builder,
+                                                       aaudio_performance_mode_t mode)
+{
+    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
+    streamBuilder->setPerformanceMode(mode);
+}
+
 AAUDIO_API void AAudioStreamBuilder_setDeviceId(AAudioStreamBuilder* builder,
-                                                     int32_t deviceId)
+                                                int32_t deviceId)
 {
     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
     streamBuilder->setDeviceId(deviceId);
@@ -195,26 +202,21 @@
     streamBuilder->setFramesPerDataCallback(frames);
 }
 
-// TODO merge AAudioInternal_openStream into AAudioStreamBuilder_openStream
-static aaudio_result_t  AAudioInternal_openStream(AudioStreamBuilder *streamBuilder,
-                                              AAudioStream** streamPtr)
-{
-    AudioStream *audioStream = nullptr;
-    aaudio_result_t result = streamBuilder->build(&audioStream);
-    if (result != AAUDIO_OK) {
-        return result;
-    } else {
-        *streamPtr = (AAudioStream*) audioStream;
-        return AAUDIO_OK;
-    }
-}
-
 AAUDIO_API aaudio_result_t  AAudioStreamBuilder_openStream(AAudioStreamBuilder* builder,
                                                      AAudioStream** streamPtr)
 {
+    AudioStream *audioStream = nullptr;
     ALOGD("AAudioStreamBuilder_openStream() ----------------------------------------------");
     AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(streamPtr);
-    return AAudioInternal_openStream(streamBuilder, streamPtr);
+    aaudio_result_t result = streamBuilder->build(&audioStream);
+    ALOGD("AAudioStreamBuilder_openStream() returns %d -----------------------------------",
+          result);
+    if (result == AAUDIO_OK) {
+        *streamPtr = (AAudioStream*) audioStream;
+    } else {
+        *streamPtr = nullptr;
+    }
+    return result;
 }
 
 AAUDIO_API aaudio_result_t  AAudioStreamBuilder_delete(AAudioStreamBuilder* builder)
@@ -408,6 +410,12 @@
     return audioStream->getXRunCount();
 }
 
+AAUDIO_API aaudio_performance_mode_t AAudioStream_getPerformanceMode(AAudioStream* stream)
+{
+    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
+    return audioStream->getPerformanceMode();
+}
+
 AAUDIO_API int32_t AAudioStream_getDeviceId(AAudioStream* stream)
 {
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 598fbaa..d1698bf 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -47,6 +47,8 @@
     mSharingMode = builder.getSharingMode();
     mSharingModeMatchRequired = builder.isSharingModeMatchRequired();
 
+    mPerformanceMode = builder.getPerformanceMode();
+
     // callbacks
     mFramesPerDataCallback = builder.getFramesPerDataCallback();
     mDataCallbackProc = builder.getDataCallbackProc();
@@ -64,6 +66,18 @@
         ALOGE("AudioStream::open(): samplesPerFrame out of range = %d", mSamplesPerFrame);
         return AAUDIO_ERROR_OUT_OF_RANGE;
     }
+
+    switch(mFormat) {
+        case AAUDIO_FORMAT_UNSPECIFIED:
+        case AAUDIO_FORMAT_PCM_I16:
+        case AAUDIO_FORMAT_PCM_FLOAT:
+            break; // valid
+        default:
+            ALOGE("AudioStream::open(): audioFormat not valid = %d", mFormat);
+            return AAUDIO_ERROR_INVALID_FORMAT;
+            // break;
+    }
+
     if (mSampleRate < 0 || mSampleRate > 1000000) {
         ALOGE("AudioStream::open(): mSampleRate out of range = %d", mSampleRate);
         return AAUDIO_ERROR_INVALID_RATE;
@@ -73,6 +87,16 @@
         return AAUDIO_ERROR_UNEXPECTED_VALUE;
     }
 
+    switch(mPerformanceMode) {
+        case AAUDIO_PERFORMANCE_MODE_NONE:
+        case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
+        case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
+            break;
+        default:
+            ALOGE("AudioStream::open(): illegal performanceMode %d", mPerformanceMode);
+            return AAUDIO_ERROR_UNEXPECTED_VALUE;
+    }
+
     return AAUDIO_OK;
 }
 
@@ -89,7 +113,6 @@
         return result;
     }
 
-    // TODO replace this when similar functionality added to AudioTrack.cpp
     int64_t durationNanos = 20 * AAUDIO_NANOS_PER_MILLISECOND; // arbitrary
     aaudio_stream_state_t state = getState();
     while (state == currentState && timeoutNanoseconds > 0) {
@@ -133,6 +156,8 @@
     return audioStream->wrapUserThread();
 }
 
+// This is not exposed in the API.
+// But it is still used internally to implement callbacks for MMAP mode.
 aaudio_result_t AudioStream::createThread(int64_t periodNanoseconds,
                                      aaudio_audio_thread_proc_t threadProc,
                                      void* threadArg)
@@ -149,8 +174,7 @@
     setPeriodNanoseconds(periodNanoseconds);
     int err = pthread_create(&mThread, nullptr, AudioStream_internalThreadProc, this);
     if (err != 0) {
-        // TODO convert errno to aaudio_result_t
-        return AAUDIO_ERROR_INTERNAL;
+        return AAudioConvert_androidToAAudioResult(-errno);
     } else {
         mHasThread = true;
         return AAUDIO_OK;
@@ -170,7 +194,6 @@
     int err = pthread_join(mThread, returnArg);
 #endif
     mHasThread = false;
-    // TODO convert errno to aaudio_result_t
-    return err ? AAUDIO_ERROR_INTERNAL : mThreadRegistrationResult;
+    return err ? AAudioConvert_androidToAAudioResult(-errno) : mThreadRegistrationResult;
 }
 
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 916870b..c49b46b 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -134,6 +134,10 @@
         return mState == AAUDIO_STREAM_STATE_STARTING || mState == AAUDIO_STREAM_STATE_STARTED;
     }
 
+    virtual bool isMMap() {
+        return false;
+    }
+
     aaudio_result_t getSampleRate() const {
         return mSampleRate;
     }
@@ -146,6 +150,14 @@
         return mSamplesPerFrame;
     }
 
+    virtual int32_t getPerformanceMode() const {
+        return mPerformanceMode;
+    }
+
+    void setPerformanceMode(aaudio_performance_mode_t performanceMode) {
+        mPerformanceMode = performanceMode;
+    }
+
     int32_t getDeviceId() const {
         return mDeviceId;
     }
@@ -223,11 +235,11 @@
 protected:
 
     virtual int64_t incrementFramesWritten(int32_t frames) {
-        return static_cast<int64_t>(mFramesWritten.increment(frames));
+        return mFramesWritten.increment(frames);
     }
 
     virtual int64_t incrementFramesRead(int32_t frames) {
-        return static_cast<int64_t>(mFramesRead.increment(frames));
+        return mFramesRead.increment(frames);
     }
 
     /**
@@ -293,6 +305,8 @@
     aaudio_direction_t     mDirection = AAUDIO_DIRECTION_OUTPUT;
     aaudio_stream_state_t  mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
 
+    aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
+
     // callback ----------------------------------
 
     AAudioStream_dataCallback   mDataCallbackProc = nullptr;  // external callback functions
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index 4e0b8c6..9bc2ef2 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -47,66 +47,80 @@
 AudioStreamBuilder::~AudioStreamBuilder() {
 }
 
+static aaudio_result_t builder_createStream(aaudio_direction_t direction,
+                                         aaudio_sharing_mode_t sharingMode,
+                                         bool tryMMap,
+                                         AudioStream **audioStreamPtr) {
+    *audioStreamPtr = nullptr;
+    aaudio_result_t result = AAUDIO_OK;
+    switch (direction) {
+
+        case AAUDIO_DIRECTION_INPUT:
+            if (sharingMode == AAUDIO_SHARING_MODE_SHARED) {
+                *audioStreamPtr = new AudioStreamRecord();
+            } else {
+                ALOGE("AudioStreamBuilder(): bad sharing mode = %d for input", sharingMode);
+                result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
+            }
+            break;
+
+        case AAUDIO_DIRECTION_OUTPUT:
+            if (tryMMap) {
+                // TODO use a singleton for the AAudioBinderClient
+                AAudioBinderClient *aaudioClient = new AAudioBinderClient();
+                *audioStreamPtr = new AudioStreamInternal(*aaudioClient, false);
+            } else {
+                *audioStreamPtr = new AudioStreamTrack();
+            }
+            break;
+
+        default:
+            ALOGE("AudioStreamBuilder(): bad direction = %d", direction);
+            result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
+    }
+    return result;
+}
+
 aaudio_result_t AudioStreamBuilder::build(AudioStream** streamPtr) {
-    AudioStream* audioStream = nullptr;
-    AAudioBinderClient *aaudioClient = nullptr;
-    const aaudio_sharing_mode_t sharingMode = getSharingMode();
+    aaudio_sharing_mode_t sharingMode = getSharingMode();
+    if ((sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE) && (MMAP_EXCLUSIVE_ENABLED == 0)) {
+        ALOGE("AudioStreamBuilder(): EXCLUSIVE sharing mode not supported");
+        return AAUDIO_ERROR_UNAVAILABLE;
+    }
 
-    switch (getDirection()) {
+    AudioStream *audioStream = nullptr;
+    *streamPtr = nullptr;
 
-    case AAUDIO_DIRECTION_INPUT:
-        switch (sharingMode) {
-            case AAUDIO_SHARING_MODE_SHARED:
-                audioStream = new(std::nothrow) AudioStreamRecord();
-                break;
-            default:
-                ALOGE("AudioStreamBuilder(): bad sharing mode = %d", sharingMode);
-                return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
-                break;
+    bool tryMMap = (sharingMode == AAUDIO_SHARING_MODE_SHARED) && MMAP_SHARED_ENABLED;
+    aaudio_result_t result = builder_createStream(getDirection(), sharingMode,
+                                                  tryMMap, &audioStream);
+    if (result == AAUDIO_OK) {
+        // Open the stream using the parameters from the builder.
+        result = audioStream->open(*this);
+        if (result == AAUDIO_OK) {
+            *streamPtr = audioStream;
+        } else {
+            bool isMMap = audioStream->isMMap();
+            delete audioStream;
+            audioStream = nullptr;
+
+            if (isMMap) {
+                ALOGD("AudioStreamBuilder.build() MMAP stream did not open so try Legacy path");
+                // If MMAP stream failed to open then TRY using a legacy stream.
+                result = builder_createStream(getDirection(), sharingMode,
+                                              false, &audioStream);
+                if (result == AAUDIO_OK) {
+                    result = audioStream->open(*this);
+                    if (result == AAUDIO_OK) {
+                        *streamPtr = audioStream;
+                    } else {
+                        delete audioStream;
+                    }
+                }
+            }
         }
-        break;
-
-    case AAUDIO_DIRECTION_OUTPUT:
-        switch (sharingMode) {
-            case AAUDIO_SHARING_MODE_SHARED:
-#if MMAP_SHARED_ENABLED
-                aaudioClient = new AAudioBinderClient();
-                audioStream = new(std::nothrow) AudioStreamInternal(*aaudioClient, false);
-#else
-                audioStream = new(std::nothrow) AudioStreamTrack();
-#endif
-                break;
-#if MMAP_EXCLUSIVE_ENABLED
-            case AAUDIO_SHARING_MODE_EXCLUSIVE:
-                aaudioClient = new AAudioBinderClient();
-                audioStream = new(std::nothrow) AudioStreamInternal(*aaudioClient, false);
-                break;
-#endif
-            default:
-                ALOGE("AudioStreamBuilder(): bad sharing mode = %d", sharingMode);
-                return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
-                break;
-        }
-        break;
-
-    default:
-        ALOGE("AudioStreamBuilder(): bad direction = %d", getDirection());
-        return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
-        break;
     }
-    if (audioStream == nullptr) {
-        delete aaudioClient;
-        return AAUDIO_ERROR_NO_MEMORY;
-    }
-    ALOGD("AudioStreamBuilder(): created audioStream = %p", audioStream);
 
-    // TODO maybe move this out of build and pass the builder to the constructors
-    // Open the stream using the parameters from the builder.
-    const aaudio_result_t result = audioStream->open(*this);
-    if (result != AAUDIO_OK) {
-        delete audioStream;
-    } else {
-        *streamPtr = audioStream;
-    }
+    ALOGD("AudioStreamBuilder(): returned %d", result);
     return result;
 }
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.h b/media/libaaudio/src/core/AudioStreamBuilder.h
index 25baf4c..569ca63 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.h
+++ b/media/libaaudio/src/core/AudioStreamBuilder.h
@@ -100,6 +100,15 @@
         return this;
     }
 
+    int32_t getPerformanceMode() const {
+        return mPerformanceMode;
+    }
+
+    AudioStreamBuilder* setPerformanceMode(aaudio_performance_mode_t performanceMode) {
+        mPerformanceMode = performanceMode;
+        return this;
+    }
+
     int32_t getDeviceId() const {
         return mDeviceId;
     }
@@ -157,14 +166,15 @@
     aaudio_result_t build(AudioStream **streamPtr);
 
 private:
-    int32_t                mSamplesPerFrame = AAUDIO_UNSPECIFIED;
-    int32_t                mSampleRate = AAUDIO_UNSPECIFIED;
-    int32_t                mDeviceId = AAUDIO_DEVICE_UNSPECIFIED;
-    aaudio_sharing_mode_t  mSharingMode = AAUDIO_SHARING_MODE_SHARED;
-    bool                   mSharingModeMatchRequired = false; // must match sharing mode requested
-    aaudio_audio_format_t  mFormat = AAUDIO_FORMAT_UNSPECIFIED;
-    aaudio_direction_t     mDirection = AAUDIO_DIRECTION_OUTPUT;
-    int32_t                mBufferCapacity = AAUDIO_UNSPECIFIED;
+    int32_t                    mSamplesPerFrame = AAUDIO_UNSPECIFIED;
+    int32_t                    mSampleRate = AAUDIO_UNSPECIFIED;
+    int32_t                    mDeviceId = AAUDIO_DEVICE_UNSPECIFIED;
+    aaudio_sharing_mode_t      mSharingMode = AAUDIO_SHARING_MODE_SHARED;
+    bool                       mSharingModeMatchRequired = false; // must match sharing mode requested
+    aaudio_audio_format_t      mFormat = AAUDIO_FORMAT_UNSPECIFIED;
+    aaudio_direction_t         mDirection = AAUDIO_DIRECTION_OUTPUT;
+    int32_t                    mBufferCapacity = AAUDIO_UNSPECIFIED;
+    aaudio_performance_mode_t  mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
 
     AAudioStream_dataCallback  mDataCallbackProc = nullptr;  // external callback functions
     void                      *mDataCallbackUserData = nullptr;
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
index baa24c9..f89234a 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -83,6 +83,7 @@
             }
             if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
                 audioBuffer->size = audioBuffer->frameCount * getBytesPerFrame();
+                incrementClientFrameCounter(audioBuffer->frameCount);
             } else {
                 audioBuffer->size = 0;
             }
@@ -108,3 +109,23 @@
     }
 }
 
+aaudio_result_t AudioStreamLegacy::getBestTimestamp(clockid_t clockId,
+                                                   int64_t *framePosition,
+                                                   int64_t *timeNanoseconds,
+                                                   ExtendedTimestamp *extendedTimestamp) {
+    int timebase;
+    switch (clockId) {
+        case CLOCK_BOOTTIME:
+            timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME;
+            break;
+        case CLOCK_MONOTONIC:
+            timebase = ExtendedTimestamp::TIMEBASE_MONOTONIC;
+            break;
+        default:
+            ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId);
+            return AAUDIO_ERROR_UNEXPECTED_VALUE;
+            break;
+    }
+    status_t status = extendedTimestamp->getBestTimestamp(framePosition, timeNanoseconds, timebase);
+    return AAudioConvert_androidToAAudioResult(status);
+}
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.h b/media/libaaudio/src/legacy/AudioStreamLegacy.h
index c109ee7..38f1a56 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.h
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.h
@@ -17,6 +17,7 @@
 #ifndef LEGACY_AUDIO_STREAM_LEGACY_H
 #define LEGACY_AUDIO_STREAM_LEGACY_H
 
+#include <media/AudioTimestamp.h>
 
 #include <aaudio/AAudio.h>
 
@@ -70,7 +71,15 @@
     // Implement FixedBlockProcessor
     int32_t onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) override;
 
+    virtual int64_t incrementClientFrameCounter(int32_t frames)  = 0;
+
 protected:
+
+    aaudio_result_t getBestTimestamp(clockid_t clockId,
+                                     int64_t *framePosition,
+                                     int64_t *timeNanoseconds,
+                                     android::ExtendedTimestamp *extendedTimestamp);
+
     FixedBlockAdapter         *mBlockAdapter = nullptr;
     aaudio_wrapping_frames_t   mPositionWhenStarting = 0;
     int32_t                    mCallbackBufferSize = 0;
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index f0a6ceb..eb6bfd5 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -177,10 +177,13 @@
 
 aaudio_result_t AudioStreamRecord::requestPause()
 {
+    // This does not make sense for an input stream.
+    // There is no real difference between pause() and stop().
     return AAUDIO_ERROR_UNIMPLEMENTED;
 }
 
 aaudio_result_t AudioStreamRecord::requestFlush() {
+    // This does not make sense for an input stream.
     return AAUDIO_ERROR_UNIMPLEMENTED;
 }
 
@@ -259,7 +262,7 @@
 
 int32_t AudioStreamRecord::getXRunCount() const
 {
-    return AAUDIO_ERROR_UNIMPLEMENTED; // TODO implement when AudioRecord supports it
+    return 0; // TODO implement when AudioRecord supports it
 }
 
 int32_t AudioStreamRecord::getFramesPerBurst() const
@@ -275,20 +278,5 @@
     if (status != NO_ERROR) {
         return AAudioConvert_androidToAAudioResult(status);
     }
-    // TODO Merge common code into AudioStreamLegacy after rebasing.
-    int timebase;
-    switch(clockId) {
-        case CLOCK_BOOTTIME:
-            timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME;
-            break;
-        case CLOCK_MONOTONIC:
-            timebase = ExtendedTimestamp::TIMEBASE_MONOTONIC;
-            break;
-        default:
-            ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId);
-            return AAUDIO_ERROR_UNEXPECTED_VALUE;
-            break;
-    }
-    status = extendedTimestamp.getBestTimestamp(framePosition, timeNanoseconds, timebase);
-    return AAudioConvert_androidToAAudioResult(status);
+    return getBestTimestamp(clockId, framePosition, timeNanoseconds, &extendedTimestamp);
 }
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.h b/media/libaaudio/src/legacy/AudioStreamRecord.h
index 897a5b3..f4a78e1 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.h
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.h
@@ -68,6 +68,10 @@
     // This is public so it can be called from the C callback function.
     void processCallback(int event, void *info) override;
 
+    int64_t incrementClientFrameCounter(int32_t frames) override {
+        return incrementFramesRead(frames);
+    }
+
 private:
     android::sp<android::AudioRecord> mAudioRecord;
     // adapts between variable sized blocks and fixed size blocks
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 96fd427..a7c7673 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -32,7 +32,6 @@
 
 // Arbitrary and somewhat generous number of bursts.
 #define DEFAULT_BURSTS_PER_BUFFER_CAPACITY     8
-static const bool FAST_TRACKS_ENABLED = true;
 
 /*
  * Create a stream that uses the AudioTrack.
@@ -62,24 +61,36 @@
     ALOGD("AudioStreamTrack::open = %p", this);
 
     // Try to create an AudioTrack
-    // TODO Support UNSPECIFIED in AudioTrack. For now, use stereo if unspecified.
+    // Use stereo if unspecified.
     int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED)
                               ? 2 : getSamplesPerFrame();
     audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(samplesPerFrame);
     ALOGD("AudioStreamTrack::open(), samplesPerFrame = %d, channelMask = 0x%08x",
             samplesPerFrame, channelMask);
 
-    // TODO add more performance options
-    audio_output_flags_t flags = FAST_TRACKS_ENABLED
-                                 ? AUDIO_OUTPUT_FLAG_FAST
-                                 : AUDIO_OUTPUT_FLAG_NONE;
+    audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
+    switch(getPerformanceMode()) {
+        case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
+            // Bypass the normal mixer and go straight to the FAST mixer.
+            flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW);
+            break;
+
+        case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
+            // This uses a mixer that wakes up less often than the FAST mixer.
+            flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+            break;
+
+        case AAUDIO_PERFORMANCE_MODE_NONE:
+        default:
+            // No flags. Use a normal mixer in front of the FAST mixer.
+            break;
+    }
 
     int32_t frameCount = builder.getBufferCapacity();
     ALOGD("AudioStreamTrack::open(), requested buffer capacity %d", frameCount);
 
     int32_t notificationFrames = 0;
 
-    // TODO implement an unspecified AudioTrack format then use that.
     audio_format_t format = (getFormat() == AAUDIO_FORMAT_UNSPECIFIED)
             ? AUDIO_FORMAT_PCM_FLOAT
             : AAudioConvert_aaudioToAndroidDataFormat(getFormat());
@@ -152,9 +163,8 @@
 
 aaudio_result_t AudioStreamTrack::close()
 {
-    // TODO maybe add close() or release() to AudioTrack API then call it from here
     if (getState() != AAUDIO_STREAM_STATE_CLOSED) {
-        mAudioTrack.clear(); // TODO is this right?
+        mAudioTrack.clear();
         setState(AAUDIO_STREAM_STATE_CLOSED);
     }
     mFixedBlockReader.close();
@@ -279,7 +289,7 @@
             if (err != OK) {
                 return AAudioConvert_androidToAAudioResult(err);
             } else if (position == 0) {
-                // Advance frames read to match written.
+                // TODO Advance frames read to match written.
                 setState(AAUDIO_STREAM_STATE_FLUSHED);
             }
         }
@@ -357,6 +367,8 @@
     case AAUDIO_STREAM_STATE_STARTING:
     case AAUDIO_STREAM_STATE_STARTED:
     case AAUDIO_STREAM_STATE_STOPPING:
+    case AAUDIO_STREAM_STATE_PAUSING:
+    case AAUDIO_STREAM_STATE_PAUSED:
         result = mAudioTrack->getPosition(&position);
         if (result == OK) {
             mFramesRead.update32(position);
@@ -376,20 +388,5 @@
     if (status != NO_ERROR) {
         return AAudioConvert_androidToAAudioResult(status);
     }
-    // TODO Merge common code into AudioStreamLegacy after rebasing.
-    int timebase;
-    switch (clockId) {
-        case CLOCK_BOOTTIME:
-            timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME;
-            break;
-        case CLOCK_MONOTONIC:
-            timebase = ExtendedTimestamp::TIMEBASE_MONOTONIC;
-            break;
-        default:
-            ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId);
-            return AAUDIO_ERROR_UNEXPECTED_VALUE;
-            break;
-    }
-    status = extendedTimestamp.getBestTimestamp(framePosition, timeNanoseconds, timebase);
-    return AAudioConvert_androidToAAudioResult(status);
+    return getBestTimestamp(clockId, framePosition, timeNanoseconds, &extendedTimestamp);
 }
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.h b/media/libaaudio/src/legacy/AudioStreamTrack.h
index 29f5d15..186a08e 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.h
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.h
@@ -68,6 +68,10 @@
     // This is public so it can be called from the C callback function.
     void processCallback(int event, void *info) override;
 
+    int64_t incrementClientFrameCounter(int32_t frames) override {
+        return incrementFramesWritten(frames);
+    }
+
 private:
 
     android::sp<android::AudioTrack> mAudioTrack;
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index 5fa228a..be2bd10 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -48,7 +48,7 @@
 }
 
 
-// TODO call clamp16_from_float function in primitives.h
+// TODO expose and call clamp16_from_float function in primitives.h
 static inline int16_t clamp16_from_float(float f) {
     /* Offset is used to expand the valid range of [-1.0, 1.0) into the 16 lsbs of the
      * floating point significand. The normal shift is 3<<22, but the -15 offset
@@ -209,18 +209,32 @@
         status = DEAD_OBJECT;
         break;
     case AAUDIO_ERROR_INVALID_STATE:
+    case AAUDIO_ERROR_UNEXPECTED_STATE:
         status = INVALID_OPERATION;
         break;
-    case AAUDIO_ERROR_UNEXPECTED_VALUE: // TODO redundant?
+    case AAUDIO_ERROR_UNEXPECTED_VALUE:
     case AAUDIO_ERROR_INVALID_RATE:
     case AAUDIO_ERROR_INVALID_FORMAT:
     case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
+    case AAUDIO_ERROR_OUT_OF_RANGE:
         status = BAD_VALUE;
         break;
     case AAUDIO_ERROR_WOULD_BLOCK:
         status = WOULD_BLOCK;
         break;
-    // TODO add more result codes
+    case AAUDIO_ERROR_NULL:
+        status = UNEXPECTED_NULL;
+        break;
+    // TODO translate these result codes
+    case AAUDIO_ERROR_INCOMPATIBLE:
+    case AAUDIO_ERROR_INTERNAL:
+    case AAUDIO_ERROR_INVALID_QUERY:
+    case AAUDIO_ERROR_UNIMPLEMENTED:
+    case AAUDIO_ERROR_UNAVAILABLE:
+    case AAUDIO_ERROR_NO_FREE_HANDLES:
+    case AAUDIO_ERROR_NO_MEMORY:
+    case AAUDIO_ERROR_TIMEOUT:
+    case AAUDIO_ERROR_NO_SERVICE:
     default:
         status = UNKNOWN_ERROR;
         break;
@@ -244,13 +258,15 @@
     case INVALID_OPERATION:
         result = AAUDIO_ERROR_INVALID_STATE;
         break;
-    case BAD_VALUE:
-        result = AAUDIO_ERROR_UNEXPECTED_VALUE;
-        break;
+        case UNEXPECTED_NULL:
+            result = AAUDIO_ERROR_NULL;
+            break;
+        case BAD_VALUE:
+            result = AAUDIO_ERROR_UNEXPECTED_VALUE;
+            break;
     case WOULD_BLOCK:
         result = AAUDIO_ERROR_WOULD_BLOCK;
         break;
-    // TODO add more status codes
     default:
         result = AAUDIO_ERROR_INTERNAL;
         break;
diff --git a/media/libaaudio/src/utility/FixedBlockAdapter.cpp b/media/libaaudio/src/utility/FixedBlockAdapter.cpp
index f4666af..63495f0 100644
--- a/media/libaaudio/src/utility/FixedBlockAdapter.cpp
+++ b/media/libaaudio/src/utility/FixedBlockAdapter.cpp
@@ -25,7 +25,7 @@
 int32_t FixedBlockAdapter::open(int32_t bytesPerFixedBlock)
 {
     mSize = bytesPerFixedBlock;
-    mStorage = new uint8_t[bytesPerFixedBlock]; // TODO use std::nothrow
+    mStorage = new uint8_t[bytesPerFixedBlock];
     mPosition = 0;
     return 0;
 }
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 4baf253..38d90bc 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -2268,7 +2268,7 @@
             // For now, we simply advance to the end of the VolumeShaper effect
             // if it has been started.
             if (shaper.isStarted()) {
-                operationToEnd->setXOffset(1.f);
+                operationToEnd->setNormalizedTime(1.f);
             }
             return mAudioTrack->applyVolumeShaper(shaper.mConfiguration, operationToEnd);
         });
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 16eb225..a4c8d53 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -874,6 +874,10 @@
      */
             bool hasStarted(); // not const
 
+            bool isPlaying() {
+                AutoMutex lock(mLock);
+                return mState == STATE_ACTIVE || mState == STATE_STOPPING;
+            }
 protected:
     /* copying audio tracks is not allowed */
                         AudioTrack(const AudioTrack& other);
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index cba5cf5..18fd857 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -275,20 +275,6 @@
     ALOGV("MediaPlayerService created");
     mNextConnId = 1;
 
-    mBatteryAudio.refCount = 0;
-    for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
-        mBatteryAudio.deviceOn[i] = 0;
-        mBatteryAudio.lastTime[i] = 0;
-        mBatteryAudio.totalTime[i] = 0;
-    }
-    // speaker is on by default
-    mBatteryAudio.deviceOn[SPEAKER] = 1;
-
-    // reset battery stats
-    // if the mediaserver has crashed, battery stats could be left
-    // in bad state, reset the state upon service start.
-    BatteryNotifier::getInstance().noteResetVideo();
-
     MediaPlayerFactory::registerBuiltinFactories();
 }
 
@@ -2042,7 +2028,7 @@
         // For now, we simply advance to the end of the VolumeShaper effect
         // if it has been started.
         if (shaper.isStarted()) {
-            operationToEnd->setXOffset(1.f);
+            operationToEnd->setNormalizedTime(1.f);
         }
         return t->applyVolumeShaper(shaper.mConfiguration, operationToEnd);
     });
@@ -2301,8 +2287,9 @@
         status = mTrack->applyVolumeShaper(configuration, operation);
         if (status >= 0) {
             (void)mVolumeHandler->applyVolumeShaper(configuration, operation);
-            // TODO: start on exact AudioTrack state (STATE_ACTIVE || STATE_STOPPING)
-            mVolumeHandler->setStarted();
+            if (mTrack->isPlaying()) { // match local AudioTrack to properly restore.
+                mVolumeHandler->setStarted();
+            }
         }
     } else {
         status = mVolumeHandler->applyVolumeShaper(configuration, operation);
@@ -2485,7 +2472,31 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-void MediaPlayerService::addBatteryData(uint32_t params)
+void MediaPlayerService::addBatteryData(uint32_t params) {
+    mBatteryTracker.addBatteryData(params);
+}
+
+status_t MediaPlayerService::pullBatteryData(Parcel* reply) {
+    return mBatteryTracker.pullBatteryData(reply);
+}
+
+MediaPlayerService::BatteryTracker::BatteryTracker() {
+    mBatteryAudio.refCount = 0;
+    for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+        mBatteryAudio.deviceOn[i] = 0;
+        mBatteryAudio.lastTime[i] = 0;
+        mBatteryAudio.totalTime[i] = 0;
+    }
+    // speaker is on by default
+    mBatteryAudio.deviceOn[SPEAKER] = 1;
+
+    // reset battery stats
+    // if the mediaserver has crashed, battery stats could be left
+    // in bad state, reset the state upon service start.
+    BatteryNotifier::getInstance().noteResetVideo();
+}
+
+void MediaPlayerService::BatteryTracker::addBatteryData(uint32_t params)
 {
     Mutex::Autolock lock(mLock);
 
@@ -2625,7 +2636,7 @@
     }
 }
 
-status_t MediaPlayerService::pullBatteryData(Parcel* reply) {
+status_t MediaPlayerService::BatteryTracker::pullBatteryData(Parcel* reply) {
     Mutex::Autolock lock(mLock);
 
     // audio output devices usage
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 009fe73..06b9cad 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -246,51 +246,62 @@
         CAMERA_PROCESS_DEATH = 4
     };
 
-    // For battery usage tracking purpose
-    struct BatteryUsageInfo {
-        // how many streams are being played by one UID
-        int     refCount;
-        // a temp variable to store the duration(ms) of audio codecs
-        // when we start a audio codec, we minus the system time from audioLastTime
-        // when we pause it, we add the system time back to the audioLastTime
-        // so after the pause, audioLastTime = pause time - start time
-        // if multiple audio streams are played (or recorded), then audioLastTime
-        // = the total playing time of all the streams
-        int32_t audioLastTime;
-        // when all the audio streams are being paused, we assign audioLastTime to
-        // this variable, so this value could be provided to the battery app
-        // in the next pullBatteryData call
-        int32_t audioTotalTime;
-
-        int32_t videoLastTime;
-        int32_t videoTotalTime;
-    };
-    KeyedVector<int, BatteryUsageInfo>    mBatteryData;
-
-    enum {
-        SPEAKER,
-        OTHER_AUDIO_DEVICE,
-        SPEAKER_AND_OTHER,
-        NUM_AUDIO_DEVICES
-    };
-
-    struct BatteryAudioFlingerUsageInfo {
-        int refCount; // how many audio streams are being played
-        int deviceOn[NUM_AUDIO_DEVICES]; // whether the device is currently used
-        int32_t lastTime[NUM_AUDIO_DEVICES]; // in ms
-        // totalTime[]: total time of audio output devices usage
-        int32_t totalTime[NUM_AUDIO_DEVICES]; // in ms
-    };
-
-    // This varialble is used to record the usage of audio output device
-    // for battery app
-    BatteryAudioFlingerUsageInfo mBatteryAudio;
-
     // Collect info of the codec usage from media player and media recorder
     virtual void                addBatteryData(uint32_t params);
     // API for the Battery app to pull the data of codecs usage
     virtual status_t            pullBatteryData(Parcel* reply);
 private:
+    struct BatteryTracker {
+        BatteryTracker();
+        // Collect info of the codec usage from media player and media recorder
+        void addBatteryData(uint32_t params);
+        // API for the Battery app to pull the data of codecs usage
+        status_t pullBatteryData(Parcel* reply);
+
+    private:
+        // For battery usage tracking purpose
+        struct BatteryUsageInfo {
+            // how many streams are being played by one UID
+            int     refCount;
+            // a temp variable to store the duration(ms) of audio codecs
+            // when we start a audio codec, we minus the system time from audioLastTime
+            // when we pause it, we add the system time back to the audioLastTime
+            // so after the pause, audioLastTime = pause time - start time
+            // if multiple audio streams are played (or recorded), then audioLastTime
+            // = the total playing time of all the streams
+            int32_t audioLastTime;
+            // when all the audio streams are being paused, we assign audioLastTime to
+            // this variable, so this value could be provided to the battery app
+            // in the next pullBatteryData call
+            int32_t audioTotalTime;
+
+            int32_t videoLastTime;
+            int32_t videoTotalTime;
+        };
+        KeyedVector<int, BatteryUsageInfo>    mBatteryData;
+
+        enum {
+            SPEAKER,
+            OTHER_AUDIO_DEVICE,
+            SPEAKER_AND_OTHER,
+            NUM_AUDIO_DEVICES
+        };
+
+        struct BatteryAudioFlingerUsageInfo {
+            int refCount; // how many audio streams are being played
+            int deviceOn[NUM_AUDIO_DEVICES]; // whether the device is currently used
+            int32_t lastTime[NUM_AUDIO_DEVICES]; // in ms
+            // totalTime[]: total time of audio output devices usage
+            int32_t totalTime[NUM_AUDIO_DEVICES]; // in ms
+        };
+
+        // This varialble is used to record the usage of audio output device
+        // for battery app
+        BatteryAudioFlingerUsageInfo mBatteryAudio;
+
+        mutable Mutex mLock;
+    };
+    BatteryTracker mBatteryTracker;
 
     class Client : public BnMediaPlayer {
         // IMediaPlayer interface
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 9fe61703..5775b43 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -1010,6 +1010,13 @@
             }
 
             // EOS
+            if (mPaused) {
+                // Do not notify EOS when paused.
+                // This is needed to avoid switch to next clip while in pause.
+                ALOGV("onDrainAudioQueue(): Do not notify EOS when paused");
+                return false;
+            }
+
             int64_t postEOSDelayUs = 0;
             if (mAudioSink->needsTrailingPadding()) {
                 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 2877ba2..9f1be22 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1063,6 +1063,34 @@
         return err;
     }
 
+    OMX_INDEXTYPE index;
+    err = mOMXNode->getExtensionIndex(
+            "OMX.google.android.index.AndroidNativeBufferConsumerUsage",
+            &index);
+
+    if (err != OK) {
+        // allow failure
+        err = OK;
+    } else {
+        int usageBits = 0;
+        if (nativeWindow->query(
+                nativeWindow,
+                NATIVE_WINDOW_CONSUMER_USAGE_BITS,
+                &usageBits) == OK) {
+            OMX_PARAM_U32TYPE params;
+            InitOMXParams(&params);
+            params.nPortIndex = kPortIndexOutput;
+            params.nU32 = (OMX_U32)usageBits;
+
+            err = mOMXNode->setParameter(index, &params, sizeof(params));
+
+            if (err != OK) {
+                ALOGE("Fail to set AndroidNativeBufferConsumerUsage: %d", err);
+                return err;
+            }
+        }
+    }
+
     OMX_U32 usage = 0;
     err = mOMXNode->getGraphicBufferUsage(kPortIndexOutput, &usage);
     if (err != 0) {
@@ -1106,7 +1134,8 @@
 
     if (err == OK) {
         err = setupNativeWindowSizeFormatAndUsage(
-                mNativeWindow.get(), &mNativeWindowUsageBits, preregister /* reconnect */);
+                mNativeWindow.get(), &mNativeWindowUsageBits,
+                preregister && !mTunneled /* reconnect */);
     }
     if (err != OK) {
         mNativeWindowUsageBits = 0;
@@ -5401,6 +5430,8 @@
             ALOGE_IF("[%s] failed to release codec instance: err=%d",
                        mCodec->mComponentName.c_str(), err);
             mCodec->mCallback->onReleaseCompleted();
+
+            mCodec->changeState(mCodec->mUninitializedState);
             break;
         }
 
diff --git a/media/libstagefright/omx/1.0/WGraphicBufferProducer.cpp b/media/libstagefright/omx/1.0/WGraphicBufferProducer.cpp
index 36bd624..650db8e 100644
--- a/media/libstagefright/omx/1.0/WGraphicBufferProducer.cpp
+++ b/media/libstagefright/omx/1.0/WGraphicBufferProducer.cpp
@@ -248,7 +248,7 @@
 
 Return<int32_t> TWGraphicBufferProducer::setSidebandStream(const hidl_handle& stream) {
     return static_cast<int32_t>(mBase->setSidebandStream(NativeHandle::create(
-            native_handle_clone(stream), true)));
+            stream ? native_handle_clone(stream) : NULL, true)));
 }
 
 Return<void> TWGraphicBufferProducer::allocateBuffers(
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index d0f64ca..db99ef2 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -1861,7 +1861,7 @@
 }
 
 void OMXNodeInstance::codecBufferFilled(omx_message &msg) {
-    Mutex::Autolock autoLock(mBufferIDLock);
+    Mutex::Autolock autoLock(mLock);
 
     if (mMaxTimestampGapUs <= 0ll || mRestorePtsFailed) {
         return;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8d018d1..a6857fe 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2962,6 +2962,10 @@
     // and then that string will be logged at the next convenient opportunity.
     const char *logString = NULL;
 
+    // Estimated time for next buffer to be written to hal. This is used only on
+    // suspended mode (for now) to help schedule the wait time until next iteration.
+    nsecs_t timeLoopNextNs = 0;
+
     checkSilentMode_l();
 #if 0
     int z = 0; // used in logFormat example
@@ -3327,6 +3331,29 @@
             } else {
                 ATRACE_BEGIN("sleep");
                 Mutex::Autolock _l(mLock);
+                // suspended requires accurate metering of sleep time.
+                if (isSuspended()) {
+                    // advance by expected sleepTime
+                    timeLoopNextNs += microseconds((nsecs_t)mSleepTimeUs);
+                    const nsecs_t nowNs = systemTime();
+
+                    // compute expected next time vs current time.
+                    // (negative deltas are treated as delays).
+                    nsecs_t deltaNs = timeLoopNextNs - nowNs;
+                    if (deltaNs < -kMaxNextBufferDelayNs) {
+                        // Delays longer than the max allowed trigger a reset.
+                        ALOGV("DelayNs: %lld, resetting timeLoopNextNs", (long long) deltaNs);
+                        deltaNs = microseconds((nsecs_t)mSleepTimeUs);
+                        timeLoopNextNs = nowNs + deltaNs;
+                    } else if (deltaNs < 0) {
+                        // Delays within the max delay allowed: zero the delta/sleepTime
+                        // to help the system catch up in the next iteration(s)
+                        ALOGV("DelayNs: %lld, catching-up", (long long) deltaNs);
+                        deltaNs = 0;
+                    }
+                    // update sleep time (which is >= 0)
+                    mSleepTimeUs = deltaNs / 1000;
+                }
                 if (!mSignalPending && mConfigEvents.isEmpty() && !exitPending()) {
                     mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)mSleepTimeUs));
                 }
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 7469710..80b368e 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -623,6 +623,12 @@
     // 14 tracks max per client allows for 2 misbehaving application leaving 4 available tracks.
     static const uint32_t kMaxTracksPerUid = 14;
 
+    // Maximum delay (in nanoseconds) for upcoming buffers in suspend mode, otherwise
+    // if delay is greater, the estimated time for timeLoopNextNs is reset.
+    // This allows for catch-up to be done for small delays, while resetting the estimate
+    // for initial conditions or large delays.
+    static const nsecs_t kMaxNextBufferDelayNs = 100000000;
+
     PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
                    audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady);
     virtual             ~PlaybackThread();
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 5480513..8fefb36 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -597,7 +597,9 @@
     status_t status = mServerProxy->obtainBuffer(&buf);
     buffer->frameCount = buf.mFrameCount;
     buffer->raw = buf.mRaw;
-    if (buf.mFrameCount == 0) {
+    if (buf.mFrameCount == 0 && !isStopping() && !isStopped() && !isPaused()) {
+        ALOGV("underrun,  framesReady(%zu) < framesDesired(%zd), state: %d",
+                buf.mFrameCount, desiredFrames, mState);
         mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
     } else {
         mAudioTrackServerProxy->tallyUnderrunFrames(0);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index e3a23f9..aaa6134 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1007,11 +1007,14 @@
         if (offloadInfo != NULL) {
             config.offload_info = *offloadInfo;
         }
+        DeviceVector outputDevices = mAvailableOutputDevices.getDevicesFromType(device);
+        String8 address = outputDevices.size() > 0 ? outputDevices.itemAt(0)->mAddress
+                : String8("");
         status = mpClientInterface->openOutput(profile->getModuleHandle(),
                                                &output,
                                                &config,
                                                &outputDesc->mDevice,
-                                               String8(""),
+                                               address,
                                                &outputDesc->mLatency,
                                                outputDesc->mFlags);
 
@@ -1699,6 +1702,12 @@
     config.channel_mask = profileChannelMask;
     config.format = profileFormat;
 
+    if (address == "") {
+        DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromType(device);
+        //   the inputs vector must be of size 1, but we don't want to crash here
+        address = inputDevices.size() > 0 ? inputDevices.itemAt(0)->mAddress : String8("");
+    }
+
     status_t status = mpClientInterface->openInput(profile->getModuleHandle(),
                                                    &input,
                                                    &config,
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 2d78f99..ef2f3b3 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -27,7 +27,6 @@
     CameraFlashlight.cpp \
     common/Camera2ClientBase.cpp \
     common/CameraDeviceBase.cpp \
-    common/CameraModule.cpp \
     common/CameraProviderManager.cpp \
     common/FrameProcessorBase.cpp \
     api1/CameraClient.cpp \
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp
index 4537ae6..836972a 100644
--- a/services/camera/libcameraservice/CameraFlashlight.cpp
+++ b/services/camera/libcameraservice/CameraFlashlight.cpp
@@ -36,16 +36,9 @@
 // CameraFlashlight implementation begins
 // used by camera service to control flashflight.
 /////////////////////////////////////////////////////////////////////
-CameraFlashlight::CameraFlashlight(CameraModule* cameraModule,
-        camera_module_callbacks_t* callbacks) :
-        mCameraModule(cameraModule),
-        mCallbacks(callbacks),
-        mFlashlightMapInitialized(false) {
-}
 
 CameraFlashlight::CameraFlashlight(sp<CameraProviderManager> providerManager,
         camera_module_callbacks_t* callbacks) :
-        mCameraModule(nullptr),
         mProviderManager(providerManager),
         mCallbacks(callbacks),
         mFlashlightMapInitialized(false) {
@@ -61,52 +54,12 @@
         return INVALID_OPERATION;
     }
 
-    status_t res = OK;
-
-    if (mCameraModule == nullptr) {
-        if (mProviderManager->supportSetTorchMode(cameraId.string())) {
-            mFlashControl = new ProviderFlashControl(mProviderManager);
-        } else {
-            // Only HAL1 devices do not support setTorchMode
-            mFlashControl =
-                    new CameraHardwareInterfaceFlashControl(mProviderManager, *mCallbacks);
-        }
-    } else if (mCameraModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) {
-        mFlashControl = new ModuleFlashControl(*mCameraModule);
-        if (mFlashControl == NULL) {
-            ALOGV("%s: cannot create flash control for module api v2.4+",
-                     __FUNCTION__);
-            return NO_MEMORY;
-        }
+    if (mProviderManager->supportSetTorchMode(cameraId.string())) {
+        mFlashControl = new ProviderFlashControl(mProviderManager);
     } else {
-        uint32_t deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
-
-        if (mCameraModule->getModuleApiVersion() >=
-                    CAMERA_MODULE_API_VERSION_2_0) {
-            camera_info info;
-            res = mCameraModule->getCameraInfo(
-                    atoi(cameraId.string()), &info);
-            if (res) {
-                ALOGE("%s: failed to get camera info for camera %s",
-                        __FUNCTION__, cameraId.string());
-                return res;
-            }
-            deviceVersion = info.device_version;
-        }
-
-        if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_0) {
-            CameraDeviceClientFlashControl *flashControl =
-                    new CameraDeviceClientFlashControl(*mCameraModule,
-                                                       *mCallbacks);
-            if (!flashControl) {
-                return NO_MEMORY;
-            }
-
-            mFlashControl = flashControl;
-        } else {
-            mFlashControl =
-                    new CameraHardwareInterfaceFlashControl(mCameraModule, *mCallbacks);
-        }
+        // Only HAL1 devices do not support setTorchMode
+        mFlashControl =
+                new CameraHardwareInterfaceFlashControl(mProviderManager, *mCallbacks);
     }
 
     return OK;
@@ -170,11 +123,7 @@
 }
 
 int CameraFlashlight::getNumberOfCameras() {
-    if (mCameraModule) {
-        return mCameraModule->getNumberOfCameras();
-    } else {
-        return mProviderManager->getStandardCameraCount();
-    }
+    return mProviderManager->getAPI1CompatibleCameraCount();
 }
 
 status_t CameraFlashlight::findFlashUnits() {
@@ -184,16 +133,10 @@
     std::vector<String8> cameraIds;
     int numberOfCameras = getNumberOfCameras();
     cameraIds.resize(numberOfCameras);
-    if (mCameraModule) {
-        for (size_t i = 0; i < cameraIds.size(); i++) {
-            cameraIds[i] = String8::format("%zu", i);
-        }
-    } else {
-        // No module, must be provider
-        std::vector<std::string> ids = mProviderManager->getStandardCameraDeviceIds();
-        for (size_t i = 0; i < cameraIds.size(); i++) {
-            cameraIds[i] = String8(ids[i].c_str());
-        }
+    // No module, must be provider
+    std::vector<std::string> ids = mProviderManager->getAPI1CompatibleCameraDeviceIds();
+    for (size_t i = 0; i < cameraIds.size(); i++) {
+        cameraIds[i] = String8(ids[i].c_str());
     }
 
     mHasFlashlightMap.clear();
@@ -251,9 +194,7 @@
 
 bool CameraFlashlight::isBackwardCompatibleMode(const String8& cameraId) {
     bool backwardCompatibleMode = false;
-    if (mCameraModule && mCameraModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_4) {
-        backwardCompatibleMode = true;
-    } else if (mProviderManager != nullptr &&
+    if (mProviderManager != nullptr &&
             !mProviderManager->supportSetTorchMode(cameraId.string())) {
         backwardCompatibleMode = true;
     }
@@ -368,366 +309,13 @@
 // ProviderFlashControl implementation ends
 
 /////////////////////////////////////////////////////////////////////
-// ModuleFlashControl implementation begins
-// Flash control for camera module v2.4 and above.
-/////////////////////////////////////////////////////////////////////
-ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule) :
-        mCameraModule(&cameraModule) {
-}
-
-ModuleFlashControl::~ModuleFlashControl() {
-}
-
-status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
-    if (!hasFlash) {
-        return BAD_VALUE;
-    }
-
-    *hasFlash = false;
-    Mutex::Autolock l(mLock);
-
-    camera_info info;
-    status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()),
-            &info);
-    if (res != 0) {
-        return res;
-    }
-
-    CameraMetadata metadata;
-    metadata = info.static_camera_characteristics;
-    camera_metadata_entry flashAvailable =
-            metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
-    if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
-        *hasFlash = true;
-    }
-
-    return OK;
-}
-
-status_t ModuleFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
-    ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
-            cameraId.string(), enabled);
-
-    Mutex::Autolock l(mLock);
-    return mCameraModule->setTorchMode(cameraId.string(), enabled);
-}
-// ModuleFlashControl implementation ends
-
-/////////////////////////////////////////////////////////////////////
-// CameraDeviceClientFlashControl implementation begins
-// Flash control for camera module <= v2.3 and camera HAL v2-v3
-/////////////////////////////////////////////////////////////////////
-CameraDeviceClientFlashControl::CameraDeviceClientFlashControl(
-        CameraModule& cameraModule,
-        const camera_module_callbacks_t& callbacks) :
-        mCameraModule(&cameraModule),
-        mCallbacks(&callbacks),
-        mTorchEnabled(false),
-        mMetadata(NULL),
-        mStreaming(false) {
-}
-
-CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() {
-    disconnectCameraDevice();
-    if (mMetadata) {
-        delete mMetadata;
-    }
-
-    mSurface.clear();
-    mSurfaceTexture.clear();
-    mProducer.clear();
-    mConsumer.clear();
-
-    if (mTorchEnabled) {
-        if (mCallbacks) {
-            ALOGV("%s: notify the framework that torch was turned off",
-                    __FUNCTION__);
-            mCallbacks->torch_mode_status_change(mCallbacks,
-                    mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
-        }
-    }
-}
-
-status_t CameraDeviceClientFlashControl::initializeSurface(
-        sp<CameraDeviceBase> &device, int32_t width, int32_t height) {
-    status_t res;
-    BufferQueue::createBufferQueue(&mProducer, &mConsumer);
-
-    mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
-            true, true);
-    if (mSurfaceTexture == NULL) {
-        return NO_MEMORY;
-    }
-
-    int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
-    res = mSurfaceTexture->setDefaultBufferSize(width, height);
-    if (res) {
-        return res;
-    }
-    res = mSurfaceTexture->setDefaultBufferFormat(format);
-    if (res) {
-        return res;
-    }
-
-    mSurface = new Surface(mProducer, /*useAsync*/ true);
-    if (mSurface == NULL) {
-        return NO_MEMORY;
-    }
-    res = device->createStream(mSurface, width, height, format,
-            HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mStreamId);
-    if (res) {
-        return res;
-    }
-
-    res = device->configureStreams();
-    if (res) {
-        return res;
-    }
-
-    return res;
-}
-
-status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize(
-        const camera_info& info, int32_t *width, int32_t *height) {
-    if (!width || !height) {
-        return BAD_VALUE;
-    }
-
-    int32_t w = INT32_MAX;
-    int32_t h = 1;
-
-    CameraMetadata metadata;
-    metadata = info.static_camera_characteristics;
-    camera_metadata_entry streamConfigs =
-            metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
-    for (size_t i = 0; i < streamConfigs.count; i += 4) {
-        int32_t fmt = streamConfigs.data.i32[i];
-        if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) {
-            int32_t ww = streamConfigs.data.i32[i + 1];
-            int32_t hh = streamConfigs.data.i32[i + 2];
-
-            if (w * h > ww * hh) {
-                w = ww;
-                h = hh;
-            }
-        }
-    }
-
-    // if stream configuration is not found, try available processed sizes.
-    if (streamConfigs.count == 0) {
-        camera_metadata_entry availableProcessedSizes =
-            metadata.find(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
-        for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
-            int32_t ww = availableProcessedSizes.data.i32[i];
-            int32_t hh = availableProcessedSizes.data.i32[i + 1];
-            if (w * h > ww * hh) {
-                w = ww;
-                h = hh;
-            }
-        }
-    }
-
-    if (w == INT32_MAX) {
-        return NAME_NOT_FOUND;
-    }
-
-    *width = w;
-    *height = h;
-
-    return OK;
-}
-
-status_t CameraDeviceClientFlashControl::connectCameraDevice(
-        const String8& cameraId) {
-    camera_info info;
-    status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info);
-    if (res != 0) {
-        ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
-                cameraId.string());
-        return res;
-    }
-
-    sp<CameraDeviceBase> device =
-            new Camera3Device(cameraId);
-    if (device == NULL) {
-        return NO_MEMORY;
-    }
-
-    res = device->initialize(mCameraModule);
-    if (res) {
-        return res;
-    }
-
-    int32_t width, height;
-    res = getSmallestSurfaceSize(info, &width, &height);
-    if (res) {
-        return res;
-    }
-    res = initializeSurface(device, width, height);
-    if (res) {
-        return res;
-    }
-
-    mCameraId = cameraId;
-    mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1);
-    mDevice = device;
-
-    return OK;
-}
-
-status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
-    if (mDevice != NULL) {
-        mDevice->disconnect();
-        mDevice.clear();
-    }
-
-    return OK;
-}
-
-
-
-status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId,
-        bool *hasFlash) {
-    ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__,
-            cameraId.string());
-
-    Mutex::Autolock l(mLock);
-    return hasFlashUnitLocked(cameraId, hasFlash);
-
-}
-
-status_t CameraDeviceClientFlashControl::hasFlashUnitLocked(
-        const String8& cameraId, bool *hasFlash) {
-    if (!hasFlash) {
-        return BAD_VALUE;
-    }
-
-    camera_info info;
-    status_t res = mCameraModule->getCameraInfo(
-            atoi(cameraId.string()), &info);
-    if (res != 0) {
-        ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
-                cameraId.string());
-        return res;
-    }
-
-    CameraMetadata metadata;
-    metadata = info.static_camera_characteristics;
-    camera_metadata_entry flashAvailable =
-            metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
-    if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
-        *hasFlash = true;
-    }
-
-    return OK;
-}
-
-status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
-    status_t res;
-
-    if (mMetadata == NULL) {
-        mMetadata = new CameraMetadata();
-        if (mMetadata == NULL) {
-            return NO_MEMORY;
-        }
-        res = mDevice->createDefaultRequest(
-                CAMERA3_TEMPLATE_PREVIEW, mMetadata);
-        if (res) {
-            return res;
-        }
-    }
-
-    uint8_t torchOn = ANDROID_FLASH_MODE_TORCH;
-    mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
-    mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
-
-    uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
-    mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
-
-    int32_t requestId = 0;
-    mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
-
-    if (mStreaming) {
-        res = mDevice->setStreamingRequest(*mMetadata);
-    } else {
-        res = mDevice->capture(*mMetadata);
-    }
-    return res;
-}
-
-
-
-
-status_t CameraDeviceClientFlashControl::setTorchMode(
-        const String8& cameraId, bool enabled) {
-    bool hasFlash = false;
-
-    Mutex::Autolock l(mLock);
-    status_t res = hasFlashUnitLocked(cameraId, &hasFlash);
-
-    // pre-check
-    if (enabled) {
-        // invalid camera?
-        if (res) {
-            return -EINVAL;
-        }
-        // no flash unit?
-        if (!hasFlash) {
-            return -ENOSYS;
-        }
-        // already opened for a different device?
-        if (mDevice != NULL && cameraId != mCameraId) {
-            return BAD_INDEX;
-        }
-    } else if (mDevice == NULL || cameraId != mCameraId) {
-        // disabling the torch mode of an un-opened or different device.
-        return OK;
-    } else {
-        // disabling the torch mode of currently opened device
-        disconnectCameraDevice();
-        mTorchEnabled = false;
-        mCallbacks->torch_mode_status_change(mCallbacks,
-            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
-        return OK;
-    }
-
-    if (mDevice == NULL) {
-        res = connectCameraDevice(cameraId);
-        if (res) {
-            return res;
-        }
-    }
-
-    res = submitTorchEnabledRequest();
-    if (res) {
-        return res;
-    }
-
-    mTorchEnabled = true;
-    mCallbacks->torch_mode_status_change(mCallbacks,
-            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
-    return OK;
-}
-// CameraDeviceClientFlashControl implementation ends
-
-
-/////////////////////////////////////////////////////////////////////
 // CameraHardwareInterfaceFlashControl implementation begins
 // Flash control for camera module <= v2.3 and camera HAL v1
 /////////////////////////////////////////////////////////////////////
-CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
-        CameraModule* cameraModule,
-        const camera_module_callbacks_t& callbacks) :
-        mCameraModule(cameraModule),
-        mProviderManager(nullptr),
-        mCallbacks(&callbacks),
-        mTorchEnabled(false) {
-}
 
 CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
         sp<CameraProviderManager> manager,
         const camera_module_callbacks_t& callbacks) :
-        mCameraModule(nullptr),
         mProviderManager(manager),
         mCallbacks(&callbacks),
         mTorchEnabled(false) {
@@ -931,12 +519,7 @@
     sp<CameraHardwareInterface> device =
             new CameraHardwareInterface(cameraId.string());
 
-    status_t res;
-    if (mCameraModule != nullptr) {
-        res = device->initialize(mCameraModule);
-    } else {
-        res = device->initialize(mProviderManager);
-    }
+    status_t res = device->initialize(mProviderManager);
     if (res) {
         ALOGE("%s: initializing camera %s failed", __FUNCTION__,
                 cameraId.string());
diff --git a/services/camera/libcameraservice/CameraFlashlight.h b/services/camera/libcameraservice/CameraFlashlight.h
index 98f269a..c86ee85 100644
--- a/services/camera/libcameraservice/CameraFlashlight.h
+++ b/services/camera/libcameraservice/CameraFlashlight.h
@@ -23,7 +23,6 @@
 #include <utils/KeyedVector.h>
 #include <utils/SortedVector.h>
 #include "common/CameraProviderManager.h"
-#include "common/CameraModule.h"
 #include "common/CameraDeviceBase.h"
 #include "device1/CameraHardwareInterface.h"
 
@@ -55,8 +54,6 @@
  */
 class CameraFlashlight : public virtual VirtualLightRefBase {
     public:
-        CameraFlashlight(CameraModule* cameraModule,
-                camera_module_callbacks_t* callbacks);
         CameraFlashlight(sp<CameraProviderManager> providerManager,
                 camera_module_callbacks_t* callbacks);
         virtual ~CameraFlashlight();
@@ -100,7 +97,6 @@
 
         sp<FlashControlBase> mFlashControl;
 
-        CameraModule *mCameraModule;
         sp<CameraProviderManager> mProviderManager;
 
         const camera_module_callbacks_t *mCallbacks;
@@ -132,86 +128,11 @@
 };
 
 /**
- * Flash control for camera module v2.4 and above.
- */
-class ModuleFlashControl : public FlashControlBase {
-    public:
-        ModuleFlashControl(CameraModule& cameraModule);
-        virtual ~ModuleFlashControl();
-
-        // FlashControlBase
-        status_t hasFlashUnit(const String8& cameraId, bool *hasFlash);
-        status_t setTorchMode(const String8& cameraId, bool enabled);
-
-    private:
-        CameraModule *mCameraModule;
-
-        Mutex mLock;
-};
-
-/**
- * Flash control for camera module <= v2.3 and camera HAL v2-v3
- */
-class CameraDeviceClientFlashControl : public FlashControlBase {
-    public:
-        CameraDeviceClientFlashControl(CameraModule& cameraModule,
-                const camera_module_callbacks_t& callbacks);
-        virtual ~CameraDeviceClientFlashControl();
-
-        // FlashControlBase
-        status_t setTorchMode(const String8& cameraId, bool enabled);
-        status_t hasFlashUnit(const String8& cameraId, bool *hasFlash);
-
-    private:
-        // connect to a camera device
-        status_t connectCameraDevice(const String8& cameraId);
-        // disconnect and free mDevice
-        status_t disconnectCameraDevice();
-
-        // initialize a surface
-        status_t initializeSurface(sp<CameraDeviceBase>& device, int32_t width,
-                int32_t height);
-
-        // submit a request to enable the torch mode
-        status_t submitTorchEnabledRequest();
-
-        // get the smallest surface size of IMPLEMENTATION_DEFINED
-        status_t getSmallestSurfaceSize(const camera_info& info, int32_t *width,
-                    int32_t *height);
-
-        // protected by mLock
-        status_t hasFlashUnitLocked(const String8& cameraId, bool *hasFlash);
-
-        CameraModule *mCameraModule;
-        const camera_module_callbacks_t *mCallbacks;
-        String8 mCameraId;
-        bool mTorchEnabled;
-        CameraMetadata *mMetadata;
-        // WORKAROUND: will be set to true for HAL v2 devices where
-        // setStreamingRequest() needs to be call for torch mode settings to
-        // take effect.
-        bool mStreaming;
-
-        sp<CameraDeviceBase> mDevice;
-
-        sp<IGraphicBufferProducer> mProducer;
-        sp<IGraphicBufferConsumer>  mConsumer;
-        sp<GLConsumer> mSurfaceTexture;
-        sp<Surface> mSurface;
-        int32_t mStreamId;
-
-        Mutex mLock;
-};
-
-/**
  * Flash control for camera module <= v2.3 and camera HAL v1
  */
 class CameraHardwareInterfaceFlashControl : public FlashControlBase {
     public:
         CameraHardwareInterfaceFlashControl(
-                CameraModule* cameraModule,
-                const camera_module_callbacks_t& callbacks);
-        CameraHardwareInterfaceFlashControl(
                 sp<CameraProviderManager> manager,
                 const camera_module_callbacks_t& callbacks);
         virtual ~CameraHardwareInterfaceFlashControl();
@@ -244,7 +165,6 @@
         // function, keepDeviceOpen is ignored.
         status_t hasFlashUnitLocked(const String8& cameraId, bool *hasFlash, bool keepDeviceOpen);
 
-        CameraModule *mCameraModule;
         sp<CameraProviderManager> mProviderManager;
         const camera_module_callbacks_t *mCallbacks;
         sp<CameraHardwareInterface> mDevice;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 39351e7..0031441 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -167,7 +167,7 @@
 CameraService::CameraService() :
         mEventLog(DEFAULT_EVENT_LOG_LENGTH),
         mNumberOfCameras(0), mNumberOfNormalCameras(0),
-        mSoundRef(0), mInitialized(false), mModule(nullptr) {
+        mSoundRef(0), mInitialized(false) {
     ALOGI("CameraService started (pid=%d)", getpid());
 
     this->camera_device_status_change = android::camera_device_status_change;
@@ -189,13 +189,7 @@
 
     status_t res = INVALID_OPERATION;
 
-    bool disableTreble = property_get_bool("camera.disable_treble", false);
-    if (disableTreble) {
-        ALOGI("Treble disabled - using legacy path");
-        res = loadLegacyHalModule();
-    } else {
-        res = enumerateProviders();
-    }
+    res = enumerateProviders();
     if (res == OK) {
         mInitialized = true;
     }
@@ -203,108 +197,6 @@
     CameraService::pingCameraServiceProxy();
 }
 
-status_t CameraService::loadLegacyHalModule() {
-    camera_module_t *rawModule;
-    int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
-            (const hw_module_t **)&rawModule);
-    if (err < 0) {
-        ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
-        logServiceError("Could not load camera HAL module", err);
-        return INVALID_OPERATION;
-    }
-
-    mModule = new CameraModule(rawModule);
-    err = mModule->init();
-    if (err != OK) {
-        ALOGE("Could not initialize camera HAL module: %d (%s)", err,
-            strerror(-err));
-        logServiceError("Could not initialize camera HAL module", err);
-
-        delete mModule;
-        mModule = nullptr;
-        return INVALID_OPERATION;
-    }
-    ALOGI("Loaded \"%s\" camera module", mModule->getModuleName());
-
-    mNumberOfCameras = mModule->getNumberOfCameras();
-    mNumberOfNormalCameras = mNumberOfCameras;
-
-    // Setup vendor tags before we call get_camera_info the first time
-    // because HAL might need to setup static vendor keys in get_camera_info
-    VendorTagDescriptor::clearGlobalVendorTagDescriptor();
-    if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_2) {
-        setUpVendorTags();
-    }
-
-    mFlashlight = new CameraFlashlight(mModule, this);
-    status_t res = mFlashlight->findFlashUnits();
-    if (res) {
-        // impossible because we haven't open any camera devices.
-        ALOGE("Failed to find flash units.");
-    }
-
-    int latestStrangeCameraId = INT_MAX;
-    for (int i = 0; i < mNumberOfCameras; i++) {
-        String8 cameraId = String8::format("%d", i);
-
-        // Get camera info
-
-        struct camera_info info;
-        bool haveInfo = true;
-        status_t rc = mModule->getCameraInfo(i, &info);
-        if (rc != NO_ERROR) {
-            ALOGE("%s: Received error loading camera info for device %d, cost and"
-                    " conflicting devices fields set to defaults for this device.",
-                    __FUNCTION__, i);
-            haveInfo = false;
-        }
-
-        // Check for backwards-compatibility support
-        if (haveInfo) {
-            if (checkCameraCapabilities(i, info, &latestStrangeCameraId) != OK) {
-                delete mModule;
-                mModule = nullptr;
-                return INVALID_OPERATION;
-            }
-        }
-
-        // Defaults to use for cost and conflicting devices
-        int cost = 100;
-        char** conflicting_devices = nullptr;
-        size_t conflicting_devices_length = 0;
-
-        // If using post-2.4 module version, query the cost + conflicting devices from the HAL
-        if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 && haveInfo) {
-            cost = info.resource_cost;
-            conflicting_devices = info.conflicting_devices;
-            conflicting_devices_length = info.conflicting_devices_length;
-        }
-
-        std::set<String8> conflicting;
-        for (size_t i = 0; i < conflicting_devices_length; i++) {
-            conflicting.emplace(String8(conflicting_devices[i]));
-        }
-
-        // Initialize state for each camera device
-        {
-            Mutex::Autolock lock(mCameraStatesLock);
-            mCameraStates.emplace(cameraId, std::make_shared<CameraState>(cameraId, cost,
-                    conflicting));
-        }
-
-        if (mFlashlight->hasFlashUnit(cameraId)) {
-            mTorchStatusMap.add(cameraId,
-                    TorchModeStatus::AVAILABLE_OFF);
-        }
-    }
-
-    if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_1) {
-        mModule->setCallbacks(this);
-    }
-
-    return OK;
-}
-
 status_t CameraService::enumerateProviders() {
     mCameraProviderManager = new CameraProviderManager();
     status_t res;
@@ -316,7 +208,8 @@
     }
 
     mNumberOfCameras = mCameraProviderManager->getCameraCount();
-    mNumberOfNormalCameras = mCameraProviderManager->getStandardCameraCount();
+    mNumberOfNormalCameras =
+            mCameraProviderManager->getAPI1CompatibleCameraCount();
 
     // Setup vendor tags before we call get_camera_info the first time
     // because HAL might need to setup static vendor keys in get_camera_info
@@ -380,10 +273,6 @@
 }
 
 CameraService::~CameraService() {
-    if (mModule) {
-        delete mModule;
-        mModule = nullptr;
-    }
     VendorTagDescriptor::clearGlobalVendorTagDescriptor();
 }
 
@@ -548,28 +437,13 @@
     }
 
     Status ret = Status::ok();
-    if (mModule != nullptr) {
-        struct camera_info info;
-        ret = filterGetInfoErrorCode(mModule->getCameraInfo(cameraId, &info));
-
-        if (ret.isOk()) {
-            cameraInfo->facing = info.facing;
-            cameraInfo->orientation = info.orientation;
-            // CameraInfo is for android.hardware.Camera which does not
-            // support external camera facing. The closest approximation would be
-            // front camera.
-            if (cameraInfo->facing == CAMERA_FACING_EXTERNAL) {
-                cameraInfo->facing = hardware::CAMERA_FACING_FRONT;
-            }
-        }
-    } else {
-        status_t err = mCameraProviderManager->getCameraInfo(std::to_string(cameraId), cameraInfo);
-        if (err != OK) {
-            ret = STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
-                    "Error retrieving camera info from device %d: %s (%d)", cameraId,
-                    strerror(-err), err);
-        }
+    status_t err = mCameraProviderManager->getCameraInfo(std::to_string(cameraId), cameraInfo);
+    if (err != OK) {
+        ret = STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
+                "Error retrieving camera info from device %d: %s (%d)", cameraId,
+                strerror(-err), err);
     }
+
     return ret;
 }
 
@@ -598,34 +472,12 @@
 
     Status ret{};
 
-    if (mModule != nullptr) {
-        int id = cameraIdToInt(String8(cameraId));
-
-        if (id < 0 || id >= mNumberOfCameras) {
-            ALOGE("%s: Invalid camera id: %d", __FUNCTION__, id);
-            return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
-                    "Invalid camera id: %d", id);
-        }
-
-        int version = getDeviceVersion(String8(cameraId));
-        if (version < CAMERA_DEVICE_API_VERSION_3_0) {
-            return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Can't get camera characteristics"
-                    " for devices with HAL version < 3.0, %d is version %x", id, version);
-        }
-
-        struct camera_info info;
-        ret = filterGetInfoErrorCode(mModule->getCameraInfo(id, &info));
-        if (ret.isOk()) {
-            *cameraInfo = info.static_camera_characteristics;
-        }
-    } else {
-        status_t res = mCameraProviderManager->getCameraCharacteristics(
-                String8(cameraId).string(), cameraInfo);
-        if (res != OK) {
-            return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera "
-                    "characteristics for device %s: %s (%d)", String8(cameraId).string(),
-                    strerror(-res), res);
-        }
+    status_t res = mCameraProviderManager->getCameraCharacteristics(
+            String8(cameraId).string(), cameraInfo);
+    if (res != OK) {
+        return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera "
+                "characteristics for device %s: %s (%d)", String8(cameraId).string(),
+                strerror(-res), res);
     }
 
     return ret;
@@ -682,39 +534,20 @@
 
     int deviceVersion = 0;
 
-    if (mModule != nullptr) {
-        int id = cameraIdToInt(cameraId);
-        if (id < 0) return -1;
+    status_t res;
+    hardware::hidl_version maxVersion{0,0};
+    res = mCameraProviderManager->getHighestSupportedVersion(cameraId.string(),
+            &maxVersion);
+    if (res != OK) return -1;
+    deviceVersion = HARDWARE_DEVICE_API_VERSION(maxVersion.get_major(), maxVersion.get_minor());
 
-        struct camera_info info;
-        if (mModule->getCameraInfo(id, &info) != OK) {
-            return -1;
-        }
-
-        if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_0) {
-            deviceVersion = info.device_version;
-        } else {
-            deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
-        }
-
-        if (facing) {
-            *facing = info.facing;
-        }
-    } else {
-        status_t res;
-        hardware::hidl_version maxVersion{0,0};
-        res = mCameraProviderManager->getHighestSupportedVersion(cameraId.string(),
-                &maxVersion);
+    hardware::CameraInfo info;
+    if (facing) {
+        res = mCameraProviderManager->getCameraInfo(cameraId.string(), &info);
         if (res != OK) return -1;
-        deviceVersion = HARDWARE_DEVICE_API_VERSION(maxVersion.get_major(), maxVersion.get_minor());
-
-        hardware::CameraInfo info;
-        if (facing) {
-            res = mCameraProviderManager->getCameraInfo(cameraId.string(), &info);
-            if (res != OK) return -1;
-            *facing = info.facing;
-        }
+        *facing = info.facing;
     }
+
     return deviceVersion;
 }
 
@@ -735,45 +568,6 @@
     }
 }
 
-bool CameraService::setUpVendorTags() {
-    ATRACE_CALL();
-    if (mModule == nullptr) return false;
-
-    vendor_tag_ops_t vOps = vendor_tag_ops_t();
-
-    // Check if vendor operations have been implemented
-    if (!mModule->isVendorTagDefined()) {
-        ALOGI("%s: No vendor tags defined for this device.", __FUNCTION__);
-        return false;
-    }
-
-    mModule->getVendorTagOps(&vOps);
-
-    // Ensure all vendor operations are present
-    if (vOps.get_tag_count == NULL || vOps.get_all_tags == NULL ||
-            vOps.get_section_name == NULL || vOps.get_tag_name == NULL ||
-            vOps.get_tag_type == NULL) {
-        ALOGE("%s: Vendor tag operations not fully defined. Ignoring definitions."
-               , __FUNCTION__);
-        return false;
-    }
-
-    // Read all vendor tag definitions into a descriptor
-    sp<VendorTagDescriptor> desc;
-    status_t res;
-    if ((res = VendorTagDescriptor::createDescriptorFromOps(&vOps, /*out*/desc))
-            != OK) {
-        ALOGE("%s: Could not generate descriptor from vendor tag operations,"
-              "received error %s (%d). Camera clients will not be able to use"
-              "vendor tags", __FUNCTION__, strerror(res), res);
-        return false;
-    }
-
-    // Set the global descriptor to use with camera metadata
-    VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
-    return true;
-}
-
 Status CameraService::makeClient(const sp<CameraService>& cameraService,
         const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
         int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
@@ -1403,25 +1197,6 @@
 
     ATRACE_CALL();
     String8 id = String8::format("%d", cameraId);
-    if (mModule != nullptr) {
-        int apiVersion = mModule->getModuleApiVersion();
-        if (halVersion != CAMERA_HAL_API_VERSION_UNSPECIFIED &&
-                apiVersion < CAMERA_MODULE_API_VERSION_2_3) {
-            /*
-             * Either the HAL version is unspecified in which case this just creates
-             * a camera client selected by the latest device version, or
-             * it's a particular version in which case the HAL must supported
-             * the open_legacy call
-             */
-            String8 msg = String8::format("Camera HAL module version %x too old for connectLegacy!",
-                    apiVersion);
-            ALOGE("%s: %s",
-                    __FUNCTION__, msg.string());
-            logRejected(id, getCallingPid(), String8(clientPackageName),
-                    msg);
-            return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.string());
-        }
-    }
 
     Status ret = Status::ok();
     sp<Client> client = nullptr;
@@ -1564,12 +1339,7 @@
         LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
                 __FUNCTION__);
 
-        if (mModule != nullptr) {
-            err = client->initialize(mModule);
-        } else {
-            err = client->initialize(mCameraProviderManager);
-        }
-
+        err = client->initialize(mCameraProviderManager);
         if (err != OK) {
             ALOGE("%s: Could not initialize client from HAL.", __FUNCTION__);
             // Errors could be from the HAL module open call or from AppOpsManager
@@ -1988,83 +1758,6 @@
     return ret;
 }
 
-
-/**
- * Check camera capabilities, such as support for basic color operation
- * Also check that the device HAL version is still in support
- */
-int CameraService::checkCameraCapabilities(int id, camera_info info, int *latestStrangeCameraId) {
-    if (mModule == nullptr) return NO_INIT;
-
-    // device_version undefined in CAMERA_MODULE_API_VERSION_1_0,
-    // All CAMERA_MODULE_API_VERSION_1_0 devices are backward-compatible
-    if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_0) {
-        // Verify the device version is in the supported range
-        switch (info.device_version) {
-            case CAMERA_DEVICE_API_VERSION_1_0:
-            case CAMERA_DEVICE_API_VERSION_3_0:
-            case CAMERA_DEVICE_API_VERSION_3_1:
-            case CAMERA_DEVICE_API_VERSION_3_2:
-            case CAMERA_DEVICE_API_VERSION_3_3:
-            case CAMERA_DEVICE_API_VERSION_3_4:
-                // in support
-                break;
-            case CAMERA_DEVICE_API_VERSION_2_0:
-            case CAMERA_DEVICE_API_VERSION_2_1:
-                // no longer supported
-            default:
-                ALOGE("%s: Device %d has HAL version %x, which is not supported",
-                        __FUNCTION__, id, info.device_version);
-                String8 msg = String8::format(
-                        "Unsupported device HAL version %x for device %d",
-                        info.device_version, id);
-                logServiceError(msg.string(), NO_INIT);
-                return NO_INIT;
-        }
-    }
-
-    // Assume all devices pre-v3.3 are backward-compatible
-    bool isBackwardCompatible = true;
-    if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_0
-            && info.device_version >= CAMERA_DEVICE_API_VERSION_3_3) {
-        isBackwardCompatible = false;
-        status_t res;
-        camera_metadata_ro_entry_t caps;
-        res = find_camera_metadata_ro_entry(
-            info.static_camera_characteristics,
-            ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
-            &caps);
-        if (res != 0) {
-            ALOGW("%s: Unable to find camera capabilities for camera device %d",
-                    __FUNCTION__, id);
-            caps.count = 0;
-        }
-        for (size_t i = 0; i < caps.count; i++) {
-            if (caps.data.u8[i] ==
-                    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) {
-                isBackwardCompatible = true;
-                break;
-            }
-        }
-    }
-
-    if (!isBackwardCompatible) {
-        mNumberOfNormalCameras--;
-        *latestStrangeCameraId = id;
-    } else {
-        if (id > *latestStrangeCameraId) {
-            ALOGE("%s: Normal camera ID %d higher than strange camera ID %d. "
-                    "This is not allowed due backward-compatibility requirements",
-                    __FUNCTION__, id, *latestStrangeCameraId);
-            logServiceError("Invalid order of camera devices", NO_INIT);
-            mNumberOfCameras = 0;
-            mNumberOfNormalCameras = 0;
-            return NO_INIT;
-        }
-    }
-    return OK;
-}
-
 std::shared_ptr<CameraService::CameraState> CameraService::getCameraState(
         const String8& cameraId) const {
     std::shared_ptr<CameraState> state;
@@ -2815,61 +2508,13 @@
                     cameraId.string());
         }
 
-        if (mModule != nullptr) {
-            dprintf(fd, "== Camera HAL device %s static information: ==\n", cameraId.string());
-
-            camera_info info;
-            status_t rc = mModule->getCameraInfo(cameraIdToInt(cameraId), &info);
-            int deviceVersion = -1;
-            if (rc != OK) {
-                dprintf(fd, "  Error reading static information!\n");
-            } else {
-                dprintf(fd, "  Facing: %s\n",
-                        info.facing == CAMERA_FACING_BACK ? "BACK" :
-                        info.facing == CAMERA_FACING_FRONT ? "FRONT" : "EXTERNAL");
-                dprintf(fd, "  Orientation: %d\n", info.orientation);
-
-                if (mModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_0) {
-                    deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
-                } else {
-                    deviceVersion = info.device_version;
-                }
-            }
-
-            auto conflicting = state.second->getConflicting();
-            dprintf(fd, "  Resource Cost: %d\n", state.second->getCost());
-            dprintf(fd, "  Conflicting Devices:");
-            for (auto& id : conflicting) {
-                dprintf(fd, " %s", id.string());
-            }
-            if (conflicting.size() == 0) {
-                dprintf(fd, " NONE");
-            }
-            dprintf(fd, "\n");
-
-            dprintf(fd, "  Device version: %#x\n", deviceVersion);
-            if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_0) {
-                dprintf(fd, "  Device static metadata:\n");
-                dump_indented_camera_metadata(info.static_camera_characteristics,
-                        fd, /*verbosity*/2, /*indentation*/4);
-            }
-        }
-
     }
 
     if (stateLocked) mCameraStatesLock.unlock();
 
     if (locked) mServiceLock.unlock();
 
-    if (mModule == nullptr) {
-        mCameraProviderManager->dump(fd, args);
-    } else {
-        dprintf(fd, "\n== Camera Module HAL static info: ==\n");
-        dprintf(fd, "Camera module HAL API version: 0x%x\n", mModule->getHalApiVersion());
-        dprintf(fd, "Camera module API version: 0x%x\n", mModule->getModuleApiVersion());
-        dprintf(fd, "Camera module name: %s\n", mModule->getModuleName());
-        dprintf(fd, "Camera module author: %s\n", mModule->getModuleAuthor());
-    }
+    mCameraProviderManager->dump(fd, args);
 
     dprintf(fd, "\n== Vendor tags: ==\n\n");
 
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index e49fe62..7d81993 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -37,7 +37,6 @@
 
 #include "CameraFlashlight.h"
 
-#include "common/CameraModule.h"
 #include "common/CameraProviderManager.h"
 #include "media/RingBuffer.h"
 #include "utils/AutoConditionLock.h"
@@ -198,7 +197,6 @@
 
     class BasicClient : public virtual RefBase {
     public:
-        virtual status_t       initialize(CameraModule *module) = 0;
         virtual status_t       initialize(sp<CameraProviderManager> manager) = 0;
         virtual binder::Status disconnect();
 
@@ -508,9 +506,6 @@
     // Delay-load the Camera HAL module
     virtual void onFirstRef();
 
-    // Load the legacy HAL module
-    status_t loadLegacyHalModule();
-
     // Eumerate all camera providers in the system
     status_t enumerateProviders();
 
@@ -568,11 +563,6 @@
     std::set<userid_t> mAllowedUsers;
 
     /**
-     * Check camera capabilities, such as support for basic color operation
-     */
-    int checkCameraCapabilities(int id, camera_info info, int *latestStrangeCameraId);
-
-    /**
      * Get the camera state for a given camera id.
      *
      * This acquires mCameraStatesLock.
@@ -687,7 +677,6 @@
     // Basic flag on whether the camera subsystem is in a usable state
     bool                mInitialized;
 
-    CameraModule*       mModule;
     sp<CameraProviderManager> mCameraProviderManager;
 
     // Guarded by mStatusListenerMutex
@@ -745,10 +734,6 @@
     // IBinder::DeathRecipient implementation
     virtual void        binderDied(const wp<IBinder> &who);
 
-    // Helpers
-
-    bool                setUpVendorTags();
-
     /**
      * Initialize and cache the metadata used by the HAL1 shim for a given cameraId.
      *
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 335e999..a28518e 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -68,10 +68,6 @@
     mLegacyMode = legacyMode;
 }
 
-status_t Camera2Client::initialize(CameraModule *module) {
-    return initializeImpl(module);
-}
-
 status_t Camera2Client::initialize(sp<CameraProviderManager> manager) {
     return initializeImpl(manager);
 }
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index 9738aca..72315d4 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -100,7 +100,6 @@
 
     virtual ~Camera2Client();
 
-    virtual status_t initialize(CameraModule *module) override;
     virtual status_t initialize(sp<CameraProviderManager> manager) override;
 
     virtual status_t dump(int fd, const Vector<String16>& args);
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index f12cc7b..075c2e3 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -62,16 +62,7 @@
     LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId);
 }
 
-status_t CameraClient::initialize(CameraModule *module) {
-    return initializeImpl<CameraModule*>(module);
-}
-
 status_t CameraClient::initialize(sp<CameraProviderManager> manager) {
-    return initializeImpl<sp<CameraProviderManager>>(manager);
-}
-
-template<typename TProviderPtr>
-status_t CameraClient::initializeImpl(TProviderPtr providerPtr) {
     int callingPid = getCallingPid();
     status_t res;
 
@@ -87,7 +78,7 @@
     snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
 
     mHardware = new CameraHardwareInterface(camera_device_name);
-    res = mHardware->initialize(providerPtr);
+    res = mHardware->initialize(manager);
     if (res != OK) {
         ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
                 __FUNCTION__, mCameraId, strerror(-res), res);
diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h
index 1073384..7f93fef 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -72,7 +72,6 @@
             bool legacyMode = false);
     ~CameraClient();
 
-    virtual status_t initialize(CameraModule *module) override;
     virtual status_t initialize(sp<CameraProviderManager> manager) override;
 
     virtual status_t dump(int fd, const Vector<String16>& args);
@@ -81,9 +80,6 @@
 
 private:
 
-    template<typename TProviderPtr>
-    status_t initializeImpl(TProviderPtr providerPtr);
-
     // check whether the calling process matches mClientPid.
     status_t                checkPid() const;
     status_t                checkPidAndHardware() const;  // also check mHardware != 0
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index f2e8df8..0429e7f 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -82,10 +82,6 @@
     ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
 }
 
-status_t CameraDeviceClient::initialize(CameraModule *module) {
-    return initializeImpl(module);
-}
-
 status_t CameraDeviceClient::initialize(sp<CameraProviderManager> manager) {
     return initializeImpl(manager);
 }
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 2a95c88..2bf73a0 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -149,7 +149,6 @@
             int servicePid);
     virtual ~CameraDeviceClient();
 
-    virtual status_t      initialize(CameraModule *module) override;
     virtual status_t      initialize(sp<CameraProviderManager> manager) override;
 
     virtual status_t      dump(int fd, const Vector<String16>& args);
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 93a584b..32ee273 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -79,11 +79,6 @@
 }
 
 template <typename TClientBase>
-status_t Camera2ClientBase<TClientBase>::initialize(CameraModule *module) {
-    return initializeImpl(module);
-}
-
-template <typename TClientBase>
 status_t Camera2ClientBase<TClientBase>::initialize(sp<CameraProviderManager> manager) {
     return initializeImpl(manager);
 }
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index a4c08ef..e898d5d 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -18,7 +18,6 @@
 #define ANDROID_SERVERS_CAMERA_CAMERA2CLIENT_BASE_H
 
 #include "common/CameraDeviceBase.h"
-#include "common/CameraModule.h"
 #include "camera/CaptureResult.h"
 
 namespace android {
@@ -56,7 +55,6 @@
                       int servicePid);
     virtual ~Camera2ClientBase();
 
-    virtual status_t      initialize(CameraModule *module);
     virtual status_t      initialize(sp<CameraProviderManager> manager);
     virtual status_t      dumpClient(int fd, const Vector<String16>& args);
 
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 44540bb..d9059f3 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -30,7 +30,6 @@
 #include "hardware/camera3.h"
 #include "camera/CameraMetadata.h"
 #include "camera/CaptureResult.h"
-#include "common/CameraModule.h"
 #include "gui/IGraphicBufferProducer.h"
 #include "device3/Camera3StreamInterface.h"
 #include "binder/Status.h"
@@ -55,7 +54,6 @@
      */
     virtual const String8& getId() const = 0;
 
-    virtual status_t initialize(CameraModule *module) = 0;
     virtual status_t initialize(sp<CameraProviderManager> manager) = 0;
     virtual status_t disconnect() = 0;
 
diff --git a/services/camera/libcameraservice/common/CameraModule.cpp b/services/camera/libcameraservice/common/CameraModule.cpp
deleted file mode 100644
index 073144c..0000000
--- a/services/camera/libcameraservice/common/CameraModule.cpp
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#define LOG_TAG "CameraModule"
-#define ATRACE_TAG ATRACE_TAG_CAMERA
-//#define LOG_NDEBUG 0
-
-#include <utils/Trace.h>
-
-#include "CameraModule.h"
-
-namespace android {
-
-void CameraModule::deriveCameraCharacteristicsKeys(
-        uint32_t deviceVersion, CameraMetadata &chars) {
-    ATRACE_CALL();
-
-    Vector<int32_t> derivedCharKeys;
-    Vector<int32_t> derivedRequestKeys;
-    Vector<int32_t> derivedResultKeys;
-    // Keys added in HAL3.3
-    if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_3) {
-        Vector<uint8_t> controlModes;
-        uint8_t data = ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE;
-        chars.update(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &data, /*count*/1);
-        data = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE;
-        chars.update(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &data, /*count*/1);
-        controlModes.push(ANDROID_CONTROL_MODE_AUTO);
-        camera_metadata_entry entry = chars.find(ANDROID_CONTROL_AVAILABLE_SCENE_MODES);
-        if (entry.count > 1 || entry.data.u8[0] != ANDROID_CONTROL_SCENE_MODE_DISABLED) {
-            controlModes.push(ANDROID_CONTROL_MODE_USE_SCENE_MODE);
-        }
-
-        // Only advertise CONTROL_OFF mode if 3A manual controls are supported.
-        bool isManualAeSupported = false;
-        bool isManualAfSupported = false;
-        bool isManualAwbSupported = false;
-        entry = chars.find(ANDROID_CONTROL_AE_AVAILABLE_MODES);
-        if (entry.count > 0) {
-            for (size_t i = 0; i < entry.count; i++) {
-                if (entry.data.u8[i] == ANDROID_CONTROL_AE_MODE_OFF) {
-                    isManualAeSupported = true;
-                    break;
-                }
-            }
-        }
-        entry = chars.find(ANDROID_CONTROL_AF_AVAILABLE_MODES);
-        if (entry.count > 0) {
-            for (size_t i = 0; i < entry.count; i++) {
-                if (entry.data.u8[i] == ANDROID_CONTROL_AF_MODE_OFF) {
-                    isManualAfSupported = true;
-                    break;
-                }
-            }
-        }
-        entry = chars.find(ANDROID_CONTROL_AWB_AVAILABLE_MODES);
-        if (entry.count > 0) {
-            for (size_t i = 0; i < entry.count; i++) {
-                if (entry.data.u8[i] == ANDROID_CONTROL_AWB_MODE_OFF) {
-                    isManualAwbSupported = true;
-                    break;
-                }
-            }
-        }
-        if (isManualAeSupported && isManualAfSupported && isManualAwbSupported) {
-            controlModes.push(ANDROID_CONTROL_MODE_OFF);
-        }
-
-        chars.update(ANDROID_CONTROL_AVAILABLE_MODES, controlModes);
-
-        entry = chars.find(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS);
-        // HAL3.2 devices passing existing CTS test should all support all LSC modes and LSC map
-        bool lensShadingModeSupported = false;
-        if (entry.count > 0) {
-            for (size_t i = 0; i < entry.count; i++) {
-                if (entry.data.i32[i] == ANDROID_SHADING_MODE) {
-                    lensShadingModeSupported = true;
-                    break;
-                }
-            }
-        }
-        Vector<uint8_t> lscModes;
-        Vector<uint8_t> lscMapModes;
-        lscModes.push(ANDROID_SHADING_MODE_FAST);
-        lscModes.push(ANDROID_SHADING_MODE_HIGH_QUALITY);
-        lscMapModes.push(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF);
-        if (lensShadingModeSupported) {
-            lscModes.push(ANDROID_SHADING_MODE_OFF);
-            lscMapModes.push(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_ON);
-        }
-        chars.update(ANDROID_SHADING_AVAILABLE_MODES, lscModes);
-        chars.update(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES, lscMapModes);
-
-        derivedCharKeys.push(ANDROID_CONTROL_AE_LOCK_AVAILABLE);
-        derivedCharKeys.push(ANDROID_CONTROL_AWB_LOCK_AVAILABLE);
-        derivedCharKeys.push(ANDROID_CONTROL_AVAILABLE_MODES);
-        derivedCharKeys.push(ANDROID_SHADING_AVAILABLE_MODES);
-        derivedCharKeys.push(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES);
-
-        // Need update android.control.availableHighSpeedVideoConfigurations since HAL3.3
-        // adds batch size to this array.
-        entry = chars.find(ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS);
-        if (entry.count > 0) {
-            Vector<int32_t> highSpeedConfig;
-            for (size_t i = 0; i < entry.count; i += 4) {
-                highSpeedConfig.add(entry.data.i32[i]); // width
-                highSpeedConfig.add(entry.data.i32[i + 1]); // height
-                highSpeedConfig.add(entry.data.i32[i + 2]); // fps_min
-                highSpeedConfig.add(entry.data.i32[i + 3]); // fps_max
-                highSpeedConfig.add(1); // batchSize_max. default to 1 for HAL3.2
-            }
-            chars.update(ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS,
-                    highSpeedConfig);
-        }
-    }
-
-    // Keys added in HAL3.4
-    if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_4) {
-        // Check if HAL supports RAW_OPAQUE output
-        camera_metadata_entry entry = chars.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
-        bool supportRawOpaque = false;
-        bool supportAnyRaw = false;
-        const int STREAM_CONFIGURATION_SIZE = 4;
-        const int STREAM_FORMAT_OFFSET = 0;
-        const int STREAM_WIDTH_OFFSET = 1;
-        const int STREAM_HEIGHT_OFFSET = 2;
-        const int STREAM_IS_INPUT_OFFSET = 3;
-        Vector<int32_t> rawOpaqueSizes;
-
-        for (size_t i=0; i < entry.count; i += STREAM_CONFIGURATION_SIZE) {
-            int32_t format = entry.data.i32[i + STREAM_FORMAT_OFFSET];
-            int32_t width = entry.data.i32[i + STREAM_WIDTH_OFFSET];
-            int32_t height = entry.data.i32[i + STREAM_HEIGHT_OFFSET];
-            int32_t isInput = entry.data.i32[i + STREAM_IS_INPUT_OFFSET];
-            if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
-                    format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
-                supportRawOpaque = true;
-                rawOpaqueSizes.push(width);
-                rawOpaqueSizes.push(height);
-                // 2 bytes per pixel. This rough estimation is only used when
-                // HAL does not fill in the opaque raw size
-                rawOpaqueSizes.push(width * height *2);
-            }
-            if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
-                    (format == HAL_PIXEL_FORMAT_RAW16 ||
-                     format == HAL_PIXEL_FORMAT_RAW10 ||
-                     format == HAL_PIXEL_FORMAT_RAW12 ||
-                     format == HAL_PIXEL_FORMAT_RAW_OPAQUE)) {
-                supportAnyRaw = true;
-            }
-        }
-
-        if (supportRawOpaque) {
-            entry = chars.find(ANDROID_SENSOR_OPAQUE_RAW_SIZE);
-            if (entry.count == 0) {
-                // Fill in estimated value if HAL does not list it
-                chars.update(ANDROID_SENSOR_OPAQUE_RAW_SIZE, rawOpaqueSizes);
-                derivedCharKeys.push(ANDROID_SENSOR_OPAQUE_RAW_SIZE);
-            }
-        }
-
-        // Check if HAL supports any RAW output, if so, fill in postRawSensitivityBoost range
-        if (supportAnyRaw) {
-            int32_t defaultRange[2] = {100, 100};
-            entry = chars.find(ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE);
-            if (entry.count == 0) {
-                // Fill in default value (100, 100)
-                chars.update(
-                        ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE,
-                        defaultRange, 2);
-                derivedCharKeys.push(ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE);
-                // Actual request/results will be derived by camera device.
-                derivedRequestKeys.push(ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST);
-                derivedResultKeys.push(ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST);
-            }
-        }
-    }
-
-    // Always add a default for the pre-correction active array if the vendor chooses to omit this
-    camera_metadata_entry entry = chars.find(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
-    if (entry.count == 0) {
-        Vector<int32_t> preCorrectionArray;
-        entry = chars.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
-        preCorrectionArray.appendArray(entry.data.i32, entry.count);
-        chars.update(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, preCorrectionArray);
-        derivedCharKeys.push(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
-    }
-
-    // Add those newly added keys to AVAILABLE_CHARACTERISTICS_KEYS
-    // This has to be done at this end of this function.
-    if (derivedCharKeys.size() > 0) {
-        appendAvailableKeys(
-                chars, ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, derivedCharKeys);
-    }
-    if (derivedRequestKeys.size() > 0) {
-        appendAvailableKeys(
-                chars, ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, derivedRequestKeys);
-    }
-    if (derivedResultKeys.size() > 0) {
-        appendAvailableKeys(
-                chars, ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, derivedResultKeys);
-    }
-    return;
-}
-
-void CameraModule::appendAvailableKeys(CameraMetadata &chars,
-        int32_t keyTag, const Vector<int32_t>& appendKeys) {
-    camera_metadata_entry entry = chars.find(keyTag);
-    Vector<int32_t> availableKeys;
-    availableKeys.setCapacity(entry.count + appendKeys.size());
-    for (size_t i = 0; i < entry.count; i++) {
-        availableKeys.push(entry.data.i32[i]);
-    }
-    for (size_t i = 0; i < appendKeys.size(); i++) {
-        availableKeys.push(appendKeys[i]);
-    }
-    chars.update(keyTag, availableKeys);
-}
-
-CameraModule::CameraModule(camera_module_t *module) {
-    if (module == NULL) {
-        ALOGE("%s: camera hardware module must not be null", __FUNCTION__);
-        assert(0);
-    }
-    mModule = module;
-}
-
-CameraModule::~CameraModule()
-{
-    while (mCameraInfoMap.size() > 0) {
-        camera_info cameraInfo = mCameraInfoMap.editValueAt(0);
-        if (cameraInfo.static_camera_characteristics != NULL) {
-            free_camera_metadata(
-                    const_cast<camera_metadata_t*>(cameraInfo.static_camera_characteristics));
-        }
-        mCameraInfoMap.removeItemsAt(0);
-    }
-}
-
-int CameraModule::init() {
-    ATRACE_CALL();
-    int res = OK;
-    if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 &&
-            mModule->init != NULL) {
-        ATRACE_BEGIN("camera_module->init");
-        res = mModule->init();
-        ATRACE_END();
-    }
-    mCameraInfoMap.setCapacity(getNumberOfCameras());
-    return res;
-}
-
-int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) {
-    ATRACE_CALL();
-    Mutex::Autolock lock(mCameraInfoLock);
-    if (cameraId < 0) {
-        ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
-        return -EINVAL;
-    }
-
-    // Only override static_camera_characteristics for API2 devices
-    int apiVersion = mModule->common.module_api_version;
-    if (apiVersion < CAMERA_MODULE_API_VERSION_2_0) {
-        int ret;
-        ATRACE_BEGIN("camera_module->get_camera_info");
-        ret = mModule->get_camera_info(cameraId, info);
-        // Fill in this so CameraService won't be confused by
-        // possibly 0 device_version
-        info->device_version = CAMERA_DEVICE_API_VERSION_1_0;
-        ATRACE_END();
-        return ret;
-    }
-
-    ssize_t index = mCameraInfoMap.indexOfKey(cameraId);
-    if (index == NAME_NOT_FOUND) {
-        // Get camera info from raw module and cache it
-        camera_info rawInfo, cameraInfo;
-        ATRACE_BEGIN("camera_module->get_camera_info");
-        int ret = mModule->get_camera_info(cameraId, &rawInfo);
-        ATRACE_END();
-        if (ret != 0) {
-            return ret;
-        }
-        int deviceVersion = rawInfo.device_version;
-        if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_0) {
-            // static_camera_characteristics is invalid
-            *info = rawInfo;
-            return ret;
-        }
-        CameraMetadata m;
-        m = rawInfo.static_camera_characteristics;
-        deriveCameraCharacteristicsKeys(rawInfo.device_version, m);
-        cameraInfo = rawInfo;
-        cameraInfo.static_camera_characteristics = m.release();
-        index = mCameraInfoMap.add(cameraId, cameraInfo);
-    }
-
-    assert(index != NAME_NOT_FOUND);
-    // return the cached camera info
-    *info = mCameraInfoMap[index];
-    return OK;
-}
-
-int CameraModule::open(const char* id, struct hw_device_t** device) {
-    int res;
-    ATRACE_BEGIN("camera_module->open");
-    res = filterOpenErrorCode(mModule->common.methods->open(&mModule->common, id, device));
-    ATRACE_END();
-    return res;
-}
-
-int CameraModule::openLegacy(
-        const char* id, uint32_t halVersion, struct hw_device_t** device) {
-    int res;
-    ATRACE_BEGIN("camera_module->open_legacy");
-    res = mModule->open_legacy(&mModule->common, id, halVersion, device);
-    ATRACE_END();
-    return res;
-}
-
-int CameraModule::getNumberOfCameras() {
-    int numCameras;
-    ATRACE_BEGIN("camera_module->get_number_of_cameras");
-    numCameras = mModule->get_number_of_cameras();
-    ATRACE_END();
-    return numCameras;
-}
-
-int CameraModule::setCallbacks(const camera_module_callbacks_t *callbacks) {
-    int res;
-    ATRACE_BEGIN("camera_module->set_callbacks");
-    res = mModule->set_callbacks(callbacks);
-    ATRACE_END();
-    return res;
-}
-
-bool CameraModule::isVendorTagDefined() {
-    return mModule->get_vendor_tag_ops != NULL;
-}
-
-void CameraModule::getVendorTagOps(vendor_tag_ops_t* ops) {
-    if (mModule->get_vendor_tag_ops) {
-        ATRACE_BEGIN("camera_module->get_vendor_tag_ops");
-        mModule->get_vendor_tag_ops(ops);
-        ATRACE_END();
-    }
-}
-
-int CameraModule::setTorchMode(const char* camera_id, bool enable) {
-    int res;
-    ATRACE_BEGIN("camera_module->set_torch_mode");
-    res = mModule->set_torch_mode(camera_id, enable);
-    ATRACE_END();
-    return res;
-}
-
-status_t CameraModule::filterOpenErrorCode(status_t err) {
-    switch(err) {
-        case NO_ERROR:
-        case -EBUSY:
-        case -EINVAL:
-        case -EUSERS:
-            return err;
-        default:
-            break;
-    }
-    return -ENODEV;
-}
-
-uint16_t CameraModule::getModuleApiVersion() {
-    return mModule->common.module_api_version;
-}
-
-const char* CameraModule::getModuleName() {
-    return mModule->common.name;
-}
-
-uint16_t CameraModule::getHalApiVersion() {
-    return mModule->common.hal_api_version;
-}
-
-const char* CameraModule::getModuleAuthor() {
-    return mModule->common.author;
-}
-
-void* CameraModule::getDso() {
-    return mModule->common.dso;
-}
-
-}; // namespace android
diff --git a/services/camera/libcameraservice/common/CameraModule.h b/services/camera/libcameraservice/common/CameraModule.h
deleted file mode 100644
index d131a26..0000000
--- a/services/camera/libcameraservice/common/CameraModule.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef ANDROID_SERVERS_CAMERA_CAMERAMODULE_H
-#define ANDROID_SERVERS_CAMERA_CAMERAMODULE_H
-
-#include <hardware/camera.h>
-#include <camera/CameraMetadata.h>
-#include <utils/Mutex.h>
-#include <utils/KeyedVector.h>
-
-namespace android {
-/**
- * A wrapper class for HAL camera module.
- *
- * This class wraps camera_module_t returned from HAL to provide a wrapped
- * get_camera_info implementation which CameraService generates some
- * camera characteristics keys defined in newer HAL version on an older HAL.
- */
-class CameraModule {
-public:
-    explicit CameraModule(camera_module_t *module);
-    virtual ~CameraModule();
-
-    // Must be called after construction
-    // Returns OK on success, NO_INIT on failure
-    int init();
-
-    int getCameraInfo(int cameraId, struct camera_info *info);
-    int getNumberOfCameras(void);
-    int open(const char* id, struct hw_device_t** device);
-    int openLegacy(const char* id, uint32_t halVersion, struct hw_device_t** device);
-    int setCallbacks(const camera_module_callbacks_t *callbacks);
-    bool isVendorTagDefined();
-    void getVendorTagOps(vendor_tag_ops_t* ops);
-    int setTorchMode(const char* camera_id, bool enable);
-    uint16_t getModuleApiVersion();
-    const char* getModuleName();
-    uint16_t getHalApiVersion();
-    const char* getModuleAuthor();
-    // Only used by CameraModuleFixture native test. Do NOT use elsewhere.
-    void *getDso();
-
-private:
-    // Derive camera characteristics keys defined after HAL device version
-    static void deriveCameraCharacteristicsKeys(uint32_t deviceVersion, CameraMetadata &chars);
-    // Helper function to append available[request|result|chars]Keys
-    static void appendAvailableKeys(CameraMetadata &chars,
-            int32_t keyTag, const Vector<int32_t>& appendKeys);
-    status_t filterOpenErrorCode(status_t err);
-    camera_module_t *mModule;
-    KeyedVector<int, camera_info> mCameraInfoMap;
-    Mutex mCameraInfoLock;
-};
-
-} // namespace android
-
-#endif
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index f3a81cb..38fe1b6 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -82,12 +82,16 @@
     return count;
 }
 
-int CameraProviderManager::getStandardCameraCount() const {
+int CameraProviderManager::getAPI1CompatibleCameraCount() const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
     int count = 0;
     for (auto& provider : mProviders) {
         if (kStandardProviderTypes.find(provider->getType()) != std::string::npos) {
-            count += provider->mUniqueDeviceCount;
+            for (auto& device : provider->mDevices) {
+                if (device->isAPI1Compatible()) {
+                    count++;
+                }
+            }
         }
     }
     return count;
@@ -104,13 +108,15 @@
     return deviceIds;
 }
 
-std::vector<std::string> CameraProviderManager::getStandardCameraDeviceIds() const {
+std::vector<std::string> CameraProviderManager::getAPI1CompatibleCameraDeviceIds() const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
     std::vector<std::string> deviceIds;
     for (auto& provider : mProviders) {
         if (kStandardProviderTypes.find(provider->getType()) != std::string::npos) {
-            for (auto& id : provider->mUniqueCameraIds) {
-                deviceIds.push_back(id);
+            for (auto& device : provider->mDevices) {
+                if (device->isAPI1Compatible()) {
+                    deviceIds.push_back(device->mId);
+                }
             }
         }
     }
@@ -983,6 +989,20 @@
 
     return OK;
 }
+bool CameraProviderManager::ProviderInfo::DeviceInfo3::isAPI1Compatible() const {
+    bool isBackwardCompatible = false;
+    camera_metadata_ro_entry_t caps = mCameraCharacteristics.find(
+            ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+    for (size_t i = 0; i < caps.count; i++) {
+        if (caps.data.u8[i] ==
+                ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) {
+            isBackwardCompatible = true;
+            break;
+        }
+    }
+
+    return isBackwardCompatible;
+}
 
 status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getCameraCharacteristics(
         CameraMetadata *characteristics) const {
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 2df4fd5..3afc1d9 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -125,16 +125,16 @@
     int getCameraCount() const;
 
     /**
-     * Retrieve the number of 'standard' cameras; these are internal and
+     * Retrieve the number of API1 compatible cameras; these are internal and
      * backwards-compatible. This is the set of cameras that will be
      * accessible via the old camera API, with IDs in range of
-     * [0, getStandardCameraCount()-1]. This value is not expected to change dynamically.
+     * [0, getAPI1CompatibleCameraCount()-1]. This value is not expected to change dynamically.
      */
-    int getStandardCameraCount() const;
+    int getAPI1CompatibleCameraCount() const;
 
     std::vector<std::string> getCameraDeviceIds() const;
 
-    std::vector<std::string> getStandardCameraDeviceIds() const;
+    std::vector<std::string> getAPI1CompatibleCameraDeviceIds() const;
 
     /**
      * Return true if a device with a given ID and major version exists
@@ -291,6 +291,7 @@
             bool hasFlashUnit() const { return mHasFlashUnit; }
             virtual status_t setTorchMode(bool enabled) = 0;
             virtual status_t getCameraInfo(hardware::CameraInfo *info) const = 0;
+            virtual bool isAPI1Compatible() const = 0;
             virtual status_t getCameraCharacteristics(CameraMetadata *characteristics) const {
                 (void) characteristics;
                 return INVALID_OPERATION;
@@ -321,7 +322,8 @@
 
             virtual status_t setTorchMode(bool enabled) override;
             virtual status_t getCameraInfo(hardware::CameraInfo *info) const override;
-
+            //In case of Device1Info assume that we are always API1 compatible
+            virtual bool isAPI1Compatible() const override { return true; }
             DeviceInfo1(const std::string& name, const metadata_vendor_id_t tagId,
                     const std::string &id, uint16_t minorVersion,
                     const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
@@ -338,6 +340,7 @@
 
             virtual status_t setTorchMode(bool enabled) override;
             virtual status_t getCameraInfo(hardware::CameraInfo *info) const override;
+            virtual bool isAPI1Compatible() const override;
             virtual status_t getCameraCharacteristics(
                     CameraMetadata *characteristics) const override;
 
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
index 9df7cd4..469c86c 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
@@ -41,37 +41,6 @@
     }
 }
 
-status_t CameraHardwareInterface::initialize(CameraModule *module)
-{
-    if (mHidlDevice != nullptr) {
-        ALOGE("%s: camera hardware interface has been initialized to HIDL path!", __FUNCTION__);
-        return INVALID_OPERATION;
-    }
-    ALOGI("Opening camera %s", mName.string());
-    camera_info info;
-    status_t res = module->getCameraInfo(atoi(mName.string()), &info);
-    if (res != OK) {
-        return res;
-    }
-
-    int rc = OK;
-    if (module->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_3 &&
-        info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {
-        // Open higher version camera device as HAL1.0 device.
-        rc = module->openLegacy(mName.string(),
-                                 CAMERA_DEVICE_API_VERSION_1_0,
-                                 (hw_device_t **)&mDevice);
-    } else {
-        rc = module->open(mName.string(), (hw_device_t **)&mDevice);
-    }
-    if (rc != OK) {
-        ALOGE("Could not open camera %s: %d", mName.string(), rc);
-        return rc;
-    }
-    initHalPreviewWindow();
-    return rc;
-}
-
 status_t CameraHardwareInterface::initialize(sp<CameraProviderManager> manager) {
     if (mDevice) {
         ALOGE("%s: camera hardware interface has been initialized to libhardware path!",
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index 907065f..1c38d00 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -28,7 +28,6 @@
 #include <system/window.h>
 #include <hardware/camera.h>
 
-#include <common/CameraModule.h>
 #include <common/CameraProviderManager.h>
 
 namespace android {
@@ -107,7 +106,6 @@
 
     ~CameraHardwareInterface();
 
-    status_t initialize(CameraModule *module);
     status_t initialize(sp<CameraProviderManager> manager);
 
     /** Set the ANativeWindow to which preview frames are sent */
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 2bdb008..4706319 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -94,81 +94,6 @@
     return mId;
 }
 
-/**
- * CameraDeviceBase interface
- */
-
-status_t Camera3Device::initialize(CameraModule *module)
-{
-    ATRACE_CALL();
-    Mutex::Autolock il(mInterfaceLock);
-    Mutex::Autolock l(mLock);
-
-    ALOGV("%s: Initializing device for camera %s", __FUNCTION__, mId.string());
-    if (mStatus != STATUS_UNINITIALIZED) {
-        CLOGE("Already initialized!");
-        return INVALID_OPERATION;
-    }
-
-    /** Open HAL device */
-
-    status_t res;
-
-    camera3_device_t *device;
-
-    ATRACE_BEGIN("CameraHal::open");
-    res = module->open(mId.string(),
-            reinterpret_cast<hw_device_t**>(&device));
-    ATRACE_END();
-
-    if (res != OK) {
-        SET_ERR_L("Could not open camera: %s (%d)", strerror(-res), res);
-        return res;
-    }
-
-    /** Cross-check device version */
-    if (device->common.version < CAMERA_DEVICE_API_VERSION_3_2) {
-        SET_ERR_L("Could not open camera: "
-                "Camera device should be at least %x, reports %x instead",
-                CAMERA_DEVICE_API_VERSION_3_2,
-                device->common.version);
-        device->common.close(&device->common);
-        return BAD_VALUE;
-    }
-
-    camera_info info;
-    res = module->getCameraInfo(atoi(mId), &info);
-    if (res != OK) return res;
-
-    if (info.device_version != device->common.version) {
-        SET_ERR_L("HAL reporting mismatched camera_info version (%x)"
-                " and device version (%x).",
-                info.device_version, device->common.version);
-        device->common.close(&device->common);
-        return BAD_VALUE;
-    }
-
-    /** Initialize device with callback functions */
-
-    ATRACE_BEGIN("CameraHal::initialize");
-    res = device->ops->initialize(device, this);
-    ATRACE_END();
-
-    if (res != OK) {
-        SET_ERR_L("Unable to initialize HAL device: %s (%d)",
-                strerror(-res), res);
-        device->common.close(&device->common);
-        return res;
-    }
-
-    /** Everything is good to go */
-
-    mDeviceInfo = info.static_camera_characteristics;
-    mInterface = std::make_unique<HalInterface>(device);
-
-    return initializeCommonLocked();
-}
-
 status_t Camera3Device::initialize(sp<CameraProviderManager> manager) {
     ATRACE_CALL();
     Mutex::Autolock il(mInterfaceLock);
@@ -2936,9 +2861,6 @@
  * HalInterface inner class methods
  */
 
-Camera3Device::HalInterface::HalInterface(camera3_device_t *device) :
-        mHal3Device(device) {}
-
 Camera3Device::HalInterface::HalInterface(
             sp<ICameraDeviceSession> &session,
             std::shared_ptr<RequestMetadataQueue> queue) :
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index c9876a6..1ca6811 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -87,7 +87,6 @@
     const String8& getId() const override;
 
     // Transitions to idle state on success.
-    status_t initialize(CameraModule *module) override;
     status_t initialize(sp<CameraProviderManager> manager) override;
     status_t disconnect() override;
     status_t dump(int fd, const Vector<String16> &args) override;
@@ -233,7 +232,6 @@
      */
     class HalInterface : public camera3::Camera3StreamBufferFreedListener {
       public:
-        HalInterface(camera3_device_t *device);
         HalInterface(sp<hardware::camera::device::V3_2::ICameraDeviceSession> &session,
                      std::shared_ptr<RequestMetadataQueue> queue);
         HalInterface(const HalInterface &other);
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index d8882c9..8248f8b 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -59,6 +59,7 @@
     std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
     delete mUpMessageQueue;
     mUpMessageQueue = nullptr;
+
     return AAUDIO_OK;
 }
 
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index d6b6ee3..9318c2e 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -133,9 +133,6 @@
     // This is used by one thread to tell another thread to exit. So it must be atomic.
     std::atomic<bool>   mThreadEnabled;
 
-
-    int                mAudioDataFileDescriptor = -1;
-
     aaudio_audio_format_t mAudioFormat = AAUDIO_FORMAT_UNSPECIFIED;
     int32_t            mFramesPerBurst = 0;
     int32_t            mSamplesPerFrame = AAUDIO_UNSPECIFIED;
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.cpp b/services/oboeservice/AAudioServiceStreamMMAP.cpp
index b2e7fc9..cadc2a4 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.cpp
+++ b/services/oboeservice/AAudioServiceStreamMMAP.cpp
@@ -60,6 +60,13 @@
     // FIXME Make closing synchronous.
     AudioClock::sleepForNanos(100 * AAUDIO_NANOS_PER_MILLISECOND);
 
+    if (mAudioDataFileDescriptor != -1) {
+        ALOGV("AAudioServiceStreamMMAP: LEAK? close(mAudioDataFileDescriptor = %d)\n",
+              mAudioDataFileDescriptor);
+        ::close(mAudioDataFileDescriptor);
+        mAudioDataFileDescriptor = -1;
+    }
+
     return AAudioServiceStreamBase::close();
 }
 
@@ -125,6 +132,9 @@
     MmapStreamInterface::stream_direction_t streamDirection = (direction == AAUDIO_DIRECTION_OUTPUT)
         ? MmapStreamInterface::DIRECTION_OUTPUT : MmapStreamInterface::DIRECTION_INPUT;
 
+    ALOGD("AAudioServiceStreamMMAP::open() request devId = %d, sRate = %d",
+          deviceId, config.sample_rate);
+
     // Open HAL stream.
     status_t status = MmapStreamInterface::openMmapStream(streamDirection,
                                                           &attributes,
@@ -161,11 +171,16 @@
                            : audio_channel_count_from_in_mask(config.channel_mask);
 
     mAudioDataFileDescriptor = mMmapBufferinfo.shared_memory_fd;
+    ALOGV("AAudioServiceStreamMMAP::open LEAK? mAudioDataFileDescriptor = %d\n",
+          mAudioDataFileDescriptor);
     mFramesPerBurst = mMmapBufferinfo.burst_size_frames;
     mCapacityInFrames = mMmapBufferinfo.buffer_size_frames;
     mAudioFormat = AAudioConvert_androidToAAudioDataFormat(config.format);
     mSampleRate = config.sample_rate;
 
+    ALOGD("AAudioServiceStreamMMAP::open() got devId = %d, sRate = %d",
+          deviceId, config.sample_rate);
+
     // Fill in AAudioStreamConfiguration
     configurationOutput.setSampleRate(mSampleRate);
     configurationOutput.setSamplesPerFrame(mSamplesPerFrame);
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.h b/services/oboeservice/AAudioServiceStreamMMAP.h
index a8e63a6..fe75a10 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.h
+++ b/services/oboeservice/AAudioServiceStreamMMAP.h
@@ -127,6 +127,7 @@
     MonotonicCounter                    mFramesWritten;
     MonotonicCounter                    mFramesRead;
     int32_t                             mPreviousFrameCounter = 0;   // from HAL
+    int                                 mAudioDataFileDescriptor = -1;
 
     // Interface to the AudioFlinger MMAP support.
     android::sp<android::MmapStreamInterface> mMmapStream;
diff --git a/services/oboeservice/AAudioServiceStreamShared.cpp b/services/oboeservice/AAudioServiceStreamShared.cpp
index b5d9927..713d1f8 100644
--- a/services/oboeservice/AAudioServiceStreamShared.cpp
+++ b/services/oboeservice/AAudioServiceStreamShared.cpp
@@ -200,6 +200,10 @@
         mEndpointManager.closeEndpoint(endpoint);
         mServiceEndpoint = nullptr;
     }
+    if (mAudioDataQueue != nullptr) {
+        delete mAudioDataQueue;
+        mAudioDataQueue = nullptr;
+    }
     return AAudioServiceStreamBase::close();
 }
 
diff --git a/services/oboeservice/Android.mk b/services/oboeservice/Android.mk
index a9c80ae..afb477e 100644
--- a/services/oboeservice/Android.mk
+++ b/services/oboeservice/Android.mk
@@ -48,8 +48,7 @@
     libcutils \
     libmediautils \
     libutils \
-    liblog \
-    libtinyalsa
+    liblog
 
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/services/oboeservice/SharedRingBuffer.cpp b/services/oboeservice/SharedRingBuffer.cpp
index 03c160d..6b3fb4c 100644
--- a/services/oboeservice/SharedRingBuffer.cpp
+++ b/services/oboeservice/SharedRingBuffer.cpp
@@ -33,9 +33,13 @@
     if (mSharedMemory != nullptr) {
         delete mFifoBuffer;
         munmap(mSharedMemory, mSharedMemorySizeInBytes);
-        close(mFileDescriptor);
         mSharedMemory = nullptr;
     }
+    if (mFileDescriptor != -1) {
+        ALOGV("SharedRingBuffer: LEAK? close(mFileDescriptor = %d)\n", mFileDescriptor);
+        close(mFileDescriptor);
+        mFileDescriptor = -1;
+    }
 }
 
 aaudio_result_t SharedRingBuffer::allocate(fifo_frames_t   bytesPerFrame,
@@ -46,10 +50,12 @@
     mDataMemorySizeInBytes = bytesPerFrame * capacityInFrames;
     mSharedMemorySizeInBytes = mDataMemorySizeInBytes + (2 * (sizeof(fifo_counter_t)));
     mFileDescriptor = ashmem_create_region("AAudioSharedRingBuffer", mSharedMemorySizeInBytes);
+    ALOGV("SharedRingBuffer::allocate() LEAK? mFileDescriptor = %d\n", mFileDescriptor);
     if (mFileDescriptor < 0) {
         ALOGE("SharedRingBuffer::allocate() ashmem_create_region() failed %d", errno);
         return AAUDIO_ERROR_INTERNAL;
     }
+
     int err = ashmem_set_prot_region(mFileDescriptor, PROT_READ|PROT_WRITE); // TODO error handling?
     if (err < 0) {
         ALOGE("SharedRingBuffer::allocate() ashmem_set_prot_region() failed %d", errno);
@@ -75,9 +81,9 @@
             (fifo_counter_t *) &mSharedMemory[SHARED_RINGBUFFER_WRITE_OFFSET];
     uint8_t *dataAddress = &mSharedMemory[SHARED_RINGBUFFER_DATA_OFFSET];
 
-    mFifoBuffer = new(std::nothrow) FifoBuffer(bytesPerFrame, capacityInFrames,
+    mFifoBuffer = new FifoBuffer(bytesPerFrame, capacityInFrames,
                                  readCounterAddress, writeCounterAddress, dataAddress);
-    return (mFifoBuffer == nullptr) ? AAUDIO_ERROR_NO_MEMORY : AAUDIO_OK;
+    return AAUDIO_OK;
 }
 
 void SharedRingBuffer::fillParcelable(AudioEndpointParcelable &endpointParcelable,