Merge "aaudio: show format as text"
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 0982bba..a16e747 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -85,6 +85,10 @@
     return mStreamUseCase;
 }
 
+int OutputConfiguration::getTimestampBase() const {
+    return mTimestampBase;
+}
+
 OutputConfiguration::OutputConfiguration() :
         mRotation(INVALID_ROTATION),
         mSurfaceSetID(INVALID_SET_ID),
@@ -95,7 +99,8 @@
         mIsShared(false),
         mIsMultiResolution(false),
         mDynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD),
-        mStreamUseCase(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) {
+        mStreamUseCase(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT),
+        mTimestampBase(TIMESTAMP_BASE_DEFAULT) {
 }
 
 OutputConfiguration::OutputConfiguration(const android::Parcel& parcel) :
@@ -188,6 +193,12 @@
         return err;
     }
 
+    int timestampBase = TIMESTAMP_BASE_DEFAULT;
+    if ((err = parcel->readInt32(&timestampBase)) != OK) {
+        ALOGE("%s: Failed to read timestamp base from parcel", __FUNCTION__);
+        return err;
+    }
+
     mRotation = rotation;
     mSurfaceSetID = setID;
     mSurfaceType = surfaceType;
@@ -197,6 +208,7 @@
     mIsShared = isShared != 0;
     mIsMultiResolution = isMultiResolution != 0;
     mStreamUseCase = streamUseCase;
+    mTimestampBase = timestampBase;
     for (auto& surface : surfaceShims) {
         ALOGV("%s: OutputConfiguration: %p, name %s", __FUNCTION__,
                 surface.graphicBufferProducer.get(),
@@ -208,9 +220,9 @@
     mDynamicRangeProfile = dynamicProfile;
 
     ALOGV("%s: OutputConfiguration: rotation = %d, setId = %d, surfaceType = %d,"
-          " physicalCameraId = %s, isMultiResolution = %d, streamUseCase = %d", __FUNCTION__,
-          mRotation, mSurfaceSetID, mSurfaceType, String8(mPhysicalCameraId).string(),
-          mIsMultiResolution, mStreamUseCase);
+          " physicalCameraId = %s, isMultiResolution = %d, streamUseCase = %d, timestampBase = %d",
+          __FUNCTION__, mRotation, mSurfaceSetID, mSurfaceType,
+          String8(mPhysicalCameraId).string(), mIsMultiResolution, mStreamUseCase, timestampBase);
 
     return err;
 }
@@ -227,6 +239,7 @@
     mIsMultiResolution = false;
     mDynamicRangeProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
     mStreamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
+    mTimestampBase = TIMESTAMP_BASE_DEFAULT;
 }
 
 OutputConfiguration::OutputConfiguration(
@@ -237,7 +250,8 @@
     mWidth(width), mHeight(height), mIsDeferred(false), mIsShared(isShared),
     mPhysicalCameraId(physicalCameraId), mIsMultiResolution(false),
     mDynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD),
-    mStreamUseCase(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) { }
+    mStreamUseCase(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT),
+    mTimestampBase(TIMESTAMP_BASE_DEFAULT) { }
 
 status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const {
 
@@ -290,6 +304,9 @@
     err = parcel->writeInt32(mStreamUseCase);
     if (err != OK) return err;
 
+    err = parcel->writeInt32(mTimestampBase);
+    if (err != OK) return err;
+
     return OK;
 }
 
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index f1cb6bd..9a91cc0 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -38,6 +38,14 @@
         SURFACE_TYPE_SURFACE_VIEW = 0,
         SURFACE_TYPE_SURFACE_TEXTURE = 1
     };
+    enum TimestampBaseByte {
+        TIMESTAMP_BASE_DEFAULT = 0,
+        TIMESTAMP_BASE_SENSOR = 1,
+        TIMESTAMP_BASE_MONOTONIC = 2,
+        TIMESTAMP_BASE_REALTIME = 3,
+        TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED = 4
+    };
+
     const std::vector<sp<IGraphicBufferProducer>>& getGraphicBufferProducers() const;
     int                        getRotation() const;
     int                        getSurfaceSetID() const;
@@ -50,6 +58,7 @@
     String16                   getPhysicalCameraId() const;
     bool                       isMultiResolution() const;
     int                        getStreamUseCase() const;
+    int                        getTimestampBase() const;
 
     // set of sensor pixel mode resolutions allowed {MAX_RESOLUTION, DEFAULT_MODE};
     const std::vector<int32_t>&            getSensorPixelModesUsed() const;
@@ -93,7 +102,8 @@
                 mIsMultiResolution == other.mIsMultiResolution &&
                 sensorPixelModesUsedEqual(other) &&
                 mDynamicRangeProfile == other.mDynamicRangeProfile &&
-                mStreamUseCase == other.mStreamUseCase );
+                mStreamUseCase == other.mStreamUseCase &&
+                mTimestampBase == other.mTimestampBase);
     }
     bool operator != (const OutputConfiguration& other) const {
         return !(*this == other);
@@ -136,6 +146,9 @@
         if (mStreamUseCase != other.mStreamUseCase) {
             return mStreamUseCase < other.mStreamUseCase;
         }
+        if (mTimestampBase != other.mTimestampBase) {
+            return mTimestampBase < other.mTimestampBase;
+        }
         return gbpsLessThan(other);
     }
 
@@ -162,6 +175,7 @@
     std::vector<int32_t>       mSensorPixelModesUsed;
     int                        mDynamicRangeProfile;
     int                        mStreamUseCase;
+    int                        mTimestampBase;
 };
 } // namespace params
 } // namespace camera2
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index eee7f7e..7b273ec 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -61,8 +61,7 @@
 status_t AudioEffect::set(const effect_uuid_t *type,
                 const effect_uuid_t *uuid,
                 int32_t priority,
-                effect_callback_t cbf,
-                void* user,
+                const wp<IAudioEffectCallback>& callback,
                 audio_session_t sessionId,
                 audio_io_handle_t io,
                 const AudioDeviceTypeAddr& device,
@@ -73,7 +72,7 @@
     sp<IMemory> cblk;
     int enabled;
 
-    ALOGV("set %p mUserData: %p uuid: %p timeLow %08x", this, user, type, type ? type->timeLow : 0);
+    ALOGV("set %p uuid: %p timeLow %08x", this, type, type ? type->timeLow : 0);
 
     if (mIEffect != 0) {
         ALOGW("Effect already in use");
@@ -96,9 +95,8 @@
     }
     mProbe = probe;
     mPriority = priority;
-    mCbf = cbf;
-    mUserData = user;
     mSessionId = sessionId;
+    mCallback = callback;
 
     memset(&mDescriptor, 0, sizeof(effect_descriptor_t));
     mDescriptor.type = *(type != NULL ? type : EFFECT_UUID_NULL);
@@ -187,11 +185,60 @@
     return mStatus;
 }
 
