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();