Merge "Audio: Support FCC_LIMIT for 22.2 testing" into sc-dev
diff --git a/media/libmediametrics/MediaMetricsItem.cpp b/media/libmediametrics/MediaMetricsItem.cpp
index a8350ea..d597a4d 100644
--- a/media/libmediametrics/MediaMetricsItem.cpp
+++ b/media/libmediametrics/MediaMetricsItem.cpp
@@ -308,6 +308,17 @@
     switch (uid) {
     case AID_RADIO:     // telephony subsystem, RIL
         return false;
+    default:
+        // Some isolated processes can access the audio system; see
+        // AudioSystem::setAudioFlingerBinder (currently only the HotwordDetectionService). Instead
+        // of also allowing access to the MediaMetrics service, it's simpler to just disable it for
+        // now.
+        // TODO(b/190151205): Either allow the HotwordDetectionService to access MediaMetrics or
+        // make this disabling specific to that process.
+        if (uid >= AID_ISOLATED_START && uid <= AID_ISOLATED_END) {
+            return false;
+        }
+        break;
     }
 
     int enabled = property_get_int32(Item::EnabledProperty, -1);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e325dfa..54a6425 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -3996,7 +3996,7 @@
         // if the move request is not received from audio policy manager, the effect must be
         // re-registered with the new strategy and output
         if (dstChain == 0) {
-            dstChain = effect->callback()->chain().promote();
+            dstChain = effect->getCallback()->chain().promote();
             if (dstChain == 0) {
                 ALOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
                 status = NO_INIT;
@@ -4046,7 +4046,7 @@
             goto Exit;
         }
 
-        dstChain = effect->callback()->chain().promote();
+        dstChain = effect->getCallback()->chain().promote();
         if (dstChain == 0) {
             thread->addEffect_l(effect);
             status = INVALID_OPERATION;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index d75b13b..d3492d9 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -152,12 +152,12 @@
     if (fromHandle) {
         if (enabled) {
             if (status != NO_ERROR) {
-                mCallback->checkSuspendOnEffectEnabled(this, false, false /*threadLocked*/);
+                getCallback()->checkSuspendOnEffectEnabled(this, false, false /*threadLocked*/);
             } else {
-                mCallback->onEffectEnable(this);
+                getCallback()->onEffectEnable(this);
             }
         } else {
-            mCallback->onEffectDisable(this);
+            getCallback()->onEffectDisable(this);
         }
     }
     return status;
@@ -247,8 +247,9 @@
             doRegister = true;
             mPolicyRegistered = mHandles.size() > 0;
             if (mPolicyRegistered) {
-                io = mCallback->io();
-                strategy = mCallback->strategy();
+                const auto callback = getCallback();
+                io = callback->io();
+                strategy = callback->strategy();
             }
         }
         // enable effect when registered according to enable state requested by controlling handle
@@ -349,8 +350,9 @@
 // unsafe method called when the effect parent thread has been destroyed
 ssize_t AudioFlinger::EffectBase::disconnectHandle(EffectHandle *handle, bool unpinIfLast)
 {
+    const auto callback = getCallback();
     ALOGV("disconnect() %p handle %p", this, handle);
-    if (mCallback->disconnectEffectHandle(handle, unpinIfLast)) {
+    if (callback->disconnectEffectHandle(handle, unpinIfLast)) {
         return mHandles.size();
     }
 
@@ -358,7 +360,7 @@
     ssize_t numHandles = removeHandle_l(handle);
     if ((numHandles == 0) && (!mPinned || unpinIfLast)) {
         mLock.unlock();
-        mCallback->updateOrphanEffectChains(this);
+        callback->updateOrphanEffectChains(this);
         mLock.lock();
     }
     return numHandles;
@@ -377,7 +379,7 @@
 }
 
 void AudioFlinger::EffectBase::checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) {
-    mCallback->checkSuspendOnEffectEnabled(this, enabled, threadLocked);
+    getCallback()->checkSuspendOnEffectEnabled(this, enabled, threadLocked);
 }
 
 static String8 effectFlagsToString(uint32_t flags) {
@@ -835,7 +837,7 @@
                 mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
         // If an insert effect is idle and input buffer is different from output buffer,
         // accumulate input onto output
-        if (mCallback->activeTrackCnt() != 0) {
+        if (getCallback()->activeTrackCnt() != 0) {
             // similar handling with data_bypass above.
             if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
                 accumulateInputToOutput();
@@ -860,6 +862,7 @@
     status_t status;
     uint32_t size;
     audio_channel_mask_t channelMask;
+    sp<EffectCallbackInterface> callback;
 
     if (mEffectInterface == 0) {
         status = NO_INIT;
@@ -870,7 +873,8 @@
     // TODO: handle configuration of input (record) SW effects above the HAL,
     // similar to output EFFECT_FLAG_TYPE_INSERT/REPLACE,
     // in which case input channel masks should be used here.
-    channelMask = mCallback->channelMask();
+    callback = getCallback();
+    channelMask = callback->channelMask();
     mConfig.inputCfg.channels = channelMask;
     mConfig.outputCfg.channels = channelMask;
 
@@ -899,7 +903,7 @@
 #endif
     }
     if (isHapticGenerator()) {
-        audio_channel_mask_t hapticChannelMask = mCallback->hapticChannelMask();
+        audio_channel_mask_t hapticChannelMask = callback->hapticChannelMask();
         mConfig.inputCfg.channels |= hapticChannelMask;
         mConfig.outputCfg.channels |= hapticChannelMask;
     }
@@ -912,11 +916,11 @@
     mConfig.outputCfg.format = EFFECT_BUFFER_FORMAT;
 
     // Don't use sample rate for thread if effect isn't offloadable.
-    if (mCallback->isOffloadOrDirect() && !isOffloaded()) {
+    if (callback->isOffloadOrDirect() && !isOffloaded()) {
         mConfig.inputCfg.samplingRate = DEFAULT_OUTPUT_SAMPLE_RATE;
         ALOGV("Overriding effect input as 48kHz");
     } else {
-        mConfig.inputCfg.samplingRate = mCallback->sampleRate();
+        mConfig.inputCfg.samplingRate = callback->sampleRate();
     }
     mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
     mConfig.inputCfg.bufferProvider.cookie = NULL;
@@ -942,11 +946,11 @@
     }
     mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
     mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
-    mConfig.inputCfg.buffer.frameCount = mCallback->frameCount();
+    mConfig.inputCfg.buffer.frameCount = callback->frameCount();
     mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
 
     ALOGV("configure() %p chain %p buffer %p framecount %zu",
-          this, mCallback->chain().promote().get(),
+          this, callback->chain().promote().get(),
           mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
 
     status_t cmdStatus;
@@ -962,7 +966,7 @@
 
 #ifdef MULTICHANNEL_EFFECT_CHAIN
     if (status != NO_ERROR &&
-            mCallback->isOutput() &&
+            callback->isOutput() &&
             (mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO
                     || mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO)) {
         // Older effects may require exact STEREO position mask.
@@ -1029,7 +1033,7 @@
             size = sizeof(int);
             *(int32_t *)p->data = VISUALIZER_PARAM_LATENCY;
 
-            uint32_t latency = mCallback->latency();
+            uint32_t latency = callback->latency();
 
             *((int32_t *)p->data + 1)= latency;
             mEffectInterface->command(EFFECT_CMD_SET_PARAM,
@@ -1076,7 +1080,7 @@
 {
     if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
          (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
-        (void)mCallback->addEffectToHal(mEffectInterface);
+        (void)getCallback()->addEffectToHal(mEffectInterface);
     }
 }
 
@@ -1089,7 +1093,7 @@
         status = start_l();
     }
     if (status == NO_ERROR) {
-        mCallback->resetVolume();
+        getCallback()->resetVolume();
     }
     return status;
 }
@@ -1139,7 +1143,7 @@
         // We have the EffectChain and EffectModule lock, permit a reentrant call to setVolume:
         // resetVolume_l --> setVolume_l --> EffectModule::setVolume
         mSetVolumeReentrantTid = gettid();
-        mCallback->resetVolume();
+        getCallback()->resetVolume();
         mSetVolumeReentrantTid = INVALID_PID;
     }
 
@@ -1172,7 +1176,7 @@
 {
     if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
              (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
-        mCallback->removeEffectFromHal(mEffectInterface);
+        getCallback()->removeEffectFromHal(mEffectInterface);
     }
     return NO_ERROR;
 }
@@ -1288,7 +1292,7 @@
 
 bool AudioFlinger::EffectModule::isOffloadedOrDirect() const
 {
-    return mCallback->isOffloadOrDirect();
+    return getCallback()->isOffloadOrDirect();
 }
 
 bool AudioFlinger::EffectModule::isVolumeControlEnabled() const
@@ -1332,7 +1336,7 @@
                 || size > mInConversionBuffer->getSize())) {
             mInConversionBuffer.clear();
             ALOGV("%s: allocating mInConversionBuffer %zu", __func__, size);
-            (void)mCallback->allocateHalBuffer(size, &mInConversionBuffer);
+            (void)getCallback()->allocateHalBuffer(size, &mInConversionBuffer);
         }
         if (mInConversionBuffer != nullptr) {
             mInConversionBuffer->setFrameCount(inFrameCount);
@@ -1376,7 +1380,7 @@
                 || size > mOutConversionBuffer->getSize())) {
             mOutConversionBuffer.clear();
             ALOGV("%s: allocating mOutConversionBuffer %zu", __func__, size);
-            (void)mCallback->allocateHalBuffer(size, &mOutConversionBuffer);
+            (void)getCallback()->allocateHalBuffer(size, &mOutConversionBuffer);
         }
         if (mOutConversionBuffer != nullptr) {
             mOutConversionBuffer->setFrameCount(outFrameCount);
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 9da95bc..661881e 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -138,8 +138,9 @@
                              int32_t __unused,
                              std::vector<uint8_t>* __unused) { return NO_ERROR; };
 
+    // mCallback is atomic so this can be lock-free.
     void setCallback(const sp<EffectCallbackInterface>& callback) { mCallback = callback; }
-    sp<EffectCallbackInterface>&     callback() { return mCallback; }
+    sp<EffectCallbackInterface> getCallback() const { return mCallback.load(); }
 
     status_t addHandle(EffectHandle *handle);
     ssize_t disconnectHandle(EffectHandle *handle, bool unpinIfLast);
@@ -170,7 +171,7 @@
     DISALLOW_COPY_AND_ASSIGN(EffectBase);
 
 mutable Mutex                 mLock;      // mutex for process, commands and handles list protection
-    sp<EffectCallbackInterface> mCallback; // parent effect chain
+    mediautils::atomic_sp<EffectCallbackInterface> mCallback; // parent effect chain
     const int                 mId;        // this instance unique ID
     const audio_session_t     mSessionId; // audio session ID
     const effect_descriptor_t mDescriptor;// effect descriptor received from effect engine
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 5e2b4e7..f62082e 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1638,7 +1638,7 @@
         detachAuxEffect_l(effect->id());
     }
 