+namespace {
+class LegacyCallbackWrapper : public AudioEffect::IAudioEffectCallback {
+ public:
+    LegacyCallbackWrapper(AudioEffect::legacy_callback_t callback, void* user):
+            mCallback(callback), mUser(user) {}
+ private:
+    void onControlStatusChanged(bool isGranted) override {
+        mCallback(AudioEffect::EVENT_CONTROL_STATUS_CHANGED, mUser, &isGranted);
+    }
+
+    void onEnableStatusChanged(bool isEnabled) override {
+        mCallback(AudioEffect::EVENT_ENABLE_STATUS_CHANGED, mUser, &isEnabled);
+    }
+
+    void onParameterChanged(std::vector<uint8_t> param) override {
+        mCallback(AudioEffect::EVENT_PARAMETER_CHANGED, mUser, param.data());
+    }
+
+    void onError(status_t errorCode) override {
+        mCallback(AudioEffect::EVENT_ERROR, mUser, &errorCode);
+    }
+
+    void onFramesProcessed(int32_t framesProcessed) override {
+        mCallback(AudioEffect::EVENT_FRAMES_PROCESSED, mUser, &framesProcessed);
+    }
+
+    const AudioEffect::legacy_callback_t mCallback;
+    void* const mUser;
+};
+} // namespace
+
+status_t AudioEffect::set(const effect_uuid_t *type,
+                const effect_uuid_t *uuid,
+                int32_t priority,
+                legacy_callback_t cbf,
+                void* user,
+                audio_session_t sessionId,
+                audio_io_handle_t io,
+                const AudioDeviceTypeAddr& device,
+                bool probe,
+                bool notifyFramesProcessed)
+{
+    if (cbf != nullptr) {
+        mLegacyWrapper = sp<LegacyCallbackWrapper>::make(cbf, user);
+    } else if (user != nullptr) {
+        LOG_ALWAYS_FATAL("%s: User provided without callback", __func__);
+    }
+    return set(type, uuid, priority, mLegacyWrapper, sessionId, io, device, probe,
+               notifyFramesProcessed);
+}
 status_t AudioEffect::set(const char *typeStr,
                 const char *uuidStr,
                 int32_t priority,
-                effect_callback_t cbf,
-                void* user,
+                const wp<IAudioEffectCallback>& callback,
                 audio_session_t sessionId,
                 audio_io_handle_t io,
                 const AudioDeviceTypeAddr& device,
@@ -213,11 +260,29 @@
         pUuid = &uuid;
     }
 
-    return set(pType, pUuid, priority, cbf, user, sessionId, io,
+    return set(pType, pUuid, priority, callback, sessionId, io,
                device, probe, notifyFramesProcessed);
 }
 
