Merge "AudioFlinger: Fix Tee compilation" into pi-dev
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 0bdfeac..9204824 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -392,19 +392,25 @@
}
aaudio_result_t AudioStreamInternal::startClient(const android::AudioClient& client,
- audio_port_handle_t *clientHandle) {
+ audio_port_handle_t *portHandle) {
+ ALOGV("%s() called", __func__);
if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
return AAUDIO_ERROR_INVALID_STATE;
}
-
- return mServiceInterface.startClient(mServiceStreamHandle, client, clientHandle);
+ aaudio_result_t result = mServiceInterface.startClient(mServiceStreamHandle,
+ client, portHandle);
+ ALOGV("%s(%d) returning %d", __func__, *portHandle, result);
+ return result;
}
-aaudio_result_t AudioStreamInternal::stopClient(audio_port_handle_t clientHandle) {
+aaudio_result_t AudioStreamInternal::stopClient(audio_port_handle_t portHandle) {
+ ALOGV("%s(%d) called", __func__, portHandle);
if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
return AAUDIO_ERROR_INVALID_STATE;
}
- return mServiceInterface.stopClient(mServiceStreamHandle, clientHandle);
+ aaudio_result_t result = mServiceInterface.stopClient(mServiceStreamHandle, portHandle);
+ ALOGV("%s(%d) returning %d", __func__, portHandle, result);
+ return result;
}
aaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId,
diff --git a/media/libmedia/include/media/MediaResource.h b/media/libmedia/include/media/MediaResource.h
index 1957a45..e1fdb9b 100644
--- a/media/libmedia/include/media/MediaResource.h
+++ b/media/libmedia/include/media/MediaResource.h
@@ -29,7 +29,8 @@
kUnspecified = 0,
kSecureCodec,
kNonSecureCodec,
- kGraphicMemory
+ kGraphicMemory,
+ kCpuBoost,
};
enum SubType {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index f25d1f1..23bee49 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -523,6 +523,7 @@
mDequeueOutputReplyID(0),
mHaveInputSurface(false),
mHavePendingInputBuffers(false),
+ mCpuBoostRequested(false),
mLatencyUnknown(0) {
if (uid == kNoUid) {
mUid = IPCThreadState::self()->getCallingUid();
@@ -1638,6 +1639,31 @@
msg->post();
}
+void MediaCodec::requestCpuBoostIfNeeded() {
+ if (mCpuBoostRequested) {
+ return;
+ }
+ int32_t colorFormat;
+ if (mSoftRenderer != NULL
+ && mOutputFormat->contains("hdr-static-info")
+ && mOutputFormat->findInt32("color-format", &colorFormat)
+ && (colorFormat == OMX_COLOR_FormatYUV420Planar16)) {
+ int32_t left, top, right, bottom, width, height;
+ int64_t totalPixel = 0;
+ if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
+ totalPixel = (right - left + 1) * (bottom - top + 1);
+ } else if (mOutputFormat->findInt32("width", &width)
+ && mOutputFormat->findInt32("height", &height)) {
+ totalPixel = width * height;
+ }
+ if (totalPixel >= 1920 * 1080) {
+ addResource(MediaResource::kCpuBoost,
+ MediaResource::kUnspecifiedSubType, 1);
+ mCpuBoostRequested = true;
+ }
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
void MediaCodec::cancelPendingDequeueOperations() {
@@ -2160,6 +2186,8 @@
}
}
+ requestCpuBoostIfNeeded();
+
if (mFlags & kFlagIsEncoder) {
// Before we announce the format change we should
// collect codec specific data and amend the output
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 48a1224..67808f1 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -369,6 +369,7 @@
bool mHaveInputSurface;
bool mHavePendingInputBuffers;
+ bool mCpuBoostRequested;
std::shared_ptr<BufferChannelBase> mBufferChannel;
@@ -425,6 +426,7 @@
uint64_t getGraphicBufferSize();
void addResource(MediaResource::Type type, MediaResource::SubType subtype, uint64_t value);
+ void requestCpuBoostIfNeeded();
bool hasPendingBuffer(int portIndex);
bool hasPendingBuffer();
diff --git a/media/utils/ISchedulingPolicyService.cpp b/media/utils/ISchedulingPolicyService.cpp
index 22fbc97..b210404 100644
--- a/media/utils/ISchedulingPolicyService.cpp
+++ b/media/utils/ISchedulingPolicyService.cpp
@@ -25,6 +25,7 @@
// Keep in sync with frameworks/base/core/java/android/os/ISchedulingPolicyService.aidl
enum {
REQUEST_PRIORITY_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+ REQUEST_CPUSET_BOOST,
};
// ----------------------------------------------------------------------
@@ -60,6 +61,23 @@
}
return reply.readInt32();
}
+
+ virtual int requestCpusetBoost(bool enable, const sp<IInterface>& client)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISchedulingPolicyService::getInterfaceDescriptor());
+ data.writeInt32(enable);
+ data.writeStrongBinder(IInterface::asBinder(client));
+ status_t status = remote()->transact(REQUEST_CPUSET_BOOST, data, &reply, 0);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ // fail on exception: force binder reconnection
+ if (reply.readExceptionCode() != 0) {
+ return DEAD_OBJECT;
+ }
+ return reply.readInt32();
+ }
};
IMPLEMENT_META_INTERFACE(SchedulingPolicyService, "android.os.ISchedulingPolicyService");
@@ -71,6 +89,7 @@
{
switch (code) {
case REQUEST_PRIORITY_TRANSACTION:
+ case REQUEST_CPUSET_BOOST:
// Not reached
return NO_ERROR;
break;
diff --git a/media/utils/ISchedulingPolicyService.h b/media/utils/ISchedulingPolicyService.h
index 1015677..e4f7c0d 100644
--- a/media/utils/ISchedulingPolicyService.h
+++ b/media/utils/ISchedulingPolicyService.h
@@ -29,6 +29,7 @@
virtual int requestPriority(/*pid_t*/int32_t pid, /*pid_t*/int32_t tid,
int32_t prio, bool isForApp, bool asynchronous) = 0;
+ virtual int requestCpusetBoost(bool enable, const sp<IInterface>& client) = 0;
};
class BnSchedulingPolicyService : public BnInterface<ISchedulingPolicyService>
diff --git a/media/utils/SchedulingPolicyService.cpp b/media/utils/SchedulingPolicyService.cpp
index d7055ef..4e9792f 100644
--- a/media/utils/SchedulingPolicyService.cpp
+++ b/media/utils/SchedulingPolicyService.cpp
@@ -59,4 +59,31 @@
return ret;
}
+int requestCpusetBoost(bool enable, const sp<IInterface> &client)
+{
+ int ret;
+ sMutex.lock();
+ sp<ISchedulingPolicyService> sps = sSchedulingPolicyService;
+ sMutex.unlock();
+ if (sps == 0) {
+ sp<IBinder> binder = defaultServiceManager()->checkService(_scheduling_policy);
+ if (binder == 0) {
+ return DEAD_OBJECT;
+ }
+ sps = interface_cast<ISchedulingPolicyService>(binder);
+ sMutex.lock();
+ sSchedulingPolicyService = sps;
+ sMutex.unlock();
+ }
+ ret = sps->requestCpusetBoost(enable, client);
+ if (ret != DEAD_OBJECT) {
+ return ret;
+ }
+ ALOGW("SchedulingPolicyService died");
+ sMutex.lock();
+ sSchedulingPolicyService.clear();
+ sMutex.unlock();
+ return ret;
+}
+
} // namespace android
diff --git a/media/utils/include/mediautils/SchedulingPolicyService.h b/media/utils/include/mediautils/SchedulingPolicyService.h
index 47d8734..a33539f 100644
--- a/media/utils/include/mediautils/SchedulingPolicyService.h
+++ b/media/utils/include/mediautils/SchedulingPolicyService.h
@@ -17,8 +17,11 @@
#ifndef _ANDROID_SCHEDULING_POLICY_SERVICE_H
#define _ANDROID_SCHEDULING_POLICY_SERVICE_H
+#include <utils/RefBase.h>
+
namespace android {
+class IInterface;
// Request elevated priority for thread tid, whose thread group leader must be pid.
// The priority parameter is currently restricted to either 1 or 2.
// The asynchronous parameter should be 'true' to return immediately,
@@ -26,6 +29,14 @@
// The default value 'false' means to return after request has been enqueued and executed.
int requestPriority(pid_t pid, pid_t tid, int32_t prio, bool isForApp, bool asynchronous = false);
+// Request to move media.codec process between SP_FOREGROUND and SP_TOP_APP.
+// When 'enable' is 'true', server will attempt to move media.codec process
+// from SP_FOREGROUND into SP_TOP_APP cpuset. A valid 'client' must be provided
+// for the server to receive death notifications. When 'enable' is 'false', server
+// will attempt to move media.codec process back to the original cpuset, and
+// 'client' is ignored in this case.
+int requestCpusetBoost(bool enable, const sp<IInterface> &client);
+
} // namespace android
#endif // _ANDROID_SCHEDULING_POLICY_SERVICE_H
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index bb85a2f..3c4f500 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -3481,8 +3481,13 @@
// FIXME not big-endian safe
write(teeFd, &temp, sizeof(temp));
close(teeFd);
- if (fd >= 0) {
- dprintf(fd, "tee copied to %s\n", teePath);
+ // TODO Should create file with temporary name and then rename to final if non-empty.
+ if (total > 0) {
+ if (fd >= 0) {
+ dprintf(fd, "tee copied to %s\n", teePath);
+ }
+ } else {
+ unlink(teePath);
}
} else {
if (fd >= 0) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index a54a71f..aba93d0 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -26,7 +26,8 @@
#define AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH 128
#define AUDIO_POLICY_XML_CONFIG_FILE_NAME "audio_policy_configuration.xml"
-#define AUDIO_POLICY_A2DP_OFFLOAD_XML_CONFIG_FILE_NAME "audio_policy_a2dp_offload_configuration.xml"
+#define AUDIO_POLICY_A2DP_OFFLOAD_DISABLED_XML_CONFIG_FILE_NAME \
+ "audio_policy_configuration_a2dp_offload_disabled.xml"
#include <inttypes.h>
#include <math.h>
@@ -3532,21 +3533,25 @@
static status_t deserializeAudioPolicyXmlConfig(AudioPolicyConfig &config) {
char audioPolicyXmlConfigFile[AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH];
+ std::vector<const char*> fileNames;
status_t ret;
- for (int i = 0; i < kConfigLocationListSize; i++) {
- PolicySerializer serializer;
- bool use_a2dp_offload_config =
- property_get_bool("persist.bluetooth.a2dp_offload.enable", false);
- snprintf(audioPolicyXmlConfigFile,
- sizeof(audioPolicyXmlConfigFile),
- "%s/%s",
- kConfigLocationList[i],
- use_a2dp_offload_config ? AUDIO_POLICY_A2DP_OFFLOAD_XML_CONFIG_FILE_NAME :
- AUDIO_POLICY_XML_CONFIG_FILE_NAME);
- ret = serializer.deserialize(audioPolicyXmlConfigFile, config);
- if (ret == NO_ERROR) {
- break;
+ if (property_get_bool("ro.bluetooth.a2dp_offload.supported", false) &&
+ property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
+ // A2DP offload supported but disabled: try to use special XML file
+ fileNames.push_back(AUDIO_POLICY_A2DP_OFFLOAD_DISABLED_XML_CONFIG_FILE_NAME);
+ }
+ fileNames.push_back(AUDIO_POLICY_XML_CONFIG_FILE_NAME);
+
+ for (const char* fileName : fileNames) {
+ for (int i = 0; i < kConfigLocationListSize; i++) {
+ PolicySerializer serializer;
+ snprintf(audioPolicyXmlConfigFile, sizeof(audioPolicyXmlConfigFile),
+ "%s/%s", kConfigLocationList[i], fileName);
+ ret = serializer.deserialize(audioPolicyXmlConfigFile, config);
+ if (ret == NO_ERROR) {
+ return ret;
+ }
}
}
return ret;
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 78bb587..28bfd3f 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -31,7 +31,8 @@
#include "ResourceManagerService.h"
#include "ServiceLog.h"
-
+#include "mediautils/SchedulingPolicyService.h"
+#include <cutils/sched_policy.h>
namespace android {
namespace {
@@ -111,6 +112,7 @@
ResourceInfo info;
info.clientId = clientId;
info.client = client;
+ info.cpuBoost = false;
infos.push_back(info);
return infos.editItemAt(infos.size() - 1);
}
@@ -201,7 +203,8 @@
: mProcessInfo(processInfo),
mServiceLog(new ServiceLog()),
mSupportsMultipleSecureCodecs(true),
- mSupportsSecureWithNonSecureCodec(true) {}
+ mSupportsSecureWithNonSecureCodec(true),
+ mCpuBoostCount(0) {}
ResourceManagerService::~ResourceManagerService() {}
@@ -239,6 +242,19 @@
ResourceInfo& info = getResourceInfoForEdit(clientId, client, infos);
// TODO: do the merge instead of append.
info.resources.appendVector(resources);
+
+ for (size_t i = 0; i < resources.size(); ++i) {
+ if (resources[i].mType == MediaResource::kCpuBoost && !info.cpuBoost) {
+ info.cpuBoost = true;
+ // Request it on every new instance of kCpuBoost, as the media.codec
+ // could have died, if we only do it the first time subsequent instances
+ // never gets the boost.
+ if (requestCpusetBoost(true, this) != OK) {
+ ALOGW("couldn't request cpuset boost");
+ }
+ mCpuBoostCount++;
+ }
+ }
if (info.deathNotifier == nullptr) {
info.deathNotifier = new DeathNotifier(this, pid, clientId);
IInterface::asBinder(client)->linkToDeath(info.deathNotifier);
@@ -270,6 +286,11 @@
ResourceInfos &infos = mMap.editValueAt(index);
for (size_t j = 0; j < infos.size(); ++j) {
if (infos[j].clientId == clientId) {
+ if (infos[j].cpuBoost && mCpuBoostCount > 0) {
+ if (--mCpuBoostCount == 0) {
+ requestCpusetBoost(false, this);
+ }
+ }
IInterface::asBinder(infos[j].client)->unlinkToDeath(infos[j].deathNotifier);
j = infos.removeAt(j);
found = true;
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index 9e97ac0..82d2a0b 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -38,6 +38,7 @@
sp<IResourceManagerClient> client;
sp<IBinder::DeathRecipient> deathNotifier;
Vector<MediaResource> resources;
+ bool cpuBoost;
};
typedef Vector<ResourceInfo> ResourceInfos;
@@ -112,6 +113,7 @@
PidResourceInfosMap mMap;
bool mSupportsMultipleSecureCodecs;
bool mSupportsSecureWithNonSecureCodec;
+ int32_t mCpuBoostCount;
};
// ----------------------------------------------------------------------------
diff --git a/services/oboeservice/AAudioEndpointManager.cpp b/services/oboeservice/AAudioEndpointManager.cpp
index ab8f4ed..04fee13 100644
--- a/services/oboeservice/AAudioEndpointManager.cpp
+++ b/services/oboeservice/AAudioEndpointManager.cpp
@@ -150,7 +150,7 @@
}
sp<AAudioServiceEndpoint> AAudioEndpointManager::openExclusiveEndpoint(
- AAudioService &aaudioService __unused,
+ AAudioService &aaudioService,
const aaudio::AAudioStreamRequest &request) {
std::lock_guard<std::mutex> lock(mExclusiveLock);
@@ -166,13 +166,14 @@
// Already open so do not allow a second stream.
return nullptr;
} else {
- sp<AAudioServiceEndpointMMAP> endpointMMap = new AAudioServiceEndpointMMAP();
+ sp<AAudioServiceEndpointMMAP> endpointMMap = new AAudioServiceEndpointMMAP(aaudioService);
ALOGV("openExclusiveEndpoint(), no match so try to open MMAP %p for dev %d",
endpointMMap.get(), configuration.getDeviceId());
endpoint = endpointMMap;
aaudio_result_t result = endpoint->open(request);
if (result != AAUDIO_OK) {
+ ALOGE("openExclusiveEndpoint(), open failed");
endpoint.clear();
} else {
mExclusiveStreams.push_back(endpointMMap);
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index ad5bb3a..5675b0b 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -288,11 +288,11 @@
aaudio_result_t result = AAUDIO_OK;
sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
if (serviceStream.get() == nullptr) {
- ALOGE("unregisterAudioThread(), illegal stream handle = 0x%0x", streamHandle);
+ ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
if (serviceStream->getRegisteredThread() != clientThreadId) {
- ALOGE("AAudioService::unregisterAudioThread(), wrong thread");
+ ALOGE("%s(), wrong thread", __func__);
result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
} else {
serviceStream->setRegisteredThread(0);
@@ -305,7 +305,7 @@
audio_port_handle_t *clientHandle) {
sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
if (serviceStream.get() == nullptr) {
- ALOGE("startClient(), illegal stream handle = 0x%0x", streamHandle);
+ ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
aaudio_result_t result = serviceStream->startClient(client, clientHandle);
@@ -313,12 +313,28 @@
}
aaudio_result_t AAudioService::stopClient(aaudio_handle_t streamHandle,
- audio_port_handle_t clientHandle) {
+ audio_port_handle_t portHandle) {
sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
if (serviceStream.get() == nullptr) {
- ALOGE("stopClient(), illegal stream handle = 0x%0x", streamHandle);
+ ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
- aaudio_result_t result = serviceStream->stopClient(clientHandle);
+ aaudio_result_t result = serviceStream->stopClient(portHandle);
+ return checkForPendingClose(serviceStream, result);
+}
+
+// This is only called internally when AudioFlinger wants to tear down a stream.
+// So we do not have to check permissions.
+aaudio_result_t AAudioService::disconnectStreamByPortHandle(audio_port_handle_t portHandle) {
+ ALOGD("%s(%d) called", __func__, portHandle);
+ sp<AAudioServiceStreamBase> serviceStream =
+ mStreamTracker.findStreamByPortHandle(portHandle);
+ if (serviceStream.get() == nullptr) {
+ ALOGE("%s(), could not find stream with portHandle = %d", __func__, portHandle);
+ return AAUDIO_ERROR_INVALID_HANDLE;
+ }
+ serviceStream->incrementServiceReferenceCount();
+ aaudio_result_t result = serviceStream->stop();
+ serviceStream->disconnect();
return checkForPendingClose(serviceStream, result);
}
diff --git a/services/oboeservice/AAudioService.h b/services/oboeservice/AAudioService.h
index bdd9e0b..d21b1cd 100644
--- a/services/oboeservice/AAudioService.h
+++ b/services/oboeservice/AAudioService.h
@@ -83,6 +83,8 @@
aaudio_result_t stopClient(aaudio::aaudio_handle_t streamHandle,
audio_port_handle_t clientHandle) override;
+ aaudio_result_t disconnectStreamByPortHandle(audio_port_handle_t portHandle);
+
private:
/**
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index 96e621a..0349034 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -78,6 +78,17 @@
return result.str();
}
+// @return true if stream found
+bool AAudioServiceEndpoint::isStreamRegistered(audio_port_handle_t portHandle) {
+ std::lock_guard<std::mutex> lock(mLockStreams);
+ for (const auto stream : mRegisteredStreams) {
+ if (stream->getPortHandle() == portHandle) {
+ return true;
+ }
+ }
+ return false;
+}
+
void AAudioServiceEndpoint::disconnectRegisteredStreams() {
std::lock_guard<std::mutex> lock(mLockStreams);
mConnected.store(false);
diff --git a/services/oboeservice/AAudioServiceEndpoint.h b/services/oboeservice/AAudioServiceEndpoint.h
index 6312c51..6015b28 100644
--- a/services/oboeservice/AAudioServiceEndpoint.h
+++ b/services/oboeservice/AAudioServiceEndpoint.h
@@ -102,6 +102,13 @@
}
protected:
+
+ /**
+ * @param portHandle
+ * @return return true if a stream with the given portHandle is registered
+ */
+ bool isStreamRegistered(audio_port_handle_t portHandle);
+
void disconnectRegisteredStreams();
mutable std::mutex mLockStreams;
@@ -116,7 +123,6 @@
int32_t mRequestedDeviceId = 0;
std::atomic<bool> mConnected{true};
-
};
} /* namespace aaudio */
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 5f1de76..f9e21fb 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -48,8 +48,10 @@
using namespace android; // TODO just import names needed
using namespace aaudio; // TODO just import names needed
-AAudioServiceEndpointMMAP::AAudioServiceEndpointMMAP()
- : mMmapStream(nullptr) {}
+
+AAudioServiceEndpointMMAP::AAudioServiceEndpointMMAP(AAudioService &audioService)
+ : mMmapStream(nullptr)
+ , mAAudioService(audioService) {}
AAudioServiceEndpointMMAP::~AAudioServiceEndpointMMAP() {}
@@ -277,14 +279,21 @@
}
aaudio_result_t AAudioServiceEndpointMMAP::startStream(sp<AAudioServiceStreamBase> stream,
- audio_port_handle_t *clientHandle) {
+ audio_port_handle_t *clientHandle __unused) {
// Start the client on behalf of the AAudio service.
// Use the port handle that was provided by openMmapStream().
- return startClient(mMmapClient, &mPortHandle);
+ audio_port_handle_t tempHandle = mPortHandle;
+ aaudio_result_t result = startClient(mMmapClient, &tempHandle);
+ // When AudioFlinger is passed a valid port handle then it should not change it.
+ LOG_ALWAYS_FATAL_IF(tempHandle != mPortHandle,
+ "%s() port handle not expected to change from %d to %d",
+ __func__, mPortHandle, tempHandle);
+ ALOGV("%s(%p) mPortHandle = %d", __func__, stream.get(), mPortHandle);
+ return result;
}
aaudio_result_t AAudioServiceEndpointMMAP::stopStream(sp<AAudioServiceStreamBase> stream,
- audio_port_handle_t clientHandle) {
+ audio_port_handle_t clientHandle __unused) {
mFramesTransferred.reset32();
// Round 64-bit counter up to a multiple of the buffer capacity.
@@ -293,24 +302,27 @@
// when the stream is stopped.
mFramesTransferred.roundUp64(getBufferCapacity());
+ // Use the port handle that was provided by openMmapStream().
+ ALOGV("%s(%p) mPortHandle = %d", __func__, stream.get(), mPortHandle);
return stopClient(mPortHandle);
}
aaudio_result_t AAudioServiceEndpointMMAP::startClient(const android::AudioClient& client,
audio_port_handle_t *clientHandle) {
if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
- ALOGV("%s(%p(uid=%d, pid=%d))", __func__, &client, client.clientUid, client.clientPid);
+ ALOGD("%s(%p(uid=%d, pid=%d))", __func__, &client, client.clientUid, client.clientPid);
audio_port_handle_t originalHandle = *clientHandle;
status_t status = mMmapStream->start(client, clientHandle);
aaudio_result_t result = AAudioConvert_androidToAAudioResult(status);
- ALOGV("%s() , %d => %d returns %d", __func__, originalHandle, *clientHandle, result);
+ ALOGD("%s() , portHandle %d => %d, returns %d", __func__, originalHandle, *clientHandle, result);
return result;
}
aaudio_result_t AAudioServiceEndpointMMAP::stopClient(audio_port_handle_t clientHandle) {
+ ALOGD("%s(portHandle = %d), called", __func__, clientHandle);
if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
aaudio_result_t result = AAudioConvert_androidToAAudioResult(mMmapStream->stop(clientHandle));
- ALOGV("%s(%d) returns %d", __func__, clientHandle, result);
+ ALOGD("%s(portHandle = %d), returns %d", __func__, clientHandle, result);
return result;
}
@@ -343,11 +355,19 @@
return 0; // TODO
}
-
-void AAudioServiceEndpointMMAP::onTearDown(audio_port_handle_t handle __unused) {
- ALOGD("%s(%p) called", __func__, this);
- //TODO: disconnect only stream corresponding to handle received
- disconnectRegisteredStreams();
+// This is called by AudioFlinger when it wants to destroy a stream.
+void AAudioServiceEndpointMMAP::onTearDown(audio_port_handle_t portHandle) {
+ ALOGD("%s(portHandle = %d) called", __func__, portHandle);
+ // Are we tearing down the EXCLUSIVE MMAP stream?
+ if (isStreamRegistered(portHandle)) {
+ ALOGD("%s(%d) tearing down this entire MMAP endpoint", __func__, portHandle);
+ disconnectRegisteredStreams();
+ } else {
+ // Must be a SHARED stream?
+ ALOGD("%s(%d) disconnect a specific stream", __func__, portHandle);
+ aaudio_result_t result = mAAudioService.disconnectStreamByPortHandle(portHandle);
+ ALOGD("%s(%d) disconnectStreamByPortHandle returned %d", __func__, portHandle, result);
+ }
};
void AAudioServiceEndpointMMAP::onVolumeChanged(audio_channel_mask_t channels,
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.h b/services/oboeservice/AAudioServiceEndpointMMAP.h
index c4c943d..5e815e0 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.h
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.h
@@ -42,7 +42,7 @@
, public android::MmapStreamCallback {
public:
- AAudioServiceEndpointMMAP();
+ explicit AAudioServiceEndpointMMAP(android::AAudioService &audioService);
virtual ~AAudioServiceEndpointMMAP();
@@ -88,8 +88,12 @@
// Interface to the AudioFlinger MMAP support.
android::sp<android::MmapStreamInterface> mMmapStream;
struct audio_mmap_buffer_info mMmapBufferinfo;
+
+ // There is only one port associated with an MMAP endpoint.
audio_port_handle_t mPortHandle = AUDIO_PORT_HANDLE_NONE;
+ android::AAudioService &mAAudioService;
+
android::base::unique_fd mAudioDataFileDescriptor;
int64_t mHardwareTimeOffsetNanos = 0; // TODO get from HAL
diff --git a/services/oboeservice/AAudioServiceEndpointShared.h b/services/oboeservice/AAudioServiceEndpointShared.h
index 227250c..d671710 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.h
+++ b/services/oboeservice/AAudioServiceEndpointShared.h
@@ -30,7 +30,7 @@
namespace aaudio {
/**
- * This manages an internal stream that is shared by multiple Client streams.
+ * This manages an AudioStreamInternal that is shared by multiple Client streams.
*/
class AAudioServiceEndpointShared : public AAudioServiceEndpoint {
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index 18f14ee..c943008 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -61,7 +61,7 @@
}
std::string AAudioServiceStreamBase::dumpHeader() {
- return std::string(" T Handle UId Run State Format Burst Chan Capacity");
+ return std::string(" T Handle UId Port Run State Format Burst Chan Capacity");
}
std::string AAudioServiceStreamBase::dump() const {
@@ -70,6 +70,7 @@
result << " 0x" << std::setfill('0') << std::setw(8) << std::hex << mHandle
<< std::dec << std::setfill(' ') ;
result << std::setw(6) << mMmapClient.clientUid;
+ result << std::setw(7) << mClientHandle;
result << std::setw(4) << (isRunning() ? "yes" : " no");
result << std::setw(6) << getState();
result << std::setw(7) << getFormat();
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index 3720596..d8102be 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -180,6 +180,10 @@
mHandle = handle;
}
+ audio_port_handle_t getPortHandle() const {
+ return mClientHandle;
+ }
+
aaudio_stream_state_t getState() const {
return mState;
}
@@ -269,6 +273,7 @@
int32_t mFramesPerBurst = 0;
android::AudioClient mMmapClient; // set in open, used in MMAP start()
+ // TODO rename mClientHandle to mPortHandle to be more consistent with AudioFlinger.
audio_port_handle_t mClientHandle = AUDIO_PORT_HANDLE_NONE;
SimpleDoubleBuffer<Timestamp> mAtomicTimestamp;
diff --git a/services/oboeservice/AAudioStreamTracker.cpp b/services/oboeservice/AAudioStreamTracker.cpp
index ef88b34..9d5d8fc 100644
--- a/services/oboeservice/AAudioStreamTracker.cpp
+++ b/services/oboeservice/AAudioStreamTracker.cpp
@@ -53,6 +53,26 @@
return serviceStream;
}
+
+// The port handle is only available when the stream is started.
+// So we have to iterate over all the streams.
+// Luckily this rarely happens.
+sp<AAudioServiceStreamBase> AAudioStreamTracker::findStreamByPortHandle(
+ audio_port_handle_t portHandle) {
+ std::lock_guard<std::mutex> lock(mHandleLock);
+ sp<AAudioServiceStreamBase> serviceStream;
+ auto it = mStreamsByHandle.begin();
+ while (it != mStreamsByHandle.end()) {
+ auto candidate = it->second;
+ if (candidate->getPortHandle() == portHandle) {
+ serviceStream = candidate;
+ break;
+ }
+ it++;
+ }
+ return serviceStream;
+}
+
// advance to next legal handle value
__attribute__((no_sanitize("integer")))
aaudio_handle_t AAudioStreamTracker::bumpHandle(aaudio_handle_t handle) {
diff --git a/services/oboeservice/AAudioStreamTracker.h b/services/oboeservice/AAudioStreamTracker.h
index 70d440d..54e46ca 100644
--- a/services/oboeservice/AAudioStreamTracker.h
+++ b/services/oboeservice/AAudioStreamTracker.h
@@ -46,6 +46,14 @@
android::sp<aaudio::AAudioServiceStreamBase> getStreamByHandle(aaudio_handle_t streamHandle);
/**
+ * Look up a stream based on the AudioPolicy portHandle.
+ * @param portHandle
+ * @return strong pointer to the stream if found or to nullptr
+ */
+ android::sp<aaudio::AAudioServiceStreamBase> findStreamByPortHandle(
+ audio_port_handle_t portHandle);
+
+ /**
* Store a strong pointer to the stream and return a unique handle for future reference.
* The handle is guaranteed not to collide with an existing stream.
* @param serviceStream