-    sp<EffectChain> chain = effect->callback()->chain().promote();
+    sp<EffectChain> chain = effect->getCallback()->chain().promote();
     if (chain != 0) {
         // remove effect chain if removing last effect
         if (chain->removeEffect_l(effect, release) == 0) {
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 83d2bc9..9c7b506 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -131,6 +131,8 @@
         "android.permission.CAMERA_OPEN_CLOSE_LISTENER");
 static const String16
         sCameraInjectExternalCameraPermission("android.permission.CAMERA_INJECT_EXTERNAL_CAMERA");
+static int sMemFd = -1;
+const char *sFileName = "lastOpenSessionDumpFile";
 
 static constexpr int32_t kVendorClientScore = resource_policy::PERCEPTIBLE_APP_ADJ;
 static constexpr int32_t kVendorClientState = ActivityManager::PROCESS_STATE_PERSISTENT_UI;
@@ -148,6 +150,11 @@
         mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE) {
     ALOGI("CameraService started (pid=%d)", getpid());
     mServiceLockWrapper = std::make_shared<WaitableMutexWrapper>(&mServiceLock);
+
+    sMemFd = memfd_create(sFileName, MFD_ALLOW_SEALING);
+    if (sMemFd == -1) {
+        ALOGE("%s:Error while creating the file:%s", __FUNCTION__, sFileName);
+    }
 }
 
 void CameraService::onFirstRef()