-
+status_t AudioEffect::set(const char *typeStr,
+                const char *uuidStr,
+                int32_t priority,
+                legacy_callback_t cbf,
+                void* user,
+                audio_session_t sessionId,
+                audio_io_handle_t io,
+                const AudioDeviceTypeAddr& device,
+                bool probe,
+                bool notifyFramesProcessed)
+{
+    if (cbf != nullptr) {
+        mLegacyWrapper = sp<LegacyCallbackWrapper>::make(cbf, user);
+    } else if (user != nullptr) {
+        LOG_ALWAYS_FATAL("%s: User provided without callback", __func__);
+    }
+    return set(typeStr, uuidStr, priority, mLegacyWrapper, sessionId, io, device, probe,
+               notifyFramesProcessed);
+}
 AudioEffect::~AudioEffect()
 {
     ALOGV("Destructor %p", this);
@@ -471,9 +536,9 @@
 {
     ALOGW("IEffect died");
     mStatus = DEAD_OBJECT;
-    if (mCbf != NULL) {
-        status_t status = DEAD_OBJECT;
-        mCbf(EVENT_ERROR, mUserData, &status);
+    auto cb = mCallback.promote();
+    if (cb != nullptr) {
+        cb->onError(mStatus);
     }
     mIEffect.clear();
 }
@@ -482,8 +547,8 @@
 
 void AudioEffect::controlStatusChanged(bool controlGranted)
 {
-    ALOGV("controlStatusChanged %p control %d callback %p mUserData %p", this, controlGranted, mCbf,
-            mUserData);
+    auto cb = mCallback.promote();
+    ALOGV("controlStatusChanged %p control %d callback %p", this, controlGranted, cb.get());
     if (controlGranted) {
         if (mStatus == ALREADY_EXISTS) {
             mStatus = NO_ERROR;
@@ -493,18 +558,19 @@
             mStatus = ALREADY_EXISTS;
         }
     }
-    if (mCbf != NULL) {
-        mCbf(EVENT_CONTROL_STATUS_CHANGED, mUserData, &controlGranted);
+    if (cb != nullptr) {
+        cb->onControlStatusChanged(controlGranted);
     }
 }
 
 void AudioEffect::enableStatusChanged(bool enabled)
 {
-    ALOGV("enableStatusChanged %p enabled %d mCbf %p", this, enabled, mCbf);
+    auto cb = mCallback.promote();
+    ALOGV("enableStatusChanged %p enabled %d mCallback %p", this, enabled, cb.get());
     if (mStatus == ALREADY_EXISTS) {
         mEnabled = enabled;
-        if (mCbf != NULL) {
-            mCbf(EVENT_ENABLE_STATUS_CHANGED, mUserData, &enabled);
+        if (cb != nullptr) {
+            cb->onEnableStatusChanged(enabled);
         }
     }
 }
@@ -516,19 +582,20 @@
     if (cmdData.empty() || replyData.empty()) {
         return;
     }
-
-    if (mCbf != NULL && cmdCode == EFFECT_CMD_SET_PARAM) {
+    auto cb = mCallback.promote();
+    if (cb != nullptr && cmdCode == EFFECT_CMD_SET_PARAM) {
         std::vector<uint8_t> cmdDataCopy(cmdData);
         effect_param_t* cmd = reinterpret_cast<effect_param_t *>(cmdDataCopy.data());
         cmd->status = *reinterpret_cast<const int32_t *>(replyData.data());
-        mCbf(EVENT_PARAMETER_CHANGED, mUserData, cmd);
+        cb->onParameterChanged(std::move(cmdDataCopy));
     }
 }
 
 void AudioEffect::framesProcessed(int32_t frames)
 {
-    if (mCbf != NULL) {
-        mCbf(EVENT_FRAMES_PROCESSED, mUserData, &frames);
+    auto cb = mCallback.promote();
+    if (cb != nullptr) {
+        cb->onFramesProcessed(frames);
     }
 }
 
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index de14e1c..4bc61f5 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -537,6 +537,8 @@
         float maxRequiredSpeed,
         audio_port_handle_t selectedDeviceId)
 {
+    LOG_ALWAYS_FATAL_IF(mInitialized, "%s: should not be called twice", __func__);
+    mInitialized = true;
     status_t status;
     uint32_t channelCount;
     pid_t callingPid;
@@ -1591,12 +1593,12 @@
 
 status_t AudioTrack::setMarkerPosition(uint32_t marker)
 {
+    AutoMutex lock(mLock);
     // The only purpose of setting marker position is to get a callback
-    if (!mCallback.promote() || isOffloadedOrDirect()) {
+    if (!mCallback.promote() || isOffloadedOrDirect_l()) {
         return INVALID_OPERATION;
     }
 
-    AutoMutex lock(mLock);
     mMarkerPosition = marker;
     mMarkerReached = false;
 
@@ -1624,12 +1626,12 @@
 
 status_t AudioTrack::setPositionUpdatePeriod(uint32_t updatePeriod)
 {
+    AutoMutex lock(mLock);
     // The only purpose of setting position update period is to get a callback
-    if (!mCallback.promote() || isOffloadedOrDirect()) {
+    if (!mCallback.promote() || isOffloadedOrDirect_l()) {
         return INVALID_OPERATION;
     }
 
-    AutoMutex lock(mLock);
     mNewPosition = updateAndGetPosition_l() + updatePeriod;
     mUpdatePeriod = updatePeriod;
 
diff --git a/media/libaudioclient/include/media/AudioEffect.h b/media/libaudioclient/include/media/AudioEffect.h
index ee262f3..56884a3 100644
--- a/media/libaudioclient/include/media/AudioEffect.h
+++ b/media/libaudioclient/include/media/AudioEffect.h
@@ -277,7 +277,7 @@
     static status_t removeStreamDefaultEffect(audio_unique_id_t id);
 
     /*
-     * Events used by callback function (effect_callback_t).
+     * Events used by callback function (legacy_callback_t).
      */
     enum event_type {
         EVENT_CONTROL_STATUS_CHANGED = 0,
@@ -287,6 +287,47 @@
         EVENT_FRAMES_PROCESSED = 4,
     };
 
+    class IAudioEffectCallback : public virtual RefBase {
+        friend AudioEffect;
+     protected:
+        /* The event is received when an application loses or
+         * gains the control of the effect engine. Loss of control happens
+         * if another application requests the use of the engine by creating an AudioEffect for
+         * the same effect type but with a higher priority. Control is returned when the
+         * application having the control deletes its AudioEffect object.
+         * @param isGranted: True if control has been granted. False if stolen.
+         */
+        virtual void onControlStatusChanged([[maybe_unused]] bool isGranted) {}
+
+        /* The event is received by all applications not having the
+         * control of the effect engine when the effect is enabled or disabled.
+         * @param isEnabled: True if enabled. False if disabled.
+         */
+        virtual void onEnableStatusChanged([[maybe_unused]] bool isEnabled) {}
+
+        /* The event is received by all applications not having the
+         * control of the effect engine when an effect parameter is changed.
+         * @param param: A vector containing the raw bytes of a effect_param_type containing
+         *   raw data representing a param type, value pair.
+         */
+        // TODO pass an AIDL parcel instead of effect_param_type
+        virtual void onParameterChanged([[maybe_unused]] std::vector<uint8_t> param) {}
+
+        /* The event is received when the binder connection to the mediaserver
+         * is no longer valid. Typically the server has been killed.
+         * @param errorCode: A code representing the type of error.
+         */
+        virtual void onError([[maybe_unused]] status_t errorCode) {}
+
+
+        /* The event is received when the audio server has processed a block of
+         * data.
+         * @param framesProcessed: The number of frames the audio server has
+         *   processed.
+         */
+        virtual void onFramesProcessed([[maybe_unused]] int32_t framesProcessed) {}
+    };
+
     /* Callback function notifying client application of a change in effect engine state or
      * configuration.
      * An effect engine can be shared by several applications but only one has the control
@@ -315,7 +356,7 @@
      *  - EVENT_ERROR:  status_t indicating the error (DEAD_OBJECT when media server dies).
      */
 
-    typedef void (*effect_callback_t)(int32_t event, void* user, void *info);
+    typedef void (*legacy_callback_t)(int32_t event, void* user, void *info);
 
 
     /* Constructor.
@@ -360,7 +401,7 @@
      * priority:    requested priority for effect control: the priority level corresponds to the
      *      value of priority parameter: negative values indicate lower priorities, positive values
      *      higher priorities, 0 being the normal priority.
-     * cbf:         optional callback function (see effect_callback_t)
+     * cbf:         optional callback function (see legacy_callback_t)
      * user:        pointer to context for use by the callback receiver.
      * sessionId:   audio session this effect is associated to.
      *      If equal to AUDIO_SESSION_OUTPUT_MIX, the effect will be global to
@@ -383,10 +424,20 @@
      *  - NO_INIT: audio flinger or audio hardware not initialized
      */
             status_t    set(const effect_uuid_t *type,
-                            const effect_uuid_t *uuid = NULL,
+                            const effect_uuid_t *uuid = nullptr,
                             int32_t priority = 0,
-                            effect_callback_t cbf = NULL,
-                            void* user = NULL,
+                            const wp<IAudioEffectCallback>& callback = nullptr,
+                            audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
+                            audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
+                            const AudioDeviceTypeAddr& device = {},
+                            bool probe = false,
+                            bool notifyFramesProcessed = false);
+
+            status_t    set(const effect_uuid_t *type,
+                            const effect_uuid_t *uuid,
+                            int32_t priority,
+                            legacy_callback_t cbf,
+                            void* user,
                             audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
                             audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
                             const AudioDeviceTypeAddr& device = {},
@@ -396,10 +447,21 @@
      * Same as above but with type and uuid specified by character strings.
      */
             status_t    set(const char *typeStr,
-                            const char *uuidStr = NULL,
+                            const char *uuidStr = nullptr,
                             int32_t priority = 0,
-                            effect_callback_t cbf = NULL,
-                            void* user = NULL,
+                            const wp<IAudioEffectCallback>& callback = nullptr,
+                            audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
+                            audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
+                            const AudioDeviceTypeAddr& device = {},
+                            bool probe = false,
+                            bool notifyFramesProcessed = false);
+
+
+            status_t    set(const char *typeStr,
+                            const char *uuidStr,
+                            int32_t priority,
+                            legacy_callback_t cbf,
+                            void* user,
                             audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
                             audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
                             const AudioDeviceTypeAddr& device = {},
@@ -535,18 +597,19 @@
 
 protected:
      android::content::AttributionSourceState mClientAttributionSource; // source for app op checks.
-     bool                    mEnabled = false;   // enable state
-     audio_session_t         mSessionId = AUDIO_SESSION_OUTPUT_MIX; // audio session ID
-     int32_t                 mPriority = 0;      // priority for effect control
-     status_t                mStatus = NO_INIT;  // effect status
-     bool                    mProbe = false;     // effect created in probe mode: all commands
-                                                 // are no ops because mIEffect is NULL
-     effect_callback_t       mCbf = nullptr;     // callback function for status, control and
-                                                 // parameter changes notifications
-     void*                   mUserData = nullptr;// client context for callback function
-     effect_descriptor_t     mDescriptor = {};   // effect descriptor
-     int32_t                 mId = -1;           // system wide unique effect engine instance ID
-     Mutex                   mLock;              // Mutex for mEnabled access
+     bool                     mEnabled = false;   // enable state
+     audio_session_t          mSessionId = AUDIO_SESSION_OUTPUT_MIX; // audio session ID
+     int32_t                  mPriority = 0;      // priority for effect control
+     status_t                 mStatus = NO_INIT;  // effect status
+     bool                     mProbe = false;     // effect created in probe mode: all commands
+                                                 // are no ops because mIEffect is nullptr
+
+     wp<IAudioEffectCallback> mCallback = nullptr; // callback interface for status, control and
+                                                   // parameter changes notifications
+     sp<IAudioEffectCallback> mLegacyWrapper = nullptr;
+     effect_descriptor_t      mDescriptor = {};   // effect descriptor
+     int32_t                  mId = -1;           // system wide unique effect engine instance ID
+     Mutex                    mLock;              // Mutex for mEnabled access
 
 
      // IEffectClient
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 16e10b5..153d4b5 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -1348,6 +1348,7 @@
     sp<IAudioTrackCallback> mLegacyCallbackWrapper;      // wrapper for legacy callback interface
     // for notification APIs
 
+    bool                    mInitialized = false;   // Set after track is initialized
     // next 2 fields are const after constructor or set()
     uint32_t                mNotificationFramesReq; // requested number of frames between each
                                                     // notification callback,
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index f50acae..f7bc177 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -178,10 +178,6 @@
         "NdkMediaDataSourceCallbacks.cpp",
     ],
 
-    include_dirs: [
-        "frameworks/av/media/libstagefright/include",
-        "frameworks/av/media/ndk/include",
-    ],
 
     export_include_dirs: [
         "include",
@@ -194,6 +190,7 @@
     ],
 
     header_libs: [
+        "libstagefright_headers",
         "libmedia_headers",
     ],
 
@@ -224,6 +221,7 @@
         "libcutils",
         "android.hardware.graphics.bufferqueue@1.0",
     ],
+
     header_libs: [
         "libstagefright_foundation_headers",
     ],
@@ -231,9 +229,6 @@
     cflags: [
         "-D__ANDROID_VNDK__",
     ],
-    include_dirs: [
-        "frameworks/av/media/ndk/",
-    ],
 }
 
 cc_library_static {
diff --git a/media/ndk/NdkMediaCodec.cpp b/media/ndk/NdkMediaCodec.cpp
index 0e2de4e..227459a 100644
--- a/media/ndk/NdkMediaCodec.cpp
+++ b/media/ndk/NdkMediaCodec.cpp
@@ -158,8 +158,7 @@
                      }
 
                      Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
-                     if (mCodec->mAsyncCallbackUserData != NULL
-                         || mCodec->mAsyncCallback.onAsyncInputAvailable != NULL) {
+                     if (mCodec->mAsyncCallback.onAsyncInputAvailable != NULL) {
                          mCodec->mAsyncCallback.onAsyncInputAvailable(
                                  mCodec,
                                  mCodec->mAsyncCallbackUserData,
@@ -205,8 +204,7 @@
                          (uint32_t)flags};
 
                      Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
-                     if (mCodec->mAsyncCallbackUserData != NULL
-                         || mCodec->mAsyncCallback.onAsyncOutputAvailable != NULL) {
+                     if (mCodec->mAsyncCallback.onAsyncOutputAvailable != NULL) {
                          mCodec->mAsyncCallback.onAsyncOutputAvailable(
                                  mCodec,
                                  mCodec->mAsyncCallbackUserData,
@@ -234,8 +232,7 @@
                      AMediaFormat *aMediaFormat = AMediaFormat_fromMsg(&copy);
 
                      Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
-                     if (mCodec->mAsyncCallbackUserData != NULL
-                         || mCodec->mAsyncCallback.onAsyncFormatChanged != NULL) {
+                     if (mCodec->mAsyncCallback.onAsyncFormatChanged != NULL) {
                          mCodec->mAsyncCallback.onAsyncFormatChanged(
                                  mCodec,
                                  mCodec->mAsyncCallbackUserData,
@@ -263,8 +260,7 @@
                            err, actionCode, detail.c_str());
 
                      Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
-                     if (mCodec->mAsyncCallbackUserData != NULL
-                         || mCodec->mAsyncCallback.onAsyncError != NULL) {
+                     if (mCodec->mAsyncCallback.onAsyncError != NULL) {
                          mCodec->mAsyncCallback.onAsyncError(
                                  mCodec,
                                  mCodec->mAsyncCallbackUserData,
@@ -474,16 +470,20 @@
         AMediaCodec *mData,
         AMediaCodecOnAsyncNotifyCallback callback,
         void *userdata) {
-    if (mData->mAsyncNotify == NULL && userdata != NULL) {
-        mData->mAsyncNotify = new AMessage(kWhatAsyncNotify, mData->mHandler);
-        status_t err = mData->mCodec->setCallback(mData->mAsyncNotify);
-        if (err != OK) {
-            ALOGE("setAsyncNotifyCallback: err(%d), failed to set async callback", err);
-            return translate_error(err);
-        }
-    }
 
     Mutex::Autolock _l(mData->mAsyncCallbackLock);
+
+    if (mData->mAsyncNotify == NULL) {
+        mData->mAsyncNotify = new AMessage(kWhatAsyncNotify, mData->mHandler);
+    }
+
+    // always call, codec may have been reset/re-configured since last call.
+    status_t err = mData->mCodec->setCallback(mData->mAsyncNotify);
+    if (err != OK) {
+        ALOGE("setAsyncNotifyCallback: err(%d), failed to set async callback", err);
+        return translate_error(err);
+    }
+
     mData->mAsyncCallback = callback;
     mData->mAsyncCallbackUserData = userdata;
 
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 11fa991..d26b730 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -861,6 +861,7 @@
     bool isMultiResolution = outputConfiguration.isMultiResolution();
     int dynamicRangeProfile = outputConfiguration.getDynamicRangeProfile();
     int streamUseCase = outputConfiguration.getStreamUseCase();
+    int timestampBase = outputConfiguration.getTimestampBase();
 
     res = SessionConfigurationUtils::checkSurfaceType(numBufferProducers, deferredConsumer,
             outputConfiguration.getSurfaceType());
@@ -905,7 +906,7 @@
         res = SessionConfigurationUtils::createSurfaceFromGbp(streamInfo,
                 isStreamInfoValid, surface, bufferProducer, mCameraIdStr,
                 mDevice->infoPhysical(physicalCameraId), sensorPixelModesUsed, dynamicRangeProfile,
-                streamUseCase);
+                streamUseCase, timestampBase);
 
         if (!res.isOk())
             return res;
@@ -951,7 +952,8 @@
                 static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
                 &streamId, physicalCameraId, streamInfo.sensorPixelModesUsed, &surfaceIds,
                 outputConfiguration.getSurfaceSetID(), isShared, isMultiResolution,
-                /*consumerUsage*/0, streamInfo.dynamicRangeProfile, streamInfo.streamUseCase);
+                /*consumerUsage*/0, streamInfo.dynamicRangeProfile, streamInfo.streamUseCase,
+                streamInfo.timestampBase);
     }
 
     if (err != OK) {
@@ -1062,7 +1064,8 @@
                 std::forward_as_tuple(width, height, format, dataSpace, consumerUsage,
                         overriddenSensorPixelModesUsed,
                         outputConfiguration.getDynamicRangeProfile(),
-                        outputConfiguration.getStreamUseCase()));
+                        outputConfiguration.getStreamUseCase(),
+                        outputConfiguration.getTimestampBase()));
 
         ALOGV("%s: Camera %s: Successfully created a new stream ID %d for a deferred surface"
                 " (%d x %d) stream with format 0x%x.",
@@ -1251,7 +1254,7 @@
     const std::vector<int32_t> &sensorPixelModesUsed =
             outputConfiguration.getSensorPixelModesUsed();
     int streamUseCase = outputConfiguration.getStreamUseCase();
-
+    int timestampBase = outputConfiguration.getTimestampBase();
     int dynamicRangeProfile = outputConfiguration.getDynamicRangeProfile();
 
     for (size_t i = 0; i < newOutputsMap.size(); i++) {
@@ -1260,7 +1263,7 @@
         res = SessionConfigurationUtils::createSurfaceFromGbp(outInfo,
                 /*isStreamInfoValid*/ false, surface, newOutputsMap.valueAt(i), mCameraIdStr,
                 mDevice->infoPhysical(physicalCameraId), sensorPixelModesUsed, dynamicRangeProfile,
-                streamUseCase);
+                streamUseCase, timestampBase);
         if (!res.isOk())
             return res;
 
@@ -1619,6 +1622,7 @@
             outputConfiguration.getSensorPixelModesUsed();
     int dynamicRangeProfile = outputConfiguration.getDynamicRangeProfile();
     int streamUseCase= outputConfiguration.getStreamUseCase();
+    int timestampBase = outputConfiguration.getTimestampBase();
     for (auto& bufferProducer : bufferProducers) {
         // Don't create multiple streams for the same target surface
         ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer));
@@ -1632,7 +1636,7 @@
         res = SessionConfigurationUtils::createSurfaceFromGbp(mStreamInfoMap[streamId],
                 true /*isStreamInfoValid*/, surface, bufferProducer, mCameraIdStr,
                 mDevice->infoPhysical(physicalId), sensorPixelModesUsed, dynamicRangeProfile,
-                streamUseCase);
+                streamUseCase, timestampBase);
 
         if (!res.isOk())
             return res;
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 6ddf500..baa21f0 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -184,7 +184,8 @@
             bool isShared = false, bool isMultiResolution = false,
             uint64_t consumerUsage = 0,
             int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
-            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) = 0;
+            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT) = 0;
 
     /**
      * Create an output stream of the requested size, format, rotation and
@@ -203,7 +204,8 @@
             bool isShared = false, bool isMultiResolution = false,
             uint64_t consumerUsage = 0,
             int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
-            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) = 0;
+            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT) = 0;
 
     /**
      * Create an input stream of width, height, and format.
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index c8f6310..f31241c 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -86,6 +86,7 @@
         mStatusWaiters(0),
         mUsePartialResult(false),
         mNumPartialResults(1),
+        mDeviceTimeBaseIsRealtime(false),
         mTimestampOffset(0),
         mNextResultFrameNumber(0),
         mNextReprocessResultFrameNumber(0),
@@ -189,11 +190,12 @@
     mIsInputStreamMultiResolution = false;
 
     // Measure the clock domain offset between camera and video/hw_composer
+    mTimestampOffset = getMonoToBoottimeOffset();
     camera_metadata_entry timestampSource =
             mDeviceInfo.find(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE);
     if (timestampSource.count > 0 && timestampSource.data.u8[0] ==
             ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME) {
-        mTimestampOffset = getMonoToBoottimeOffset();
+        mDeviceTimeBaseIsRealtime = true;
     }
 
     // Will the HAL be sending in early partial result metadata?
@@ -978,7 +980,7 @@
             const String8& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
-            uint64_t consumerUsage, int dynamicRangeProfile, int streamUseCase) {
+            uint64_t consumerUsage, int dynamicRangeProfile, int streamUseCase, int timestampBase) {
     ATRACE_CALL();
 
     if (consumer == nullptr) {
@@ -992,7 +994,7 @@
     return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
             format, dataSpace, rotation, id, physicalCameraId, sensorPixelModesUsed, surfaceIds,
             streamSetId, isShared, isMultiResolution, consumerUsage, dynamicRangeProfile,
-            streamUseCase);
+            streamUseCase, timestampBase);
 }
 
 static bool isRawFormat(int format) {
@@ -1012,16 +1014,18 @@
         android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
         const String8& physicalCameraId, const std::unordered_set<int32_t> &sensorPixelModesUsed,
         std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
-        uint64_t consumerUsage, int dynamicRangeProfile, int streamUseCase) {
+        uint64_t consumerUsage, int dynamicRangeProfile, int streamUseCase, int timestampBase) {
     ATRACE_CALL();
 
     Mutex::Autolock il(mInterfaceLock);
     nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
     Mutex::Autolock l(mLock);
     ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
-            " consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s, isMultiResolution %d",
+            " consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s, isMultiResolution %d"
+            " dynamicRangeProfile %d, streamUseCase %d, timestampBase %d",
             mId.string(), mNextStreamId, width, height, format, dataSpace, rotation,
-            consumerUsage, isShared, physicalCameraId.string(), isMultiResolution);
+            consumerUsage, isShared, physicalCameraId.string(), isMultiResolution,
+            dynamicRangeProfile, streamUseCase, timestampBase);
 
     status_t res;
     bool wasActive = false;
@@ -1090,7 +1094,8 @@
         newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
                 width, height, blobBufferSize, format, dataSpace, rotation,
                 mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
-                isMultiResolution, dynamicRangeProfile, streamUseCase);
+                isMultiResolution, dynamicRangeProfile, streamUseCase, mDeviceTimeBaseIsRealtime,
+                timestampBase);
     } else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
         bool maxResolution =
                 sensorPixelModesUsed.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
@@ -1104,22 +1109,26 @@
         newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
                 width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
                 mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
-                isMultiResolution, dynamicRangeProfile, streamUseCase);
+                isMultiResolution, dynamicRangeProfile, streamUseCase, mDeviceTimeBaseIsRealtime,
+                timestampBase);
     } else if (isShared) {
         newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
                 width, height, format, consumerUsage, dataSpace, rotation,
                 mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
-                mUseHalBufManager, dynamicRangeProfile, streamUseCase);
+                mUseHalBufManager, dynamicRangeProfile, streamUseCase, mDeviceTimeBaseIsRealtime,
+                timestampBase);
     } else if (consumers.size() == 0 && hasDeferredConsumer) {
         newStream = new Camera3OutputStream(mNextStreamId,
                 width, height, format, consumerUsage, dataSpace, rotation,
                 mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
-                isMultiResolution, dynamicRangeProfile, streamUseCase);
+                isMultiResolution, dynamicRangeProfile, streamUseCase, mDeviceTimeBaseIsRealtime,
+                timestampBase);
     } else {
         newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
                 width, height, format, dataSpace, rotation,
                 mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
-                isMultiResolution, dynamicRangeProfile, streamUseCase);
+                isMultiResolution, dynamicRangeProfile, streamUseCase, mDeviceTimeBaseIsRealtime,
+                timestampBase);
     }
 
     size_t consumerCount = consumers.size();
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index d466ae4..0f5e65b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -135,7 +135,8 @@
             uint64_t consumerUsage = 0,
             int dynamicRangeProfile =
             ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
-            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) override;
+            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT) override;
 
     status_t createStream(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
@@ -148,7 +149,8 @@
             uint64_t consumerUsage = 0,
             int dynamicRangeProfile =
             ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
-            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) override;
+            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT) override;
 
     status_t createInputStream(
             uint32_t width, uint32_t height, int format, bool isMultiResolution,
@@ -526,6 +528,7 @@
 
     /**** End scope for mLock ****/
 
+    bool                       mDeviceTimeBaseIsRealtime;
     // The offset converting from clock domain of other subsystem
     // (video/hardware composer) to that of camera. Assumption is that this
     // offset won't change during the life cycle of the camera device. In other
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index dc3a6f3..f737ed6 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -34,11 +34,12 @@
         android_dataspace dataSpace, camera_stream_rotation_t rotation,
         const String8& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
-        int setId, bool isMultiResolution, int dynamicRangeProfile, int streamUseCase) :
+        int setId, bool isMultiResolution, int dynamicRangeProfile, int streamUseCase,
+        bool deviceTimeBaseIsRealtime, int timestampBase) :
         Camera3Stream(id, type,
                 width, height, maxSize, format, dataSpace, rotation,
                 physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
-                dynamicRangeProfile, streamUseCase),
+                dynamicRangeProfile, streamUseCase, deviceTimeBaseIsRealtime, timestampBase),
         mTotalBufferCount(0),
         mHandoutTotalBufferCount(0),
         mHandoutOutputBufferCount(0),
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index f2b1536..300f207 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -39,7 +39,9 @@
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
             int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
-            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
+            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+            bool deviceTimeBaseIsRealtime = false,
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
 
   public:
 
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 95d19ec..a82d19b 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -47,11 +47,12 @@
         nsecs_t timestampOffset, const String8& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
         int setId, bool isMultiResolution, int dynamicRangeProfile,
-        int streamUseCase) :
+        int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase) :
         Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
                             /*maxSize*/0, format, dataSpace, rotation,
                             physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
-                            dynamicRangeProfile, streamUseCase),
+                            dynamicRangeProfile, streamUseCase, deviceTimeBaseIsRealtime,
+                            timestampBase),
         mConsumer(consumer),
         mTransform(0),
         mTraceFirstBuffer(true),
@@ -77,14 +78,14 @@
         nsecs_t timestampOffset, const String8& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
         int setId, bool isMultiResolution, int dynamicRangeProfile,
-        int streamUseCase) :
+        int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase) :
         Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height, maxSize,
                             format, dataSpace, rotation, physicalCameraId, sensorPixelModesUsed,
