Merge "AudioFlinger: Allocate client memory based on total device memory"

gugelfrei
Andy Hung 7 years ago committed by Android (Google) Code Review
commit 03570a65a4

@ -1059,11 +1059,11 @@ size_t AudioSystem::getPrimaryOutputFrameCount()
return af->getPrimaryOutputFrameCount();
}
status_t AudioSystem::setLowRamDevice(bool isLowRamDevice)
status_t AudioSystem::setLowRamDevice(bool isLowRamDevice, int64_t totalMemory)
{
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
return af->setLowRamDevice(isLowRamDevice);
return af->setLowRamDevice(isLowRamDevice, totalMemory);
}
void AudioSystem::clearAudioConfigCache()

@ -707,14 +707,18 @@ public:
return reply.readInt64();
}
virtual status_t setLowRamDevice(bool isLowRamDevice)
virtual status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) override
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
data.writeInt32((int) isLowRamDevice);
remote()->transact(SET_LOW_RAM_DEVICE, data, &reply);
return reply.readInt32();
static_assert(NO_ERROR == 0, "NO_ERROR must be 0");
return data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor())
?: data.writeInt32((int) isLowRamDevice)
?: data.writeInt64(totalMemory)
?: remote()->transact(SET_LOW_RAM_DEVICE, data, &reply)
?: reply.readInt32();
}
virtual status_t listAudioPorts(unsigned int *num_ports,
struct audio_port *ports)
{
@ -1281,8 +1285,13 @@ status_t BnAudioFlinger::onTransact(
} break;
case SET_LOW_RAM_DEVICE: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
bool isLowRamDevice = data.readInt32() != 0;
reply->writeInt32(setLowRamDevice(isLowRamDevice));
int32_t isLowRamDevice;
int64_t totalMemory;
const status_t status =
data.readInt32(&isLowRamDevice) ?:
data.readInt64(&totalMemory) ?:
setLowRamDevice(isLowRamDevice != 0, totalMemory);
(void)reply->writeInt32(status);
return NO_ERROR;
} break;
case LIST_AUDIO_PORTS: {

@ -285,7 +285,7 @@ public:
static uint32_t getPrimaryOutputSamplingRate();
static size_t getPrimaryOutputFrameCount();
static status_t setLowRamDevice(bool isLowRamDevice);
static status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory);
// Check if hw offload is possible for given format, stream type, sample rate,
// bit rate, duration, video and streaming or offload property is enabled