@@ -1637,6 +1644,21 @@
     }
 
     *device = client;
+
+    Mutex::Autolock lock(mServiceLock);
+
+    // Clear the previous cached logs and reposition the
+    // file offset to beginning of the file to log new data.
+    // If either truncate or lseek fails, close the previous file and create a new one.
+    if ((ftruncate(sMemFd, 0) == -1) || (lseek(sMemFd, 0, SEEK_SET) == -1)) {
+        ALOGE("%s: Error while truncating the file:%s", __FUNCTION__, sFileName);
+        // Close the previous memfd.
+        close(sMemFd);
+        // If failure to wipe the data, then create a new file and
+        // assign the new value to sMemFd.
+        sMemFd = memfd_create(sFileName, MFD_ALLOW_SEALING);
+    }
+
     return ret;
 }
 
@@ -3832,6 +3854,27 @@
     return locked;
 }
 
+void CameraService::cacheDump() {
+    const Vector<String16>& args = Vector<String16>();
+    ATRACE_CALL();
+
+    Mutex::Autolock lock(mServiceLock);
+
+    Mutex::Autolock l(mCameraStatesLock);
+
+    // Start collecting the info for open sessions and store it in temp file.
+    for (const auto& state : mCameraStates) {
+        String8 cameraId = state.first;
+
+        auto clientDescriptor = mActiveClientManager.get(cameraId);
+        if (clientDescriptor != nullptr) {
+           dprintf(sMemFd, "== Camera device %s dynamic info: ==\n", cameraId.string());
+           // Log the current open session info before device is disconnected.
+           dumpOpenSessionClientLogs(sMemFd, args, cameraId);
+        }
+    }
+}
+
 status_t CameraService::dump(int fd, const Vector<String16>& args) {
     ATRACE_CALL();
 
@@ -3898,21 +3941,10 @@
 
         auto clientDescriptor = mActiveClientManager.get(cameraId);
         if (clientDescriptor != nullptr) {
-            dprintf(fd, "  Device %s is open. Client instance dump:\n",
-                    cameraId.string());
-            dprintf(fd, "    Client priority score: %d state: %d\n",
-                    clientDescriptor->getPriority().getScore(),
-                    clientDescriptor->getPriority().getState());
-            dprintf(fd, "    Client PID: %d\n", clientDescriptor->getOwnerId());
-
-            auto client = clientDescriptor->getValue();
-            dprintf(fd, "    Client package: %s\n",
-                    String8(client->getPackageName()).string());
-
-            client->dumpClient(fd, args);
+            // log the current open session info
+            dumpOpenSessionClientLogs(fd, args, cameraId);
         } else {
-            dprintf(fd, "  Device %s is closed, no client instance\n",
-                    cameraId.string());
+            dumpClosedSessionClientLogs(fd, cameraId);
         }
 
     }