-                            setId, isMultiResolution, dynamicRangeProfile, streamUseCase),
+                            setId, isMultiResolution, dynamicRangeProfile, streamUseCase,
+                            deviceTimeBaseIsRealtime, timestampBase),
         mConsumer(consumer),
         mTransform(0),
         mTraceFirstBuffer(true),
-        mUseMonoTimestamp(false),
         mUseBufferManager(false),
         mTimestampOffset(timestampOffset),
         mConsumerUsage(0),
@@ -113,11 +114,12 @@
         const String8& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
         int setId, bool isMultiResolution, int dynamicRangeProfile,
-        int streamUseCase) :
+        int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase) :
         Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
                             /*maxSize*/0, format, dataSpace, rotation,
                             physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
-                            dynamicRangeProfile, streamUseCase),
+                            dynamicRangeProfile, streamUseCase, deviceTimeBaseIsRealtime,
+                            timestampBase),
         mConsumer(nullptr),
         mTransform(0),
         mTraceFirstBuffer(true),
@@ -152,18 +154,19 @@
                                          android_dataspace dataSpace,
                                          camera_stream_rotation_t rotation,
                                          const String8& physicalCameraId,
-                                        const std::unordered_set<int32_t> &sensorPixelModesUsed,
+                                         const std::unordered_set<int32_t> &sensorPixelModesUsed,
                                          uint64_t consumerUsage, nsecs_t timestampOffset,
                                          int setId, bool isMultiResolution,