@ -454,8 +454,9 @@ public:
// Intended for AudioService to inform AudioFlinger of device's low RAM attribute,
// and should be called at most once. For a definition of what "low RAM" means, see
// android.app.ActivityManager.isLowRamDevice().
virtual status_t setLowRamDevice(bool isLowRamDevice) = 0;
// android.app.ActivityManager.isLowRamDevice(). The totalMemory parameter
// is obtained from android.app.ActivityManager.MemoryInfo.totalMem.
virtual status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) = 0;
/* List available audio ports and their attributes */
virtual status_t listAudioPorts(unsigned int *num_ports,

@ -155,6 +155,8 @@ AudioFlinger::AudioFlinger()
mBtNrecIsOff(false),
mIsLowRamDevice(true),
mIsDeviceTypeKnown(false),
mTotalMemory(0),
mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes),
mGlobalEffectEnableTime(0),
mSystemReady(false)
{
@ -1512,17 +1514,9 @@ AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
mAudioFlinger(audioFlinger),
mPid(pid)
{
size_t heapSize = property_get_int32("ro.af.client_heap_size_kbyte", 0);
heapSize *= 1024;
if (!heapSize) {
heapSize = kClientSharedHeapSizeBytes;
// Increase heap size on non low ram devices to limit risk of reconnection failure for
// invalidated tracks
if (!audioFlinger->isLowRamDevice()) {
heapSize *= kClientSharedHeapSizeMultiplier;
}
}
mMemoryDealer = new MemoryDealer(heapSize, "AudioFlinger::Client");
mMemoryDealer = new MemoryDealer(
audioFlinger->getClientSharedHeapSize(),
(std::string("AudioFlinger::Client(") + std::to_string(pid) + ")").c_str());
}
// Client destructor must be called with AudioFlinger::mClientLock held
@ -1860,7 +1854,7 @@ size_t AudioFlinger::getPrimaryOutputFrameCount()
// ----------------------------------------------------------------------------
status_t AudioFlinger::setLowRamDevice(bool isLowRamDevice)
status_t AudioFlinger::setLowRamDevice(bool isLowRamDevice, int64_t totalMemory)
{
uid_t uid = IPCThreadState::self()->getCallingUid();
if (uid != AID_SYSTEM) {
@ -1871,10 +1865,43 @@ status_t AudioFlinger::setLowRamDevice(bool isLowRamDevice)
return INVALID_OPERATION;
}
mIsLowRamDevice = isLowRamDevice;
mTotalMemory = totalMemory;
// mIsLowRamDevice and mTotalMemory are obtained through ActivityManager;
// see ActivityManager.isLowRamDevice() and ActivityManager.getMemoryInfo().
// mIsLowRamDevice generally represent devices with less than 1GB of memory,
// though actual setting is determined through device configuration.
constexpr int64_t GB = 1024 * 1024 * 1024;
mClientSharedHeapSize =
isLowRamDevice ? kMinimumClientSharedHeapSizeBytes
: mTotalMemory < 2 * GB ? 4 * kMinimumClientSharedHeapSizeBytes
: mTotalMemory < 3 * GB ? 8 * kMinimumClientSharedHeapSizeBytes
: mTotalMemory < 4 * GB ? 16 * kMinimumClientSharedHeapSizeBytes
: 32 * kMinimumClientSharedHeapSizeBytes;
mIsDeviceTypeKnown = true;
// TODO: Cache the client shared heap size in a persistent property.
// It's possible that a native process or Java service or app accesses audioserver
// after it is registered by system server, but before AudioService updates
// the memory info. This would occur immediately after boot or an audioserver
// crash and restore. Before update from AudioService, the client would get the
// minimum heap size.
ALOGD("isLowRamDevice:%s totalMemory:%lld mClientSharedHeapSize:%zu",
(isLowRamDevice ? "true" : "false"),
(long long)mTotalMemory,
mClientSharedHeapSize.load());
return NO_ERROR;
}
size_t AudioFlinger::getClientSharedHeapSize() const
{
size_t heapSizeInBytes = property_get_int32("ro.af.client_heap_size_kbyte", 0) * 1024;
if (heapSizeInBytes != 0) { // read-only property overrides all.
return heapSizeInBytes;
}
return mClientSharedHeapSize;
}
audio_hw_sync_t AudioFlinger::getAudioHwSyncForSession(audio_session_t sessionId)
{
Mutex::Autolock _l(mLock);

@ -94,12 +94,6 @@ class ServerProxy;
static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3);
// Max shared memory size for audio tracks and audio records per client process
static const size_t kClientSharedHeapSizeBytes = 1024*1024;
// Shared memory size multiplier for non low ram devices
static const size_t kClientSharedHeapSizeMultiplier = 4;
#define INCLUDING_FROM_AUDIOFLINGER_H
class AudioFlinger :
@ -227,7 +221,7 @@ public:
virtual uint32_t getPrimaryOutputSamplingRate();
virtual size_t getPrimaryOutputFrameCount();
virtual status_t setLowRamDevice(bool isLowRamDevice);
virtual status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) override;
/* List available audio ports and their attributes */
virtual status_t listAudioPorts(unsigned int *num_ports,
@ -829,15 +823,18 @@ public:
static const size_t kTeeSinkTrackFramesDefault = 0x200000;
#endif
// This method reads from a variable without mLock, but the variable is updated under mLock. So
// we might read a stale value, or a value that's inconsistent with respect to other variables.
// In this case, it's safe because the return value isn't used for making an important decision.
// The reason we don't want to take mLock is because it could block the caller for a long time.
// These methods read variables atomically without mLock,
// though the variables are updated with mLock.
bool isLowRamDevice() const { return mIsLowRamDevice; }
size_t getClientSharedHeapSize() const;
private:
bool mIsLowRamDevice;
std::atomic<bool> mIsLowRamDevice;
bool mIsDeviceTypeKnown;
int64_t mTotalMemory;
std::atomic<size_t> mClientSharedHeapSize;
static constexpr size_t kMinimumClientSharedHeapSizeBytes = 1024 * 1024; // 1MB
nsecs_t mGlobalEffectEnableTime; // when a global effect was last enabled
sp<PatchPanel> mPatchPanel;

Loading…
Cancel
Save