@@ -3969,9 +4001,53 @@
             }
         }
     }
+
+    Mutex::Autolock lock(mServiceLock);
+
+    // Dump info from previous open sessions.
+    // Reposition the offset to beginning of the file before reading
+
+    if ((sMemFd >= 0) && (lseek(sMemFd, 0, SEEK_SET) != -1)) {
+        dprintf(fd, "\n**********Dumpsys from previous open session**********\n");
+        ssize_t size_read;
+        char buf[4096];
+        while ((size_read = read(sMemFd, buf, (sizeof(buf) - 1))) > 0) {
+            // Read data from file to a small buffer and write it to fd.
+            write(fd, buf, size_read);
+            if (size_read == -1){
+                ALOGE("%s: Error during reading the file:%s", __FUNCTION__, sFileName);
+                break;
+            }
+        }
+        dprintf(fd, "\n**********End of Dumpsys from previous open session**********\n");
+    } else {
+        ALOGE("%s: Error during reading the file:%s", __FUNCTION__, sFileName);
+    }
     return NO_ERROR;
 }
 
+void CameraService::dumpOpenSessionClientLogs(int fd,
+        const Vector<String16>& args, const String8& cameraId) {
+    auto clientDescriptor = mActiveClientManager.get(cameraId);
+    dprintf(fd, "  Device %s is open. Client instance dump:\n",
+        cameraId.string());
+    dprintf(fd, "    Client priority score: %d state: %d\n",
+        clientDescriptor->getPriority().getScore(),
+        clientDescriptor->getPriority().getState());
+    dprintf(fd, "    Client PID: %d\n", clientDescriptor->getOwnerId());
+
+    auto client = clientDescriptor->getValue();
+    dprintf(fd, "    Client package: %s\n",
+        String8(client->getPackageName()).string());
+
+    client->dumpClient(fd, args);
+}
+
+void CameraService::dumpClosedSessionClientLogs(int fd, const String8& cameraId) {
+    dprintf(fd, "  Device %s is closed, no client instance\n",
+                    cameraId.string());
+}
+
 void CameraService::dumpEventLog(int fd) {
     dprintf(fd, "\n== Camera service events log (most recent at top): ==\n");
 
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d1ed59a..7b0037e 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -202,6 +202,8 @@
             std::vector<hardware::CameraStatus>* cameraStatuses, bool isVendor = false,
             bool isProcessLocalTest = false);
 
+    void cacheDump();
+
     // Monitored UIDs availability notification
     void                notifyMonitoredUids();
 
@@ -785,6 +787,12 @@
     // Return NO_ERROR if the device with a give ID can be connected to
     status_t checkIfDeviceIsUsable(const String8& cameraId) const;
 
+    // Adds client logs during open session to the file pointed by fd.
+    void dumpOpenSessionClientLogs(int fd, const Vector<String16>& args, const String8& cameraId);
+
+    // Adds client logs during closed session to the file pointed by fd.
+    void dumpClosedSessionClientLogs(int fd, const String8& cameraId);
+
     // Container for managing currently active application-layer clients
     CameraClientManager mActiveClientManager;
 
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index ce479a1..56e5ae1 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -195,6 +195,8 @@
 
     ALOGV("Camera %s: Shutting down", TClientBase::mCameraIdStr.string());
 
+    // Before detaching the device, cache the info from current open session
+    Camera2ClientBase::getCameraService()->cacheDump();
     detachDevice();
 
     CameraService::BasicClient::disconnect();