-                                         int dynamicRangeProfile, int streamUseCase) :
+                                         int dynamicRangeProfile, int streamUseCase,
+                                         bool deviceTimeBaseIsRealtime, int timestampBase) :
         Camera3IOStreamBase(id, type, width, height,
                             /*maxSize*/0,
                             format, dataSpace, rotation,
                             physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
-                            dynamicRangeProfile, streamUseCase),
+                            dynamicRangeProfile, streamUseCase, deviceTimeBaseIsRealtime,
+                            timestampBase),
         mTransform(0),
         mTraceFirstBuffer(true),
-        mUseMonoTimestamp(false),
         mUseBufferManager(false),
         mTimestampOffset(timestampOffset),
         mConsumerUsage(consumerUsage),
@@ -365,13 +368,10 @@
             dumpImageToDisk(timestamp, anwBuffer, anwReleaseFence);
         }
 
-        /* Certain consumers (such as AudioSource or HardwareComposer) use
-         * MONOTONIC time, causing time misalignment if camera timestamp is
-         * in BOOTTIME. Do the conversion if necessary. */
         nsecs_t t = mPreviewFrameScheduler != nullptr ? readoutTimestamp : timestamp;
-        nsecs_t adjustedTs = mUseMonoTimestamp ? t - mTimestampOffset : t;
+        t -= mTimestampOffset;
         if (mPreviewFrameScheduler != nullptr) {
-            res = mPreviewFrameScheduler->queuePreviewBuffer(adjustedTs, transform,
+            res = mPreviewFrameScheduler->queuePreviewBuffer(t, transform,
                     anwBuffer, anwReleaseFence);
             if (res != OK) {
                 ALOGE("%s: Stream %d: Error queuing buffer to preview buffer scheduler: %s (%d)",
@@ -380,7 +380,7 @@
             }
         } else {
             setTransform(transform);
-            res = native_window_set_buffers_timestamp(mConsumer.get(), adjustedTs);
+            res = native_window_set_buffers_timestamp(mConsumer.get(), t);
             if (res != OK) {
                 ALOGE("%s: Stream %d: Error setting timestamp: %s (%d)",
                       __FUNCTION__, mId, strerror(-res), res);
@@ -572,10 +572,18 @@
     }
 
     mTotalBufferCount = maxConsumerBuffers + camera_stream::max_buffers;
-    if (allowPreviewScheduler && isConsumedByHWComposer()) {
+
+    int timestampBase = getTimestampBase();
+    bool isDefaultTimeBase = (timestampBase ==
+            OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
+    if (allowPreviewScheduler)  {
         // We cannot distinguish between a SurfaceView and an ImageReader of
         // preview buffer format. The PreviewFrameScheduler needs to handle both.
-        if (!property_get_bool("camera.disable_preview_scheduler", false)) {
+        bool forceChoreographer = (timestampBase ==
+                OutputConfiguration::TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED);
+        bool defaultToChoreographer = (isDefaultTimeBase && isConsumedByHWComposer() &&
+                !property_get_bool("camera.disable_preview_scheduler", false));
+        if (forceChoreographer || defaultToChoreographer) {
             mPreviewFrameScheduler = std::make_unique<PreviewFrameScheduler>(*this, mConsumer);
             mTotalBufferCount += PreviewFrameScheduler::kQueueDepthWatermark;
         }
@@ -584,7 +592,27 @@
     mHandoutTotalBufferCount = 0;
     mFrameCount = 0;
     mLastTimestamp = 0;
-    mUseMonoTimestamp = (isConsumedByHWComposer() || isVideoStream());
+
+    if (isDeviceTimeBaseRealtime()) {
+        if (isDefaultTimeBase && !isConsumedByHWComposer() && !isVideoStream()) {
+            // Default time base, but not hardware composer or video encoder
+            mTimestampOffset = 0;
+        } else if (timestampBase == OutputConfiguration::TIMESTAMP_BASE_REALTIME ||
+                timestampBase == OutputConfiguration::TIMESTAMP_BASE_SENSOR) {
+            mTimestampOffset = 0;
+        }
+        // If timestampBase is CHOREOGRAPHER SYNCED or MONOTONIC, leave
+        // timestamp offset as bootTime - monotonicTime.
+    } else {
+        if (timestampBase == OutputConfiguration::TIMESTAMP_BASE_REALTIME) {
+            // Reverse offset for monotonicTime -> bootTime
+            mTimestampOffset = -mTimestampOffset;
+        } else {
+            // If timestampBase is DEFAULT, MONOTONIC, SENSOR, or
+            // CHOREOGRAPHER_SYNCED, timestamp offset is 0.
+            mTimestampOffset = 0;
+        }
+    }
 
     res = native_window_set_buffer_count(mConsumer.get(),
             mTotalBufferCount);
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 7d2d32e..c7910b7 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -91,7 +91,9 @@
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
             int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
-            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
+            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+            bool deviceTimeBaseIsRealtime = false,
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
     /**
      * Set up a stream for formats that have a variable buffer size for the same
      * dimensions, such as compressed JPEG.
@@ -105,7 +107,9 @@
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
             int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
-            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
+            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+            bool deviceTimeBaseIsRealtime = false,
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
     /**
      * Set up a stream with deferred consumer for formats that have 2 dimensions, such as
      * RAW and YUV. The consumer must be set before using this stream for output. A valid
@@ -118,7 +122,9 @@
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
             int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
-            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
+            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+            bool deviceTimeBaseIsRealtime = false,
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
 
     virtual ~Camera3OutputStream();
 
@@ -247,7 +253,9 @@
             uint64_t consumerUsage = 0, nsecs_t timestampOffset = 0,
             int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
             int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
-            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
+            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+            bool deviceTimeBaseIsRealtime = false,
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
 
     /**
      * Note that we release the lock briefly in this function
@@ -289,9 +297,6 @@
     // Name of Surface consumer
     String8           mConsumerName;
 
-    // Whether consumer assumes MONOTONIC timestamp
-    bool mUseMonoTimestamp;
-
     /**
      * GraphicBuffer manager this stream is registered to. Used to replace the buffer
      * allocation/deallocation role of BufferQueue.
@@ -310,7 +315,11 @@
     bool mUseBufferManager;
 
     /**
-     * Timestamp offset for video and hardware composer consumed streams
+     * Offset used to override camera HAL produced timestamps
+     *
+     * The offset is first initialized to bootTime - monotonicTime in
+     * constructor, and may later be updated based on the client's timestampBase
+     * setting.
      */
     nsecs_t mTimestampOffset;
 
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index fbd1e56..047897e 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -34,11 +34,11 @@
         nsecs_t timestampOffset, const String8& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
         int setId, bool useHalBufManager, int dynamicProfile,
-        int streamUseCase) :
+        int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase) :
         Camera3OutputStream(id, CAMERA_STREAM_OUTPUT, width, height,
                             format, dataSpace, rotation, physicalCameraId, sensorPixelModesUsed,
                             consumerUsage, timestampOffset, setId, /*isMultiResolution*/false,
-                            dynamicProfile, streamUseCase),
+                            dynamicProfile, streamUseCase, deviceTimeBaseIsRealtime, timestampBase),
         mUseHalBufManager(useHalBufManager) {
     size_t consumerCount = std::min(surfaces.size(), kMaxOutputs);
     if (surfaces.size() > consumerCount) {
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index 223d52b..dc22c42 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -42,7 +42,9 @@
             int setId = CAMERA3_STREAM_SET_ID_INVALID,
             bool useHalBufManager = false,
             int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
-            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
+            int streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
+            bool deviceTimeBaseIsRealtime = false,
+            int timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
 
     virtual ~Camera3SharedOutputStream();
 
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 6b093b3..3f0299b 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -55,7 +55,7 @@
         const String8& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
         int setId, bool isMultiResolution, int dynamicRangeProfile,
-        int streamUseCase) :
+        int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase) :
     camera_stream(),
     mId(id),
     mSetId(setId),
@@ -80,7 +80,9 @@
     mOriginalDataSpace(dataSpace),
     mPhysicalCameraId(physicalCameraId),
     mLastTimestamp(0),
-    mIsMultiResolution(isMultiResolution) {
+    mIsMultiResolution(isMultiResolution),
+    mDeviceTimeBaseIsRealtime(deviceTimeBaseIsRealtime),
+    mTimestampBase(timestampBase) {
 
     camera_stream::stream_type = type;
     camera_stream::width = width;
@@ -181,6 +183,14 @@
     return camera_stream::use_case;
 }
 
+int Camera3Stream::getTimestampBase() const {
+    return mTimestampBase;
+}
+
+bool Camera3Stream::isDeviceTimeBaseRealtime() const {
+    return mDeviceTimeBaseIsRealtime;
+}
+
 void Camera3Stream::setOfflineProcessingSupport(bool support) {
     mSupportOfflineProcessing = support;
 }
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index ada570b..8232ce0 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -179,6 +179,8 @@
     int               getMaxHalBuffers() const;
     const String8&    physicalCameraId() const;
     int               getStreamUseCase() const;
+    int               getTimestampBase() const;
+    bool              isDeviceTimeBaseRealtime() const;
 
     void              setOfflineProcessingSupport(bool) override;
     bool              getOfflineProcessingSupport() const override;
@@ -507,7 +509,7 @@
             const String8& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             int setId, bool isMultiResolution, int dynamicRangeProfile,
-            int streamUseCase);
+            int streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase);
 
     wp<Camera3StreamBufferFreedListener> mBufferFreedListener;
 
@@ -630,6 +632,9 @@
 
     bool mIsMultiResolution = false;
     bool mSupportOfflineProcessing = false;
+
+    bool mDeviceTimeBaseIsRealtime;
+    int mTimestampBase;
 }; // class Camera3Stream
 
 }; // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index 7b1597b..8962fac 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -19,6 +19,7 @@
 
 #include <utils/RefBase.h>
 
+#include <camera/camera2/OutputConfiguration.h>
 #include <camera/CameraMetadata.h>
 #include "Camera3StreamBufferListener.h"
 #include "Camera3StreamBufferFreedListener.h"
@@ -111,18 +112,20 @@
         std::unordered_set<int32_t> sensorPixelModesUsed;
         int dynamicRangeProfile;
         int streamUseCase;
+        int timestampBase;
         OutputStreamInfo() :
             width(-1), height(-1), format(-1), dataSpace(HAL_DATASPACE_UNKNOWN),
             consumerUsage(0),
             dynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD),
-            streamUseCase(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) {}
+            streamUseCase(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT),
+            timestampBase(OutputConfiguration::TIMESTAMP_BASE_DEFAULT) {}
         OutputStreamInfo(int _width, int _height, int _format, android_dataspace _dataSpace,
                 uint64_t _consumerUsage, const std::unordered_set<int32_t>& _sensorPixelModesUsed,
-                int _dynamicRangeProfile, int _streamUseCase) :
+                int _dynamicRangeProfile, int _streamUseCase, int _timestampBase) :
             width(_width), height(_height), format(_format),
             dataSpace(_dataSpace), consumerUsage(_consumerUsage),
             sensorPixelModesUsed(_sensorPixelModesUsed), dynamicRangeProfile(_dynamicRangeProfile),
-            streamUseCase(_streamUseCase) {}
+            streamUseCase(_streamUseCase), timestampBase(_timestampBase) {}
 };
 
 /**
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index 548fb0b..751f24f 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -334,7 +334,7 @@
         sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
         const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
         const std::vector<int32_t> &sensorPixelModesUsed, int dynamicRangeProfile,
-        int streamUseCase) {
+        int streamUseCase, int timestampBase) {
     // bufferProducer must be non-null
     if (gbp == nullptr) {
         String8 msg = String8::format("Camera %s: Surface is NULL", logicalCameraId.string());
@@ -454,6 +454,13 @@
         ALOGE("%s: %s", __FUNCTION__, msg.string());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
     }
+    if (timestampBase < OutputConfiguration::TIMESTAMP_BASE_DEFAULT ||
+            timestampBase > OutputConfiguration::TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED) {
+        String8 msg = String8::format("Camera %s: invalid timestamp base %d",
+                logicalCameraId.string(), timestampBase);
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
 
     if (!isStreamInfoValid) {
         streamInfo.width = width;
@@ -464,6 +471,7 @@
         streamInfo.sensorPixelModesUsed = overriddenSensorPixelModes;
         streamInfo.dynamicRangeProfile = dynamicRangeProfile;
         streamInfo.streamUseCase = streamUseCase;
+        streamInfo.timestampBase = timestampBase;
         return binder::Status::ok();
     }
     if (width != streamInfo.width) {
@@ -697,6 +705,7 @@
         }
 
         int streamUseCase = it.getStreamUseCase();
+        int timestampBase = it.getTimestampBase();
         if (deferredConsumer) {
             streamInfo.width = it.getWidth();
             streamInfo.height = it.getHeight();
@@ -731,7 +740,7 @@
             sp<Surface> surface;
             res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
                     logicalCameraId, metadataChosen, sensorPixelModesUsed, dynamicRangeProfile,
-                    streamUseCase);
+                    streamUseCase, timestampBase);
 
             if (!res.isOk())
                 return res;
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index 8dfc11d..3dcbdbc 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -98,7 +98,7 @@
         sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
         const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
         const std::vector<int32_t> &sensorPixelModesUsed,  int dynamicRangeProfile,
-        int streamUseCase);
+        int streamUseCase, int timestampBase);
 
 void mapStreamInfo(const camera3::OutputStreamInfo &streamInfo,
         camera3::camera_stream_rotation_t rotation, String8 physicalId, int32_t groupId,
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 2a53ef3..3f18b95 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -188,7 +188,8 @@
           __func__, audioFormat, getDeviceId(), getSessionId());
 
     // Create MMAP/NOIRQ buffer.
-    if (createMmapBuffer(&mAudioDataFileDescriptor) != AAUDIO_OK) {
+    result = createMmapBuffer(&mAudioDataFileDescriptor);
+    if (result != AAUDIO_OK) {
         goto error;
     }
 
diff --git a/services/tuner/TunerFilter.cpp b/services/tuner/TunerFilter.cpp
index fb5bfa3..e8c7767 100644
--- a/services/tuner/TunerFilter.cpp
+++ b/services/tuner/TunerFilter.cpp
@@ -337,6 +337,9 @@
         }
     }
 
+    if (mFilterCallback != nullptr) {
+        mFilterCallback->detachCallbacks();
+    }
     auto res = mFilter->close();
     mFilter = nullptr;
     mStarted = false;
@@ -470,6 +473,12 @@
     }
 }
 
+void TunerFilter::FilterCallback::detachCallbacks() {
+    Mutex::Autolock _l(mCallbackLock);
+    mOriginalCallback = nullptr;
+    mTunerFilterCallback = nullptr;
+}
+
 }  // namespace tuner
 }  // namespace tv
 }  // namespace media
diff --git a/services/tuner/TunerFilter.h b/services/tuner/TunerFilter.h
index 529c191..93d8898 100644
--- a/services/tuner/TunerFilter.h
+++ b/services/tuner/TunerFilter.h
@@ -67,6 +67,7 @@
         void sendSharedFilterStatus(int32_t status);
         void attachSharedFilterCallback(const shared_ptr<ITunerFilterCallback>& in_cb);
         void detachSharedFilterCallback();
+        void detachCallbacks();
 
     private:
         shared_ptr<ITunerFilterCallback> mTunerFilterCallback;
diff --git a/services/tuner/hidl/TunerHidlFilter.cpp b/services/tuner/hidl/TunerHidlFilter.cpp
index a5bbf39..6d8ae03 100644
--- a/services/tuner/hidl/TunerHidlFilter.cpp
+++ b/services/tuner/hidl/TunerHidlFilter.cpp
@@ -510,6 +510,9 @@
         }
     }
 
+    if (mFilterCallback != nullptr) {
+        mFilterCallback->detachCallbacks();
+    }
     HidlResult res = mFilter->close();
     mFilter = nullptr;
     mFilter_1_1 = nullptr;
@@ -970,6 +973,12 @@
     }
 }
 
+void TunerHidlFilter::FilterCallback::detachCallbacks() {
+    Mutex::Autolock _l(mCallbackLock);
+    mOriginalCallback = nullptr;
+    mTunerFilterCallback = nullptr;
+}
+
 /////////////// FilterCallback Helper Methods ///////////////////////
 void TunerHidlFilter::FilterCallback::getAidlFilterEvent(
         const vector<HidlDemuxFilterEvent::Event>& events,
diff --git a/services/tuner/hidl/TunerHidlFilter.h b/services/tuner/hidl/TunerHidlFilter.h
index b8fad22..63c7a1b 100644
--- a/services/tuner/hidl/TunerHidlFilter.h
+++ b/services/tuner/hidl/TunerHidlFilter.h
@@ -129,6 +129,7 @@
         void sendSharedFilterStatus(int32_t status);
         void attachSharedFilterCallback(const shared_ptr<ITunerFilterCallback>& in_cb);
         void detachSharedFilterCallback();
+        void detachCallbacks();
 
     private:
         void getAidlFilterEvent(const vector<HidlDemuxFilterEvent::Event>& events,