summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camera/libcameraservice/Android.mk66
-rw-r--r--camera/libcameraservice/CameraHardwareStub.cpp410
-rw-r--r--camera/libcameraservice/CameraHardwareStub.h133
-rw-r--r--camera/libcameraservice/CameraService.cpp1273
-rw-r--r--camera/libcameraservice/CameraService.h194
-rw-r--r--camera/libcameraservice/CannedJpeg.h734
-rw-r--r--camera/libcameraservice/FakeCamera.cpp433
-rw-r--r--camera/libcameraservice/FakeCamera.h67
-rw-r--r--camera/tests/CameraServiceTest/Android.mk26
-rw-r--r--camera/tests/CameraServiceTest/CameraServiceTest.cpp919
-rw-r--r--cmds/surfaceflinger/Android.mk2
-rw-r--r--libs/audioflinger/A2dpAudioInterface.cpp466
-rw-r--r--libs/audioflinger/A2dpAudioInterface.h135
-rw-r--r--libs/audioflinger/Android.mk131
-rw-r--r--libs/audioflinger/AudioBufferProvider.h49
-rw-r--r--libs/audioflinger/AudioDumpInterface.cpp573
-rw-r--r--libs/audioflinger/AudioDumpInterface.h170
-rw-r--r--libs/audioflinger/AudioFlinger.cpp6078
-rw-r--r--libs/audioflinger/AudioFlinger.h1148
-rw-r--r--libs/audioflinger/AudioHardwareGeneric.cpp411
-rw-r--r--libs/audioflinger/AudioHardwareGeneric.h151
-rw-r--r--libs/audioflinger/AudioHardwareInterface.cpp182
-rw-r--r--libs/audioflinger/AudioHardwareStub.cpp209
-rw-r--r--libs/audioflinger/AudioHardwareStub.h106
-rw-r--r--libs/audioflinger/AudioMixer.cpp1195
-rw-r--r--libs/audioflinger/AudioMixer.h207
-rw-r--r--libs/audioflinger/AudioPolicyManagerBase.cpp1973
-rw-r--r--libs/audioflinger/AudioPolicyService.cpp924
-rw-r--r--libs/audioflinger/AudioPolicyService.h223
-rw-r--r--libs/audioflinger/AudioResampler.cpp595
-rw-r--r--libs/audioflinger/AudioResampler.h93
-rw-r--r--libs/audioflinger/AudioResamplerCubic.cpp184
-rw-r--r--libs/audioflinger/AudioResamplerCubic.h68
-rw-r--r--libs/audioflinger/AudioResamplerSinc.cpp358
-rw-r--r--libs/audioflinger/AudioResamplerSinc.h88
-rw-r--r--services/surfaceflinger/Android.mk (renamed from libs/surfaceflinger/Android.mk)0
-rw-r--r--services/surfaceflinger/Barrier.h (renamed from libs/surfaceflinger/Barrier.h)0
-rw-r--r--services/surfaceflinger/BlurFilter.cpp (renamed from libs/surfaceflinger/BlurFilter.cpp)0
-rw-r--r--services/surfaceflinger/BlurFilter.h (renamed from libs/surfaceflinger/BlurFilter.h)0
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.cpp (renamed from libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp)0
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.h (renamed from libs/surfaceflinger/DisplayHardware/DisplayHardware.h)0
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp (renamed from libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp)0
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h (renamed from libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h)0
-rw-r--r--services/surfaceflinger/GLExtensions.cpp (renamed from libs/surfaceflinger/GLExtensions.cpp)0
-rw-r--r--services/surfaceflinger/GLExtensions.h (renamed from libs/surfaceflinger/GLExtensions.h)0
-rw-r--r--services/surfaceflinger/Layer.cpp (renamed from libs/surfaceflinger/Layer.cpp)0
-rw-r--r--services/surfaceflinger/Layer.h (renamed from libs/surfaceflinger/Layer.h)0
-rw-r--r--services/surfaceflinger/LayerBase.cpp (renamed from libs/surfaceflinger/LayerBase.cpp)0
-rw-r--r--services/surfaceflinger/LayerBase.h (renamed from libs/surfaceflinger/LayerBase.h)0
-rw-r--r--services/surfaceflinger/LayerBlur.cpp (renamed from libs/surfaceflinger/LayerBlur.cpp)0
-rw-r--r--services/surfaceflinger/LayerBlur.h (renamed from libs/surfaceflinger/LayerBlur.h)0
-rw-r--r--services/surfaceflinger/LayerBuffer.cpp (renamed from libs/surfaceflinger/LayerBuffer.cpp)0
-rw-r--r--services/surfaceflinger/LayerBuffer.h (renamed from libs/surfaceflinger/LayerBuffer.h)0
-rw-r--r--services/surfaceflinger/LayerDim.cpp (renamed from libs/surfaceflinger/LayerDim.cpp)0
-rw-r--r--services/surfaceflinger/LayerDim.h (renamed from libs/surfaceflinger/LayerDim.h)0
-rw-r--r--services/surfaceflinger/MODULE_LICENSE_APACHE2 (renamed from libs/surfaceflinger/MODULE_LICENSE_APACHE2)0
-rw-r--r--services/surfaceflinger/MessageQueue.cpp (renamed from libs/surfaceflinger/MessageQueue.cpp)0
-rw-r--r--services/surfaceflinger/MessageQueue.h (renamed from libs/surfaceflinger/MessageQueue.h)0
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp (renamed from libs/surfaceflinger/SurfaceFlinger.cpp)0
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h (renamed from libs/surfaceflinger/SurfaceFlinger.h)0
-rw-r--r--services/surfaceflinger/TextureManager.cpp (renamed from libs/surfaceflinger/TextureManager.cpp)0
-rw-r--r--services/surfaceflinger/TextureManager.h (renamed from libs/surfaceflinger/TextureManager.h)0
-rw-r--r--services/surfaceflinger/Transform.cpp (renamed from libs/surfaceflinger/Transform.cpp)0
-rw-r--r--services/surfaceflinger/Transform.h (renamed from libs/surfaceflinger/Transform.h)0
-rw-r--r--services/surfaceflinger/clz.cpp (renamed from libs/surfaceflinger/clz.cpp)0
-rw-r--r--services/surfaceflinger/clz.h (renamed from libs/surfaceflinger/clz.h)0
-rw-r--r--services/surfaceflinger/tests/Android.mk (renamed from libs/surfaceflinger/tests/Android.mk)0
-rw-r--r--services/surfaceflinger/tests/overlays/Android.mk (renamed from libs/surfaceflinger/tests/overlays/Android.mk)0
-rw-r--r--services/surfaceflinger/tests/overlays/overlays.cpp (renamed from libs/surfaceflinger/tests/overlays/overlays.cpp)0
-rw-r--r--services/surfaceflinger/tests/resize/Android.mk (renamed from libs/surfaceflinger/tests/resize/Android.mk)0
-rw-r--r--services/surfaceflinger/tests/resize/resize.cpp (renamed from libs/surfaceflinger/tests/resize/resize.cpp)0
71 files changed, 1 insertions, 19973 deletions
diff --git a/camera/libcameraservice/Android.mk b/camera/libcameraservice/Android.mk
deleted file mode 100644
index 87975af..0000000
--- a/camera/libcameraservice/Android.mk
+++ /dev/null
@@ -1,66 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# Set USE_CAMERA_STUB if you don't want to use the hardware camera.
-
-# force these builds to use camera stub only
-ifneq ($(filter sooner generic sim,$(TARGET_DEVICE)),)
- USE_CAMERA_STUB:=true
-endif
-
-ifeq ($(USE_CAMERA_STUB),)
- USE_CAMERA_STUB:=false
-endif
-
-ifeq ($(USE_CAMERA_STUB),true)
-#
-# libcamerastub
-#
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- CameraHardwareStub.cpp \
- FakeCamera.cpp
-
-LOCAL_MODULE:= libcamerastub
-
-ifeq ($(TARGET_SIMULATOR),true)
-LOCAL_CFLAGS += -DSINGLE_PROCESS
-endif
-
-LOCAL_SHARED_LIBRARIES:= libui
-
-include $(BUILD_STATIC_LIBRARY)
-endif # USE_CAMERA_STUB
-
-#
-# libcameraservice
-#
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- CameraService.cpp
-
-LOCAL_SHARED_LIBRARIES:= \
- libui \
- libutils \
- libbinder \
- libcutils \
- libmedia \
- libcamera_client \
- libsurfaceflinger_client
-
-LOCAL_MODULE:= libcameraservice
-
-ifeq ($(TARGET_SIMULATOR),true)
-LOCAL_CFLAGS += -DSINGLE_PROCESS
-endif
-
-ifeq ($(USE_CAMERA_STUB), true)
-LOCAL_STATIC_LIBRARIES += libcamerastub
-else
-LOCAL_SHARED_LIBRARIES += libcamera
-endif
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/camera/libcameraservice/CameraHardwareStub.cpp b/camera/libcameraservice/CameraHardwareStub.cpp
deleted file mode 100644
index b3e0ee6..0000000
--- a/camera/libcameraservice/CameraHardwareStub.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "CameraHardwareStub"
-#include <utils/Log.h>
-
-#include "CameraHardwareStub.h"
-#include <utils/threads.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-
-#include "CannedJpeg.h"
-
-namespace android {
-
-CameraHardwareStub::CameraHardwareStub()
- : mParameters(),
- mPreviewHeap(0),
- mRawHeap(0),
- mFakeCamera(0),
- mPreviewFrameSize(0),
- mNotifyCb(0),
- mDataCb(0),
- mDataCbTimestamp(0),
- mCallbackCookie(0),
- mMsgEnabled(0),
- mCurrentPreviewFrame(0)
-{
- initDefaultParameters();
-}
-
-void CameraHardwareStub::initDefaultParameters()
-{
- CameraParameters p;
-
- p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240");
- p.setPreviewSize(320, 240);
- p.setPreviewFrameRate(15);
- p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP);
-
- p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240");
- p.setPictureSize(320, 240);
- p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
-
- if (setParameters(p) != NO_ERROR) {
- LOGE("Failed to set default parameters?!");
- }
-}
-
-void CameraHardwareStub::initHeapLocked()
-{
- // Create raw heap.
- int picture_width, picture_height;
- mParameters.getPictureSize(&picture_width, &picture_height);
- mRawHeap = new MemoryHeapBase(picture_width * picture_height * 3 / 2);
-
- int preview_width, preview_height;
- mParameters.getPreviewSize(&preview_width, &preview_height);
- LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height);
-
- // Note that we enforce yuv420sp in setParameters().
- int how_big = preview_width * preview_height * 3 / 2;
-
- // If we are being reinitialized to the same size as before, no
- // work needs to be done.
- if (how_big == mPreviewFrameSize)
- return;
-
- mPreviewFrameSize = how_big;
-
- // Make a new mmap'ed heap that can be shared across processes.
- // use code below to test with pmem
- mPreviewHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount);
- // Make an IMemory for each frame so that we can reuse them in callbacks.
- for (int i = 0; i < kBufferCount; i++) {
- mBuffers[i] = new MemoryBase(mPreviewHeap, i * mPreviewFrameSize, mPreviewFrameSize);
- }
-
- // Recreate the fake camera to reflect the current size.
- delete mFakeCamera;
- mFakeCamera = new FakeCamera(preview_width, preview_height);
-}
-
-CameraHardwareStub::~CameraHardwareStub()
-{
- delete mFakeCamera;
- mFakeCamera = 0; // paranoia
-}
-
-sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const
-{
- return mPreviewHeap;
-}
-
-sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const
-{
- return mRawHeap;
-}
-
-void CameraHardwareStub::setCallbacks(notify_callback notify_cb,
- data_callback data_cb,
- data_callback_timestamp data_cb_timestamp,
- void* user)
-{
- Mutex::Autolock lock(mLock);
- mNotifyCb = notify_cb;
- mDataCb = data_cb;
- mDataCbTimestamp = data_cb_timestamp;
- mCallbackCookie = user;
-}
-
-void CameraHardwareStub::enableMsgType(int32_t msgType)
-{
- Mutex::Autolock lock(mLock);
- mMsgEnabled |= msgType;
-}
-
-void CameraHardwareStub::disableMsgType(int32_t msgType)
-{
- Mutex::Autolock lock(mLock);
- mMsgEnabled &= ~msgType;
-}
-
-bool CameraHardwareStub::msgTypeEnabled(int32_t msgType)
-{
- Mutex::Autolock lock(mLock);
- return (mMsgEnabled & msgType);
-}
-
-// ---------------------------------------------------------------------------
-
-int CameraHardwareStub::previewThread()
-{
- mLock.lock();
- // the attributes below can change under our feet...
-
- int previewFrameRate = mParameters.getPreviewFrameRate();
-
- // Find the offset within the heap of the current buffer.
- ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize;
-
- sp<MemoryHeapBase> heap = mPreviewHeap;
-
- // this assumes the internal state of fake camera doesn't change
- // (or is thread safe)
- FakeCamera* fakeCamera = mFakeCamera;
-
- sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame];
-
- mLock.unlock();
-
- // TODO: here check all the conditions that could go wrong
- if (buffer != 0) {
- // Calculate how long to wait between frames.
- int delay = (int)(1000000.0f / float(previewFrameRate));
-
- // This is always valid, even if the client died -- the memory
- // is still mapped in our process.
- void *base = heap->base();
-
- // Fill the current frame with the fake camera.
- uint8_t *frame = ((uint8_t *)base) + offset;
- fakeCamera->getNextFrameAsYuv420(frame);
-
- //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);
-
- // Notify the client of a new frame.
- if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
- mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);
-
- // Advance the buffer pointer.
- mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
-
- // Wait for it...
- usleep(delay);
- }
-
- return NO_ERROR;
-}
-
-status_t CameraHardwareStub::startPreview()
-{
- Mutex::Autolock lock(mLock);
- if (mPreviewThread != 0) {
- // already running
- return INVALID_OPERATION;
- }
- mPreviewThread = new PreviewThread(this);
- return NO_ERROR;
-}
-
-void CameraHardwareStub::stopPreview()
-{
- sp<PreviewThread> previewThread;
-
- { // scope for the lock
- Mutex::Autolock lock(mLock);
- previewThread = mPreviewThread;
- }
-
- // don't hold the lock while waiting for the thread to quit
- if (previewThread != 0) {
- previewThread->requestExitAndWait();
- }
-
- Mutex::Autolock lock(mLock);
- mPreviewThread.clear();
-}
-
-bool CameraHardwareStub::previewEnabled() {
- return mPreviewThread != 0;
-}
-
-status_t CameraHardwareStub::startRecording()
-{
- return UNKNOWN_ERROR;
-}
-
-void CameraHardwareStub::stopRecording()
-{
-}
-
-bool CameraHardwareStub::recordingEnabled()
-{
- return false;
-}
-
-void CameraHardwareStub::releaseRecordingFrame(const sp<IMemory>& mem)
-{
-}
-
-// ---------------------------------------------------------------------------
-
-int CameraHardwareStub::beginAutoFocusThread(void *cookie)
-{
- CameraHardwareStub *c = (CameraHardwareStub *)cookie;
- return c->autoFocusThread();
-}
-
-int CameraHardwareStub::autoFocusThread()
-{
- if (mMsgEnabled & CAMERA_MSG_FOCUS)
- mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
- return NO_ERROR;
-}
-
-status_t CameraHardwareStub::autoFocus()
-{
- Mutex::Autolock lock(mLock);
- if (createThread(beginAutoFocusThread, this) == false)
- return UNKNOWN_ERROR;
- return NO_ERROR;
-}
-
-status_t CameraHardwareStub::cancelAutoFocus()
-{
- return NO_ERROR;
-}
-
-/*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
-{
- CameraHardwareStub *c = (CameraHardwareStub *)cookie;
- return c->pictureThread();
-}
-
-int CameraHardwareStub::pictureThread()
-{
- if (mMsgEnabled & CAMERA_MSG_SHUTTER)
- mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
-
- if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
- //FIXME: use a canned YUV image!
- // In the meantime just make another fake camera picture.
- int w, h;
- mParameters.getPictureSize(&w, &h);
- sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2);
- FakeCamera cam(w, h);
- cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base());
- mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);
- }
-
- if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
- sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
- sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
- memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
- mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);
- }
- return NO_ERROR;
-}
-
-status_t CameraHardwareStub::takePicture()
-{
- stopPreview();
- if (createThread(beginPictureThread, this) == false)
- return UNKNOWN_ERROR;
- return NO_ERROR;
-}
-
-status_t CameraHardwareStub::cancelPicture()
-{
- return NO_ERROR;
-}
-
-status_t CameraHardwareStub::dump(int fd, const Vector<String16>& args) const
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- AutoMutex lock(&mLock);
- if (mFakeCamera != 0) {
- mFakeCamera->dump(fd);
- mParameters.dump(fd, args);
- snprintf(buffer, 255, " preview frame(%d), size (%d), running(%s)\n", mCurrentPreviewFrame, mPreviewFrameSize, mPreviewRunning?"true": "false");
- result.append(buffer);
- } else {
- result.append("No camera client yet.\n");
- }
- write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-status_t CameraHardwareStub::setParameters(const CameraParameters& params)
-{
- Mutex::Autolock lock(mLock);
- // XXX verify params
-
- if (strcmp(params.getPreviewFormat(),
- CameraParameters::PIXEL_FORMAT_YUV420SP) != 0) {
- LOGE("Only yuv420sp preview is supported");
- return -1;
- }
-
- if (strcmp(params.getPictureFormat(),
- CameraParameters::PIXEL_FORMAT_JPEG) != 0) {
- LOGE("Only jpeg still pictures are supported");
- return -1;
- }
-
- int w, h;
- params.getPictureSize(&w, &h);
- if (w != kCannedJpegWidth && h != kCannedJpegHeight) {
- LOGE("Still picture size must be size of canned JPEG (%dx%d)",
- kCannedJpegWidth, kCannedJpegHeight);
- return -1;
- }
-
- mParameters = params;
- initHeapLocked();
-
- return NO_ERROR;
-}
-
-CameraParameters CameraHardwareStub::getParameters() const
-{
- Mutex::Autolock lock(mLock);
- return mParameters;
-}
-
-status_t CameraHardwareStub::sendCommand(int32_t command, int32_t arg1,
- int32_t arg2)
-{
- return BAD_VALUE;
-}
-
-void CameraHardwareStub::release()
-{
-}
-
-sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
-{
- return new CameraHardwareStub();
-}
-
-static CameraInfo sCameraInfo[] = {
- {
- CAMERA_FACING_BACK,
- 90, /* orientation */
- }
-};
-
-extern "C" int HAL_getNumberOfCameras()
-{
- return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);
-}
-
-extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)
-{
- memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
-}
-
-extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId)
-{
- return CameraHardwareStub::createInstance();
-}
-
-}; // namespace android
diff --git a/camera/libcameraservice/CameraHardwareStub.h b/camera/libcameraservice/CameraHardwareStub.h
deleted file mode 100644
index d3427ba..0000000
--- a/camera/libcameraservice/CameraHardwareStub.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_HARDWARE_CAMERA_HARDWARE_STUB_H
-#define ANDROID_HARDWARE_CAMERA_HARDWARE_STUB_H
-
-#include "FakeCamera.h"
-#include <utils/threads.h>
-#include <camera/CameraHardwareInterface.h>
-#include <binder/MemoryBase.h>
-#include <binder/MemoryHeapBase.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class CameraHardwareStub : public CameraHardwareInterface {
-public:
- virtual sp<IMemoryHeap> getPreviewHeap() const;
- virtual sp<IMemoryHeap> getRawHeap() const;
-
- virtual void setCallbacks(notify_callback notify_cb,
- data_callback data_cb,
- data_callback_timestamp data_cb_timestamp,
- void* user);
-
- virtual void enableMsgType(int32_t msgType);
- virtual void disableMsgType(int32_t msgType);
- virtual bool msgTypeEnabled(int32_t msgType);
-
- virtual status_t startPreview();
- virtual void stopPreview();
- virtual bool previewEnabled();
-
- virtual status_t startRecording();
- virtual void stopRecording();
- virtual bool recordingEnabled();
- virtual void releaseRecordingFrame(const sp<IMemory>& mem);
-
- virtual status_t autoFocus();
- virtual status_t cancelAutoFocus();
- virtual status_t takePicture();
- virtual status_t cancelPicture();
- virtual status_t dump(int fd, const Vector<String16>& args) const;
- virtual status_t setParameters(const CameraParameters& params);
- virtual CameraParameters getParameters() const;
- virtual status_t sendCommand(int32_t command, int32_t arg1,
- int32_t arg2);
- virtual void release();
-
- static sp<CameraHardwareInterface> createInstance();
-
-private:
- CameraHardwareStub();
- virtual ~CameraHardwareStub();
-
- static const int kBufferCount = 4;
-
- class PreviewThread : public Thread {
- CameraHardwareStub* mHardware;
- public:
- PreviewThread(CameraHardwareStub* hw) :
-#ifdef SINGLE_PROCESS
- // In single process mode this thread needs to be a java thread,
- // since we won't be calling through the binder.
- Thread(true),
-#else
- Thread(false),
-#endif
- mHardware(hw) { }
- virtual void onFirstRef() {
- run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
- }
- virtual bool threadLoop() {
- mHardware->previewThread();
- // loop until we need to quit
- return true;
- }
- };
-
- void initDefaultParameters();
- void initHeapLocked();
-
- int previewThread();
-
- static int beginAutoFocusThread(void *cookie);
- int autoFocusThread();
-
- static int beginPictureThread(void *cookie);
- int pictureThread();
-
- mutable Mutex mLock;
-
- CameraParameters mParameters;
-
- sp<MemoryHeapBase> mPreviewHeap;
- sp<MemoryHeapBase> mRawHeap;
- sp<MemoryBase> mBuffers[kBufferCount];
-
- FakeCamera *mFakeCamera;
- bool mPreviewRunning;
- int mPreviewFrameSize;
-
- // protected by mLock
- sp<PreviewThread> mPreviewThread;
-
- notify_callback mNotifyCb;
- data_callback mDataCb;
- data_callback_timestamp mDataCbTimestamp;
- void *mCallbackCookie;
-
- int32_t mMsgEnabled;
-
- // only used from PreviewThread
- int mCurrentPreviewFrame;
-};
-
-}; // namespace android
-
-#endif
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
deleted file mode 100644
index 10668a4..0000000
--- a/camera/libcameraservice/CameraService.cpp
+++ /dev/null
@@ -1,1273 +0,0 @@
-/*
-**
-** Copyright (C) 2008, The Android Open Source Project
-** Copyright (C) 2008 HTC Inc.
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "CameraService"
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <pthread.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/MemoryBase.h>
-#include <binder/MemoryHeapBase.h>
-#include <cutils/atomic.h>
-#include <hardware/hardware.h>
-#include <media/AudioSystem.h>
-#include <media/mediaplayer.h>
-#include <surfaceflinger/ISurface.h>
-#include <ui/Overlay.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/String16.h>
-
-#include "CameraService.h"
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-// Logging support -- this is for debugging only
-// Use "adb shell dumpsys media.camera -v 1" to change it.
-static volatile int32_t gLogLevel = 0;
-
-#define LOG1(...) LOGD_IF(gLogLevel >= 1, __VA_ARGS__);
-#define LOG2(...) LOGD_IF(gLogLevel >= 2, __VA_ARGS__);
-
-static void setLogLevel(int level) {
- android_atomic_write(level, &gLogLevel);
-}
-
-// ----------------------------------------------------------------------------
-
-static int getCallingPid() {
- return IPCThreadState::self()->getCallingPid();
-}
-
-static int getCallingUid() {
- return IPCThreadState::self()->getCallingUid();
-}
-
-// ----------------------------------------------------------------------------
-
-// This is ugly and only safe if we never re-create the CameraService, but
-// should be ok for now.
-static CameraService *gCameraService;
-
-CameraService::CameraService()
-:mSoundRef(0)
-{
- LOGI("CameraService started (pid=%d)", getpid());
-
- mNumberOfCameras = HAL_getNumberOfCameras();
- if (mNumberOfCameras > MAX_CAMERAS) {
- LOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
- mNumberOfCameras, MAX_CAMERAS);
- mNumberOfCameras = MAX_CAMERAS;
- }
-
- for (int i = 0; i < mNumberOfCameras; i++) {
- setCameraFree(i);
- }
-
- gCameraService = this;
-}
-
-CameraService::~CameraService() {
- for (int i = 0; i < mNumberOfCameras; i++) {
- if (mBusy[i]) {
- LOGE("camera %d is still in use in destructor!", i);
- }
- }
-
- gCameraService = NULL;
-}
-
-int32_t CameraService::getNumberOfCameras() {
- return mNumberOfCameras;
-}
-
-status_t CameraService::getCameraInfo(int cameraId,
- struct CameraInfo* cameraInfo) {
- if (cameraId < 0 || cameraId >= mNumberOfCameras) {
- return BAD_VALUE;
- }
-
- HAL_getCameraInfo(cameraId, cameraInfo);
- return OK;
-}
-
-sp<ICamera> CameraService::connect(
- const sp<ICameraClient>& cameraClient, int cameraId) {
- int callingPid = getCallingPid();
- LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
-
- sp<Client> client;
- if (cameraId < 0 || cameraId >= mNumberOfCameras) {
- LOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
- callingPid, cameraId);
- return NULL;
- }
-
- Mutex::Autolock lock(mServiceLock);
- if (mClient[cameraId] != 0) {
- client = mClient[cameraId].promote();
- if (client != 0) {
- if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
- LOG1("CameraService::connect X (pid %d) (the same client)",
- callingPid);
- return client;
- } else {
- LOGW("CameraService::connect X (pid %d) rejected (existing client).",
- callingPid);
- return NULL;
- }
- }
- mClient[cameraId].clear();
- }
-
- if (mBusy[cameraId]) {
- LOGW("CameraService::connect X (pid %d) rejected"
- " (camera %d is still busy).", callingPid, cameraId);
- return NULL;
- }
-
- client = new Client(this, cameraClient, cameraId, callingPid);
- mClient[cameraId] = client;
- LOG1("CameraService::connect X");
- return client;
-}
-
-void CameraService::removeClient(const sp<ICameraClient>& cameraClient) {
- int callingPid = getCallingPid();
- LOG1("CameraService::removeClient E (pid %d)", callingPid);
-
- for (int i = 0; i < mNumberOfCameras; i++) {
- // Declare this before the lock to make absolutely sure the
- // destructor won't be called with the lock held.
- sp<Client> client;
-
- Mutex::Autolock lock(mServiceLock);
-
- // This happens when we have already disconnected (or this is
- // just another unused camera).
- if (mClient[i] == 0) continue;
-
- // Promote mClient. It can fail if we are called from this path:
- // Client::~Client() -> disconnect() -> removeClient().
- client = mClient[i].promote();
-
- if (client == 0) {
- mClient[i].clear();
- continue;
- }
-
- if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
- // Found our camera, clear and leave.
- LOG1("removeClient: clear camera %d", i);
- mClient[i].clear();
- break;
- }
- }
-
- LOG1("CameraService::removeClient X (pid %d)", callingPid);
-}
-
-sp<CameraService::Client> CameraService::getClientById(int cameraId) {
- if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
- return mClient[cameraId].promote();
-}
-
-void CameraService::instantiate() {
- defaultServiceManager()->addService(String16("media.camera"),
- new CameraService());
-}
-
-status_t CameraService::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
- // Permission checks
- switch (code) {
- case BnCameraService::CONNECT:
- const int pid = getCallingPid();
- const int self_pid = getpid();
- if (pid != self_pid) {
- // we're called from a different process, do the real check
- if (!checkCallingPermission(
- String16("android.permission.CAMERA"))) {
- const int uid = getCallingUid();
- LOGE("Permission Denial: "
- "can't use the camera pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
- }
- break;
- }
-
- return BnCameraService::onTransact(code, data, reply, flags);
-}
-
-// The reason we need this busy bit is a new CameraService::connect() request
-// may come in while the previous Client's destructor has not been run or is
-// still running. If the last strong reference of the previous Client is gone
-// but the destructor has not been finished, we should not allow the new Client
-// to be created because we need to wait for the previous Client to tear down
-// the hardware first.
-void CameraService::setCameraBusy(int cameraId) {
- android_atomic_write(1, &mBusy[cameraId]);
-}
-
-void CameraService::setCameraFree(int cameraId) {
- android_atomic_write(0, &mBusy[cameraId]);
-}
-
-// We share the media players for shutter and recording sound for all clients.
-// A reference count is kept to determine when we will actually release the
-// media players.
-
-static MediaPlayer* newMediaPlayer(const char *file) {
- MediaPlayer* mp = new MediaPlayer();
- if (mp->setDataSource(file, NULL) == NO_ERROR) {
- mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE);
- mp->prepare();
- } else {
- LOGE("Failed to load CameraService sounds: %s", file);
- return NULL;
- }
- return mp;
-}
-
-void CameraService::loadSound() {
- Mutex::Autolock lock(mSoundLock);
- LOG1("CameraService::loadSound ref=%d", mSoundRef);
- if (mSoundRef++) return;
-
- mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
- mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
-}
-
-void CameraService::releaseSound() {
- Mutex::Autolock lock(mSoundLock);
- LOG1("CameraService::releaseSound ref=%d", mSoundRef);
- if (--mSoundRef) return;
-
- for (int i = 0; i < NUM_SOUNDS; i++) {
- if (mSoundPlayer[i] != 0) {
- mSoundPlayer[i]->disconnect();
- mSoundPlayer[i].clear();
- }
- }
-}
-
-void CameraService::playSound(sound_kind kind) {
- LOG1("playSound(%d)", kind);
- Mutex::Autolock lock(mSoundLock);
- sp<MediaPlayer> player = mSoundPlayer[kind];
- if (player != 0) {
- // do not play the sound if stream volume is 0
- // (typically because ringer mode is silent).
- int index;
- AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
- if (index != 0) {
- player->seekTo(0);
- player->start();
- }
- }
-}
-
-// ----------------------------------------------------------------------------
-
-CameraService::Client::Client(const sp<CameraService>& cameraService,
- const sp<ICameraClient>& cameraClient, int cameraId, int clientPid) {
- int callingPid = getCallingPid();
- LOG1("Client::Client E (pid %d)", callingPid);
-
- mCameraService = cameraService;
- mCameraClient = cameraClient;
- mCameraId = cameraId;
- mClientPid = clientPid;
-
- mHardware = HAL_openCameraHardware(cameraId);
- mUseOverlay = mHardware->useOverlay();
- mMsgEnabled = 0;
-
- mHardware->setCallbacks(notifyCallback,
- dataCallback,
- dataCallbackTimestamp,
- (void *)cameraId);
-
- // Enable zoom, error, and focus messages by default
- enableMsgType(CAMERA_MSG_ERROR |
- CAMERA_MSG_ZOOM |
- CAMERA_MSG_FOCUS);
- mOverlayW = 0;
- mOverlayH = 0;
-
- // Callback is disabled by default
- mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
- mOrientation = 0;
- cameraService->setCameraBusy(cameraId);
- cameraService->loadSound();
- LOG1("Client::Client X (pid %d)", callingPid);
-}
-
-static void *unregister_surface(void *arg) {
- ISurface *surface = (ISurface *)arg;
- surface->unregisterBuffers();
- IPCThreadState::self()->flushCommands();
- return NULL;
-}
-
-// tear down the client
-CameraService::Client::~Client() {
- int callingPid = getCallingPid();
- LOG1("Client::~Client E (pid %d, this %p)", callingPid, this);
-
- if (mSurface != 0 && !mUseOverlay) {
- pthread_t thr;
- // We unregister the buffers in a different thread because binder does
- // not let us make sychronous transactions in a binder destructor (that
- // is, upon our reaching a refcount of zero.)
- pthread_create(&thr,
- NULL, // attr
- unregister_surface,
- mSurface.get());
- pthread_join(thr, NULL);
- }
-
- // set mClientPid to let disconnet() tear down the hardware
- mClientPid = callingPid;
- disconnect();
- mCameraService->releaseSound();
- LOG1("Client::~Client X (pid %d, this %p)", callingPid, this);
-}
-
-// ----------------------------------------------------------------------------
-
-status_t CameraService::Client::checkPid() const {
- int callingPid = getCallingPid();
- if (callingPid == mClientPid) return NO_ERROR;
-
- LOGW("attempt to use a locked camera from a different process"
- " (old pid %d, new pid %d)", mClientPid, callingPid);
- return EBUSY;
-}
-
-status_t CameraService::Client::checkPidAndHardware() const {
- status_t result = checkPid();
- if (result != NO_ERROR) return result;
- if (mHardware == 0) {
- LOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid());
- return INVALID_OPERATION;
- }
- return NO_ERROR;
-}
-
-status_t CameraService::Client::lock() {
- int callingPid = getCallingPid();
- LOG1("lock (pid %d)", callingPid);
- Mutex::Autolock lock(mLock);
-
- // lock camera to this client if the the camera is unlocked
- if (mClientPid == 0) {
- mClientPid = callingPid;
- return NO_ERROR;
- }
-
- // returns NO_ERROR if the client already owns the camera, EBUSY otherwise
- return checkPid();
-}
-
-status_t CameraService::Client::unlock() {
- int callingPid = getCallingPid();
- LOG1("unlock (pid %d)", callingPid);
- Mutex::Autolock lock(mLock);
-
- // allow anyone to use camera (after they lock the camera)
- status_t result = checkPid();
- if (result == NO_ERROR) {
- mClientPid = 0;
- LOG1("clear mCameraClient (pid %d)", callingPid);
- // we need to remove the reference to ICameraClient so that when the app
- // goes away, the reference count goes to 0.
- mCameraClient.clear();
- }
- return result;
-}
-
-// connect a new client to the camera
-status_t CameraService::Client::connect(const sp<ICameraClient>& client) {
- int callingPid = getCallingPid();
- LOG1("connect E (pid %d)", callingPid);
- Mutex::Autolock lock(mLock);
-
- if (mClientPid != 0 && checkPid() != NO_ERROR) {
- LOGW("Tried to connect to a locked camera (old pid %d, new pid %d)",
- mClientPid, callingPid);
- return EBUSY;
- }
-
- if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) {
- LOG1("Connect to the same client");
- return NO_ERROR;
- }
-
- mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
- mClientPid = callingPid;
- mCameraClient = client;
-
- LOG1("connect X (pid %d)", callingPid);
- return NO_ERROR;
-}
-
-void CameraService::Client::disconnect() {
- int callingPid = getCallingPid();
- LOG1("disconnect E (pid %d)", callingPid);
- Mutex::Autolock lock(mLock);
-
- if (checkPid() != NO_ERROR) {
- LOGW("different client - don't disconnect");
- return;
- }
-
- if (mClientPid <= 0) {
- LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
- return;
- }
-
- // Make sure disconnect() is done once and once only, whether it is called
- // from the user directly, or called by the destructor.
- if (mHardware == 0) return;
-
- LOG1("hardware teardown");
- // Before destroying mHardware, we must make sure it's in the
- // idle state.
- // Turn off all messages.
- disableMsgType(CAMERA_MSG_ALL_MSGS);
- mHardware->stopPreview();
- mHardware->cancelPicture();
- // Release the hardware resources.
- mHardware->release();
- // Release the held overlay resources.
- if (mUseOverlay) {
- mOverlayRef = 0;
- }
- mHardware.clear();
-
- mCameraService->removeClient(mCameraClient);
- mCameraService->setCameraFree(mCameraId);
-
- LOG1("disconnect X (pid %d)", callingPid);
-}
-
-// ----------------------------------------------------------------------------
-
-// set the ISurface that the preview will use
-status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) {
- LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
- Mutex::Autolock lock(mLock);
- status_t result = checkPidAndHardware();
- if (result != NO_ERROR) return result;
-
- result = NO_ERROR;
-
- // return if no change in surface.
- // asBinder() is safe on NULL (returns NULL)
- if (surface->asBinder() == mSurface->asBinder()) {
- return result;
- }
-
- if (mSurface != 0) {
- LOG1("clearing old preview surface %p", mSurface.get());
- if (mUseOverlay) {
- // Force the destruction of any previous overlay
- sp<Overlay> dummy;
- mHardware->setOverlay(dummy);
- } else {
- mSurface->unregisterBuffers();
- }
- }
- mSurface = surface;
- mOverlayRef = 0;
- // If preview has been already started, set overlay or register preview
- // buffers now.
- if (mHardware->previewEnabled()) {
- if (mUseOverlay) {
- result = setOverlay();
- } else if (mSurface != 0) {
- result = registerPreviewBuffers();
- }
- }
-
- return result;
-}
-
-status_t CameraService::Client::registerPreviewBuffers() {
- int w, h;
- CameraParameters params(mHardware->getParameters());
- params.getPreviewSize(&w, &h);
-
- // FIXME: don't use a hardcoded format here.
- ISurface::BufferHeap buffers(w, h, w, h,
- HAL_PIXEL_FORMAT_YCrCb_420_SP,
- mOrientation,
- 0,
- mHardware->getPreviewHeap());
-
- status_t result = mSurface->registerBuffers(buffers);
- if (result != NO_ERROR) {
- LOGE("registerBuffers failed with status %d", result);
- }
- return result;
-}
-
-status_t CameraService::Client::setOverlay() {
- int w, h;
- CameraParameters params(mHardware->getParameters());
- params.getPreviewSize(&w, &h);
-
- if (w != mOverlayW || h != mOverlayH) {
- // Force the destruction of any previous overlay
- sp<Overlay> dummy;
- mHardware->setOverlay(dummy);
- mOverlayRef = 0;
- }
-
- status_t result = NO_ERROR;
- if (mSurface == 0) {
- result = mHardware->setOverlay(NULL);
- } else {
- if (mOverlayRef == 0) {
- // FIXME:
- // Surfaceflinger may hold onto the previous overlay reference for some
- // time after we try to destroy it. retry a few times. In the future, we
- // should make the destroy call block, or possibly specify that we can
- // wait in the createOverlay call if the previous overlay is in the
- // process of being destroyed.
- for (int retry = 0; retry < 50; ++retry) {
- mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT,
- mOrientation);
- if (mOverlayRef != 0) break;
- LOGW("Overlay create failed - retrying");
- usleep(20000);
- }
- if (mOverlayRef == 0) {
- LOGE("Overlay Creation Failed!");
- return -EINVAL;
- }
- result = mHardware->setOverlay(new Overlay(mOverlayRef));
- }
- }
- if (result != NO_ERROR) {
- LOGE("mHardware->setOverlay() failed with status %d\n", result);
- return result;
- }
-
- mOverlayW = w;
- mOverlayH = h;
-
- return result;
-}
-
-// set the preview callback flag to affect how the received frames from
-// preview are handled.
-void CameraService::Client::setPreviewCallbackFlag(int callback_flag) {
- LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid());
- Mutex::Autolock lock(mLock);
- if (checkPidAndHardware() != NO_ERROR) return;
-
- mPreviewCallbackFlag = callback_flag;
-
- // If we don't use overlay, we always need the preview frame for display.
- // If we do use overlay, we only need the preview frame if the user
- // wants the data.
- if (mUseOverlay) {
- if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) {
- enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
- } else {
- disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
- }
- }
-}
-
-// start preview mode
-status_t CameraService::Client::startPreview() {
- LOG1("startPreview (pid %d)", getCallingPid());
- return startCameraMode(CAMERA_PREVIEW_MODE);
-}
-
-// start recording mode
-status_t CameraService::Client::startRecording() {
- LOG1("startRecording (pid %d)", getCallingPid());
- return startCameraMode(CAMERA_RECORDING_MODE);
-}
-
-// start preview or recording
-status_t CameraService::Client::startCameraMode(camera_mode mode) {
- LOG1("startCameraMode(%d)", mode);
- Mutex::Autolock lock(mLock);
- status_t result = checkPidAndHardware();
- if (result != NO_ERROR) return result;
-
- switch(mode) {
- case CAMERA_PREVIEW_MODE:
- if (mSurface == 0) {
- LOG1("mSurface is not set yet.");
- // still able to start preview in this case.
- }
- return startPreviewMode();
- case CAMERA_RECORDING_MODE:
- if (mSurface == 0) {
- LOGE("mSurface must be set before startRecordingMode.");
- return INVALID_OPERATION;
- }
- return startRecordingMode();
- default:
- return UNKNOWN_ERROR;
- }
-}
-
-status_t CameraService::Client::startPreviewMode() {
- LOG1("startPreviewMode");
- status_t result = NO_ERROR;
-
- // if preview has been enabled, nothing needs to be done
- if (mHardware->previewEnabled()) {
- return NO_ERROR;
- }
-
- if (mUseOverlay) {
- // If preview display has been set, set overlay now.
- if (mSurface != 0) {
- result = setOverlay();
- }
- if (result != NO_ERROR) return result;
- result = mHardware->startPreview();
- } else {
- enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
- result = mHardware->startPreview();
- if (result != NO_ERROR) return result;
- // If preview display has been set, register preview buffers now.
- if (mSurface != 0) {
- // Unregister here because the surface may be previously registered
- // with the raw (snapshot) heap.
- mSurface->unregisterBuffers();
- result = registerPreviewBuffers();
- }
- }
- return result;
-}
-
-status_t CameraService::Client::startRecordingMode() {
- LOG1("startRecordingMode");
- status_t result = NO_ERROR;
-
- // if recording has been enabled, nothing needs to be done
- if (mHardware->recordingEnabled()) {
- return NO_ERROR;
- }
-
- // if preview has not been started, start preview first
- if (!mHardware->previewEnabled()) {
- result = startPreviewMode();
- if (result != NO_ERROR) {
- return result;
- }
- }
-
- // start recording mode
- enableMsgType(CAMERA_MSG_VIDEO_FRAME);
- mCameraService->playSound(SOUND_RECORDING);
- result = mHardware->startRecording();
- if (result != NO_ERROR) {
- LOGE("mHardware->startRecording() failed with status %d", result);
- }
- return result;
-}
-
-// stop preview mode
-void CameraService::Client::stopPreview() {
- LOG1("stopPreview (pid %d)", getCallingPid());
- Mutex::Autolock lock(mLock);
- if (checkPidAndHardware() != NO_ERROR) return;
-
- disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
- mHardware->stopPreview();
-
- if (mSurface != 0 && !mUseOverlay) {
- mSurface->unregisterBuffers();
- }
-
- mPreviewBuffer.clear();
-}
-
-// stop recording mode
-void CameraService::Client::stopRecording() {
- LOG1("stopRecording (pid %d)", getCallingPid());
- Mutex::Autolock lock(mLock);
- if (checkPidAndHardware() != NO_ERROR) return;
-
- mCameraService->playSound(SOUND_RECORDING);
- disableMsgType(CAMERA_MSG_VIDEO_FRAME);
- mHardware->stopRecording();
-
- mPreviewBuffer.clear();
-}
-
-// release a recording frame
-void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) {
- Mutex::Autolock lock(mLock);
- if (checkPidAndHardware() != NO_ERROR) return;
- mHardware->releaseRecordingFrame(mem);
-}
-
-bool CameraService::Client::previewEnabled() {
- LOG1("previewEnabled (pid %d)", getCallingPid());
-
- Mutex::Autolock lock(mLock);
- if (checkPidAndHardware() != NO_ERROR) return false;
- return mHardware->previewEnabled();
-}
-
-bool CameraService::Client::recordingEnabled() {
- LOG1("recordingEnabled (pid %d)", getCallingPid());
-
- Mutex::Autolock lock(mLock);
- if (checkPidAndHardware() != NO_ERROR) return false;
- return mHardware->recordingEnabled();
-}
-
-status_t CameraService::Client::autoFocus() {
- LOG1("autoFocus (pid %d)", getCallingPid());
-
- Mutex::Autolock lock(mLock);
- status_t result = checkPidAndHardware();
- if (result != NO_ERROR) return result;
-
- return mHardware->autoFocus();
-}
-
-status_t CameraService::Client::cancelAutoFocus() {
- LOG1("cancelAutoFocus (pid %d)", getCallingPid());
-
- Mutex::Autolock lock(mLock);
- status_t result = checkPidAndHardware();
- if (result != NO_ERROR) return result;
-
- return mHardware->cancelAutoFocus();
-}
-
-// take a picture - image is returned in callback
-status_t CameraService::Client::takePicture() {
- LOG1("takePicture (pid %d)", getCallingPid());
-
- Mutex::Autolock lock(mLock);
- status_t result = checkPidAndHardware();
- if (result != NO_ERROR) return result;
-
- enableMsgType(CAMERA_MSG_SHUTTER |
- CAMERA_MSG_POSTVIEW_FRAME |
- CAMERA_MSG_RAW_IMAGE |
- CAMERA_MSG_COMPRESSED_IMAGE);
-
- return mHardware->takePicture();
-}
-
-// set preview/capture parameters - key/value pairs
-status_t CameraService::Client::setParameters(const String8& params) {
- LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string());
-
- Mutex::Autolock lock(mLock);
- status_t result = checkPidAndHardware();
- if (result != NO_ERROR) return result;
-
- CameraParameters p(params);
- return mHardware->setParameters(p);
-}
-
-// get preview/capture parameters - key/value pairs
-String8 CameraService::Client::getParameters() const {
- Mutex::Autolock lock(mLock);
- if (checkPidAndHardware() != NO_ERROR) return String8();
-
- String8 params(mHardware->getParameters().flatten());
- LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string());
- return params;
-}
-
-status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
- LOG1("sendCommand (pid %d)", getCallingPid());
- Mutex::Autolock lock(mLock);
- status_t result = checkPidAndHardware();
- if (result != NO_ERROR) return result;
-
- if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
- // The orientation cannot be set during preview.
- if (mHardware->previewEnabled()) {
- return INVALID_OPERATION;
- }
- switch (arg1) {
- case 0:
- mOrientation = ISurface::BufferHeap::ROT_0;
- break;
- case 90:
- mOrientation = ISurface::BufferHeap::ROT_90;
- break;
- case 180:
- mOrientation = ISurface::BufferHeap::ROT_180;
- break;
- case 270:
- mOrientation = ISurface::BufferHeap::ROT_270;
- break;
- default:
- return BAD_VALUE;
- }
- return OK;
- }
-
- return mHardware->sendCommand(cmd, arg1, arg2);
-}
-
-// ----------------------------------------------------------------------------
-
-void CameraService::Client::enableMsgType(int32_t msgType) {
- android_atomic_or(msgType, &mMsgEnabled);
- mHardware->enableMsgType(msgType);
-}
-
-void CameraService::Client::disableMsgType(int32_t msgType) {
- android_atomic_and(~msgType, &mMsgEnabled);
- mHardware->disableMsgType(msgType);
-}
-
-#define CHECK_MESSAGE_INTERVAL 10 // 10ms
-bool CameraService::Client::lockIfMessageWanted(int32_t msgType) {
- int sleepCount = 0;
- while (mMsgEnabled & msgType) {
- if (mLock.tryLock() == NO_ERROR) {
- if (sleepCount > 0) {
- LOG1("lockIfMessageWanted(%d): waited for %d ms",
- msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
- }
- return true;
- }
- if (sleepCount++ == 0) {
- LOG1("lockIfMessageWanted(%d): enter sleep", msgType);
- }
- usleep(CHECK_MESSAGE_INTERVAL * 1000);
- }
- LOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);
- return false;
-}
-
-// ----------------------------------------------------------------------------
-
-// Converts from a raw pointer to the client to a strong pointer during a
-// hardware callback. This requires the callbacks only happen when the client
-// is still alive.
-sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user) {
- sp<Client> client = gCameraService->getClientById((int) user);
-
- // This could happen if the Client is in the process of shutting down (the
- // last strong reference is gone, but the destructor hasn't finished
- // stopping the hardware).
- if (client == 0) return NULL;
-
- // The checks below are not necessary and are for debugging only.
- if (client->mCameraService.get() != gCameraService) {
- LOGE("mismatch service!");
- return NULL;
- }
-
- if (client->mHardware == 0) {
- LOGE("mHardware == 0: callback after disconnect()?");
- return NULL;
- }
-
- return client;
-}
-
-// Callback messages can be dispatched to internal handlers or pass to our
-// client's callback functions, depending on the message type.
-//
-// notifyCallback:
-// CAMERA_MSG_SHUTTER handleShutter
-// (others) c->notifyCallback
-// dataCallback:
-// CAMERA_MSG_PREVIEW_FRAME handlePreviewData
-// CAMERA_MSG_POSTVIEW_FRAME handlePostview
-// CAMERA_MSG_RAW_IMAGE handleRawPicture
-// CAMERA_MSG_COMPRESSED_IMAGE handleCompressedPicture
-// (others) c->dataCallback
-// dataCallbackTimestamp
-// (others) c->dataCallbackTimestamp
-//
-// NOTE: the *Callback functions grab mLock of the client before passing
-// control to handle* functions. So the handle* functions must release the
-// lock before calling the ICameraClient's callbacks, so those callbacks can
-// invoke methods in the Client class again (For example, the preview frame
-// callback may want to releaseRecordingFrame). The handle* functions must
-// release the lock after all accesses to member variables, so it must be
-// handled very carefully.
-
-void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1,
- int32_t ext2, void* user) {
- LOG2("notifyCallback(%d)", msgType);
-
- sp<Client> client = getClientFromCookie(user);
- if (client == 0) return;
- if (!client->lockIfMessageWanted(msgType)) return;
-
- switch (msgType) {
- case CAMERA_MSG_SHUTTER:
- // ext1 is the dimension of the yuv picture.
- client->handleShutter((image_rect_type *)ext1);
- break;
- default:
- client->handleGenericNotify(msgType, ext1, ext2);
- break;
- }
-}
-
-void CameraService::Client::dataCallback(int32_t msgType,
- const sp<IMemory>& dataPtr, void* user) {
- LOG2("dataCallback(%d)", msgType);
-
- sp<Client> client = getClientFromCookie(user);
- if (client == 0) return;
- if (!client->lockIfMessageWanted(msgType)) return;
-
- if (dataPtr == 0) {
- LOGE("Null data returned in data callback");
- client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
- return;
- }
-
- switch (msgType) {
- case CAMERA_MSG_PREVIEW_FRAME:
- client->handlePreviewData(dataPtr);
- break;
- case CAMERA_MSG_POSTVIEW_FRAME:
- client->handlePostview(dataPtr);
- break;
- case CAMERA_MSG_RAW_IMAGE:
- client->handleRawPicture(dataPtr);
- break;
- case CAMERA_MSG_COMPRESSED_IMAGE:
- client->handleCompressedPicture(dataPtr);
- break;
- default:
- client->handleGenericData(msgType, dataPtr);
- break;
- }
-}
-
-void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,
- int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
- LOG2("dataCallbackTimestamp(%d)", msgType);
-
- sp<Client> client = getClientFromCookie(user);
- if (client == 0) return;
- if (!client->lockIfMessageWanted(msgType)) return;
-
- if (dataPtr == 0) {
- LOGE("Null data returned in data with timestamp callback");
- client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
- return;
- }
-
- client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
-}
-
-// snapshot taken callback
-// "size" is the width and height of yuv picture for registerBuffer.
-// If it is NULL, use the picture size from parameters.
-void CameraService::Client::handleShutter(image_rect_type *size) {
- mCameraService->playSound(SOUND_SHUTTER);
-
- // Screen goes black after the buffer is unregistered.
- if (mSurface != 0 && !mUseOverlay) {
- mSurface->unregisterBuffers();
- }
-
- sp<ICameraClient> c = mCameraClient;
- if (c != 0) {
- mLock.unlock();
- c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
- if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
- }
- disableMsgType(CAMERA_MSG_SHUTTER);
-
- // It takes some time before yuvPicture callback to be called.
- // Register the buffer for raw image here to reduce latency.
- if (mSurface != 0 && !mUseOverlay) {
- int w, h;
- CameraParameters params(mHardware->getParameters());
- if (size == NULL) {
- params.getPictureSize(&w, &h);
- } else {
- w = size->width;
- h = size->height;
- w &= ~1;
- h &= ~1;
- LOG1("Snapshot image width=%d, height=%d", w, h);
- }
- // FIXME: don't use hardcoded format constants here
- ISurface::BufferHeap buffers(w, h, w, h,
- HAL_PIXEL_FORMAT_YCrCb_420_SP, mOrientation, 0,
- mHardware->getRawHeap());
-
- mSurface->registerBuffers(buffers);
- IPCThreadState::self()->flushCommands();
- }
-
- mLock.unlock();
-}
-
-// preview callback - frame buffer update
-void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) {
- ssize_t offset;
- size_t size;
- sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-
- if (!mUseOverlay) {
- if (mSurface != 0) {
- mSurface->postBuffer(offset);
- }
- }
-
- // local copy of the callback flags
- int flags = mPreviewCallbackFlag;
-
- // is callback enabled?
- if (!(flags & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
- // If the enable bit is off, the copy-out and one-shot bits are ignored
- LOG2("frame callback is disabled");
- mLock.unlock();
- return;
- }
-
- // hold a strong pointer to the client
- sp<ICameraClient> c = mCameraClient;
-
- // clear callback flags if no client or one-shot mode
- if (c == 0 || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
- LOG2("Disable preview callback");
- mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
- FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
- FRAME_CALLBACK_FLAG_ENABLE_MASK);
- if (mUseOverlay) {
- disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
- }
- }
-
- if (c != 0) {
- // Is the received frame copied out or not?
- if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
- LOG2("frame is copied");
- copyFrameAndPostCopiedFrame(c, heap, offset, size);
- } else {
- LOG2("frame is forwarded");
- mLock.unlock();
- c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
- }
- } else {
- mLock.unlock();
- }
-}
-
-// picture callback - postview image ready
-void CameraService::Client::handlePostview(const sp<IMemory>& mem) {
- disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
-
- sp<ICameraClient> c = mCameraClient;
- mLock.unlock();
- if (c != 0) {
- c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
- }
-}
-
-// picture callback - raw image ready
-void CameraService::Client::handleRawPicture(const sp<IMemory>& mem) {
- disableMsgType(CAMERA_MSG_RAW_IMAGE);
-
- ssize_t offset;
- size_t size;
- sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-
- // Put the YUV version of the snapshot in the preview display.
- if (mSurface != 0 && !mUseOverlay) {
- mSurface->postBuffer(offset);
- }
-
- sp<ICameraClient> c = mCameraClient;
- mLock.unlock();
- if (c != 0) {
- c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
- }
-}
-
-// picture callback - compressed picture ready
-void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) {
- disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
-
- sp<ICameraClient> c = mCameraClient;
- mLock.unlock();
- if (c != 0) {
- c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
- }
-}
-
-
-void CameraService::Client::handleGenericNotify(int32_t msgType,
- int32_t ext1, int32_t ext2) {
- sp<ICameraClient> c = mCameraClient;
- mLock.unlock();
- if (c != 0) {
- c->notifyCallback(msgType, ext1, ext2);
- }
-}
-
-void CameraService::Client::handleGenericData(int32_t msgType,
- const sp<IMemory>& dataPtr) {
- sp<ICameraClient> c = mCameraClient;
- mLock.unlock();
- if (c != 0) {
- c->dataCallback(msgType, dataPtr);
- }
-}
-
-void CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp,
- int32_t msgType, const sp<IMemory>& dataPtr) {
- sp<ICameraClient> c = mCameraClient;
- mLock.unlock();
- if (c != 0) {
- c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
- }
-}
-
-void CameraService::Client::copyFrameAndPostCopiedFrame(
- const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap,
- size_t offset, size_t size) {
- LOG2("copyFrameAndPostCopiedFrame");
- // It is necessary to copy out of pmem before sending this to
- // the callback. For efficiency, reuse the same MemoryHeapBase
- // provided it's big enough. Don't allocate the memory or
- // perform the copy if there's no callback.
- // hold the preview lock while we grab a reference to the preview buffer
- sp<MemoryHeapBase> previewBuffer;
-
- if (mPreviewBuffer == 0) {
- mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
- } else if (size > mPreviewBuffer->virtualSize()) {
- mPreviewBuffer.clear();
- mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
- }
- if (mPreviewBuffer == 0) {
- LOGE("failed to allocate space for preview buffer");
- mLock.unlock();
- return;
- }
- previewBuffer = mPreviewBuffer;
-
- memcpy(previewBuffer->base(), (uint8_t *)heap->base() + offset, size);
-
- sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
- if (frame == 0) {
- LOGE("failed to allocate space for frame callback");
- mLock.unlock();
- return;
- }
-
- mLock.unlock();
- client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
-}
-
-// ----------------------------------------------------------------------------
-
-static const int kDumpLockRetries = 50;
-static const int kDumpLockSleep = 60000;
-
-static bool tryLock(Mutex& mutex)
-{
- bool locked = false;
- for (int i = 0; i < kDumpLockRetries; ++i) {
- if (mutex.tryLock() == NO_ERROR) {
- locked = true;
- break;
- }
- usleep(kDumpLockSleep);
- }
- return locked;
-}
-
-status_t CameraService::dump(int fd, const Vector<String16>& args) {
- static const char* kDeadlockedString = "CameraService may be deadlocked\n";
-
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
- snprintf(buffer, SIZE, "Permission Denial: "
- "can't dump CameraService from pid=%d, uid=%d\n",
- getCallingPid(),
- getCallingUid());
- result.append(buffer);
- write(fd, result.string(), result.size());
- } else {
- bool locked = tryLock(mServiceLock);
- // failed to lock - CameraService is probably deadlocked
- if (!locked) {
- String8 result(kDeadlockedString);
- write(fd, result.string(), result.size());
- }
-
- bool hasClient = false;
- for (int i = 0; i < mNumberOfCameras; i++) {
- sp<Client> client = mClient[i].promote();
- if (client == 0) continue;
- hasClient = true;
- sprintf(buffer, "Client[%d] (%p) PID: %d\n",
- i,
- client->getCameraClient()->asBinder().get(),
- client->mClientPid);
- result.append(buffer);
- write(fd, result.string(), result.size());
- client->mHardware->dump(fd, args);
- }
- if (!hasClient) {
- result.append("No camera client yet.\n");
- write(fd, result.string(), result.size());
- }
-
- if (locked) mServiceLock.unlock();
-
- // change logging level
- int n = args.size();
- for (int i = 0; i + 1 < n; i++) {
- if (args[i] == String16("-v")) {
- String8 levelStr(args[i+1]);
- int level = atoi(levelStr.string());
- sprintf(buffer, "Set Log Level to %d", level);
- result.append(buffer);
- setLogLevel(level);
- }
- }
- }
- return NO_ERROR;
-}
-
-}; // namespace android
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
deleted file mode 100644
index 8193e77..0000000
--- a/camera/libcameraservice/CameraService.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
-**
-** Copyright (C) 2008, The Android Open Source Project
-** Copyright (C) 2008 HTC Inc.
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
-#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
-
-#include <camera/ICameraService.h>
-#include <camera/CameraHardwareInterface.h>
-
-/* This needs to be increased if we can have more cameras */
-#define MAX_CAMERAS 2
-
-namespace android {
-
-class MemoryHeapBase;
-class MediaPlayer;
-
-class CameraService: public BnCameraService
-{
- class Client;
-public:
- static void instantiate();
-
- CameraService();
- virtual ~CameraService();
-
- virtual int32_t getNumberOfCameras();
- virtual status_t getCameraInfo(int cameraId,
- struct CameraInfo* cameraInfo);
- virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId);
- virtual void removeClient(const sp<ICameraClient>& cameraClient);
- virtual sp<Client> getClientById(int cameraId);
-
- virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags);
-
- enum sound_kind {
- SOUND_SHUTTER = 0,
- SOUND_RECORDING = 1,
- NUM_SOUNDS
- };
-
- void loadSound();
- void playSound(sound_kind kind);
- void releaseSound();
-
-private:
- Mutex mServiceLock;
- wp<Client> mClient[MAX_CAMERAS]; // protected by mServiceLock
- int mNumberOfCameras;
-
- // atomics to record whether the hardware is allocated to some client.
- volatile int32_t mBusy[MAX_CAMERAS];
- void setCameraBusy(int cameraId);
- void setCameraFree(int cameraId);
-
- // sounds
- Mutex mSoundLock;
- sp<MediaPlayer> mSoundPlayer[NUM_SOUNDS];
- int mSoundRef; // reference count (release all MediaPlayer when 0)
-
- class Client : public BnCamera
- {
- public:
- // ICamera interface (see ICamera for details)
- virtual void disconnect();
- virtual status_t connect(const sp<ICameraClient>& client);
- virtual status_t lock();
- virtual status_t unlock();
- virtual status_t setPreviewDisplay(const sp<ISurface>& surface);
- virtual void setPreviewCallbackFlag(int flag);
- virtual status_t startPreview();
- virtual void stopPreview();
- virtual bool previewEnabled();
- virtual status_t startRecording();
- virtual void stopRecording();
- virtual bool recordingEnabled();
- virtual void releaseRecordingFrame(const sp<IMemory>& mem);
- virtual status_t autoFocus();
- virtual status_t cancelAutoFocus();
- virtual status_t takePicture();
- virtual status_t setParameters(const String8& params);
- virtual String8 getParameters() const;
- virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
- private:
- friend class CameraService;
- Client(const sp<CameraService>& cameraService,
- const sp<ICameraClient>& cameraClient,
- int cameraId,
- int clientPid);
- ~Client();
-
- // return our camera client
- const sp<ICameraClient>& getCameraClient() { return mCameraClient; }
-
- // check whether the calling process matches mClientPid.
- status_t checkPid() const;
- status_t checkPidAndHardware() const; // also check mHardware != 0
-
- // these are internal functions used to set up preview buffers
- status_t registerPreviewBuffers();
- status_t setOverlay();
-
- // camera operation mode
- enum camera_mode {
- CAMERA_PREVIEW_MODE = 0, // frame automatically released
- CAMERA_RECORDING_MODE = 1, // frame has to be explicitly released by releaseRecordingFrame()
- };
- // these are internal functions used for preview/recording
- status_t startCameraMode(camera_mode mode);
- status_t startPreviewMode();
- status_t startRecordingMode();
-
- // these are static callback functions
- static void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user);
- static void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user);
- static void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr, void* user);
- // convert client from cookie
- static sp<Client> getClientFromCookie(void* user);
- // handlers for messages
- void handleShutter(image_rect_type *size);
- void handlePreviewData(const sp<IMemory>& mem);
- void handlePostview(const sp<IMemory>& mem);
- void handleRawPicture(const sp<IMemory>& mem);
- void handleCompressedPicture(const sp<IMemory>& mem);
- void handleGenericNotify(int32_t msgType, int32_t ext1, int32_t ext2);
- void handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr);
- void handleGenericDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
-
- void copyFrameAndPostCopiedFrame(
- const sp<ICameraClient>& client,
- const sp<IMemoryHeap>& heap,
- size_t offset, size_t size);
-
- // these are initialized in the constructor.
- sp<CameraService> mCameraService; // immutable after constructor
- sp<ICameraClient> mCameraClient;
- int mCameraId; // immutable after constructor
- pid_t mClientPid;
- sp<CameraHardwareInterface> mHardware; // cleared after disconnect()
- bool mUseOverlay; // immutable after constructor
- sp<OverlayRef> mOverlayRef;
- int mOverlayW;
- int mOverlayH;
- int mPreviewCallbackFlag;
- int mOrientation;
-
- // Ensures atomicity among the public methods
- mutable Mutex mLock;
- sp<ISurface> mSurface;
-
- // If the user want us to return a copy of the preview frame (instead
- // of the original one), we allocate mPreviewBuffer and reuse it if possible.
- sp<MemoryHeapBase> mPreviewBuffer;
-
- // We need to avoid the deadlock when the incoming command thread and
- // the CameraHardwareInterface callback thread both want to grab mLock.
- // An extra flag is used to tell the callback thread that it should stop
- // trying to deliver the callback messages if the client is not
- // interested in it anymore. For example, if the client is calling
- // stopPreview(), the preview frame messages do not need to be delivered
- // anymore.
-
- // This function takes the same parameter as the enableMsgType() and
- // disableMsgType() functions in CameraHardwareInterface.
- void enableMsgType(int32_t msgType);
- void disableMsgType(int32_t msgType);
- volatile int32_t mMsgEnabled;
-
- // This function keeps trying to grab mLock, or give up if the message
- // is found to be disabled. It returns true if mLock is grabbed.
- bool lockIfMessageWanted(int32_t msgType);
- };
-};
-
-} // namespace android
-
-#endif
diff --git a/camera/libcameraservice/CannedJpeg.h b/camera/libcameraservice/CannedJpeg.h
deleted file mode 100644
index b6266fb..0000000
--- a/camera/libcameraservice/CannedJpeg.h
+++ /dev/null
@@ -1,734 +0,0 @@
-const int kCannedJpegWidth = 320;
-const int kCannedJpegHeight = 240;
-const int kCannedJpegSize = 8733;
-
-const char kCannedJpeg[] = {
- 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
- 0x01, 0x01, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0xff, 0xe1, 0x00, 0x66,
- 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x49, 0x49, 0x2a, 0x00, 0x08, 0x00,
- 0x00, 0x00, 0x04, 0x00, 0x1a, 0x01, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x3e, 0x00, 0x00, 0x00, 0x1b, 0x01, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x46, 0x00, 0x00, 0x00, 0x28, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x31, 0x01, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x50, 0x61, 0x69, 0x6e, 0x74, 0x2e, 0x4e, 0x45, 0x54, 0x20, 0x76, 0x33,
- 0x2e, 0x33, 0x36, 0x00, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02,
- 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x05,
- 0x08, 0x05, 0x05, 0x04, 0x04, 0x05, 0x0a, 0x07, 0x07, 0x06, 0x08, 0x0c,
- 0x0a, 0x0c, 0x0c, 0x0b, 0x0a, 0x0b, 0x0b, 0x0d, 0x0e, 0x12, 0x10, 0x0d,
- 0x0e, 0x11, 0x0e, 0x0b, 0x0b, 0x10, 0x16, 0x10, 0x11, 0x13, 0x14, 0x15,
- 0x15, 0x15, 0x0c, 0x0f, 0x17, 0x18, 0x16, 0x14, 0x18, 0x12, 0x14, 0x15,
- 0x14, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05,
- 0x09, 0x05, 0x05, 0x09, 0x14, 0x0d, 0x0b, 0x0d, 0x14, 0x14, 0x14, 0x14,
- 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
- 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
- 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
- 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xff, 0xc0,
- 0x00, 0x11, 0x08, 0x00, 0xf0, 0x01, 0x40, 0x03, 0x01, 0x22, 0x00, 0x02,
- 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00, 0x1f, 0x00, 0x00, 0x01,
- 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
- 0x0a, 0x0b, 0xff, 0xc4, 0x00, 0xb5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03,
- 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01,
- 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13,
- 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23,
- 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82,
- 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29,
- 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
- 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
- 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
- 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a,
- 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4,
- 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
- 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca,
- 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3,
- 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
- 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc4, 0x00, 0x1f, 0x01, 0x00, 0x03,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
- 0x0a, 0x0b, 0xff, 0xc4, 0x00, 0xb5, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04,
- 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00,
- 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51,
- 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1,
- 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a,
- 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27,
- 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
- 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75,
- 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
- 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2,
- 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5,
- 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
- 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2,
- 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5,
- 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00,
- 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0xf9, 0xd2, 0xa3, 0x95, 0xbb,
- 0x54, 0x84, 0xe0, 0x66, 0xa0, 0x27, 0x27, 0x35, 0xed, 0x9e, 0x50, 0x95,
- 0x2c, 0x4b, 0xc6, 0x6a, 0x35, 0x1b, 0x8e, 0x2a, 0x70, 0x30, 0x28, 0x00,
- 0xa8, 0xe5, 0x6e, 0x71, 0x52, 0x31, 0xda, 0x33, 0x50, 0x13, 0x93, 0x40,
- 0x09, 0x52, 0xc6, 0xb8, 0x19, 0xf5, 0xa6, 0x2a, 0xee, 0x6c, 0x54, 0xd4,
- 0x00, 0x54, 0x52, 0x36, 0x5b, 0x1e, 0x95, 0x23, 0xb6, 0xd5, 0xcd, 0x41,
- 0x40, 0x05, 0x4c, 0x8b, 0xb5, 0x7d, 0xea, 0x34, 0x5d, 0xcd, 0xed, 0x53,
- 0x50, 0x01, 0x50, 0xbb, 0x6e, 0x6f, 0x6a, 0x91, 0xdb, 0x6a, 0xfb, 0xd4,
- 0x34, 0x00, 0x54, 0xe8, 0xbb, 0x57, 0x15, 0x1c, 0x6b, 0x96, 0xcf, 0xa5,
- 0x4b, 0x40, 0x05, 0x42, 0xcd, 0xb9, 0xb3, 0x4f, 0x91, 0xb0, 0x31, 0xeb,
- 0x51, 0x50, 0x02, 0x81, 0x93, 0x53, 0xa8, 0xda, 0x31, 0x51, 0xc4, 0xbc,
- 0xe6, 0xa4, 0xa0, 0x00, 0x9c, 0x0a, 0x81, 0x8e, 0xe3, 0x9a, 0x92, 0x56,
- 0xe3, 0x15, 0x15, 0x00, 0x28, 0x19, 0x38, 0xa9, 0xc0, 0xc0, 0xc5, 0x47,
- 0x12, 0xf7, 0xa9, 0x28, 0x00, 0x27, 0x00, 0x9a, 0x80, 0x9c, 0x9c, 0xd3,
- 0xe5, 0x6e, 0xd5, 0x1d, 0x00, 0x2a, 0x8d, 0xc7, 0x15, 0x3d, 0x32, 0x35,
- 0xc0, 0xcf, 0xad, 0x3e, 0x80, 0x11, 0x8e, 0xd1, 0x9a, 0x82, 0x9f, 0x23,
- 0x64, 0xe3, 0xd2, 0x99, 0x40, 0x0e, 0x45, 0xdc, 0xde, 0xd5, 0x35, 0x36,
- 0x35, 0xc2, 0xfb, 0x9a, 0x75, 0x00, 0x35, 0xdb, 0x6a, 0xfb, 0xd4, 0x34,
- 0xe9, 0x1b, 0x73, 0x7b, 0x0a, 0x6d, 0x00, 0x3e, 0x35, 0xcb, 0x7b, 0x0a,
- 0x96, 0x91, 0x17, 0x6a, 0xd2, 0xd0, 0x03, 0x64, 0x6c, 0x2f, 0xb9, 0xa8,
- 0x69, 0xce, 0xdb, 0x9a, 0x9b, 0xd6, 0x80, 0x1f, 0x12, 0xe4, 0xe7, 0xd2,
- 0xa5, 0xa4, 0x51, 0xb4, 0x62, 0x97, 0xa5, 0x00, 0x67, 0xc9, 0xad, 0xd8,
- 0x91, 0x81, 0x72, 0x9f, 0x9d, 0x47, 0xfd, 0xb3, 0x65, 0xff, 0x00, 0x3f,
- 0x29, 0x5f, 0xa0, 0x1f, 0xf0, 0xe9, 0x6f, 0x09, 0x7f, 0xd0, 0xfb, 0xad,
- 0x7f, 0xe0, 0x24, 0x34, 0x7f, 0xc3, 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43,
- 0xee, 0xb5, 0xff, 0x00, 0x80, 0x90, 0xd7, 0x3f, 0xb7, 0x87, 0x73, 0x6f,
- 0x63, 0x33, 0xe0, 0x28, 0xf5, 0x9b, 0x11, 0xc9, 0xb9, 0x4c, 0xfd, 0x69,
- 0xff, 0x00, 0xdb, 0x96, 0x1f, 0xf3, 0xf5, 0x1f, 0xe7, 0x5f, 0x7d, 0x7f,
- 0xc3, 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee, 0xb5, 0xff, 0x00, 0x80,
- 0x90, 0xd1, 0xff, 0x00, 0x0e, 0x96, 0xf0, 0x97, 0xfd, 0x0f, 0xba, 0xd7,
- 0xfe, 0x02, 0x43, 0x47, 0xb7, 0x87, 0x70, 0xf6, 0x33, 0x3e, 0x02, 0x93,
- 0x5b, 0xb1, 0x3c, 0x0b, 0x94, 0xc7, 0xd6, 0x99, 0xfd, 0xb3, 0x65, 0xff,
- 0x00, 0x3f, 0x29, 0xf9, 0xd7, 0xe8, 0x07, 0xfc, 0x3a, 0x5b, 0xc2, 0x5f,
- 0xf4, 0x3e, 0xeb, 0x5f, 0xf8, 0x09, 0x0d, 0x1f, 0xf0, 0xe9, 0x6f, 0x09,
- 0x7f, 0xd0, 0xfb, 0xad, 0x7f, 0xe0, 0x24, 0x34, 0xbd, 0xbc, 0x03, 0xd8,
- 0xcc, 0xf8, 0x0e, 0x3d, 0x6a, 0xc1, 0x47, 0x37, 0x29, 0x9f, 0xad, 0x3b,
- 0xfb, 0x72, 0xc3, 0xfe, 0x7e, 0xa3, 0xfc, 0xeb, 0xef, 0xaf, 0xf8, 0x74,
- 0xb7, 0x84, 0xbf, 0xe8, 0x7d, 0xd6, 0xbf, 0xf0, 0x12, 0x1a, 0x3f, 0xe1,
- 0xd2, 0xde, 0x12, 0xff, 0x00, 0xa1, 0xf7, 0x5a, 0xff, 0x00, 0xc0, 0x48,
- 0x69, 0xfb, 0x78, 0x77, 0x0f, 0x63, 0x33, 0xe0, 0x19, 0x35, 0xbb, 0x26,
- 0x3c, 0x5c, 0xa6, 0x3e, 0xb4, 0xdf, 0xed, 0x9b, 0x2f, 0xf9, 0xf9, 0x4a,
- 0xfd, 0x00, 0xff, 0x00, 0x87, 0x4b, 0x78, 0x4b, 0xfe, 0x87, 0xdd, 0x6b,
- 0xff, 0x00, 0x01, 0x21, 0xa3, 0xfe, 0x1d, 0x2d, 0xe1, 0x2f, 0xfa, 0x1f,
- 0x75, 0xaf, 0xfc, 0x04, 0x86, 0x97, 0xb7, 0x80, 0x7b, 0x19, 0x9f, 0x01,
- 0xa6, 0xb5, 0x60, 0xab, 0xff, 0x00, 0x1f, 0x51, 0xe7, 0xeb, 0x4e, 0xfe,
- 0xdc, 0xb0, 0xff, 0x00, 0x9f, 0xa8, 0xff, 0x00, 0x3a, 0xfb, 0xeb, 0xfe,
- 0x1d, 0x2d, 0xe1, 0x2f, 0xfa, 0x1f, 0x75, 0xaf, 0xfc, 0x04, 0x86, 0x8f,
- 0xf8, 0x74, 0xb7, 0x84, 0xbf, 0xe8, 0x7d, 0xd6, 0xbf, 0xf0, 0x12, 0x1a,
- 0x3d, 0xbc, 0x03, 0xd8, 0xcc, 0xf8, 0x05, 0xf5, 0xab, 0x26, 0x6f, 0xf8,
- 0xf9, 0x4c, 0x7d, 0x69, 0xbf, 0xdb, 0x36, 0x5f, 0xf3, 0xf2, 0x9f, 0x9d,
- 0x7e, 0x80, 0x7f, 0xc3, 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee, 0xb5,
- 0xff, 0x00, 0x80, 0x90, 0xd1, 0xff, 0x00, 0x0e, 0x96, 0xf0, 0x97, 0xfd,
- 0x0f, 0xba, 0xd7, 0xfe, 0x02, 0x43, 0x47, 0xb7, 0x80, 0x7b, 0x19, 0x9f,
- 0x02, 0x26, 0xb5, 0x60, 0xab, 0x8f, 0xb5, 0x47, 0xf9, 0xd2, 0xff, 0x00,
- 0x6e, 0x58, 0x7f, 0xcf, 0xd4, 0x7f, 0x9d, 0x7d, 0xf5, 0xff, 0x00, 0x0e,
- 0x96, 0xf0, 0x97, 0xfd, 0x0f, 0xba, 0xd7, 0xfe, 0x02, 0x43, 0x47, 0xfc,
- 0x3a, 0x5b, 0xc2, 0x5f, 0xf4, 0x3e, 0xeb, 0x5f, 0xf8, 0x09, 0x0d, 0x1e,
- 0xde, 0x01, 0xec, 0x66, 0x7c, 0x00, 0xda, 0xd5, 0x93, 0x1c, 0xfd, 0xa5,
- 0x3f, 0x3a, 0x4f, 0xed, 0x8b, 0x2f, 0xf9, 0xf9, 0x4f, 0xce, 0xbf, 0x40,
- 0x3f, 0xe1, 0xd2, 0xde, 0x12, 0xff, 0x00, 0xa1, 0xf7, 0x5a, 0xff, 0x00,
- 0xc0, 0x48, 0x68, 0xff, 0x00, 0x87, 0x4b, 0x78, 0x4b, 0xfe, 0x87, 0xdd,
- 0x6b, 0xff, 0x00, 0x01, 0x21, 0xa7, 0xed, 0xe1, 0xdc, 0x3d, 0x8c, 0xcf,
- 0x81, 0x57, 0x5a, 0xb0, 0x51, 0x8f, 0xb5, 0x47, 0xf9, 0xd1, 0xfd, 0xb9,
- 0x61, 0xff, 0x00, 0x3f, 0x49, 0xf9, 0xd7, 0xdf, 0x5f, 0xf0, 0xe9, 0x6f,
- 0x09, 0x7f, 0xd0, 0xfb, 0xad, 0x7f, 0xe0, 0x24, 0x34, 0x7f, 0xc3, 0xa5,
- 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee, 0xb5, 0xff, 0x00, 0x80, 0x90, 0xd2,
- 0xf6, 0xf0, 0x0f, 0x63, 0x33, 0xe0, 0x06, 0xd6, 0xac, 0x98, 0xe7, 0xed,
- 0x29, 0xf9, 0xd2, 0x0d, 0x62, 0xcb, 0xfe, 0x7e, 0x53, 0xf3, 0xaf, 0xd0,
- 0x0f, 0xf8, 0x74, 0xb7, 0x84, 0xbf, 0xe8, 0x7d, 0xd6, 0xbf, 0xf0, 0x12,
- 0x1a, 0x3f, 0xe1, 0xd2, 0xde, 0x12, 0xff, 0x00, 0xa1, 0xf7, 0x5a, 0xff,
- 0x00, 0xc0, 0x48, 0x69, 0xfb, 0x78, 0x77, 0x0f, 0x63, 0x33, 0xe0, 0x51,
- 0xad, 0xd8, 0x01, 0x8f, 0xb5, 0x47, 0xf9, 0xd0, 0x75, 0xcb, 0x0c, 0x7f,
- 0xc7, 0xca, 0x7e, 0x75, 0xf7, 0xd7, 0xfc, 0x3a, 0x5b, 0xc2, 0x5f, 0xf4,
- 0x3e, 0xeb, 0x5f, 0xf8, 0x09, 0x0d, 0x1f, 0xf0, 0xe9, 0x6f, 0x09, 0x7f,
- 0xd0, 0xfb, 0xad, 0x7f, 0xe0, 0x24, 0x34, 0x7b, 0x78, 0x77, 0x0f, 0x63,
- 0x33, 0xf3, 0xfc, 0xeb, 0x36, 0x44, 0xff, 0x00, 0xc7, 0xca, 0x7e, 0x74,
- 0xa3, 0x58, 0xb1, 0x24, 0x66, 0xe5, 0x31, 0xf5, 0xaf, 0xbf, 0xff, 0x00,
- 0xe1, 0xd2, 0xde, 0x12, 0xff, 0x00, 0xa1, 0xf7, 0x5a, 0xff, 0x00, 0xc0,
- 0x48, 0x68, 0xff, 0x00, 0x87, 0x4b, 0x78, 0x4b, 0xfe, 0x87, 0xdd, 0x6b,
- 0xff, 0x00, 0x01, 0x21, 0xa3, 0xdb, 0xc3, 0xb8, 0x7b, 0x19, 0x9f, 0x02,
- 0xff, 0x00, 0x6d, 0xd8, 0x7f, 0xcf, 0xd4, 0x7f, 0x9d, 0x07, 0x5c, 0xb1,
- 0x03, 0x8b, 0x94, 0xcf, 0xd6, 0xbe, 0xfa, 0xff, 0x00, 0x87, 0x4b, 0x78,
- 0x4b, 0xfe, 0x87, 0xdd, 0x6b, 0xff, 0x00, 0x01, 0x21, 0xa3, 0xfe, 0x1d,
- 0x2d, 0xe1, 0x2f, 0xfa, 0x1f, 0x75, 0xaf, 0xfc, 0x04, 0x86, 0x8f, 0x6f,
- 0x0e, 0xe1, 0xec, 0x66, 0x7e, 0x7f, 0xff, 0x00, 0x6c, 0xd9, 0x7f, 0xcf,
- 0xca, 0x7e, 0x74, 0xab, 0xac, 0x58, 0xe7, 0x9b, 0x94, 0xc7, 0xd6, 0xbe,
- 0xff, 0x00, 0xff, 0x00, 0x87, 0x4b, 0x78, 0x4b, 0xfe, 0x87, 0xdd, 0x6b,
- 0xff, 0x00, 0x01, 0x21, 0xa3, 0xfe, 0x1d, 0x2d, 0xe1, 0x2f, 0xfa, 0x1f,
- 0x75, 0xaf, 0xfc, 0x04, 0x86, 0x8f, 0x6f, 0x0e, 0xe1, 0xec, 0x66, 0x7c,
- 0x0b, 0xfd, 0xb9, 0x61, 0xff, 0x00, 0x3f, 0x51, 0xfe, 0x74, 0x8d, 0xae,
- 0x58, 0xed, 0x38, 0xb9, 0x4c, 0xfd, 0x6b, 0xef, 0xbf, 0xf8, 0x74, 0xb7,
- 0x84, 0xbf, 0xe8, 0x7d, 0xd6, 0xbf, 0xf0, 0x12, 0x1a, 0x3f, 0xe1, 0xd2,
- 0xde, 0x12, 0xff, 0x00, 0xa1, 0xf7, 0x5a, 0xff, 0x00, 0xc0, 0x48, 0x68,
- 0xf6, 0xf0, 0xee, 0x1e, 0xc6, 0x67, 0xe7, 0xff, 0x00, 0xf6, 0xc5, 0x97,
- 0xfc, 0xfc, 0xa7, 0xe7, 0x4e, 0x4d, 0x62, 0xc7, 0x77, 0x37, 0x29, 0xf9,
- 0xd7, 0xdf, 0xdf, 0xf0, 0xe9, 0x6f, 0x09, 0x7f, 0xd0, 0xfb, 0xad, 0x7f,
- 0xe0, 0x24, 0x34, 0x7f, 0xc3, 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee,
- 0xb5, 0xff, 0x00, 0x80, 0x90, 0xd1, 0xed, 0xe1, 0xdc, 0x3d, 0x8c, 0xcf,
- 0x81, 0x7f, 0xb7, 0x2c, 0x3f, 0xe7, 0xea, 0x3f, 0xce, 0x91, 0xf5, 0xcb,
- 0x1c, 0x71, 0x72, 0x9f, 0x9d, 0x7d, 0xf7, 0xff, 0x00, 0x0e, 0x96, 0xf0,
- 0x97, 0xfd, 0x0f, 0xba, 0xd7, 0xfe, 0x02, 0x43, 0x47, 0xfc, 0x3a, 0x5b,
- 0xc2, 0x5f, 0xf4, 0x3e, 0xeb, 0x5f, 0xf8, 0x09, 0x0d, 0x1e, 0xde, 0x1d,
- 0xc3, 0xd8, 0xcc, 0xfc, 0xff, 0x00, 0xfe, 0xd9, 0xb2, 0xff, 0x00, 0x9f,
- 0x94, 0xfc, 0xe9, 0xd1, 0xeb, 0x36, 0x20, 0xe4, 0xdc, 0xa7, 0xe7, 0x5f,
- 0x7f, 0x7f, 0xc3, 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee, 0xb5, 0xff,
- 0x00, 0x80, 0x90, 0xd1, 0xff, 0x00, 0x0e, 0x96, 0xf0, 0x97, 0xfd, 0x0f,
- 0xba, 0xd7, 0xfe, 0x02, 0x43, 0x47, 0xb7, 0x87, 0x70, 0xf6, 0x33, 0x3e,
- 0x05, 0xfe, 0xdc, 0xb0, 0xff, 0x00, 0x9f, 0xa8, 0xff, 0x00, 0x3a, 0x6c,
- 0x9a, 0xdd, 0x89, 0x18, 0x17, 0x29, 0xf9, 0xd7, 0xdf, 0x9f, 0xf0, 0xe9,
- 0x6f, 0x09, 0x7f, 0xd0, 0xfb, 0xad, 0x7f, 0xe0, 0x24, 0x34, 0x7f, 0xc3,
- 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee, 0xb5, 0xff, 0x00, 0x80, 0x90,
- 0xd1, 0xed, 0xe1, 0xdc, 0x3d, 0x8c, 0xcf, 0xbc, 0xa8, 0xa2, 0x8a, 0xf3,
- 0x0e, 0xf0, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a,
- 0x28, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a,
- 0x28, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0xa0, 0xbb, 0xbd, 0xb7, 0xb0,
- 0x88, 0x49, 0x73, 0x3c, 0x56, 0xf1, 0x96, 0x0a, 0x1e, 0x57, 0x0a, 0x09,
- 0x3d, 0x06, 0x4f, 0x7a, 0x9e, 0x95, 0xd3, 0x76, 0xea, 0x01, 0x45, 0x14,
- 0x53, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a, 0x82, 0xda, 0xf6, 0xde,
- 0xf0, 0xca, 0x2d, 0xe7, 0x8a, 0x73, 0x13, 0x98, 0xe4, 0xf2, 0xdc, 0x36,
- 0xc6, 0x1d, 0x54, 0xe3, 0xa1, 0xf6, 0xa4, 0xda, 0x4e, 0xcc, 0x09, 0xe8,
- 0xa2, 0x8a, 0x60, 0x14, 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x14,
- 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x14,
- 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x02, 0xb8,
- 0x51, 0x45, 0x14, 0x05, 0xc2, 0x8a, 0x28, 0xa0, 0x2e, 0x14, 0x51, 0x45,
- 0x01, 0x70, 0xa2, 0x8a, 0x28, 0x18, 0x51, 0x45, 0x14, 0x0a, 0xe1, 0x45,
- 0x14, 0x50, 0x17, 0x0a, 0x28, 0xa2, 0x80, 0xb9, 0xca, 0xfc, 0x4a, 0xf0,
- 0x52, 0x78, 0xef, 0xc2, 0xb7, 0x1a, 0x76, 0xef, 0x2e, 0xe5, 0x4f, 0x9d,
- 0x6c, 0xe4, 0xe0, 0x09, 0x00, 0x38, 0xcf, 0xb1, 0xc9, 0x1f, 0x8e, 0x7b,
- 0x57, 0x3d, 0xf0, 0x5b, 0xc7, 0x53, 0x6b, 0xba, 0x6c, 0xda, 0x16, 0xaa,
- 0x5a, 0x3d, 0x73, 0x4a, 0xfd, 0xd4, 0x8b, 0x2f, 0xdf, 0x91, 0x01, 0xc0,
- 0x27, 0xdc, 0x1e, 0x0f, 0xe0, 0x7b, 0xd7, 0xa3, 0x5c, 0xdc, 0xc5, 0x67,
- 0x04, 0x93, 0xcf, 0x2a, 0x43, 0x0c, 0x60, 0xb3, 0xc9, 0x23, 0x05, 0x55,
- 0x1e, 0xa4, 0x9e, 0x95, 0xf3, 0x47, 0xc4, 0x8f, 0x1f, 0xe9, 0x36, 0xdf,
- 0x10, 0xed, 0x3c, 0x41, 0xe1, 0x39, 0x99, 0xaf, 0xa1, 0xe2, 0xea, 0x42,
- 0x98, 0x82, 0x72, 0x38, 0xe3, 0x90, 0x4e, 0x46, 0x41, 0xe9, 0x9c, 0x0c,
- 0x7a, 0xd7, 0xc4, 0x67, 0x98, 0x9a, 0x59, 0x3e, 0x26, 0x9e, 0x64, 0xa6,
- 0x93, 0x7e, 0xec, 0xe3, 0x7d, 0x65, 0x1e, 0xe9, 0x77, 0x8b, 0xd7, 0xd3,
- 0x4b, 0x99, 0x4d, 0xa8, 0xbe, 0x63, 0xe9, 0xca, 0x2b, 0xe4, 0x3d, 0x73,
- 0xe3, 0x3f, 0x8b, 0xb5, 0xc6, 0x6d, 0xfa, 0xb4, 0x96, 0x71, 0x9e, 0x91,
- 0x59, 0x0f, 0x28, 0x0f, 0xc4, 0x7c, 0xdf, 0x99, 0xae, 0x56, 0xe7, 0x5a,
- 0xd4, 0x6f, 0x18, 0xb5, 0xc5, 0xfd, 0xd4, 0xec, 0x7b, 0xc9, 0x33, 0x31,
- 0xfd, 0x4d, 0x78, 0x75, 0xf8, 0xfb, 0x0b, 0x07, 0x6a, 0x14, 0x65, 0x25,
- 0xe6, 0xd2, 0xff, 0x00, 0x32, 0x1d, 0x75, 0xd1, 0x1f, 0x73, 0x51, 0x5f,
- 0x0b, 0xdb, 0xea, 0xf7, 0xf6, 0xad, 0xba, 0x0b, 0xdb, 0x88, 0x58, 0x77,
- 0x8e, 0x56, 0x53, 0xfa, 0x1a, 0xe9, 0xf4, 0x5f, 0x8b, 0xfe, 0x2e, 0xd0,
- 0xd9, 0x7c, 0xad, 0x66, 0x7b, 0x84, 0x1f, 0xf2, 0xce, 0xec, 0xf9, 0xc0,
- 0xff, 0x00, 0xdf, 0x59, 0x23, 0xf0, 0x34, 0xa8, 0x71, 0xf6, 0x1a, 0x4e,
- 0xd5, 0xa8, 0x4a, 0x2b, 0xc9, 0xa7, 0xfe, 0x40, 0xab, 0xae, 0xa8, 0xfa,
- 0x13, 0xe2, 0xff, 0x00, 0x8f, 0xcf, 0x82, 0xfc, 0x3e, 0x21, 0xb3, 0x6d,
- 0xda, 0xcd, 0xfe, 0x62, 0xb5, 0x45, 0xe5, 0x97, 0xb1, 0x7c, 0x7b, 0x67,
- 0x8f, 0x72, 0x3d, 0xea, 0x5f, 0x84, 0x7e, 0x05, 0x6f, 0x04, 0x78, 0x60,
- 0x2d, 0xd1, 0x2d, 0xa9, 0xde, 0xb0, 0x9e, 0xe8, 0x93, 0x9d, 0xad, 0x8e,
- 0x17, 0xf0, 0x1d, 0x4f, 0xa9, 0x35, 0xe2, 0x5e, 0x13, 0xf8, 0x89, 0x61,
- 0xac, 0xfc, 0x49, 0x8f, 0xc4, 0x3e, 0x30, 0x76, 0xcc, 0x68, 0x16, 0xd8,
- 0x43, 0x19, 0x68, 0x61, 0x61, 0xd0, 0x91, 0x92, 0x40, 0x1c, 0x9e, 0x33,
- 0xc9, 0xcd, 0x7d, 0x3b, 0x63, 0x7f, 0x6d, 0xaa, 0x5a, 0x45, 0x75, 0x69,
- 0x3c, 0x77, 0x36, 0xd2, 0x8d, 0xc9, 0x2c, 0x4c, 0x19, 0x58, 0x7b, 0x11,
- 0x5e, 0xde, 0x4d, 0x8b, 0xa3, 0x9d, 0xe3, 0x2a, 0x66, 0x1c, 0xe9, 0xf2,
- 0x5e, 0x30, 0x8f, 0x58, 0xae, 0xb2, 0x6b, 0xbc, 0xbf, 0x05, 0xa1, 0x50,
- 0x6a, 0x6f, 0x98, 0xb1, 0x45, 0x14, 0x57, 0xdc, 0x9b, 0x5c, 0x28, 0xa2,
- 0x8a, 0x02, 0xe1, 0x45, 0x14, 0x50, 0x17, 0x0a, 0x28, 0xa2, 0x80, 0xb8,
- 0x51, 0x45, 0x14, 0x05, 0xc2, 0x8a, 0x28, 0xa0, 0x2e, 0x14, 0x51, 0x45,
- 0x01, 0x70, 0xa2, 0x8a, 0x28, 0x0b, 0x8d, 0xcd, 0x19, 0xa6, 0xe4, 0x51,
- 0x91, 0x55, 0x62, 0x47, 0x66, 0x8c, 0xd3, 0x72, 0x28, 0xc8, 0xa2, 0xc0,
- 0x3b, 0x34, 0x66, 0x9b, 0x91, 0x46, 0x45, 0x16, 0x01, 0xd9, 0xa3, 0x34,
- 0xdc, 0x8a, 0x32, 0x28, 0xb0, 0x0e, 0xcd, 0x19, 0xa6, 0xe4, 0x52, 0xe4,
- 0x51, 0x60, 0xb8, 0xb9, 0xa3, 0x34, 0xdc, 0x8a, 0x32, 0x28, 0xb0, 0x0e,
- 0xdd, 0x46, 0x69, 0xb9, 0x14, 0x64, 0x51, 0x60, 0x1d, 0x9a, 0xa7, 0xac,
- 0x6b, 0x16, 0x9a, 0x0e, 0x9b, 0x71, 0xa8, 0x5f, 0x4c, 0x20, 0xb5, 0x81,
- 0x37, 0xbb, 0x9e, 0xc3, 0xd0, 0x7a, 0x93, 0xd0, 0x0a, 0xb5, 0x91, 0x5f,
- 0x39, 0xfe, 0xd1, 0x1e, 0x37, 0x7d, 0x4b, 0x5a, 0x4f, 0x0f, 0x5b, 0x48,
- 0x45, 0xa5, 0x96, 0x1e, 0x70, 0xa7, 0xef, 0xca, 0x46, 0x40, 0x3f, 0xee,
- 0x83, 0xf9, 0x93, 0xe9, 0x5e, 0x06, 0x79, 0x9a, 0xc3, 0x27, 0xc1, 0x4b,
- 0x12, 0xd5, 0xe5, 0xb4, 0x57, 0x76, 0xff, 0x00, 0xab, 0xbf, 0x24, 0x44,
- 0xe5, 0xca, 0xae, 0x72, 0xbf, 0x12, 0xbe, 0x2a, 0xea, 0x3e, 0x3e, 0xbd,
- 0x78, 0xd5, 0x9e, 0xd3, 0x48, 0x46, 0xfd, 0xd5, 0xa2, 0x9f, 0xbd, 0xe8,
- 0xcf, 0xea, 0x7f, 0x41, 0xdb, 0xd4, 0xc3, 0xe0, 0x5f, 0x85, 0x1a, 0xd7,
- 0x8f, 0xed, 0xe6, 0xb9, 0xb1, 0xf2, 0x2d, 0xed, 0x22, 0x6d, 0x86, 0x7b,
- 0x96, 0x21, 0x59, 0xb1, 0x9c, 0x0c, 0x02, 0x4f, 0x51, 0xf9, 0xd7, 0x19,
- 0x5e, 0xcd, 0xf0, 0x73, 0xe3, 0x16, 0x97, 0xe1, 0x0d, 0x06, 0x4d, 0x23,
- 0x57, 0x49, 0x63, 0x44, 0x95, 0xa5, 0x86, 0x78, 0x53, 0x78, 0x21, 0xba,
- 0xab, 0x0e, 0xb9, 0xcf, 0x7f, 0x7f, 0x6a, 0xfc, 0x1b, 0x2e, 0xa9, 0x87,
- 0xcd, 0xb3, 0x2f, 0x69, 0x9c, 0xd5, 0x6a, 0x2e, 0xfa, 0xde, 0xda, 0xf4,
- 0x57, 0xe8, 0xbf, 0xe1, 0x8e, 0x48, 0xda, 0x52, 0xf7, 0x8f, 0x30, 0xf1,
- 0x57, 0x85, 0x75, 0x0f, 0x06, 0xeb, 0x12, 0x69, 0xba, 0x94, 0x42, 0x3b,
- 0x84, 0x01, 0x83, 0x21, 0xca, 0xba, 0x9e, 0x8c, 0xa7, 0xb8, 0xac, 0x8a,
- 0xed, 0x3e, 0x2c, 0xf8, 0xee, 0x1f, 0x1f, 0xf8, 0x9c, 0x5e, 0xda, 0xc2,
- 0xf0, 0xda, 0x41, 0x08, 0x82, 0x2f, 0x33, 0x01, 0xd8, 0x02, 0x49, 0x63,
- 0xe9, 0xc9, 0x3c, 0x57, 0x17, 0x5e, 0x26, 0x3e, 0x9e, 0x1e, 0x96, 0x2a,
- 0xa4, 0x30, 0xb2, 0xe6, 0xa6, 0x9b, 0xb3, 0xee, 0x88, 0x76, 0xbe, 0x81,
- 0x5a, 0x1a, 0x06, 0x83, 0x7b, 0xe2, 0x7d, 0x5e, 0xdf, 0x4d, 0xd3, 0xe2,
- 0xf3, 0xae, 0xa7, 0x38, 0x55, 0xce, 0x00, 0x00, 0x64, 0x92, 0x7b, 0x00,
- 0x39, 0xac, 0xfa, 0xea, 0x3e, 0x1b, 0x78, 0xc1, 0x7c, 0x0d, 0xe2, 0xcb,
- 0x5d, 0x52, 0x58, 0x4c, 0xf6, 0xe1, 0x5a, 0x39, 0x51, 0x3e, 0xf6, 0xd6,
- 0x18, 0x24, 0x7b, 0x8e, 0x0d, 0x67, 0x83, 0x85, 0x1a, 0x98, 0x8a, 0x70,
- 0xc4, 0x4b, 0x96, 0x0d, 0xae, 0x67, 0xd9, 0x5f, 0x50, 0x56, 0xbe, 0xa6,
- 0x97, 0x8d, 0x7e, 0x0e, 0xeb, 0xde, 0x06, 0xd3, 0x17, 0x50, 0xbb, 0x36,
- 0xf7, 0x56, 0x99, 0x0b, 0x24, 0x96, 0xae, 0x4f, 0x96, 0x4f, 0x4d, 0xc0,
- 0x81, 0xc1, 0x3c, 0x66, 0xa9, 0xfc, 0x3e, 0xf8, 0x93, 0xaa, 0x78, 0x03,
- 0x50, 0x0f, 0x6c, 0xe6, 0x7b, 0x07, 0x6f, 0xdf, 0xd9, 0x3b, 0x7c, 0x8e,
- 0x3d, 0x47, 0xa3, 0x7b, 0xfe, 0x79, 0xaf, 0x45, 0xf8, 0xad, 0xf1, 0xb3,
- 0x47, 0xf1, 0x27, 0x85, 0x26, 0xd2, 0x34, 0x84, 0x9a, 0x67, 0xbb, 0x2b,
- 0xe6, 0xcb, 0x34, 0x7b, 0x04, 0x6a, 0x18, 0x36, 0x07, 0xa9, 0xc8, 0x1e,
- 0xd5, 0xe1, 0x95, 0xf4, 0x39, 0xab, 0xc2, 0x65, 0x79, 0x84, 0x67, 0x93,
- 0x55, 0x6d, 0x24, 0x9d, 0xd3, 0xbd, 0x9f, 0x55, 0x7e, 0xaa, 0xd6, 0xbe,
- 0xfb, 0xd8, 0xb9, 0x5a, 0x32, 0xf7, 0x59, 0xf6, 0xef, 0x86, 0xbc, 0x49,
- 0x63, 0xe2, 0xbd, 0x1a, 0xdf, 0x53, 0xd3, 0xe5, 0xf3, 0x2d, 0xe6, 0x1d,
- 0xfe, 0xf2, 0x1e, 0xea, 0xc3, 0xb1, 0x15, 0xa9, 0x9a, 0xf9, 0x7b, 0xe0,
- 0x27, 0x8d, 0xe4, 0xf0, 0xef, 0x8a, 0x53, 0x4a, 0x9e, 0x43, 0xfd, 0x9f,
- 0xa9, 0x30, 0x8f, 0x69, 0x3c, 0x24, 0xdf, 0xc0, 0xc3, 0xeb, 0xf7, 0x7f,
- 0x11, 0xe9, 0x5f, 0x4f, 0xe4, 0x57, 0xee, 0x3c, 0x3f, 0x9b, 0xc7, 0x39,
- 0xc1, 0x2a, 0xed, 0x5a, 0x6b, 0x49, 0x2f, 0x3f, 0xf2, 0x7b, 0xfe, 0x1d,
- 0x0e, 0xb8, 0x4f, 0x99, 0x5c, 0x76, 0x4d, 0x19, 0xa6, 0xe4, 0x51, 0x91,
- 0x5f, 0x4b, 0x62, 0xc7, 0x64, 0xd1, 0x9a, 0x6e, 0x45, 0x19, 0x14, 0x58,
- 0x2e, 0x3b, 0x34, 0x66, 0x9b, 0x91, 0x46, 0x45, 0x16, 0x0b, 0x8e, 0xcd,
- 0x19, 0xa6, 0xe4, 0x51, 0x91, 0x45, 0x80, 0x76, 0x68, 0xcd, 0x37, 0x34,
- 0x64, 0x51, 0x60, 0xb8, 0xec, 0xd1, 0x9a, 0x6e, 0x45, 0x19, 0x14, 0x58,
- 0x07, 0x64, 0xd1, 0x9a, 0x6e, 0x45, 0x19, 0x14, 0x58, 0x06, 0x6e, 0xa3,
- 0x75, 0x37, 0x34, 0x66, 0xae, 0xc4, 0x5c, 0x76, 0xea, 0x37, 0x53, 0x73,
- 0x46, 0x68, 0xb0, 0x5c, 0x76, 0xea, 0x37, 0x53, 0x73, 0x46, 0x68, 0xb0,
- 0x5c, 0x76, 0xea, 0x37, 0x53, 0x72, 0x28, 0xcd, 0x16, 0x0b, 0x8e, 0xdd,
- 0x46, 0xea, 0x6e, 0x68, 0xcd, 0x16, 0x0b, 0x8e, 0xdd, 0x46, 0xea, 0x6e,
- 0x68, 0xcd, 0x16, 0x0b, 0x8e, 0xdd, 0x46, 0xea, 0xc4, 0xf1, 0x57, 0x8c,
- 0x34, 0xaf, 0x06, 0x69, 0xff, 0x00, 0x6b, 0xd5, 0x2e, 0x44, 0x28, 0xc7,
- 0x08, 0x8a, 0x37, 0x3c, 0x87, 0xd1, 0x47, 0x7f, 0xe5, 0x5c, 0x0d, 0x9f,
- 0xed, 0x1f, 0xe1, 0xcb, 0x8b, 0xc1, 0x14, 0xd6, 0x97, 0xf6, 0xb0, 0x93,
- 0x81, 0x3b, 0xa2, 0xb0, 0x1e, 0xe4, 0x06, 0x27, 0xf2, 0xcd, 0x78, 0xf8,
- 0xac, 0xdf, 0x2f, 0xc0, 0xd4, 0x54, 0x71, 0x35, 0xa3, 0x19, 0x3e, 0x8d,
- 0xfe, 0x7d, 0xbe, 0x64, 0xb9, 0x25, 0xb9, 0xeb, 0x05, 0xf6, 0x82, 0x4f,
- 0x41, 0x5f, 0x10, 0xeb, 0x7a, 0x93, 0xeb, 0x3a, 0xcd, 0xf5, 0xfc, 0x84,
- 0x97, 0xb9, 0x9d, 0xe6, 0x39, 0xff, 0x00, 0x69, 0x89, 0xfe, 0xb5, 0xf6,
- 0xad, 0x8e, 0xa1, 0x6b, 0xab, 0x58, 0xc5, 0x75, 0x69, 0x34, 0x77, 0x36,
- 0xb3, 0x2e, 0xe4, 0x91, 0x0e, 0x55, 0x85, 0x78, 0x5f, 0xfc, 0x2d, 0x5f,
- 0x87, 0x3f, 0xf4, 0x25, 0x27, 0xfe, 0x00, 0xdb, 0xff, 0x00, 0x8d, 0x7c,
- 0x67, 0x18, 0xe1, 0xa8, 0x63, 0x61, 0x87, 0x55, 0x31, 0x31, 0xa7, 0x1f,
- 0x79, 0xab, 0xdd, 0xf3, 0x7c, 0x3a, 0xab, 0x76, 0xfd, 0x4c, 0xea, 0x59,
- 0xdb, 0x53, 0xc4, 0x68, 0xaf, 0x6e, 0xff, 0x00, 0x85, 0xab, 0xf0, 0xe7,
- 0xfe, 0x84, 0xa4, 0xff, 0x00, 0xc0, 0x1b, 0x7f, 0xf1, 0xa3, 0xfe, 0x16,
- 0xaf, 0xc3, 0x9f, 0xfa, 0x12, 0x93, 0xff, 0x00, 0x00, 0x6d, 0xff, 0x00,
- 0xc6, 0xbf, 0x33, 0xfe, 0xc5, 0xc0, 0xff, 0x00, 0xd0, 0x7c, 0x3e, 0xe9,
- 0x7f, 0x91, 0x8f, 0x2a, 0xee, 0x78, 0x8d, 0x15, 0xed, 0xdf, 0xf0, 0xb5,
- 0x7e, 0x1c, 0xff, 0x00, 0xd0, 0x94, 0x9f, 0xf8, 0x03, 0x6f, 0xfe, 0x34,
- 0x7f, 0xc2, 0xd5, 0xf8, 0x73, 0xff, 0x00, 0x42, 0x52, 0x7f, 0xe0, 0x0d,
- 0xbf, 0xf8, 0xd1, 0xfd, 0x8b, 0x81, 0xff, 0x00, 0xa0, 0xf8, 0x7d, 0xd2,
- 0xff, 0x00, 0x20, 0xe5, 0x5d, 0xcf, 0x11, 0xa2, 0xbd, 0xbb, 0xfe, 0x16,
- 0xaf, 0xc3, 0x9f, 0xfa, 0x12, 0x93, 0xff, 0x00, 0x00, 0x6d, 0xff, 0x00,
- 0xc6, 0x8f, 0xf8, 0x5a, 0xbf, 0x0e, 0x7f, 0xe8, 0x4a, 0x4f, 0xfc, 0x01,
- 0xb7, 0xff, 0x00, 0x1a, 0x3f, 0xb1, 0x70, 0x3f, 0xf4, 0x1f, 0x0f, 0xba,
- 0x5f, 0xe4, 0x1c, 0xab, 0xb9, 0xe2, 0x34, 0x57, 0xb7, 0x7f, 0xc2, 0xd5,
- 0xf8, 0x73, 0xff, 0x00, 0x42, 0x52, 0x7f, 0xe0, 0x0d, 0xbf, 0xf8, 0xd1,
- 0xff, 0x00, 0x0b, 0x57, 0xe1, 0xcf, 0xfd, 0x09, 0x49, 0xff, 0x00, 0x80,
- 0x36, 0xff, 0x00, 0xe3, 0x47, 0xf6, 0x2e, 0x07, 0xfe, 0x83, 0xe1, 0xf7,
- 0x4b, 0xfc, 0x83, 0x95, 0x77, 0x3c, 0x52, 0x09, 0xde, 0xda, 0x78, 0xe6,
- 0x89, 0x8a, 0x49, 0x1b, 0x07, 0x56, 0x1d, 0x41, 0x07, 0x20, 0xd7, 0xdb,
- 0xfa, 0x5d, 0xf0, 0xd4, 0x74, 0xdb, 0x4b, 0xb0, 0x30, 0x27, 0x85, 0x25,
- 0x03, 0xfd, 0xe5, 0x07, 0xfa, 0xd7, 0x85, 0xff, 0x00, 0xc2, 0xd5, 0xf8,
- 0x73, 0xff, 0x00, 0x42, 0x52, 0x7f, 0xe0, 0x0d, 0xbf, 0xf8, 0xd7, 0xb6,
- 0x69, 0x1a, 0x95, 0xa5, 0xc7, 0x87, 0xec, 0xaf, 0xe1, 0x55, 0xb3, 0xb1,
- 0x7b, 0x54, 0x99, 0x11, 0xf0, 0x82, 0x28, 0xca, 0x02, 0x01, 0xec, 0x30,
- 0x3f, 0x0e, 0x2b, 0xf4, 0x7e, 0x0e, 0xc2, 0xd0, 0xc1, 0xce, 0xbc, 0x69,
- 0x62, 0x63, 0x51, 0x34, 0x9b, 0x4a, 0xfa, 0x5a, 0xfa, 0xeb, 0xea, 0x6d,
- 0x4e, 0xca, 0xfa, 0x9a, 0x5b, 0xa8, 0xdd, 0x5e, 0x57, 0xab, 0xfe, 0xd1,
- 0x3e, 0x1b, 0xd3, 0xaf, 0x1a, 0x0b, 0x68, 0x6e, 0xf5, 0x15, 0x53, 0x83,
- 0x34, 0x28, 0xaa, 0x87, 0xe9, 0xb8, 0x82, 0x7f, 0x2a, 0xeb, 0xbc, 0x1b,
- 0xf1, 0x07, 0x45, 0xf1, 0xcd, 0xbb, 0xbe, 0x99, 0x70, 0x7c, 0xe8, 0xc6,
- 0x64, 0xb6, 0x98, 0x6d, 0x91, 0x07, 0xa9, 0x1d, 0xc7, 0xb8, 0xc8, 0xaf,
- 0xb7, 0xc3, 0xe7, 0x19, 0x76, 0x2a, 0xb7, 0xd5, 0xe8, 0x56, 0x8c, 0xa7,
- 0xd9, 0x3f, 0xcb, 0xbf, 0xc8, 0xd1, 0x49, 0x3d, 0x2e, 0x74, 0xdb, 0xa8,
- 0xcd, 0x37, 0x34, 0x64, 0x57, 0xb2, 0x55, 0xc7, 0x6e, 0xa3, 0x75, 0x37,
- 0x34, 0x66, 0x8b, 0x05, 0xc7, 0x6e, 0xa3, 0x75, 0x37, 0x34, 0x66, 0x8b,
- 0x05, 0xc7, 0x6e, 0xa3, 0x75, 0x37, 0x34, 0x66, 0x8b, 0x05, 0xc7, 0x6e,
- 0xa3, 0x75, 0x37, 0x34, 0x64, 0x51, 0x60, 0xb8, 0xed, 0xd4, 0x6e, 0xa6,
- 0xe4, 0x51, 0x9a, 0x2c, 0x17, 0x1b, 0x9a, 0x33, 0x51, 0xee, 0xa3, 0x75,
- 0x55, 0x88, 0xb9, 0x26, 0x68, 0xcd, 0x47, 0xba, 0x8d, 0xd4, 0x58, 0x2e,
- 0x49, 0x9a, 0x33, 0x51, 0xee, 0xa3, 0x75, 0x16, 0x15, 0xc9, 0x32, 0x28,
- 0xa8, 0xf7, 0x51, 0xba, 0x8b, 0x0e, 0xe4, 0x99, 0xa3, 0x35, 0x1e, 0xea,
- 0x37, 0x51, 0x60, 0xb9, 0x26, 0x68, 0xcd, 0x47, 0xba, 0x8c, 0xd3, 0xb0,
- 0x5c, 0xf9, 0x7b, 0xe3, 0xb6, 0xaf, 0x3e, 0xa5, 0xf1, 0x0e, 0xf2, 0xde,
- 0x47, 0x26, 0x1b, 0x24, 0x48, 0x62, 0x4e, 0xc0, 0x15, 0x0c, 0x4f, 0xe2,
- 0x58, 0xfe, 0x95, 0xe7, 0x95, 0xda, 0x7c, 0x64, 0xff, 0x00, 0x92, 0x97,
- 0xad, 0xff, 0x00, 0xbf, 0x1f, 0xfe, 0x8a, 0x4a, 0xe2, 0xeb, 0xf9, 0x47,
- 0x3a, 0x9c, 0xaa, 0x66, 0x78, 0x99, 0x49, 0xdd, 0xf3, 0xcb, 0xf0, 0x6d,
- 0x23, 0x92, 0x5b, 0x9e, 0xf7, 0xfb, 0x34, 0xeb, 0x13, 0xcd, 0x67, 0xac,
- 0xe9, 0xb2, 0x39, 0x6b, 0x78, 0x1a, 0x39, 0xa2, 0x04, 0xfd, 0xd2, 0xdb,
- 0x83, 0x0f, 0xc7, 0x68, 0xfd, 0x6b, 0xc1, 0x2b, 0xda, 0xff, 0x00, 0x66,
- 0x73, 0x8b, 0xed, 0x7f, 0xfe, 0xb9, 0xc3, 0xfc, 0xde, 0xbc, 0x52, 0xbd,
- 0x8c, 0xd2, 0x72, 0x9e, 0x4b, 0x97, 0x39, 0x3b, 0xdb, 0xda, 0xaf, 0x92,
- 0x92, 0xb1, 0x4f, 0xe1, 0x41, 0x45, 0x14, 0x57, 0xc6, 0x90, 0x14, 0x51,
- 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x15, 0xef,
- 0x7f, 0x13, 0xf5, 0x89, 0xf4, 0xef, 0x82, 0xbe, 0x19, 0xb6, 0x81, 0xca,
- 0x0b, 0xc8, 0x2d, 0x62, 0x94, 0x83, 0xd5, 0x04, 0x3b, 0x88, 0xfc, 0x48,
- 0x15, 0xe0, 0x95, 0xed, 0x7f, 0x17, 0x0f, 0xfc, 0x5a, 0x5f, 0x05, 0xff,
- 0x00, 0xd7, 0x38, 0x3f, 0xf4, 0x45, 0x7d, 0x96, 0x47, 0x39, 0x43, 0x03,
- 0x98, 0x4a, 0x2e, 0xcf, 0x91, 0x7e, 0x32, 0xb3, 0xfc, 0x0a, 0x8e, 0xcc,
- 0xf1, 0x4a, 0xe9, 0xbe, 0x1a, 0x6a, 0xf3, 0xe8, 0xbe, 0x3a, 0xd1, 0x67,
- 0x81, 0xca, 0x99, 0x2e, 0x52, 0x07, 0x00, 0xfd, 0xe4, 0x76, 0x0a, 0xc0,
- 0xfe, 0x07, 0xf4, 0xae, 0x66, 0xb6, 0x3c, 0x1b, 0xff, 0x00, 0x23, 0x7e,
- 0x87, 0xff, 0x00, 0x5f, 0xd0, 0x7f, 0xe8, 0xc5, 0xaf, 0x9b, 0xc0, 0xce,
- 0x54, 0xf1, 0x54, 0xa7, 0x07, 0x66, 0xa4, 0xbf, 0x31, 0x2d, 0xcf, 0xb4,
- 0x33, 0x46, 0x6a, 0x3d, 0xd4, 0x6e, 0xaf, 0xeb, 0x9b, 0x1d, 0x57, 0x24,
- 0xcd, 0x19, 0xa8, 0xf7, 0x51, 0xba, 0x8b, 0x0e, 0xe4, 0x99, 0xa3, 0x35,
- 0x1e, 0xea, 0x37, 0x51, 0x60, 0xb9, 0x26, 0x68, 0xcd, 0x47, 0xba, 0x8d,
- 0xd4, 0x58, 0x2e, 0x49, 0x9a, 0x33, 0x51, 0xee, 0xa3, 0x75, 0x16, 0x15,
- 0xc9, 0x33, 0x46, 0x6a, 0x3d, 0xd4, 0x6e, 0xa2, 0xc3, 0xb8, 0xdd, 0xd4,
- 0x9b, 0xa9, 0xbb, 0xa8, 0xdd, 0x5a, 0x19, 0xdc, 0x7e, 0xea, 0x4d, 0xd4,
- 0xdd, 0xd4, 0x6e, 0xa0, 0x57, 0x1f, 0xba, 0x8d, 0xd4, 0xcd, 0xd4, 0x6e,
- 0xa0, 0x77, 0x1f, 0xba, 0x8d, 0xd4, 0xcd, 0xd4, 0x6e, 0xa4, 0x2b, 0x8f,
- 0xdd, 0x49, 0xba, 0x9b, 0xba, 0x8d, 0xd4, 0xc2, 0xe3, 0xb7, 0x52, 0xee,
- 0xa6, 0x6e, 0xa3, 0x75, 0x20, 0xb9, 0xf2, 0x9f, 0xc6, 0x3f, 0xf9, 0x29,
- 0x5a, 0xdf, 0xfb, 0xf1, 0xff, 0x00, 0xe8, 0xb4, 0xae, 0x32, 0xbb, 0x2f,
- 0x8c, 0x5c, 0xfc, 0x49, 0xd6, 0xff, 0x00, 0xdf, 0x8f, 0xff, 0x00, 0x45,
- 0xa5, 0x71, 0xb5, 0xfc, 0x99, 0x9c, 0x7f, 0xc8, 0xcb, 0x13, 0xfe, 0x39,
- 0xff, 0x00, 0xe9, 0x4c, 0xc1, 0xee, 0x7b, 0x57, 0xec, 0xd2, 0x71, 0x7d,
- 0xaf, 0x7f, 0xd7, 0x38, 0x7f, 0x9b, 0xd7, 0x8a, 0xd7, 0xb4, 0x7e, 0xcd,
- 0x67, 0x17, 0xda, 0xf7, 0xfd, 0x73, 0x87, 0xf9, 0xbd, 0x78, 0xbd, 0x7b,
- 0x19, 0x97, 0xfc, 0x89, 0x32, 0xef, 0xfb, 0x8b, 0xff, 0x00, 0xa5, 0x21,
- 0xbd, 0x90, 0x51, 0x45, 0x15, 0xf2, 0x02, 0x0a, 0x28, 0xa2, 0x80, 0x0a,
- 0x28, 0xa2, 0x80, 0x0a, 0x28, 0xa2, 0x80, 0x0a, 0xf6, 0xaf, 0x8b, 0x47,
- 0x3f, 0x09, 0x7c, 0x17, 0xff, 0x00, 0x5c, 0xe0, 0xff, 0x00, 0xd1, 0x15,
- 0xe2, 0xb5, 0xed, 0x1f, 0x16, 0x4f, 0xfc, 0x5a, 0x6f, 0x06, 0x7f, 0xd7,
- 0x38, 0x3f, 0xf4, 0x45, 0x7d, 0x7e, 0x4d, 0xff, 0x00, 0x22, 0xfc, 0xc3,
- 0xfc, 0x11, 0xff, 0x00, 0xd2, 0x90, 0xd6, 0xcc, 0xf1, 0x7a, 0xd8, 0xf0,
- 0x67, 0xfc, 0x8e, 0x1a, 0x17, 0xfd, 0x7f, 0xc1, 0xff, 0x00, 0xa3, 0x16,
- 0xb1, 0xeb, 0x63, 0xc1, 0xdf, 0xf2, 0x37, 0x68, 0x7f, 0xf5, 0xfd, 0x07,
- 0xfe, 0x8c, 0x5a, 0xf9, 0xbc, 0x27, 0xfb, 0xcd, 0x3f, 0xf1, 0x2f, 0xcc,
- 0x48, 0xfb, 0x2b, 0x75, 0x1b, 0xa9, 0x9b, 0xa8, 0xdd, 0x5f, 0xd8, 0x16,
- 0x37, 0xb8, 0xfd, 0xd4, 0x6e, 0xa6, 0x6e, 0xa3, 0x75, 0x20, 0xb8, 0xed,
- 0xd4, 0xbb, 0xa9, 0x9b, 0xa8, 0xdd, 0x4c, 0x2e, 0x3f, 0x75, 0x26, 0xea,
- 0x6e, 0xea, 0x37, 0x52, 0x0b, 0x8f, 0xdd, 0x49, 0xba, 0x9b, 0xba, 0x8d,
- 0xd4, 0xec, 0x3b, 0x8f, 0xdd, 0x49, 0xba, 0x9b, 0xba, 0x8d, 0xd4, 0x0a,
- 0xe4, 0x74, 0x53, 0x33, 0x4b, 0x93, 0x57, 0x63, 0x3b, 0x8e, 0xa2, 0x9b,
- 0x9a, 0x4c, 0xd1, 0x60, 0xb8, 0xfa, 0x29, 0x99, 0xa3, 0x34, 0x58, 0x2e,
- 0x3f, 0x34, 0x53, 0x33, 0x4b, 0x93, 0x45, 0x82, 0xe3, 0xa8, 0xcd, 0x33,
- 0x34, 0x66, 0x8b, 0x05, 0xc7, 0xd1, 0x4d, 0xc9, 0xa3, 0x26, 0x8b, 0x05,
- 0xcf, 0x96, 0x3e, 0x30, 0x7f, 0xc9, 0x48, 0xd6, 0xbf, 0xdf, 0x8f, 0xff,
- 0x00, 0x45, 0xa5, 0x71, 0xb5, 0xdd, 0xfc, 0x6c, 0xd3, 0xa6, 0xb1, 0xf8,
- 0x85, 0x7f, 0x2c, 0x8a, 0x44, 0x77, 0x4b, 0x1c, 0xd1, 0xb7, 0x66, 0x1b,
- 0x02, 0x9f, 0xd5, 0x4d, 0x70, 0x95, 0xfc, 0x97, 0x9d, 0x42, 0x50, 0xcc,
- 0xf1, 0x31, 0x92, 0xb7, 0xbf, 0x2f, 0xfd, 0x29, 0x90, 0x7b, 0x3f, 0xec,
- 0xdb, 0xff, 0x00, 0x1f, 0xba, 0xef, 0xfd, 0x73, 0x87, 0xf9, 0xbd, 0x78,
- 0xc5, 0x7b, 0x87, 0xec, 0xe3, 0xa7, 0x4d, 0x1c, 0x3a, 0xd5, 0xf3, 0x29,
- 0x58, 0x24, 0x31, 0xc2, 0x8d, 0xfd, 0xe2, 0x37, 0x16, 0xfc, 0xb2, 0x3f,
- 0x3a, 0xf0, 0xfa, 0xf6, 0x73, 0x58, 0x4a, 0x19, 0x26, 0x5b, 0xcc, 0xad,
- 0x7f, 0x6a, 0xff, 0x00, 0xf2, 0x64, 0x01, 0x45, 0x14, 0x57, 0xc6, 0x00,
- 0x51, 0x45, 0x14, 0x00, 0x51, 0x45, 0x14, 0x00, 0x51, 0x45, 0x14, 0x00,
- 0x57, 0xb3, 0xfc, 0x57, 0xff, 0x00, 0x92, 0x51, 0xe0, 0xdf, 0xfa, 0xe7,
- 0x07, 0xfe, 0x88, 0xaf, 0x18, 0xaf, 0x70, 0xf8, 0x9b, 0xa7, 0x4d, 0x79,
- 0xf0, 0x77, 0xc3, 0x37, 0x11, 0x29, 0x74, 0xb5, 0x8a, 0xd9, 0xe4, 0xc7,
- 0x65, 0x30, 0xed, 0xcf, 0xe6, 0x40, 0xfc, 0x6b, 0xec, 0xf2, 0x38, 0x4a,
- 0x78, 0x0c, 0xc1, 0x45, 0x5f, 0xdc, 0x5f, 0x84, 0xae, 0xc0, 0xf0, 0xfa,
- 0xd8, 0xf0, 0x6f, 0xfc, 0x8d, 0xfa, 0x1f, 0xfd, 0x7f, 0x41, 0xff, 0x00,
- 0xa3, 0x16, 0xb1, 0xeb, 0xa2, 0xf8, 0x79, 0xa7, 0x4d, 0xaa, 0x78, 0xdf,
- 0x45, 0x86, 0x15, 0x2c, 0xcb, 0x75, 0x1c, 0xad, 0x8e, 0xca, 0x8c, 0x18,
- 0x9f, 0xc8, 0x57, 0xcd, 0x60, 0x61, 0x29, 0xe2, 0xe9, 0x46, 0x2a, 0xed,
- 0xca, 0x3f, 0x9a, 0x03, 0xeb, 0x9c, 0xd1, 0x4c, 0xcd, 0x2e, 0x4d, 0x7f,
- 0x60, 0x58, 0xbb, 0x8e, 0xa2, 0x99, 0x9a, 0x33, 0x45, 0x82, 0xe3, 0xe8,
- 0xa6, 0x66, 0x8c, 0xd1, 0x60, 0xb8, 0xfa, 0x29, 0x99, 0xa5, 0xc9, 0xa2,
- 0xc1, 0x71, 0xd9, 0xa2, 0x9b, 0x93, 0x49, 0x9a, 0x2c, 0x17, 0x1f, 0x45,
- 0x33, 0x34, 0x66, 0x8b, 0x05, 0xc6, 0x6e, 0xa3, 0x75, 0x30, 0x90, 0x3a,
- 0x9c, 0x51, 0x9a, 0xd2, 0xc6, 0x57, 0x1f, 0xba, 0x8d, 0xd4, 0xda, 0x4c,
- 0xd1, 0x60, 0xb8, 0xfd, 0xd4, 0x6e, 0xa6, 0x02, 0x0f, 0x43, 0x9a, 0x37,
- 0x01, 0xdf, 0x14, 0x58, 0x2e, 0x3f, 0x75, 0x1b, 0xa9, 0xb4, 0x94, 0x58,
- 0x2e, 0x3f, 0x75, 0x1b, 0xa9, 0xb4, 0x80, 0x83, 0xd0, 0xe6, 0x8b, 0x05,
- 0xc7, 0xee, 0xa3, 0x75, 0x30, 0x90, 0x3a, 0x9c, 0x51, 0x9a, 0x2c, 0x17,
- 0x31, 0x3c, 0x5d, 0xe0, 0xcd, 0x2f, 0xc6, 0xb6, 0x2b, 0x6f, 0xa8, 0xc4,
- 0x4b, 0x26, 0x4c, 0x53, 0xc6, 0x71, 0x24, 0x64, 0xf5, 0xc1, 0xfe, 0x87,
- 0x8a, 0xe0, 0x6d, 0x3f, 0x67, 0x7d, 0x32, 0x2b, 0xb0, 0xf7, 0x1a, 0xad,
- 0xcc, 0xf6, 0xe0, 0xe7, 0xca, 0x58, 0xd5, 0x09, 0x1e, 0x85, 0xb2, 0x7f,
- 0x95, 0x7a, 0xd5, 0x25, 0x78, 0x38, 0xcc, 0x87, 0x2c, 0xcc, 0x2b, 0x2a,
- 0xf8, 0x9a, 0x2a, 0x52, 0xef, 0xaa, 0xfb, 0xec, 0xd5, 0xfe, 0x77, 0x0b,
- 0x95, 0xf4, 0xad, 0x32, 0xd3, 0x44, 0xb0, 0x86, 0xca, 0xc6, 0x05, 0xb7,
- 0xb6, 0x88, 0x61, 0x23, 0x4e, 0x83, 0xfc, 0x4f, 0xbd, 0x7c, 0x6b, 0x5f,
- 0x69, 0x57, 0xc5, 0xb5, 0xf9, 0x8f, 0x88, 0xb0, 0x8d, 0x38, 0xe0, 0xe1,
- 0x05, 0x64, 0xb9, 0xec, 0x97, 0xfd, 0xb8, 0x34, 0x14, 0x51, 0x45, 0x7e,
- 0x32, 0x30, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a,
- 0x28, 0x00, 0xaf, 0xad, 0xfc, 0x2b, 0x04, 0x57, 0x9e, 0x06, 0xd1, 0xad,
- 0xe7, 0x8d, 0x66, 0x86, 0x4d, 0x3a, 0x04, 0x78, 0xdc, 0x65, 0x58, 0x18,
- 0xd7, 0x20, 0x8a, 0xf9, 0x22, 0xbe, 0xba, 0xf0, 0x67, 0xfc, 0x89, 0xfa,
- 0x17, 0xfd, 0x78, 0x41, 0xff, 0x00, 0xa2, 0xd6, 0xbf, 0x5c, 0xf0, 0xee,
- 0x2a, 0x58, 0x9c, 0x42, 0x7b, 0x72, 0xaf, 0xcc, 0x47, 0x05, 0xab, 0x7e,
- 0xcf, 0x7a, 0x4d, 0xdd, 0xdb, 0x4b, 0x65, 0xa8, 0x4f, 0x63, 0x13, 0x1c,
- 0xf9, 0x25, 0x04, 0x80, 0x7b, 0x02, 0x48, 0x3f, 0x9e, 0x6b, 0xaf, 0xf0,
- 0x57, 0xc3, 0xcd, 0x27, 0xc0, 0xd1, 0xb9, 0xb3, 0x47, 0x9a, 0xee, 0x41,
- 0xb6, 0x4b, 0xa9, 0xb0, 0x5c, 0x8f, 0x41, 0xe8, 0x3d, 0x87, 0xe3, 0x5d,
- 0x36, 0x69, 0x6b, 0xf5, 0x7c, 0x37, 0x0f, 0xe5, 0x78, 0x3a, 0xff, 0x00,
- 0x59, 0xa1, 0x41, 0x46, 0x7d, 0xf5, 0xd3, 0xd1, 0x6c, 0xbe, 0x49, 0x0a,
- 0xe3, 0xb7, 0x51, 0xba, 0x99, 0x9a, 0x03, 0x03, 0xde, 0xbd, 0xfb, 0x05,
- 0xc7, 0xee, 0xa3, 0x75, 0x30, 0x90, 0x06, 0x4f, 0x14, 0x51, 0x60, 0xb8,
- 0xfd, 0xd4, 0x6e, 0xa6, 0xd1, 0x45, 0x82, 0xe3, 0xb7, 0x51, 0xba, 0x98,
- 0x08, 0x3d, 0x0e, 0x68, 0x24, 0x0e, 0xf4, 0x58, 0x2e, 0x3f, 0x75, 0x1b,
- 0xa9, 0x94, 0xb4, 0x58, 0x2e, 0x3b, 0x75, 0x1b, 0xa9, 0x99, 0xa0, 0x10,
- 0x7a, 0x1a, 0x2c, 0x17, 0x31, 0x62, 0xbd, 0x91, 0x46, 0xf7, 0x90, 0x3e,
- 0xd3, 0xf7, 0x1b, 0xa9, 0xad, 0x58, 0xa5, 0x13, 0x46, 0xae, 0xbd, 0x08,
- 0xac, 0x3f, 0x38, 0xff, 0x00, 0x71, 0x3f, 0xef, 0x91, 0x56, 0x52, 0xf1,
- 0xe3, 0x48, 0x55, 0x42, 0x80, 0x7a, 0x80, 0x3d, 0xeb, 0xb2, 0x70, 0xbe,
- 0xc7, 0x9d, 0x4e, 0xaf, 0x2e, 0xec, 0xd6, 0xcd, 0x36, 0x59, 0x44, 0x31,
- 0xb3, 0xb7, 0x41, 0x49, 0xba, 0xb3, 0x1e, 0xf2, 0x49, 0x12, 0x65, 0x60,
- 0x08, 0x1d, 0x01, 0x1e, 0xf5, 0x84, 0x61, 0xcc, 0x75, 0x4e, 0xa7, 0x22,
- 0x1b, 0x2d, 0xec, 0x8c, 0x0b, 0xa4, 0x81, 0x37, 0x1f, 0xb8, 0xbd, 0x7e,
- 0xb4, 0xb1, 0x5e, 0xc8, 0xa0, 0x3b, 0xb8, 0x7d, 0xa7, 0xee, 0x37, 0x5f,
- 0xad, 0x57, 0xf3, 0x8f, 0xf7, 0x13, 0xfe, 0xf9, 0x14, 0x79, 0xc7, 0xfb,
- 0x89, 0xff, 0x00, 0x7c, 0x8a, 0xeb, 0xe5, 0x56, 0xb5, 0x8e, 0x0e, 0x77,
- 0x7b, 0xdc, 0xdd, 0x8e, 0x41, 0x2a, 0x2b, 0xaf, 0x42, 0x33, 0x4e, 0xac,
- 0xa8, 0xef, 0x1d, 0x3c, 0x85, 0x00, 0x05, 0x3d, 0x40, 0x1e, 0xe6, 0xb4,
- 0x77, 0x57, 0x24, 0xa3, 0xca, 0x77, 0xc2, 0x7c, 0xe8, 0x74, 0x92, 0x08,
- 0xd1, 0x99, 0x8f, 0x00, 0x66, 0xb2, 0xa5, 0xbd, 0x91, 0x81, 0x74, 0x70,
- 0x99, 0x38, 0xd8, 0x3a, 0xfd, 0x69, 0xd2, 0x5e, 0x3b, 0xf9, 0xea, 0x40,
- 0x2a, 0x3a, 0x02, 0x3d, 0xc5, 0x55, 0xf3, 0x8f, 0xf7, 0x13, 0xfe, 0xf9,
- 0x15, 0xbc, 0x21, 0x6d, 0xce, 0x6a, 0x95, 0x6f, 0xa2, 0x64, 0xf1, 0x5e,
- 0x48, 0xa3, 0x7b, 0x48, 0x1f, 0x69, 0xfb, 0x8d, 0xd4, 0xd6, 0xac, 0x52,
- 0x89, 0xa3, 0x57, 0x5e, 0x86, 0xb0, 0xfc, 0xe3, 0xfd, 0xc4, 0xff, 0x00,
- 0xbe, 0x45, 0x59, 0x4b, 0xc7, 0x8d, 0x61, 0x0a, 0x14, 0x03, 0xd4, 0x01,
- 0xef, 0x44, 0xe1, 0x7d, 0x85, 0x4e, 0xaf, 0x2e, 0xec, 0xd6, 0xcd, 0x15,
- 0x1e, 0xea, 0x5d, 0xd5, 0xcd, 0x63, 0xba, 0xe3, 0xeb, 0xc0, 0xbc, 0x71,
- 0xf0, 0x57, 0x55, 0x83, 0x57, 0x9e, 0xe7, 0x44, 0x85, 0x6f, 0x6c, 0xa6,
- 0x72, 0xe2, 0x25, 0x70, 0xaf, 0x16, 0x4e, 0x76, 0xe0, 0x91, 0x91, 0xe9,
- 0x8a, 0xf7, 0xad, 0xd4, 0x66, 0xbe, 0x7f, 0x39, 0xc8, 0xf0, 0x99, 0xe5,
- 0x18, 0xd2, 0xc4, 0xdd, 0x72, 0xbb, 0xa6, 0xb7, 0x5d, 0xfb, 0xef, 0xe8,
- 0x17, 0xb1, 0xf2, 0xc5, 0xff, 0x00, 0xc3, 0x5f, 0x12, 0xe9, 0x96, 0x53,
- 0x5d, 0xdd, 0x69, 0x52, 0x43, 0x6f, 0x0a, 0x97, 0x92, 0x42, 0xe8, 0x42,
- 0x81, 0xd4, 0xf0, 0x6b, 0x99, 0xaf, 0xaa, 0xfe, 0x21, 0x9c, 0xf8, 0x1f,
- 0x5c, 0xff, 0x00, 0xaf, 0x47, 0xfe, 0x55, 0xf2, 0xa5, 0x7e, 0x01, 0xc5,
- 0x59, 0x1e, 0x1f, 0x22, 0xc4, 0x53, 0xa3, 0x87, 0x93, 0x92, 0x94, 0x6f,
- 0xef, 0x5b, 0xbd, 0xba, 0x24, 0x5a, 0x77, 0x0a, 0xe9, 0xec, 0xbe, 0x19,
- 0xf8, 0x9b, 0x51, 0xb3, 0x86, 0xea, 0xdb, 0x49, 0x92, 0x5b, 0x79, 0x90,
- 0x49, 0x1b, 0x87, 0x40, 0x19, 0x48, 0xc8, 0x3d, 0x6b, 0x98, 0xaf, 0xac,
- 0x3c, 0x08, 0x71, 0xe0, 0xad, 0x0b, 0xfe, 0xbc, 0xa1, 0xff, 0x00, 0xd0,
- 0x05, 0x57, 0x0a, 0xe4, 0x58, 0x7c, 0xf6, 0xbd, 0x5a, 0x58, 0x89, 0x4a,
- 0x2a, 0x2a, 0xfe, 0xed, 0xbb, 0xdb, 0xaa, 0x60, 0xdd, 0x8f, 0x9e, 0xdb,
- 0xe1, 0x4f, 0x8a, 0xd1, 0x4b, 0x1d, 0x1a, 0x50, 0x00, 0xc9, 0x3e, 0x62,
- 0x7f, 0xf1, 0x55, 0xc9, 0xd7, 0xd9, 0x17, 0x4d, 0xfe, 0x8d, 0x37, 0xfb,
- 0x87, 0xf9, 0x57, 0xc6, 0xf5, 0xd1, 0xc5, 0x9c, 0x3d, 0x86, 0xc8, 0x5d,
- 0x05, 0x87, 0x9c, 0xa5, 0xcf, 0xcd, 0x7e, 0x6b, 0x74, 0xb6, 0xd6, 0x4b,
- 0xb8, 0x27, 0x70, 0xae, 0x87, 0x47, 0xf0, 0x07, 0x88, 0x35, 0xfb, 0x04,
- 0xbd, 0xb0, 0xd3, 0x64, 0xb9, 0xb5, 0x72, 0x42, 0xc8, 0xae, 0xa0, 0x12,
- 0x0e, 0x0f, 0x53, 0xeb, 0x5c, 0xf5, 0x7d, 0x27, 0xf0, 0x54, 0xe3, 0xe1,
- 0xed, 0x8f, 0xfd, 0x74, 0x97, 0xff, 0x00, 0x43, 0x35, 0xe7, 0x70, 0xbe,
- 0x4f, 0x43, 0x3c, 0xc6, 0xcb, 0x0d, 0x5e, 0x4d, 0x25, 0x16, 0xf4, 0xb5,
- 0xee, 0x9a, 0x5d, 0x53, 0xee, 0x0d, 0xd8, 0xf3, 0x1f, 0x0d, 0x7c, 0x12,
- 0xd7, 0xb5, 0x3d, 0x42, 0x31, 0xa9, 0x40, 0x34, 0xdb, 0x20, 0xc0, 0xc8,
- 0xee, 0xea, 0xce, 0x47, 0x70, 0xa0, 0x13, 0xcf, 0xb9, 0xe2, 0xbe, 0x87,
- 0xb7, 0x82, 0x3b, 0x4b, 0x78, 0xa0, 0x89, 0x42, 0x45, 0x12, 0x84, 0x45,
- 0x1d, 0x80, 0x18, 0x02, 0x97, 0x34, 0x9b, 0xab, 0xfa, 0x07, 0x25, 0xe1,
- 0xfc, 0x1e, 0x45, 0x09, 0x47, 0x0d, 0x76, 0xe5, 0xbb, 0x7a, 0xbd, 0x36,
- 0x5a, 0x24, 0xad, 0xf2, 0x22, 0xf7, 0x24, 0xcd, 0x19, 0xa8, 0xf7, 0x51,
- 0xba, 0xbe, 0x96, 0xc1, 0x71, 0xd2, 0x48, 0x22, 0x46, 0x76, 0xe0, 0x0e,
- 0x6b, 0x2a, 0x5b, 0xd9, 0x18, 0x17, 0x47, 0x11, 0xe4, 0xe3, 0x60, 0xeb,
- 0xf5, 0xa7, 0x49, 0x78, 0xef, 0xe7, 0xa9, 0x00, 0xa8, 0xe8, 0x08, 0xf7,
- 0x02, 0xaa, 0xf9, 0xc7, 0xfb, 0x89, 0xff, 0x00, 0x7c, 0x8a, 0xe9, 0x84,
- 0x2d, 0xb9, 0xc5, 0x56, 0xaf, 0x36, 0x89, 0x93, 0xc5, 0x7b, 0x22, 0x8d,
- 0xef, 0x20, 0x7d, 0xa7, 0xee, 0x37, 0x53, 0x5a, 0xd1, 0x4a, 0x26, 0x8d,
- 0x5d, 0x7a, 0x1a, 0xc2, 0xf3, 0x8f, 0xf7, 0x13, 0xfe, 0xf9, 0x15, 0x65,
- 0x2f, 0x1e, 0x34, 0x84, 0x28, 0x50, 0x09, 0xe4, 0x01, 0xef, 0x44, 0xe1,
- 0x7d, 0x85, 0x4e, 0xaf, 0x2e, 0xec, 0xd6, 0xa6, 0xcb, 0x28, 0x86, 0x36,
- 0x76, 0xe8, 0x29, 0x37, 0x56, 0x63, 0xde, 0x3c, 0x89, 0x30, 0x60, 0xa4,
- 0x0e, 0x80, 0x8f, 0x7a, 0xc2, 0x30, 0xe6, 0x3a, 0xa7, 0x53, 0x91, 0x0d,
- 0x96, 0xf6, 0x46, 0x05, 0xd2, 0x40, 0x9b, 0x8f, 0xdc, 0x5e, 0xa3, 0xde,
- 0x96, 0x2b, 0xd9, 0x14, 0x07, 0x77, 0x0f, 0xb4, 0xfd, 0xc6, 0xeb, 0xf5,
- 0xaa, 0xfe, 0x71, 0xfe, 0xe2, 0x7f, 0xdf, 0x22, 0x8f, 0x38, 0xff, 0x00,
- 0x71, 0x3f, 0xef, 0x91, 0x5d, 0x7c, 0xaa, 0xd6, 0xb1, 0xc1, 0xce, 0xef,
- 0x7b, 0x9b, 0xb1, 0xc8, 0x25, 0x45, 0x75, 0xe8, 0x46, 0x69, 0xd5, 0x95,
- 0x1d, 0xe3, 0xa0, 0x81, 0x46, 0x02, 0x9e, 0xa0, 0x0f, 0x72, 0x2b, 0x4b,
- 0x35, 0xc9, 0x28, 0xf2, 0x9d, 0xf0, 0xa9, 0xce, 0x85, 0x92, 0x41, 0x1a,
- 0x33, 0xb7, 0x40, 0x32, 0x6b, 0x2a, 0x5b, 0xd9, 0x1c, 0x17, 0x47, 0x09,
- 0x93, 0x8d, 0x83, 0xaf, 0xd6, 0x9d, 0x25, 0xe3, 0xbf, 0x9e, 0xa4, 0x02,
- 0xa3, 0xa0, 0x23, 0xdc, 0x55, 0x5f, 0x38, 0xff, 0x00, 0x71, 0x3f, 0xef,
- 0x91, 0x5b, 0xc2, 0x16, 0xdc, 0xe6, 0xa9, 0x57, 0x9b, 0x44, 0xc8, 0xea,
- 0x70, 0xa4, 0x88, 0x30, 0x09, 0xff, 0x00, 0xf5, 0xd3, 0x4d, 0xbb, 0x09,
- 0x84, 0x59, 0x1b, 0xbd, 0x7b, 0x56, 0x95, 0xb4, 0x66, 0x18, 0x42, 0x13,
- 0x92, 0x3d, 0x2a, 0xe5, 0x2b, 0x23, 0x2a, 0x70, 0x72, 0x6d, 0x32, 0x7a,
- 0xc8, 0x2a, 0x40, 0x9f, 0x20, 0x8f, 0xff, 0x00, 0x5d, 0x6a, 0xe6, 0xa3,
- 0xb9, 0x8c, 0xcf, 0x09, 0x40, 0x40, 0x27, 0xd6, 0xb1, 0x83, 0xe5, 0x3a,
- 0x6a, 0x47, 0x99, 0x5c, 0xc7, 0xa2, 0xa5, 0x5b, 0x76, 0x69, 0x8c, 0x59,
- 0x1b, 0xbf, 0x4a, 0x3e, 0xce, 0xde, 0x7f, 0x95, 0x91, 0xbb, 0xd7, 0xb5,
- 0x74, 0xdd, 0x1c, 0x3c, 0xac, 0x7a, 0xa9, 0x2d, 0x6f, 0x80, 0x7f, 0xcb,
- 0x1a, 0xd6, 0xa8, 0x6d, 0xe3, 0x30, 0xc2, 0xa8, 0x48, 0x24, 0x77, 0x15,
- 0x26, 0x6b, 0x9a, 0x6f, 0x99, 0x9d, 0xf4, 0xe3, 0xca, 0x8c, 0xb6, 0x52,
- 0x1a, 0xe3, 0x20, 0xff, 0x00, 0x96, 0x15, 0x5e, 0xb6, 0x2e, 0x23, 0x33,
- 0x44, 0xc8, 0x08, 0x04, 0xd6, 0x67, 0xd9, 0xdb, 0xcf, 0xf2, 0xb2, 0x37,
- 0x7a, 0xf6, 0xad, 0xa1, 0x24, 0xd1, 0xcb, 0x52, 0x0e, 0x2d, 0x58, 0x8a,
- 0xa7, 0x0a, 0x48, 0x83, 0x00, 0x9f, 0xff, 0x00, 0x5d, 0x34, 0xdb, 0xb2,
- 0xcc, 0x22, 0xc8, 0xdd, 0xeb, 0xda, 0xb4, 0xad, 0xa3, 0x30, 0xc2, 0xaa,
- 0x4e, 0x48, 0xf4, 0xa2, 0x52, 0xb2, 0x0a, 0x70, 0x72, 0x6d, 0x32, 0x7a,
- 0x29, 0xa4, 0xd1, 0x9a, 0xe5, 0xb1, 0xde, 0x3a, 0x8a, 0x6e, 0x73, 0x41,
- 0x34, 0x58, 0x0e, 0x7f, 0xe2, 0x1f, 0xfc, 0x88, 0xfa, 0xe7, 0xfd, 0x7a,
- 0xbf, 0xf2, 0xaf, 0x95, 0xab, 0xeb, 0x2f, 0x18, 0x58, 0x4b, 0xaa, 0xf8,
- 0x57, 0x56, 0xb4, 0x80, 0x6e, 0x9a, 0x6b, 0x69, 0x15, 0x17, 0xd5, 0xb6,
- 0x9c, 0x0f, 0xce, 0xbe, 0x4e, 0x65, 0x2a, 0x48, 0x20, 0x82, 0x38, 0x20,
- 0xf6, 0xaf, 0xc1, 0x7c, 0x46, 0x84, 0x96, 0x32, 0x84, 0xed, 0xa3, 0x8b,
- 0x5f, 0x73, 0xff, 0x00, 0x82, 0x8d, 0x20, 0x25, 0x7d, 0x5d, 0xe0, 0x5f,
- 0xf9, 0x12, 0xf4, 0x2f, 0xfa, 0xf2, 0x87, 0xff, 0x00, 0x40, 0x15, 0xf2,
- 0x9a, 0x23, 0x48, 0xea, 0x88, 0xa5, 0x9d, 0x8e, 0x02, 0x81, 0x92, 0x4d,
- 0x7d, 0x69, 0xe1, 0x8b, 0x19, 0x34, 0xbf, 0x0d, 0xe9, 0x76, 0x73, 0x71,
- 0x2c, 0x16, 0xd1, 0xc6, 0xe3, 0xd0, 0x85, 0x00, 0xd5, 0x78, 0x73, 0x09,
- 0x3c, 0x56, 0x22, 0x76, 0xd1, 0x45, 0x2f, 0xc7, 0xfe, 0x00, 0x4c, 0xd0,
- 0xba, 0xff, 0x00, 0x8f, 0x69, 0xbf, 0xdc, 0x3f, 0xca, 0xbe, 0x39, 0xaf,
- 0xb1, 0xe5, 0x5f, 0x32, 0x27, 0x4c, 0xe3, 0x72, 0x91, 0x9a, 0xf9, 0x03,
- 0x50, 0xb1, 0x9b, 0x4c, 0xbe, 0xb8, 0xb4, 0x9d, 0x0a, 0x4d, 0x04, 0x86,
- 0x37, 0x53, 0xd8, 0x83, 0x8a, 0xed, 0xf1, 0x22, 0x12, 0xff, 0x00, 0x65,
- 0x9d, 0xb4, 0xf7, 0xd7, 0xfe, 0x92, 0x10, 0x2b, 0xd7, 0xd2, 0x5f, 0x05,
- 0xbf, 0xe4, 0x9f, 0x58, 0xff, 0x00, 0xd7, 0x49, 0x7f, 0xf4, 0x33, 0x5f,
- 0x36, 0xd7, 0xd3, 0x9f, 0x0a, 0x74, 0xe9, 0xb4, 0xbf, 0x01, 0xe9, 0x91,
- 0x4e, 0xa5, 0x24, 0x75, 0x69, 0x76, 0x9e, 0xa0, 0x33, 0x12, 0x3f, 0x42,
- 0x2b, 0xc3, 0xf0, 0xf6, 0x12, 0x96, 0x69, 0x52, 0x49, 0x68, 0xa0, 0xff,
- 0x00, 0x19, 0x44, 0x72, 0xd8, 0xeb, 0xe8, 0xa6, 0xe6, 0x8c, 0xd7, 0xf4,
- 0x3d, 0x8c, 0x87, 0x51, 0x4d, 0xcd, 0x19, 0xa2, 0xc0, 0x65, 0xb2, 0x90,
- 0xd7, 0x19, 0x04, 0x7f, 0xfb, 0x42, 0xab, 0xd6, 0xc5, 0xc4, 0x66, 0x68,
- 0x59, 0x07, 0x04, 0xfa, 0xd6, 0x67, 0xd9, 0xdb, 0xcf, 0xf2, 0xb2, 0x37,
- 0x7a, 0xf6, 0xae, 0xa8, 0x4a, 0xe8, 0xe0, 0xa9, 0x07, 0x16, 0xac, 0x45,
- 0x53, 0x85, 0x24, 0x41, 0x80, 0x4f, 0xff, 0x00, 0xae, 0x9a, 0x6d, 0xd9,
- 0x66, 0x11, 0x64, 0x6e, 0xf5, 0xed, 0x5a, 0x76, 0xd1, 0x98, 0x21, 0x0a,
- 0x48, 0x27, 0xda, 0x89, 0x4a, 0xc8, 0x29, 0xc1, 0xc9, 0xb4, 0xc9, 0xab,
- 0x20, 0xa9, 0x02, 0x7c, 0x82, 0x3f, 0xfd, 0x75, 0xab, 0x9a, 0x8a, 0xe6,
- 0x33, 0x34, 0x45, 0x41, 0xc1, 0xf7, 0xac, 0x60, 0xf9, 0x4e, 0x9a, 0x91,
- 0xe6, 0x46, 0x45, 0x15, 0x28, 0xb7, 0x66, 0x98, 0xc5, 0x91, 0xb8, 0x77,
- 0xed, 0x47, 0xd9, 0xdb, 0xcf, 0xf2, 0xb2, 0x37, 0x7a, 0xf6, 0xae, 0x9b,
- 0xa3, 0x87, 0x95, 0x8f, 0x55, 0x25, 0xad, 0xf0, 0x0f, 0xf9, 0x63, 0x5a,
- 0xd5, 0x0d, 0xba, 0x18, 0x61, 0x54, 0x24, 0x12, 0x3d, 0x2a, 0x4c, 0xd7,
- 0x34, 0xdf, 0x33, 0x3b, 0xe9, 0xc7, 0x95, 0x19, 0x6c, 0xa4, 0x35, 0xc6,
- 0x41, 0xff, 0x00, 0x2c, 0x2a, 0xbd, 0x6c, 0x5c, 0x46, 0x66, 0x85, 0x90,
- 0x1c, 0x13, 0xeb, 0x59, 0x9f, 0x67, 0x6f, 0x3f, 0xca, 0xc8, 0xdd, 0xfa,
- 0x56, 0xd0, 0x92, 0x68, 0xe5, 0xa9, 0x06, 0x9a, 0xb1, 0xa0, 0xd6, 0xc1,
- 0xae, 0x04, 0xb9, 0x39, 0x1d, 0xaa, 0x6a, 0x28, 0xae, 0x76, 0xdb, 0x3a,
- 0xd2, 0xb6, 0xc1, 0x45, 0x14, 0x52, 0x19, 0x0a, 0xdb, 0x05, 0xb8, 0x32,
- 0xe4, 0xe4, 0xf6, 0xa3, 0xec, 0xc3, 0xed, 0x1e, 0x6e, 0x4e, 0x7d, 0x2a,
- 0x6a, 0x2a, 0xb9, 0x99, 0x3c, 0xa8, 0x28, 0xa2, 0x8a, 0x92, 0x82, 0xa1,
- 0xfb, 0x30, 0xfb, 0x47, 0x9b, 0x93, 0x9f, 0x4a, 0x9a, 0x8a, 0x69, 0xd8,
- 0x4d, 0x5f, 0x72, 0x16, 0xb6, 0x0d, 0x70, 0x25, 0xc9, 0xc8, 0xed, 0x53,
- 0x51, 0x45, 0x0d, 0xb6, 0x09, 0x5b, 0x60, 0xa2, 0x8a, 0x29, 0x0c, 0x28,
- 0xa2, 0x8a, 0x00, 0x2b, 0x83, 0xf1, 0x57, 0xc1, 0xdd, 0x1b, 0xc4, 0xb7,
- 0xaf, 0x79, 0x1b, 0xcb, 0xa7, 0x5d, 0x48, 0x73, 0x21, 0x80, 0x02, 0x8e,
- 0x7d, 0x4a, 0x9e, 0xff, 0x00, 0x42, 0x2b, 0xbc, 0xa2, 0xbc, 0xfc, 0x76,
- 0x5f, 0x85, 0xcc, 0xa9, 0xfb, 0x1c, 0x5d, 0x35, 0x38, 0xf9, 0xfe, 0x8f,
- 0x75, 0xf2, 0x1a, 0x6d, 0x1c, 0x3f, 0x84, 0xbe, 0x11, 0xe8, 0xde, 0x16,
- 0xbb, 0x4b, 0xc2, 0xd2, 0x5f, 0xde, 0x27, 0x29, 0x24, 0xf8, 0xda, 0x87,
- 0xd5, 0x54, 0x77, 0xf7, 0x39, 0xae, 0xe2, 0x8a, 0x29, 0xe0, 0xb0, 0x18,
- 0x5c, 0xba, 0x97, 0xb1, 0xc2, 0x53, 0x50, 0x8f, 0x97, 0xeb, 0xd5, 0xfc,
- 0xc2, 0xed, 0x85, 0x71, 0xfe, 0x31, 0xf8, 0x5f, 0xa4, 0x78, 0xc6, 0x6f,
- 0xb4, 0xcd, 0xe6, 0x5a, 0x5e, 0xe3, 0x06, 0xe2, 0x0c, 0x65, 0xc7, 0x6d,
- 0xc0, 0xf5, 0xfe, 0x7e, 0xf5, 0xd8, 0x51, 0x55, 0x8c, 0xc1, 0x61, 0xf1,
- 0xf4, 0x9d, 0x0c, 0x54, 0x14, 0xe2, 0xfa, 0x3f, 0xeb, 0x46, 0x17, 0x68,
- 0xf3, 0xbf, 0x0f, 0x7c, 0x11, 0xd1, 0x74, 0x6b, 0xc4, 0xb9, 0xb9, 0x96,
- 0x5d, 0x49, 0xd0, 0xe5, 0x63, 0x94, 0x05, 0x8f, 0x3e, 0xa5, 0x47, 0x5f,
- 0xc4, 0xe3, 0xda, 0xbd, 0x13, 0xa5, 0x14, 0x56, 0x38, 0x1c, 0xb7, 0x07,
- 0x96, 0x41, 0xd3, 0xc1, 0xd3, 0x50, 0x4f, 0x7b, 0x75, 0xf5, 0x7b, 0xb0,
- 0x6d, 0xb0, 0xa2, 0x8a, 0x2b, 0xd3, 0x10, 0x51, 0x45, 0x14, 0x00, 0x54,
- 0x3f, 0x66, 0x1f, 0x68, 0xf3, 0x72, 0x73, 0xe9, 0x53, 0x51, 0x4d, 0x3b,
- 0x09, 0xab, 0xee, 0x42, 0xd6, 0xc1, 0xae, 0x04, 0xb9, 0x39, 0x1d, 0xaa,
- 0x6a, 0x28, 0xa1, 0xb6, 0xc1, 0x2b, 0x6c, 0x14, 0x51, 0x45, 0x21, 0x90,
- 0xad, 0xb0, 0x5b, 0x83, 0x2e, 0x4e, 0x4f, 0x6a, 0x3e, 0xcc, 0x3e, 0xd1,
- 0xe6, 0xe4, 0xe7, 0xd2, 0xa6, 0xa2, 0xab, 0x99, 0x93, 0xca, 0x82, 0x8a,
- 0x28, 0xa9, 0x28, 0x2a, 0x1f, 0xb3, 0x0f, 0xb4, 0x79, 0xb9, 0x39, 0xf4,
- 0xa9, 0xa8, 0xa6, 0x9d, 0x84, 0xd5, 0xf7, 0x3e, 0x20, 0xff, 0x00, 0x87,
- 0xa6, 0xf8, 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xa3,
- 0xfe, 0x1e, 0x9b, 0xe1, 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a, 0x8a,
- 0xbe, 0x17, 0xfe, 0xc6, 0xb2, 0xff, 0x00, 0x9f, 0x64, 0xa7, 0x47, 0xa2,
- 0x59, 0x31, 0xe6, 0xd9, 0x31, 0x45, 0x8e, 0x9e, 0x44, 0x7d, 0xcd, 0xff,
- 0x00, 0x0f, 0x4d, 0xf0, 0xb7, 0xfd, 0x08, 0xfa, 0xc7, 0xfe, 0x05, 0x45,
- 0x47, 0xfc, 0x3d, 0x37, 0xc2, 0xdf, 0xf4, 0x23, 0xeb, 0x1f, 0xf8, 0x15,
- 0x15, 0x7c, 0x3b, 0xfd, 0x87, 0x61, 0xff, 0x00, 0x3e, 0xb1, 0xfe, 0x54,
- 0xd9, 0x34, 0x6b, 0x05, 0x1c, 0x5b, 0x47, 0x9f, 0xa5, 0x16, 0x0e, 0x44,
- 0x7d, 0xc9, 0xff, 0x00, 0x0f, 0x4d, 0xf0, 0xb7, 0xfd, 0x08, 0xfa, 0xc7,
- 0xfe, 0x05, 0x45, 0x47, 0xfc, 0x3d, 0x37, 0xc2, 0xdf, 0xf4, 0x23, 0xeb,
- 0x1f, 0xf8, 0x15, 0x15, 0x7c, 0x2f, 0xfd, 0x8d, 0x65, 0xff, 0x00, 0x3e,
- 0xc9, 0xf9, 0x53, 0xe3, 0xd1, 0x2c, 0x4f, 0x26, 0xd9, 0x31, 0xf4, 0xa2,
- 0xc1, 0xc8, 0x8f, 0xb9, 0x7f, 0xe1, 0xe9, 0xbe, 0x16, 0xff, 0x00, 0xa1,
- 0x1f, 0x58, 0xff, 0x00, 0xc0, 0xa8, 0xa8, 0xff, 0x00, 0x87, 0xa6, 0xf8,
- 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xaf, 0x87, 0x7f,
- 0xb0, 0xec, 0x3f, 0xe7, 0xd6, 0x3f, 0xca, 0x99, 0x26, 0x8d, 0x62, 0x38,
- 0x16, 0xc9, 0x9a, 0x2c, 0x1c, 0x88, 0xfb, 0x97, 0xfe, 0x1e, 0x9b, 0xe1,
- 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a, 0x8a, 0x8f, 0xf8, 0x7a, 0x6f,
- 0x85, 0xbf, 0xe8, 0x47, 0xd6, 0x3f, 0xf0, 0x2a, 0x2a, 0xf8, 0x5f, 0xfb,
- 0x1a, 0xcb, 0xfe, 0x7d, 0x93, 0xf2, 0xa9, 0x23, 0xd1, 0x2c, 0x48, 0xc9,
- 0xb6, 0x4f, 0xca, 0x8b, 0x07, 0x22, 0x3e, 0xe4, 0xff, 0x00, 0x87, 0xa6,
- 0xf8, 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xa3, 0xfe,
- 0x1e, 0x9b, 0xe1, 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a, 0x8a, 0xbe,
- 0x1d, 0xfe, 0xc3, 0xb0, 0xff, 0x00, 0x9f, 0x58, 0xff, 0x00, 0x2a, 0x64,
- 0x9a, 0x35, 0x88, 0x38, 0x16, 0xc9, 0xf9, 0x51, 0x60, 0xe4, 0x47, 0xdc,
- 0xbf, 0xf0, 0xf4, 0xdf, 0x0b, 0x7f, 0xd0, 0x8f, 0xac, 0x7f, 0xe0, 0x54,
- 0x54, 0x7f, 0xc3, 0xd3, 0x7c, 0x2d, 0xff, 0x00, 0x42, 0x3e, 0xb1, 0xff,
- 0x00, 0x81, 0x51, 0x57, 0xc2, 0xff, 0x00, 0xd8, 0xd6, 0x5f, 0xf3, 0xec,
- 0x9f, 0x95, 0x48, 0x9a, 0x1d, 0x89, 0x19, 0x36, 0xc9, 0xf9, 0x51, 0x60,
- 0xe4, 0x47, 0xdc, 0x9f, 0xf0, 0xf4, 0xdf, 0x0b, 0x7f, 0xd0, 0x8f, 0xac,
- 0x7f, 0xe0, 0x54, 0x54, 0x7f, 0xc3, 0xd3, 0x7c, 0x2d, 0xff, 0x00, 0x42,
- 0x3e, 0xb1, 0xff, 0x00, 0x81, 0x51, 0x57, 0xc3, 0xbf, 0xd8, 0x76, 0x1f,
- 0xf3, 0xeb, 0x1f, 0xe5, 0x51, 0xbe, 0x8d, 0x63, 0x9c, 0x0b, 0x64, 0xfc,
- 0xa8, 0xb0, 0x72, 0x23, 0xee, 0x6f, 0xf8, 0x7a, 0x6f, 0x85, 0xbf, 0xe8,
- 0x47, 0xd6, 0x3f, 0xf0, 0x2a, 0x2a, 0x3f, 0xe1, 0xe9, 0xbe, 0x16, 0xff,
- 0x00, 0xa1, 0x1f, 0x58, 0xff, 0x00, 0xc0, 0xa8, 0xab, 0xe1, 0x7f, 0xec,
- 0x7b, 0x2f, 0xf9, 0xf6, 0x4f, 0xca, 0x9b, 0x2e, 0x9d, 0xa7, 0xdb, 0xed,
- 0x53, 0x67, 0xe6, 0xc8, 0xc0, 0x90, 0xb1, 0xae, 0x4e, 0x3d, 0x68, 0xb0,
- 0x72, 0x23, 0xee, 0xaf, 0xf8, 0x7a, 0x6f, 0x85, 0xbf, 0xe8, 0x47, 0xd6,
- 0x3f, 0xf0, 0x2a, 0x2a, 0x3f, 0xe1, 0xe9, 0xbe, 0x16, 0xff, 0x00, 0xa1,
- 0x1f, 0x58, 0xff, 0x00, 0xc0, 0xa8, 0xab, 0xe1, 0x1f, 0x23, 0x4b, 0xd8,
- 0x1b, 0xec, 0x44, 0x8d, 0xbb, 0x9b, 0x09, 0xf7, 0x06, 0x48, 0xc9, 0xe7,
- 0xd8, 0xfe, 0x54, 0x3d, 0x9e, 0x9e, 0x2e, 0x04, 0x66, 0xcb, 0x60, 0x27,
- 0x68, 0x72, 0xbf, 0x29, 0x3f, 0x5c, 0xd1, 0x60, 0xe4, 0x47, 0xdd, 0xdf,
- 0xf0, 0xf4, 0xdf, 0x0b, 0x7f, 0xd0, 0x8f, 0xac, 0x7f, 0xe0, 0x54, 0x54,
- 0x7f, 0xc3, 0xd3, 0x7c, 0x2d, 0xff, 0x00, 0x42, 0x3e, 0xb1, 0xff, 0x00,
- 0x81, 0x51, 0x57, 0xc1, 0x82, 0xdf, 0x4e, 0x1b, 0xb7, 0xd9, 0x98, 0x88,
- 0x19, 0xda, 0xeb, 0xc9, 0xe7, 0x1c, 0x73, 0xea, 0x45, 0x4d, 0x1d, 0x9e,
- 0x9a, 0x46, 0x0d, 0x91, 0x12, 0x02, 0x41, 0x8c, 0xaf, 0xcd, 0x9c, 0x67,
- 0xd7, 0xd2, 0x8b, 0x07, 0x22, 0x3e, 0xed, 0xff, 0x00, 0x87, 0xa6, 0xf8,
- 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xa3, 0xfe, 0x1e,
- 0x9b, 0xe1, 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a, 0x8a, 0xbe, 0x16,
- 0xb7, 0xd3, 0xf4, 0xeb, 0x86, 0x65, 0xfb, 0x1f, 0x96, 0xea, 0x01, 0x2b,
- 0x22, 0xe0, 0xe0, 0xf7, 0xa7, 0x36, 0x8f, 0x62, 0x49, 0xc5, 0xb2, 0x62,
- 0x8b, 0x07, 0x22, 0x3e, 0xe7, 0xff, 0x00, 0x87, 0xa6, 0xf8, 0x5b, 0xfe,
- 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xa3, 0xfe, 0x1e, 0x9b, 0xe1,
- 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a, 0x8a, 0xbe, 0x17, 0xfe, 0xc6,
- 0xb2, 0x3f, 0xf2, 0xec, 0x95, 0x30, 0xd0, 0xec, 0x40, 0xff, 0x00, 0x8f,
- 0x64, 0xa2, 0xc1, 0xc8, 0x8f, 0xb8, 0xbf, 0xe1, 0xe9, 0xbe, 0x16, 0xff,
- 0x00, 0xa1, 0x1f, 0x58, 0xff, 0x00, 0xc0, 0xa8, 0xa8, 0xff, 0x00, 0x87,
- 0xa6, 0xf8, 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xaf,
- 0x87, 0x7f, 0xb1, 0x2c, 0x07, 0xfc, 0xba, 0xc7, 0xf9, 0x54, 0x27, 0x47,
- 0xb2, 0x27, 0xfe, 0x3d, 0x92, 0x8b, 0x07, 0x22, 0x3e, 0xe8, 0xff, 0x00,
- 0x87, 0xa6, 0xf8, 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2,
- 0xa3, 0xfe, 0x1e, 0x9b, 0xe1, 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a,
- 0x8a, 0xbe, 0x17, 0x1a, 0x2d, 0x91, 0x38, 0xfb, 0x32, 0x54, 0xdf, 0xd8,
- 0x76, 0x1f, 0xf3, 0xea, 0x9f, 0x95, 0x16, 0x0e, 0x44, 0x7d, 0xc5, 0xff,
- 0x00, 0x0f, 0x4d, 0xf0, 0xb7, 0xfd, 0x08, 0xfa, 0xc7, 0xfe, 0x05, 0x45,
- 0x47, 0xfc, 0x3d, 0x37, 0xc2, 0xdf, 0xf4, 0x23, 0xeb, 0x1f, 0xf8, 0x15,
- 0x15, 0x7c, 0x3a, 0x74, 0x4b, 0x00, 0x33, 0xf6, 0x58, 0xff, 0x00, 0x2a,
- 0x84, 0xe8, 0xd6, 0x5f, 0xf3, 0xec, 0x94, 0x58, 0x39, 0x11, 0xf7, 0x47,
- 0xfc, 0x3d, 0x37, 0xc2, 0xdf, 0xf4, 0x23, 0xeb, 0x1f, 0xf8, 0x15, 0x15,
- 0x1f, 0xf0, 0xf4, 0xdf, 0x0b, 0x7f, 0xd0, 0x8f, 0xac, 0x7f, 0xe0, 0x54,
- 0x55, 0xf0, 0xc2, 0xe8, 0xb6, 0x4c, 0x40, 0xfb, 0x32, 0x54, 0xbf, 0xd8,
- 0x76, 0x1f, 0xf3, 0xea, 0x94, 0x58, 0x39, 0x11, 0xf7, 0x17, 0xfc, 0x3d,
- 0x37, 0xc2, 0xdf, 0xf4, 0x23, 0xeb, 0x1f, 0xf8, 0x15, 0x15, 0x1f, 0xf0,
- 0xf4, 0xdf, 0x0b, 0x7f, 0xd0, 0x8f, 0xac, 0x7f, 0xe0, 0x54, 0x55, 0xf0,
- 0xe3, 0x68, 0xb6, 0x0a, 0x09, 0xfb, 0x2c, 0x7f, 0x95, 0x45, 0xfd, 0x8d,
- 0x65, 0xff, 0x00, 0x3e, 0xc9, 0x45, 0x83, 0x91, 0x1f, 0x74, 0x7f, 0xc3,
- 0xd3, 0x7c, 0x2d, 0xff, 0x00, 0x42, 0x3e, 0xb1, 0xff, 0x00, 0x81, 0x51,
- 0x51, 0xff, 0x00, 0x0f, 0x4d, 0xf0, 0xb7, 0xfd, 0x08, 0xfa, 0xc7, 0xfe,
- 0x05, 0x45, 0x5f, 0x0c, 0x26, 0x89, 0x64, 0xcd, 0xff, 0x00, 0x1e, 0xc9,
- 0x52, 0xff, 0x00, 0x61, 0xd8, 0x7f, 0xcf, 0xac, 0x7f, 0x95, 0x16, 0x0e,
- 0x44, 0x7d, 0xc5, 0xff, 0x00, 0x0f, 0x4d, 0xf0, 0xb7, 0xfd, 0x08, 0xfa,
- 0xc7, 0xfe, 0x05, 0x45, 0x47, 0xfc, 0x3d, 0x37, 0xc2, 0xdf, 0xf4, 0x23,
- 0xeb, 0x1f, 0xf8, 0x15, 0x15, 0x7c, 0x38, 0xfa, 0x2d, 0x82, 0xaf, 0xfc,
- 0x7a, 0xc7, 0xf9, 0x54, 0x5f, 0xd8, 0xd6, 0x5f, 0xf3, 0xec, 0x94, 0x58,
- 0x39, 0x11, 0x72, 0xa7, 0x45, 0xda, 0xb8, 0xa8, 0xe3, 0x5c, 0xb6, 0x7d,
- 0x2a, 0x5a, 0xa2, 0xc2, 0xa1, 0x66, 0xdc, 0xd9, 0xa7, 0xc8, 0xd8, 0x18,
- 0xf5, 0xa8, 0xa8, 0x01, 0x40, 0xc9, 0xa9, 0xd4, 0x6d, 0x18, 0xa8, 0xe2,
- 0x5e, 0x73, 0x52, 0x50, 0x00, 0x4e, 0x05, 0x40, 0xc7, 0x71, 0xcd, 0x49,
- 0x2b, 0x71, 0x8a, 0x8a, 0x80, 0x14, 0x0c, 0x9c, 0x54, 0xe0, 0x60, 0x62,
- 0xa3, 0x89, 0x7b, 0xd4, 0x94, 0x00, 0x13, 0x80, 0x4d, 0x40, 0x4e, 0x4e,
- 0x69, 0xf2, 0xb7, 0x6a, 0x8e, 0x80, 0x15, 0x46, 0xe3, 0x8a, 0x9e, 0x99,
- 0x1a, 0xe0, 0x67, 0xd6, 0x9f, 0x40, 0x08, 0xc7, 0x68, 0xcd, 0x41, 0x4f,
- 0x91, 0xb2, 0x71, 0xe9, 0x4c, 0xa0, 0x07, 0x22, 0xee, 0x6f, 0x6a, 0x27,
- 0xb5, 0x59, 0xa4, 0x49, 0x37, 0xbc, 0x6e, 0xbc, 0x06, 0x43, 0x8c, 0x8f,
- 0x43, 0xed, 0x52, 0x46, 0xb8, 0x5f, 0x73, 0x4e, 0xa0, 0x0a, 0xa6, 0xca,
- 0x38, 0xa2, 0x95, 0x41, 0x6f, 0xde, 0x2e, 0xc3, 0xcf, 0x6c, 0x93, 0xff,
- 0x00, 0xb3, 0x1a, 0x87, 0xec, 0x60, 0xca, 0xae, 0xd2, 0x48, 0xe1, 0x4e,
- 0x42, 0x12, 0x36, 0x83, 0xf9, 0x55, 0xa9, 0x1b, 0x73, 0x7b, 0x0a, 0x6d,
- 0x00, 0x57, 0x8b, 0x49, 0xb7, 0x0c, 0xfb, 0x53, 0xcb, 0x0c, 0x00, 0x21,
- 0x38, 0xe8, 0x72, 0x0f, 0xd6, 0xa6, 0x5d, 0x39, 0x17, 0x90, 0xf2, 0x79,
- 0x99, 0x2c, 0x64, 0x27, 0x2c, 0x4e, 0xdc, 0x7e, 0x82, 0xac, 0xa2, 0xed,
- 0x5a, 0x5a, 0x00, 0xad, 0x1d, 0xaa, 0xdb, 0x16, 0x6f, 0x31, 0xe5, 0x91,
- 0xc0, 0x05, 0xe4, 0x39, 0x38, 0x1d, 0xbf, 0x5a, 0x5a, 0x73, 0xb6, 0xe6,
- 0xa6, 0xf5, 0xa0, 0x07, 0xc4, 0xb9, 0x39, 0xf4, 0xa9, 0x69, 0x14, 0x6d,
- 0x18, 0xa5, 0xe9, 0x40, 0x0c, 0x95, 0xb0, 0x31, 0x51, 0x52, 0xb1, 0xdc,
- 0x49, 0xa0, 0x0c, 0x9c, 0x50, 0x03, 0xe2, 0x5e, 0xf5, 0x25, 0x00, 0x60,
- 0x62, 0x82, 0x70, 0x33, 0x40, 0x11, 0xca, 0xdd, 0xaa, 0x3a, 0x52, 0x72,
- 0x73, 0x42, 0x8d, 0xc4, 0x0a, 0x00, 0x92, 0x25, 0xc0, 0xcd, 0x3e, 0x8e,
- 0x94, 0x8c, 0x76, 0x82, 0x68, 0x02, 0x39, 0x5b, 0x27, 0x1e, 0x94, 0xca,
- 0x3a, 0xd3, 0x91, 0x77, 0x35, 0x00, 0x49, 0x1a, 0xe1, 0x7d, 0xcd, 0x3a,
- 0x8a, 0x47, 0x6d, 0xab, 0x40, 0x11, 0xc8, 0xd9, 0x6f, 0x61, 0x4c, 0xa2,
- 0x9d, 0x1a, 0xee, 0x6f, 0x61, 0x40, 0x1f, 0xff, 0xd9
-};
diff --git a/camera/libcameraservice/FakeCamera.cpp b/camera/libcameraservice/FakeCamera.cpp
deleted file mode 100644
index f3a6a67..0000000
--- a/camera/libcameraservice/FakeCamera.cpp
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "FakeCamera"
-#include <utils/Log.h>
-
-#include <string.h>
-#include <stdlib.h>
-#include <utils/String8.h>
-
-#include "FakeCamera.h"
-
-
-namespace android {
-
-// TODO: All this rgb to yuv should probably be in a util class.
-
-// TODO: I think something is wrong in this class because the shadow is kBlue
-// and the square color should alternate between kRed and kGreen. However on the
-// emulator screen these are all shades of gray. Y seems ok but the U and V are
-// probably not.
-
-static int tables_initialized = 0;
-uint8_t *gYTable, *gCbTable, *gCrTable;
-
-static int
-clamp(int x)
-{
- if (x > 255) return 255;
- if (x < 0) return 0;
- return x;
-}
-
-/* the equation used by the video code to translate YUV to RGB looks like this
- *
- * Y = (Y0 - 16)*k0
- * Cb = Cb0 - 128
- * Cr = Cr0 - 128
- *
- * G = ( Y - k1*Cr - k2*Cb )
- * R = ( Y + k3*Cr )
- * B = ( Y + k4*Cb )
- *
- */
-
-static const double k0 = 1.164;
-static const double k1 = 0.813;
-static const double k2 = 0.391;
-static const double k3 = 1.596;
-static const double k4 = 2.018;
-
-/* let's try to extract the value of Y
- *
- * G + k1/k3*R + k2/k4*B = Y*( 1 + k1/k3 + k2/k4 )
- *
- * Y = ( G + k1/k3*R + k2/k4*B ) / (1 + k1/k3 + k2/k4)
- * Y0 = ( G0 + k1/k3*R0 + k2/k4*B0 ) / ((1 + k1/k3 + k2/k4)*k0) + 16
- *
- * let define:
- * kYr = k1/k3
- * kYb = k2/k4
- * kYy = k0 * ( 1 + kYr + kYb )
- *
- * we have:
- * Y = ( G + kYr*R + kYb*B )
- * Y0 = clamp[ Y/kYy + 16 ]
- */
-
-static const double kYr = k1/k3;
-static const double kYb = k2/k4;
-static const double kYy = k0*( 1. + kYr + kYb );
-
-static void
-initYtab( void )
-{
- const int imax = (int)( (kYr + kYb)*(31 << 2) + (61 << 3) + 0.1 );
- int i;
-
- gYTable = (uint8_t *)malloc(imax);
-
- for(i=0; i<imax; i++) {
- int x = (int)(i/kYy + 16.5);
- if (x < 16) x = 16;
- else if (x > 235) x = 235;
- gYTable[i] = (uint8_t) x;
- }
-}
-
-/*
- * the source is RGB565, so adjust for 8-bit range of input values:
- *
- * G = (pixels >> 3) & 0xFC;
- * R = (pixels >> 8) & 0xF8;
- * B = (pixels & 0x1f) << 3;
- *
- * R2 = (pixels >> 11) R = R2*8
- * B2 = (pixels & 0x1f) B = B2*8
- *
- * kYr*R = kYr2*R2 => kYr2 = kYr*8
- * kYb*B = kYb2*B2 => kYb2 = kYb*8
- *
- * we want to use integer multiplications:
- *
- * SHIFT1 = 9
- *
- * (ALPHA*R2) >> SHIFT1 == R*kYr => ALPHA = kYr*8*(1 << SHIFT1)
- *
- * ALPHA = kYr*(1 << (SHIFT1+3))
- * BETA = kYb*(1 << (SHIFT1+3))
- */
-
-static const int SHIFT1 = 9;
-static const int ALPHA = (int)( kYr*(1 << (SHIFT1+3)) + 0.5 );
-static const int BETA = (int)( kYb*(1 << (SHIFT1+3)) + 0.5 );
-
-/*
- * now let's try to get the values of Cb and Cr
- *
- * R-B = (k3*Cr - k4*Cb)
- *
- * k3*Cr = k4*Cb + (R-B)
- * k4*Cb = k3*Cr - (R-B)
- *
- * R-G = (k1+k3)*Cr + k2*Cb
- * = (k1+k3)*Cr + k2/k4*(k3*Cr - (R-B)/k0)
- * = (k1 + k3 + k2*k3/k4)*Cr - k2/k4*(R-B)
- *
- * kRr*Cr = (R-G) + kYb*(R-B)
- *
- * Cr = ((R-G) + kYb*(R-B))/kRr
- * Cr0 = clamp(Cr + 128)
- */
-
-static const double kRr = (k1 + k3 + k2*k3/k4);
-
-static void
-initCrtab( void )
-{
- uint8_t *pTable;
- int i;
-
- gCrTable = (uint8_t *)malloc(768*2);
-
- pTable = gCrTable + 384;
- for(i=-384; i<384; i++)
- pTable[i] = (uint8_t) clamp( i/kRr + 128.5 );
-}
-
-/*
- * B-G = (k2 + k4)*Cb + k1*Cr
- * = (k2 + k4)*Cb + k1/k3*(k4*Cb + (R-B))
- * = (k2 + k4 + k1*k4/k3)*Cb + k1/k3*(R-B)
- *
- * kBb*Cb = (B-G) - kYr*(R-B)
- *
- * Cb = ((B-G) - kYr*(R-B))/kBb
- * Cb0 = clamp(Cb + 128)
- *
- */
-
-static const double kBb = (k2 + k4 + k1*k4/k3);
-
-static void
-initCbtab( void )
-{
- uint8_t *pTable;
- int i;
-
- gCbTable = (uint8_t *)malloc(768*2);
-
- pTable = gCbTable + 384;
- for(i=-384; i<384; i++)
- pTable[i] = (uint8_t) clamp( i/kBb + 128.5 );
-}
-
-/*
- * SHIFT2 = 16
- *
- * DELTA = kYb*(1 << SHIFT2)
- * GAMMA = kYr*(1 << SHIFT2)
- */
-
-static const int SHIFT2 = 16;
-static const int DELTA = kYb*(1 << SHIFT2);
-static const int GAMMA = kYr*(1 << SHIFT2);
-
-int32_t ccrgb16toyuv_wo_colorkey(uint8_t *rgb16, uint8_t *yuv420,
- uint32_t *param, uint8_t *table[])
-{
- uint16_t *inputRGB = (uint16_t*)rgb16;
- uint8_t *outYUV = yuv420;
- int32_t width_dst = param[0];
- int32_t height_dst = param[1];
- int32_t pitch_dst = param[2];
- int32_t mheight_dst = param[3];
- int32_t pitch_src = param[4];
- uint8_t *y_tab = table[0];
- uint8_t *cb_tab = table[1];
- uint8_t *cr_tab = table[2];
-
- int32_t size16 = pitch_dst*mheight_dst;
- int32_t i,j,count;
- int32_t ilimit,jlimit;
- uint8_t *tempY,*tempU,*tempV;
- uint16_t pixels;
- int tmp;
-uint32_t temp;
-
- tempY = outYUV;
- tempU = outYUV + (height_dst * pitch_dst);
- tempV = tempU + 1;
-
- jlimit = height_dst;
- ilimit = width_dst;
-
- for(j=0; j<jlimit; j+=1)
- {
- for (i=0; i<ilimit; i+=2)
- {
- int32_t G_ds = 0, B_ds = 0, R_ds = 0;
- uint8_t y0, y1, u, v;
-
- pixels = inputRGB[i];
- temp = (BETA*(pixels & 0x001F) + ALPHA*(pixels>>11) );
- y0 = y_tab[(temp>>SHIFT1) + ((pixels>>3) & 0x00FC)];
-
- G_ds += (pixels>>1) & 0x03E0;
- B_ds += (pixels<<5) & 0x03E0;
- R_ds += (pixels>>6) & 0x03E0;
-
- pixels = inputRGB[i+1];
- temp = (BETA*(pixels & 0x001F) + ALPHA*(pixels>>11) );
- y1 = y_tab[(temp>>SHIFT1) + ((pixels>>3) & 0x00FC)];
-
- G_ds += (pixels>>1) & 0x03E0;
- B_ds += (pixels<<5) & 0x03E0;
- R_ds += (pixels>>6) & 0x03E0;
-
- R_ds >>= 1;
- B_ds >>= 1;
- G_ds >>= 1;
-
- tmp = R_ds - B_ds;
-
- u = cb_tab[(((B_ds-G_ds)<<SHIFT2) - GAMMA*tmp)>>(SHIFT2+2)];
- v = cr_tab[(((R_ds-G_ds)<<SHIFT2) + DELTA*tmp)>>(SHIFT2+2)];
-
- tempY[0] = y0;
- tempY[1] = y1;
- tempY += 2;
-
- if ((j&1) == 0) {
- tempU[0] = u;
- tempV[0] = v;
- tempU += 2;
- tempV += 2;
- }
- }
-
- inputRGB += pitch_src;
- }
-
- return 1;
-}
-
-#define min(a,b) ((a)<(b)?(a):(b))
-#define max(a,b) ((a)>(b)?(a):(b))
-
-static void convert_rgb16_to_yuv420(uint8_t *rgb, uint8_t *yuv, int width, int height)
-{
- if (!tables_initialized) {
- initYtab();
- initCrtab();
- initCbtab();
- tables_initialized = 1;
- }
-
- uint32_t param[6];
- param[0] = (uint32_t) width;
- param[1] = (uint32_t) height;
- param[2] = (uint32_t) width;
- param[3] = (uint32_t) height;
- param[4] = (uint32_t) width;
- param[5] = (uint32_t) 0;
-
- uint8_t *table[3];
- table[0] = gYTable;
- table[1] = gCbTable + 384;
- table[2] = gCrTable + 384;
-
- ccrgb16toyuv_wo_colorkey(rgb, yuv, param, table);
-}
-
-const int FakeCamera::kRed;
-const int FakeCamera::kGreen;
-const int FakeCamera::kBlue;
-
-FakeCamera::FakeCamera(int width, int height)
- : mTmpRgb16Buffer(0)
-{
- setSize(width, height);
-}
-
-FakeCamera::~FakeCamera()
-{
- delete[] mTmpRgb16Buffer;
-}
-
-void FakeCamera::setSize(int width, int height)
-{
- mWidth = width;
- mHeight = height;
- mCounter = 0;
- mCheckX = 0;
- mCheckY = 0;
-
- // This will cause it to be reallocated on the next call
- // to getNextFrameAsYuv420().
- delete[] mTmpRgb16Buffer;
- mTmpRgb16Buffer = 0;
-}
-
-void FakeCamera::getNextFrameAsRgb565(uint16_t *buffer)
-{
- int size = mWidth / 10;
-
- drawCheckerboard(buffer, size);
-
- int x = ((mCounter*3)&255);
- if(x>128) x = 255 - x;
- int y = ((mCounter*5)&255);
- if(y>128) y = 255 - y;
-
- drawSquare(buffer, x*size/32, y*size/32, (size*5)>>1, (mCounter&0x100)?kRed:kGreen, kBlue);
-
- mCounter++;
-}
-
-void FakeCamera::getNextFrameAsYuv420(uint8_t *buffer)
-{
- if (mTmpRgb16Buffer == 0)
- mTmpRgb16Buffer = new uint16_t[mWidth * mHeight];
-
- getNextFrameAsRgb565(mTmpRgb16Buffer);
- convert_rgb16_to_yuv420((uint8_t*)mTmpRgb16Buffer, buffer, mWidth, mHeight);
-}
-
-void FakeCamera::drawSquare(uint16_t *dst, int x, int y, int size, int color, int shadow)
-{
- int square_xstop, square_ystop, shadow_xstop, shadow_ystop;
-
- square_xstop = min(mWidth, x+size);
- square_ystop = min(mHeight, y+size);
- shadow_xstop = min(mWidth, x+size+(size/4));
- shadow_ystop = min(mHeight, y+size+(size/4));
-
- // Do the shadow.
- uint16_t *sh = &dst[(y+(size/4))*mWidth];
- for (int j = y + (size/4); j < shadow_ystop; j++) {
- for (int i = x + (size/4); i < shadow_xstop; i++) {
- sh[i] &= shadow;
- }
- sh += mWidth;
- }
-
- // Draw the square.
- uint16_t *sq = &dst[y*mWidth];
- for (int j = y; j < square_ystop; j++) {
- for (int i = x; i < square_xstop; i++) {
- sq[i] = color;
- }
- sq += mWidth;
- }
-}
-
-void FakeCamera::drawCheckerboard(uint16_t *dst, int size)
-{
- bool black = true;
-
- if((mCheckX/size)&1)
- black = false;
- if((mCheckY/size)&1)
- black = !black;
-
- int county = mCheckY%size;
- int checkxremainder = mCheckX%size;
-
- for(int y=0;y<mHeight;y++) {
- int countx = checkxremainder;
- bool current = black;
- for(int x=0;x<mWidth;x++) {
- dst[y*mWidth+x] = current?0:0xffff;
- if(countx++ >= size) {
- countx=0;
- current = !current;
- }
- }
- if(county++ >= size) {
- county=0;
- black = !black;
- }
- }
- mCheckX += 3;
- mCheckY++;
-}
-
-
-void FakeCamera::dump(int fd) const
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- snprintf(buffer, 255, " width x height (%d x %d), counter (%d), check x-y coordinate(%d, %d)\n", mWidth, mHeight, mCounter, mCheckX, mCheckY);
- result.append(buffer);
- ::write(fd, result.string(), result.size());
-}
-
-
-}; // namespace android
diff --git a/camera/libcameraservice/FakeCamera.h b/camera/libcameraservice/FakeCamera.h
deleted file mode 100644
index 724de20..0000000
--- a/camera/libcameraservice/FakeCamera.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_HARDWARE_FAKECAMERA_H
-#define ANDROID_HARDWARE_FAKECAMERA_H
-
-#include <sys/types.h>
-#include <stdint.h>
-
-namespace android {
-
-/*
- * FakeCamera is used in the CameraHardwareStub to provide a fake video feed
- * when the system does not have a camera in hardware.
- * The fake video is a moving black and white checkerboard background with a
- * bouncing gray square in the foreground.
- * This class is not thread-safe.
- *
- * TODO: Since the major methods provides a raw/uncompressed video feed, rename
- * this class to RawVideoSource.
- */
-
-class FakeCamera {
-public:
- FakeCamera(int width, int height);
- ~FakeCamera();
-
- void setSize(int width, int height);
- void getNextFrameAsYuv420(uint8_t *buffer);
- // Write to the fd a string representing the current state.
- void dump(int fd) const;
-
-private:
- // TODO: remove the uint16_t buffer param everywhere since it is a field of
- // this class.
- void getNextFrameAsRgb565(uint16_t *buffer);
-
- void drawSquare(uint16_t *buffer, int x, int y, int size, int color, int shadow);
- void drawCheckerboard(uint16_t *buffer, int size);
-
- static const int kRed = 0xf800;
- static const int kGreen = 0x07c0;
- static const int kBlue = 0x003e;
-
- int mWidth, mHeight;
- int mCounter;
- int mCheckX, mCheckY;
- uint16_t *mTmpRgb16Buffer;
-};
-
-}; // namespace android
-
-#endif // ANDROID_HARDWARE_FAKECAMERA_H
diff --git a/camera/tests/CameraServiceTest/Android.mk b/camera/tests/CameraServiceTest/Android.mk
deleted file mode 100644
index cf4e42f..0000000
--- a/camera/tests/CameraServiceTest/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= CameraServiceTest.cpp
-
-LOCAL_MODULE:= CameraServiceTest
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_C_INCLUDES += \
- frameworks/base/libs
-
-LOCAL_CFLAGS :=
-
-LOCAL_SHARED_LIBRARIES += \
- libbinder \
- libcutils \
- libutils \
- libui \
- libcamera_client \
- libsurfaceflinger_client
-
-# Disable it because the ISurface interface may change, and before we have a
-# chance to fix this test, we don't want to break normal builds.
-#include $(BUILD_EXECUTABLE)
diff --git a/camera/tests/CameraServiceTest/CameraServiceTest.cpp b/camera/tests/CameraServiceTest/CameraServiceTest.cpp
deleted file mode 100644
index 3c8d553..0000000
--- a/camera/tests/CameraServiceTest/CameraServiceTest.cpp
+++ /dev/null
@@ -1,919 +0,0 @@
-#define LOG_TAG "CameraServiceTest"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <surfaceflinger/ISurface.h>
-#include <camera/Camera.h>
-#include <camera/CameraParameters.h>
-#include <ui/GraphicBuffer.h>
-#include <camera/ICamera.h>
-#include <camera/ICameraClient.h>
-#include <camera/ICameraService.h>
-#include <ui/Overlay.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
-#include <utils/KeyedVector.h>
-#include <utils/Log.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-using namespace android;
-
-//
-// Assertion and Logging utilities
-//
-#define INFO(...) \
- do { \
- printf(__VA_ARGS__); \
- printf("\n"); \
- LOGD(__VA_ARGS__); \
- } while(0)
-
-void assert_fail(const char *file, int line, const char *func, const char *expr) {
- INFO("assertion failed at file %s, line %d, function %s:",
- file, line, func);
- INFO("%s", expr);
- abort();
-}
-
-void assert_eq_fail(const char *file, int line, const char *func,
- const char *expr, int actual) {
- INFO("assertion failed at file %s, line %d, function %s:",
- file, line, func);
- INFO("(expected) %s != (actual) %d", expr, actual);
- abort();
-}
-
-#define ASSERT(e) \
- do { \
- if (!(e)) \
- assert_fail(__FILE__, __LINE__, __func__, #e); \
- } while(0)
-
-#define ASSERT_EQ(expected, actual) \
- do { \
- int _x = (actual); \
- if (_x != (expected)) \
- assert_eq_fail(__FILE__, __LINE__, __func__, #expected, _x); \
- } while(0)
-
-//
-// Holder service for pass objects between processes.
-//
-class IHolder : public IInterface {
-protected:
- enum {
- HOLDER_PUT = IBinder::FIRST_CALL_TRANSACTION,
- HOLDER_GET,
- HOLDER_CLEAR
- };
-public:
- DECLARE_META_INTERFACE(Holder);
-
- virtual void put(sp<IBinder> obj) = 0;
- virtual sp<IBinder> get() = 0;
- virtual void clear() = 0;
-};
-
-class BnHolder : public BnInterface<IHolder> {
- virtual status_t onTransact(uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-class BpHolder : public BpInterface<IHolder> {
-public:
- BpHolder(const sp<IBinder>& impl)
- : BpInterface<IHolder>(impl) {
- }
-
- virtual void put(sp<IBinder> obj) {
- Parcel data, reply;
- data.writeStrongBinder(obj);
- remote()->transact(HOLDER_PUT, data, &reply, IBinder::FLAG_ONEWAY);
- }
-
- virtual sp<IBinder> get() {
- Parcel data, reply;
- remote()->transact(HOLDER_GET, data, &reply);
- return reply.readStrongBinder();
- }
-
- virtual void clear() {
- Parcel data, reply;
- remote()->transact(HOLDER_CLEAR, data, &reply);
- }
-};
-
-IMPLEMENT_META_INTERFACE(Holder, "CameraServiceTest.Holder");
-
-status_t BnHolder::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
- switch(code) {
- case HOLDER_PUT: {
- put(data.readStrongBinder());
- return NO_ERROR;
- } break;
- case HOLDER_GET: {
- reply->writeStrongBinder(get());
- return NO_ERROR;
- } break;
- case HOLDER_CLEAR: {
- clear();
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-class HolderService : public BnHolder {
- virtual void put(sp<IBinder> obj) {
- mObj = obj;
- }
- virtual sp<IBinder> get() {
- return mObj;
- }
- virtual void clear() {
- mObj.clear();
- }
-private:
- sp<IBinder> mObj;
-};
-
-//
-// A mock CameraClient
-//
-class MCameraClient : public BnCameraClient {
-public:
- virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2);
- virtual void dataCallback(int32_t msgType, const sp<IMemory>& data);
- virtual void dataCallbackTimestamp(nsecs_t timestamp,
- int32_t msgType, const sp<IMemory>& data);
-
- // new functions
- void clearStat();
- enum OP { EQ, GE, LE, GT, LT };
- void assertNotify(int32_t msgType, OP op, int count);
- void assertData(int32_t msgType, OP op, int count);
- void waitNotify(int32_t msgType, OP op, int count);
- void waitData(int32_t msgType, OP op, int count);
- void assertDataSize(int32_t msgType, OP op, int dataSize);
-
- void setReleaser(ICamera *releaser) {
- mReleaser = releaser;
- }
-private:
- Mutex mLock;
- Condition mCond;
- DefaultKeyedVector<int32_t, int> mNotifyCount;
- DefaultKeyedVector<int32_t, int> mDataCount;
- DefaultKeyedVector<int32_t, int> mDataSize;
- bool test(OP op, int v1, int v2);
- void assertTest(OP op, int v1, int v2);
-
- ICamera *mReleaser;
-};
-
-void MCameraClient::clearStat() {
- Mutex::Autolock _l(mLock);
- mNotifyCount.clear();
- mDataCount.clear();
- mDataSize.clear();
-}
-
-bool MCameraClient::test(OP op, int v1, int v2) {
- switch (op) {
- case EQ: return v1 == v2;
- case GT: return v1 > v2;
- case LT: return v1 < v2;
- case GE: return v1 >= v2;
- case LE: return v1 <= v2;
- default: ASSERT(0); break;
- }
- return false;
-}
-
-void MCameraClient::assertTest(OP op, int v1, int v2) {
- if (!test(op, v1, v2)) {
- LOGE("assertTest failed: op=%d, v1=%d, v2=%d", op, v1, v2);
- ASSERT(0);
- }
-}
-
-void MCameraClient::assertNotify(int32_t msgType, OP op, int count) {
- Mutex::Autolock _l(mLock);
- int v = mNotifyCount.valueFor(msgType);
- assertTest(op, v, count);
-}
-
-void MCameraClient::assertData(int32_t msgType, OP op, int count) {
- Mutex::Autolock _l(mLock);
- int v = mDataCount.valueFor(msgType);
- assertTest(op, v, count);
-}
-
-void MCameraClient::assertDataSize(int32_t msgType, OP op, int dataSize) {
- Mutex::Autolock _l(mLock);
- int v = mDataSize.valueFor(msgType);
- assertTest(op, v, dataSize);
-}
-
-void MCameraClient::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) {
- INFO("%s", __func__);
- Mutex::Autolock _l(mLock);
- ssize_t i = mNotifyCount.indexOfKey(msgType);
- if (i < 0) {
- mNotifyCount.add(msgType, 1);
- } else {
- ++mNotifyCount.editValueAt(i);
- }
- mCond.signal();
-}
-
-void MCameraClient::dataCallback(int32_t msgType, const sp<IMemory>& data) {
- INFO("%s", __func__);
- int dataSize = data->size();
- INFO("data type = %d, size = %d", msgType, dataSize);
- Mutex::Autolock _l(mLock);
- ssize_t i = mDataCount.indexOfKey(msgType);
- if (i < 0) {
- mDataCount.add(msgType, 1);
- mDataSize.add(msgType, dataSize);
- } else {
- ++mDataCount.editValueAt(i);
- mDataSize.editValueAt(i) = dataSize;
- }
- mCond.signal();
-
- if (msgType == CAMERA_MSG_VIDEO_FRAME) {
- ASSERT(mReleaser != NULL);
- mReleaser->releaseRecordingFrame(data);
- }
-}
-
-void MCameraClient::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
- const sp<IMemory>& data) {
- dataCallback(msgType, data);
-}
-
-void MCameraClient::waitNotify(int32_t msgType, OP op, int count) {
- INFO("waitNotify: %d, %d, %d", msgType, op, count);
- Mutex::Autolock _l(mLock);
- while (true) {
- int v = mNotifyCount.valueFor(msgType);
- if (test(op, v, count)) {
- break;
- }
- mCond.wait(mLock);
- }
-}
-
-void MCameraClient::waitData(int32_t msgType, OP op, int count) {
- INFO("waitData: %d, %d, %d", msgType, op, count);
- Mutex::Autolock _l(mLock);
- while (true) {
- int v = mDataCount.valueFor(msgType);
- if (test(op, v, count)) {
- break;
- }
- mCond.wait(mLock);
- }
-}
-
-//
-// A mock Surface
-//
-class MSurface : public BnSurface {
-public:
- virtual status_t registerBuffers(const BufferHeap& buffers);
- virtual void postBuffer(ssize_t offset);
- virtual void unregisterBuffers();
- virtual sp<OverlayRef> createOverlay(
- uint32_t w, uint32_t h, int32_t format, int32_t orientation);
- virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage);
- virtual status_t setBufferCount(int bufferCount);
-
- // new functions
- void clearStat();
- void waitUntil(int c0, int c1, int c2);
-
-private:
- // check callback count
- Condition mCond;
- Mutex mLock;
- int registerBuffersCount;
- int postBufferCount;
- int unregisterBuffersCount;
-};
-
-status_t MSurface::registerBuffers(const BufferHeap& buffers) {
- INFO("%s", __func__);
- Mutex::Autolock _l(mLock);
- ++registerBuffersCount;
- mCond.signal();
- return NO_ERROR;
-}
-
-void MSurface::postBuffer(ssize_t offset) {
- // INFO("%s", __func__);
- Mutex::Autolock _l(mLock);
- ++postBufferCount;
- mCond.signal();
-}
-
-void MSurface::unregisterBuffers() {
- INFO("%s", __func__);
- Mutex::Autolock _l(mLock);
- ++unregisterBuffersCount;
- mCond.signal();
-}
-
-sp<GraphicBuffer> MSurface::requestBuffer(int bufferIdx, int usage) {
- INFO("%s", __func__);
- return NULL;
-}
-
-status_t MSurface::setBufferCount(int bufferCount) {
- INFO("%s", __func__);
- return NULL;
-}
-
-void MSurface::clearStat() {
- Mutex::Autolock _l(mLock);
- registerBuffersCount = 0;
- postBufferCount = 0;
- unregisterBuffersCount = 0;
-}
-
-void MSurface::waitUntil(int c0, int c1, int c2) {
- INFO("waitUntil: %d %d %d", c0, c1, c2);
- Mutex::Autolock _l(mLock);
- while (true) {
- if (registerBuffersCount >= c0 &&
- postBufferCount >= c1 &&
- unregisterBuffersCount >= c2) {
- break;
- }
- mCond.wait(mLock);
- }
-}
-
-sp<OverlayRef> MSurface::createOverlay(uint32_t w, uint32_t h, int32_t format,
- int32_t orientation) {
- // Not implemented.
- ASSERT(0);
- return NULL;
-}
-
-//
-// Utilities to use the Holder service
-//
-sp<IHolder> getHolder() {
- sp<IServiceManager> sm = defaultServiceManager();
- ASSERT(sm != 0);
- sp<IBinder> binder = sm->getService(String16("CameraServiceTest.Holder"));
- ASSERT(binder != 0);
- sp<IHolder> holder = interface_cast<IHolder>(binder);
- ASSERT(holder != 0);
- return holder;
-}
-
-void putTempObject(sp<IBinder> obj) {
- INFO("%s", __func__);
- getHolder()->put(obj);
-}
-
-sp<IBinder> getTempObject() {
- INFO("%s", __func__);
- return getHolder()->get();
-}
-
-void clearTempObject() {
- INFO("%s", __func__);
- getHolder()->clear();
-}
-
-//
-// Get a Camera Service
-//
-sp<ICameraService> getCameraService() {
- sp<IServiceManager> sm = defaultServiceManager();
- ASSERT(sm != 0);
- sp<IBinder> binder = sm->getService(String16("media.camera"));
- ASSERT(binder != 0);
- sp<ICameraService> cs = interface_cast<ICameraService>(binder);
- ASSERT(cs != 0);
- return cs;
-}
-
-int getNumberOfCameras() {
- sp<ICameraService> cs = getCameraService();
- return cs->getNumberOfCameras();
-}
-
-//
-// Various Connect Tests
-//
-void testConnect(int cameraId) {
- INFO("%s", __func__);
- sp<ICameraService> cs = getCameraService();
- sp<MCameraClient> cc = new MCameraClient();
- sp<ICamera> c = cs->connect(cc, cameraId);
- ASSERT(c != 0);
- c->disconnect();
-}
-
-void testAllowConnectOnceOnly(int cameraId) {
- INFO("%s", __func__);
- sp<ICameraService> cs = getCameraService();
- // Connect the first client.
- sp<MCameraClient> cc = new MCameraClient();
- sp<ICamera> c = cs->connect(cc, cameraId);
- ASSERT(c != 0);
- // Same client -- ok.
- ASSERT(cs->connect(cc, cameraId) != 0);
- // Different client -- not ok.
- sp<MCameraClient> cc2 = new MCameraClient();
- ASSERT(cs->connect(cc2, cameraId) == 0);
- c->disconnect();
-}
-
-void testReconnectFailed() {
- INFO("%s", __func__);
- sp<ICamera> c = interface_cast<ICamera>(getTempObject());
- sp<MCameraClient> cc = new MCameraClient();
- ASSERT(c->connect(cc) != NO_ERROR);
-}
-
-void testReconnectSuccess() {
- INFO("%s", __func__);
- sp<ICamera> c = interface_cast<ICamera>(getTempObject());
- sp<MCameraClient> cc = new MCameraClient();
- ASSERT(c->connect(cc) == NO_ERROR);
- c->disconnect();
-}
-
-void testLockFailed() {
- INFO("%s", __func__);
- sp<ICamera> c = interface_cast<ICamera>(getTempObject());
- ASSERT(c->lock() != NO_ERROR);
-}
-
-void testLockUnlockSuccess() {
- INFO("%s", __func__);
- sp<ICamera> c = interface_cast<ICamera>(getTempObject());
- ASSERT(c->lock() == NO_ERROR);
- ASSERT(c->unlock() == NO_ERROR);
-}
-
-void testLockSuccess() {
- INFO("%s", __func__);
- sp<ICamera> c = interface_cast<ICamera>(getTempObject());
- ASSERT(c->lock() == NO_ERROR);
- c->disconnect();
-}
-
-//
-// Run the connect tests in another process.
-//
-const char *gExecutable;
-
-struct FunctionTableEntry {
- const char *name;
- void (*func)();
-};
-
-FunctionTableEntry function_table[] = {
-#define ENTRY(x) {#x, &x}
- ENTRY(testReconnectFailed),
- ENTRY(testReconnectSuccess),
- ENTRY(testLockUnlockSuccess),
- ENTRY(testLockFailed),
- ENTRY(testLockSuccess),
-#undef ENTRY
-};
-
-void runFunction(const char *tag) {
- INFO("runFunction: %s", tag);
- int entries = sizeof(function_table) / sizeof(function_table[0]);
- for (int i = 0; i < entries; i++) {
- if (strcmp(function_table[i].name, tag) == 0) {
- (*function_table[i].func)();
- return;
- }
- }
- ASSERT(0);
-}
-
-void runInAnotherProcess(const char *tag) {
- pid_t pid = fork();
- if (pid == 0) {
- execlp(gExecutable, gExecutable, tag, NULL);
- ASSERT(0);
- } else {
- int status;
- ASSERT_EQ(pid, wait(&status));
- ASSERT_EQ(0, status);
- }
-}
-
-void testReconnect(int cameraId) {
- INFO("%s", __func__);
- sp<ICameraService> cs = getCameraService();
- sp<MCameraClient> cc = new MCameraClient();
- sp<ICamera> c = cs->connect(cc, cameraId);
- ASSERT(c != 0);
- // Reconnect to the same client -- ok.
- ASSERT(c->connect(cc) == NO_ERROR);
- // Reconnect to a different client (but the same pid) -- ok.
- sp<MCameraClient> cc2 = new MCameraClient();
- ASSERT(c->connect(cc2) == NO_ERROR);
- c->disconnect();
- cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
-}
-
-void testLockUnlock(int cameraId) {
- sp<ICameraService> cs = getCameraService();
- sp<MCameraClient> cc = new MCameraClient();
- sp<ICamera> c = cs->connect(cc, cameraId);
- ASSERT(c != 0);
- // We can lock as many times as we want.
- ASSERT(c->lock() == NO_ERROR);
- ASSERT(c->lock() == NO_ERROR);
- // Lock from a different process -- not ok.
- putTempObject(c->asBinder());
- runInAnotherProcess("testLockFailed");
- // Unlock then lock from a different process -- ok.
- ASSERT(c->unlock() == NO_ERROR);
- runInAnotherProcess("testLockUnlockSuccess");
- // Unlock then lock from a different process -- ok.
- runInAnotherProcess("testLockSuccess");
- clearTempObject();
-}
-
-void testReconnectFromAnotherProcess(int cameraId) {
- INFO("%s", __func__);
-
- sp<ICameraService> cs = getCameraService();
- sp<MCameraClient> cc = new MCameraClient();
- sp<ICamera> c = cs->connect(cc, cameraId);
- ASSERT(c != 0);
- // Reconnect from a different process -- not ok.
- putTempObject(c->asBinder());
- runInAnotherProcess("testReconnectFailed");
- // Unlock then reconnect from a different process -- ok.
- ASSERT(c->unlock() == NO_ERROR);
- runInAnotherProcess("testReconnectSuccess");
- clearTempObject();
-}
-
-// We need to flush the command buffer after the reference
-// to ICamera is gone. The sleep is for the server to run
-// the destructor for it.
-static void flushCommands() {
- IPCThreadState::self()->flushCommands();
- usleep(200000); // 200ms
-}
-
-// Run a test case
-#define RUN(class_name, cameraId) do { \
- { \
- INFO(#class_name); \
- class_name instance; \
- instance.init(cameraId); \
- instance.run(); \
- } \
- flushCommands(); \
-} while(0)
-
-// Base test case after the the camera is connected.
-class AfterConnect {
-public:
- void init(int cameraId) {
- cs = getCameraService();
- cc = new MCameraClient();
- c = cs->connect(cc, cameraId);
- ASSERT(c != 0);
- }
-
-protected:
- sp<ICameraService> cs;
- sp<MCameraClient> cc;
- sp<ICamera> c;
-
- ~AfterConnect() {
- c->disconnect();
- c.clear();
- cc.clear();
- cs.clear();
- }
-};
-
-class TestSetPreviewDisplay : public AfterConnect {
-public:
- void run() {
- sp<MSurface> surface = new MSurface();
- ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
- c->disconnect();
- cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
- }
-};
-
-class TestStartPreview : public AfterConnect {
-public:
- void run() {
- sp<MSurface> surface = new MSurface();
- ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
-
- ASSERT(c->startPreview() == NO_ERROR);
- ASSERT(c->previewEnabled() == true);
-
- surface->waitUntil(1, 10, 0); // needs 1 registerBuffers and 10 postBuffer
- surface->clearStat();
-
- sp<MSurface> another_surface = new MSurface();
- c->setPreviewDisplay(another_surface); // just to make sure unregisterBuffers
- // is called.
- surface->waitUntil(0, 0, 1); // needs unregisterBuffers
-
- cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
- }
-};
-
-class TestStartPreviewWithoutDisplay : public AfterConnect {
-public:
- void run() {
- ASSERT(c->startPreview() == NO_ERROR);
- ASSERT(c->previewEnabled() == true);
- c->disconnect();
- cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
- }
-};
-
-// Base test case after the the camera is connected and the preview is started.
-class AfterStartPreview : public AfterConnect {
-public:
- void init(int cameraId) {
- AfterConnect::init(cameraId);
- surface = new MSurface();
- ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
- ASSERT(c->startPreview() == NO_ERROR);
- }
-
-protected:
- sp<MSurface> surface;
-
- ~AfterStartPreview() {
- surface.clear();
- }
-};
-
-class TestAutoFocus : public AfterStartPreview {
-public:
- void run() {
- cc->assertNotify(CAMERA_MSG_FOCUS, MCameraClient::EQ, 0);
- c->autoFocus();
- cc->waitNotify(CAMERA_MSG_FOCUS, MCameraClient::EQ, 1);
- c->disconnect();
- cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
- }
-};
-
-class TestStopPreview : public AfterStartPreview {
-public:
- void run() {
- ASSERT(c->previewEnabled() == true);
- c->stopPreview();
- ASSERT(c->previewEnabled() == false);
- c->disconnect();
- cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
- }
-};
-
-class TestTakePicture: public AfterStartPreview {
-public:
- void run() {
- ASSERT(c->takePicture() == NO_ERROR);
- cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1);
- cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
- cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
- c->stopPreview();
- c->disconnect();
- cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
- }
-};
-
-class TestTakeMultiplePictures: public AfterStartPreview {
-public:
- void run() {
- for (int i = 0; i < 10; i++) {
- cc->clearStat();
- ASSERT(c->takePicture() == NO_ERROR);
- cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1);
- cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
- cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
- }
- c->disconnect();
- cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
- }
-};
-
-class TestGetParameters: public AfterStartPreview {
-public:
- void run() {
- String8 param_str = c->getParameters();
- INFO("%s", static_cast<const char*>(param_str));
- }
-};
-
-static bool getNextSize(const char **ptrS, int *w, int *h) {
- const char *s = *ptrS;
-
- // skip over ','
- if (*s == ',') s++;
-
- // remember start position in p
- const char *p = s;
- while (*s != '\0' && *s != 'x') {
- s++;
- }
- if (*s == '\0') return false;
-
- // get the width
- *w = atoi(p);
-
- // skip over 'x'
- ASSERT(*s == 'x');
- p = s + 1;
- while (*s != '\0' && *s != ',') {
- s++;
- }
-
- // get the height
- *h = atoi(p);
- *ptrS = s;
- return true;
-}
-
-class TestPictureSize : public AfterStartPreview {
-public:
- void checkOnePicture(int w, int h) {
- const float rate = 0.9; // byte per pixel limit
- int pixels = w * h;
-
- CameraParameters param(c->getParameters());
- param.setPictureSize(w, h);
- // disable thumbnail to get more accurate size.
- param.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, 0);
- param.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, 0);
- c->setParameters(param.flatten());
-
- cc->clearStat();
- ASSERT(c->takePicture() == NO_ERROR);
- cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
- //cc->assertDataSize(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, pixels*3/2);
- cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
- cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::LT,
- int(pixels * rate));
- cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::GT, 0);
- cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
- }
-
- void run() {
- CameraParameters param(c->getParameters());
- int w, h;
- const char *s = param.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES);
- while (getNextSize(&s, &w, &h)) {
- LOGD("checking picture size %dx%d", w, h);
- checkOnePicture(w, h);
- }
- }
-};
-
-class TestPreviewCallbackFlag : public AfterConnect {
-public:
- void run() {
- sp<MSurface> surface = new MSurface();
- ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
-
- // Try all flag combinations.
- for (int v = 0; v < 8; v++) {
- LOGD("TestPreviewCallbackFlag: flag=%d", v);
- usleep(100000); // sleep a while to clear the in-flight callbacks.
- cc->clearStat();
- c->setPreviewCallbackFlag(v);
- ASSERT(c->previewEnabled() == false);
- ASSERT(c->startPreview() == NO_ERROR);
- ASSERT(c->previewEnabled() == true);
- sleep(2);
- c->stopPreview();
- if ((v & FRAME_CALLBACK_FLAG_ENABLE_MASK) == 0) {
- cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 0);
- } else {
- if ((v & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) == 0) {
- cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::GE, 10);
- } else {
- cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 1);
- }
- }
- }
- }
-};
-
-class TestRecording : public AfterConnect {
-public:
- void run() {
- ASSERT(c->recordingEnabled() == false);
- sp<MSurface> surface = new MSurface();
- ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
- c->setPreviewCallbackFlag(FRAME_CALLBACK_FLAG_ENABLE_MASK);
- cc->setReleaser(c.get());
- c->startRecording();
- ASSERT(c->recordingEnabled() == true);
- sleep(2);
- c->stopRecording();
- usleep(100000); // sleep a while to clear the in-flight callbacks.
- cc->setReleaser(NULL);
- cc->assertData(CAMERA_MSG_VIDEO_FRAME, MCameraClient::GE, 10);
- }
-};
-
-class TestPreviewSize : public AfterStartPreview {
-public:
- void checkOnePicture(int w, int h) {
- int size = w*h*3/2; // should read from parameters
-
- c->stopPreview();
-
- CameraParameters param(c->getParameters());
- param.setPreviewSize(w, h);
- c->setPreviewCallbackFlag(FRAME_CALLBACK_FLAG_ENABLE_MASK);
- c->setParameters(param.flatten());
-
- c->startPreview();
-
- cc->clearStat();
- cc->waitData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::GE, 1);
- cc->assertDataSize(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, size);
- }
-
- void run() {
- CameraParameters param(c->getParameters());
- int w, h;
- const char *s = param.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES);
- while (getNextSize(&s, &w, &h)) {
- LOGD("checking preview size %dx%d", w, h);
- checkOnePicture(w, h);
- }
- }
-};
-
-void runHolderService() {
- defaultServiceManager()->addService(
- String16("CameraServiceTest.Holder"), new HolderService());
- ProcessState::self()->startThreadPool();
-}
-
-int main(int argc, char **argv)
-{
- if (argc != 1) {
- runFunction(argv[1]);
- return 0;
- }
- INFO("CameraServiceTest start");
- gExecutable = argv[0];
- runHolderService();
- int n = getNumberOfCameras();
- INFO("%d Cameras available", n);
-
- for (int id = 0; id < n; id++) {
- INFO("Testing camera %d", id);
- testConnect(id); flushCommands();
- testAllowConnectOnceOnly(id); flushCommands();
- testReconnect(id); flushCommands();
- testLockUnlock(id); flushCommands();
- testReconnectFromAnotherProcess(id); flushCommands();
-
- RUN(TestSetPreviewDisplay, id);
- RUN(TestStartPreview, id);
- RUN(TestStartPreviewWithoutDisplay, id);
- RUN(TestAutoFocus, id);
- RUN(TestStopPreview, id);
- RUN(TestTakePicture, id);
- RUN(TestTakeMultiplePictures, id);
- RUN(TestGetParameters, id);
- RUN(TestPictureSize, id);
- RUN(TestPreviewCallbackFlag, id);
- RUN(TestRecording, id);
- RUN(TestPreviewSize, id);
- }
-
- INFO("CameraServiceTest finished");
-}
diff --git a/cmds/surfaceflinger/Android.mk b/cmds/surfaceflinger/Android.mk
index bfa58a1..1df32bb 100644
--- a/cmds/surfaceflinger/Android.mk
+++ b/cmds/surfaceflinger/Android.mk
@@ -10,7 +10,7 @@ LOCAL_SHARED_LIBRARIES := \
libutils
LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../../libs/surfaceflinger
+ $(LOCAL_PATH)/../../services/surfaceflinger
LOCAL_MODULE:= surfaceflinger
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp
deleted file mode 100644
index 995e31c..0000000
--- a/libs/audioflinger/A2dpAudioInterface.cpp
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <math.h>
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "A2dpAudioInterface"
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include "A2dpAudioInterface.h"
-#include "audio/liba2dp.h"
-
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-//AudioHardwareInterface* A2dpAudioInterface::createA2dpInterface()
-//{
-// AudioHardwareInterface* hw = 0;
-//
-// hw = AudioHardwareInterface::create();
-// LOGD("new A2dpAudioInterface(hw: %p)", hw);
-// hw = new A2dpAudioInterface(hw);
-// return hw;
-//}
-
-A2dpAudioInterface::A2dpAudioInterface(AudioHardwareInterface* hw) :
- mOutput(0), mHardwareInterface(hw), mBluetoothEnabled(true), mSuspended(false)
-{
-}
-
-A2dpAudioInterface::~A2dpAudioInterface()
-{
- closeOutputStream((AudioStreamOut *)mOutput);
- delete mHardwareInterface;
-}
-
-status_t A2dpAudioInterface::initCheck()
-{
- if (mHardwareInterface == 0) return NO_INIT;
- return mHardwareInterface->initCheck();
-}
-
-AudioStreamOut* A2dpAudioInterface::openOutputStream(
- uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
-{
- if (!AudioSystem::isA2dpDevice((AudioSystem::audio_devices)devices)) {
- LOGV("A2dpAudioInterface::openOutputStream() open HW device: %x", devices);
- return mHardwareInterface->openOutputStream(devices, format, channels, sampleRate, status);
- }
-
- status_t err = 0;
-
- // only one output stream allowed
- if (mOutput) {
- if (status)
- *status = -1;
- return NULL;
- }
-
- // create new output stream
- A2dpAudioStreamOut* out = new A2dpAudioStreamOut();
- if ((err = out->set(devices, format, channels, sampleRate)) == NO_ERROR) {
- mOutput = out;
- mOutput->setBluetoothEnabled(mBluetoothEnabled);
- mOutput->setSuspended(mSuspended);
- } else {
- delete out;
- }
-
- if (status)
- *status = err;
- return mOutput;
-}
-
-void A2dpAudioInterface::closeOutputStream(AudioStreamOut* out) {
- if (mOutput == 0 || mOutput != out) {
- mHardwareInterface->closeOutputStream(out);
- }
- else {
- delete mOutput;
- mOutput = 0;
- }
-}
-
-
-AudioStreamIn* A2dpAudioInterface::openInputStream(
- uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
- AudioSystem::audio_in_acoustics acoustics)
-{
- return mHardwareInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics);
-}
-
-void A2dpAudioInterface::closeInputStream(AudioStreamIn* in)
-{
- return mHardwareInterface->closeInputStream(in);
-}
-
-status_t A2dpAudioInterface::setMode(int mode)
-{
- return mHardwareInterface->setMode(mode);
-}
-
-status_t A2dpAudioInterface::setMicMute(bool state)
-{
- return mHardwareInterface->setMicMute(state);
-}
-
-status_t A2dpAudioInterface::getMicMute(bool* state)
-{
- return mHardwareInterface->getMicMute(state);
-}
-
-status_t A2dpAudioInterface::setParameters(const String8& keyValuePairs)
-{
- AudioParameter param = AudioParameter(keyValuePairs);
- String8 value;
- String8 key;
- status_t status = NO_ERROR;
-
- LOGV("setParameters() %s", keyValuePairs.string());
-
- key = "bluetooth_enabled";
- if (param.get(key, value) == NO_ERROR) {
- mBluetoothEnabled = (value == "true");
- if (mOutput) {
- mOutput->setBluetoothEnabled(mBluetoothEnabled);
- }
- param.remove(key);
- }
- key = String8("A2dpSuspended");
- if (param.get(key, value) == NO_ERROR) {
- mSuspended = (value == "true");
- if (mOutput) {
- mOutput->setSuspended(mSuspended);
- }
- param.remove(key);
- }
-
- if (param.size()) {
- status_t hwStatus = mHardwareInterface->setParameters(param.toString());
- if (status == NO_ERROR) {
- status = hwStatus;
- }
- }
-
- return status;
-}
-
-String8 A2dpAudioInterface::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- AudioParameter a2dpParam = AudioParameter();
- String8 value;
- String8 key;
-
- key = "bluetooth_enabled";
- if (param.get(key, value) == NO_ERROR) {
- value = mBluetoothEnabled ? "true" : "false";
- a2dpParam.add(key, value);
- param.remove(key);
- }
- key = "A2dpSuspended";
- if (param.get(key, value) == NO_ERROR) {
- value = mSuspended ? "true" : "false";
- a2dpParam.add(key, value);
- param.remove(key);
- }
-
- String8 keyValuePairs = a2dpParam.toString();
-
- if (param.size()) {
- if (keyValuePairs != "") {
- keyValuePairs += ";";
- }
- keyValuePairs += mHardwareInterface->getParameters(param.toString());
- }
-
- LOGV("getParameters() %s", keyValuePairs.string());
- return keyValuePairs;
-}
-
-size_t A2dpAudioInterface::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
-{
- return mHardwareInterface->getInputBufferSize(sampleRate, format, channelCount);
-}
-
-status_t A2dpAudioInterface::setVoiceVolume(float v)
-{
- return mHardwareInterface->setVoiceVolume(v);
-}
-
-status_t A2dpAudioInterface::setMasterVolume(float v)
-{
- return mHardwareInterface->setMasterVolume(v);
-}
-
-status_t A2dpAudioInterface::dump(int fd, const Vector<String16>& args)
-{
- return mHardwareInterface->dumpState(fd, args);
-}
-
-// ----------------------------------------------------------------------------
-
-A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() :
- mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL),
- // assume BT enabled to start, this is safe because its only the
- // enabled->disabled transition we are worried about
- mBluetoothEnabled(true), mDevice(0), mClosing(false), mSuspended(false)
-{
- // use any address by default
- strcpy(mA2dpAddress, "00:00:00:00:00:00");
- init();
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::set(
- uint32_t device, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
-{
- int lFormat = pFormat ? *pFormat : 0;
- uint32_t lChannels = pChannels ? *pChannels : 0;
- uint32_t lRate = pRate ? *pRate : 0;
-
- LOGD("A2dpAudioStreamOut::set %x, %d, %d, %d\n", device, lFormat, lChannels, lRate);
-
- // fix up defaults
- if (lFormat == 0) lFormat = format();
- if (lChannels == 0) lChannels = channels();
- if (lRate == 0) lRate = sampleRate();
-
- // check values
- if ((lFormat != format()) ||
- (lChannels != channels()) ||
- (lRate != sampleRate())){
- if (pFormat) *pFormat = format();
- if (pChannels) *pChannels = channels();
- if (pRate) *pRate = sampleRate();
- return BAD_VALUE;
- }
-
- if (pFormat) *pFormat = lFormat;
- if (pChannels) *pChannels = lChannels;
- if (pRate) *pRate = lRate;
-
- mDevice = device;
- return NO_ERROR;
-}
-
-A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut()
-{
- LOGV("A2dpAudioStreamOut destructor");
- standby();
- close();
- LOGV("A2dpAudioStreamOut destructor returning from close()");
-}
-
-ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes)
-{
- Mutex::Autolock lock(mLock);
-
- size_t remaining = bytes;
- status_t status = -1;
-
- if (!mBluetoothEnabled || mClosing || mSuspended) {
- LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \
- mBluetoothEnabled %d, mClosing %d, mSuspended %d",
- mBluetoothEnabled, mClosing, mSuspended);
- goto Error;
- }
-
- status = init();
- if (status < 0)
- goto Error;
-
- while (remaining > 0) {
- status = a2dp_write(mData, buffer, remaining);
- if (status <= 0) {
- LOGE("a2dp_write failed err: %d\n", status);
- goto Error;
- }
- remaining -= status;
- buffer = ((char *)buffer) + status;
- }
-
- mStandby = false;
-
- return bytes;
-
-Error:
- // Simulate audio output timing in case of error
- usleep(((bytes * 1000 )/ frameSize() / sampleRate()) * 1000);
-
- return status;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::init()
-{
- if (!mData) {
- status_t status = a2dp_init(44100, 2, &mData);
- if (status < 0) {
- LOGE("a2dp_init failed err: %d\n", status);
- mData = NULL;
- return status;
- }
- a2dp_set_sink(mData, mA2dpAddress);
- }
-
- return 0;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::standby()
-{
- int result = 0;
-
- if (mClosing) {
- LOGV("Ignore standby, closing");
- return result;
- }
-
- Mutex::Autolock lock(mLock);
-
- if (!mStandby) {
- result = a2dp_stop(mData);
- if (result == 0)
- mStandby = true;
- }
-
- return result;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::setParameters(const String8& keyValuePairs)
-{
- AudioParameter param = AudioParameter(keyValuePairs);
- String8 value;
- String8 key = String8("a2dp_sink_address");
- status_t status = NO_ERROR;
- int device;
- LOGV("A2dpAudioStreamOut::setParameters() %s", keyValuePairs.string());
-
- if (param.get(key, value) == NO_ERROR) {
- if (value.length() != strlen("00:00:00:00:00:00")) {
- status = BAD_VALUE;
- } else {
- setAddress(value.string());
- }
- param.remove(key);
- }
- key = String8("closing");
- if (param.get(key, value) == NO_ERROR) {
- mClosing = (value == "true");
- param.remove(key);
- }
- key = AudioParameter::keyRouting;
- if (param.getInt(key, device) == NO_ERROR) {
- if (AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device)) {
- mDevice = device;
- status = NO_ERROR;
- } else {
- status = BAD_VALUE;
- }
- param.remove(key);
- }
-
- if (param.size()) {
- status = BAD_VALUE;
- }
- return status;
-}
-
-String8 A2dpAudioInterface::A2dpAudioStreamOut::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- String8 value;
- String8 key = String8("a2dp_sink_address");
-
- if (param.get(key, value) == NO_ERROR) {
- value = mA2dpAddress;
- param.add(key, value);
- }
- key = AudioParameter::keyRouting;
- if (param.get(key, value) == NO_ERROR) {
- param.addInt(key, (int)mDevice);
- }
-
- LOGV("A2dpAudioStreamOut::getParameters() %s", param.toString().string());
- return param.toString();
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address)
-{
- Mutex::Autolock lock(mLock);
-
- if (strlen(address) != strlen("00:00:00:00:00:00"))
- return -EINVAL;
-
- strcpy(mA2dpAddress, address);
- if (mData)
- a2dp_set_sink(mData, mA2dpAddress);
-
- return NO_ERROR;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::setBluetoothEnabled(bool enabled)
-{
- LOGD("setBluetoothEnabled %d", enabled);
-
- Mutex::Autolock lock(mLock);
-
- mBluetoothEnabled = enabled;
- if (!enabled) {
- return close_l();
- }
- return NO_ERROR;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::setSuspended(bool onOff)
-{
- LOGV("setSuspended %d", onOff);
- mSuspended = onOff;
- standby();
- return NO_ERROR;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::close()
-{
- Mutex::Autolock lock(mLock);
- LOGV("A2dpAudioStreamOut::close() calling close_l()");
- return close_l();
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::close_l()
-{
- if (mData) {
- LOGV("A2dpAudioStreamOut::close_l() calling a2dp_cleanup(mData)");
- a2dp_cleanup(mData);
- mData = NULL;
- }
- return NO_ERROR;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::dump(int fd, const Vector<String16>& args)
-{
- return NO_ERROR;
-}
-
-status_t A2dpAudioInterface::A2dpAudioStreamOut::getRenderPosition(uint32_t *driverFrames)
-{
- //TODO: enable when supported by driver
- return INVALID_OPERATION;
-}
-
-}; // namespace android
diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h
deleted file mode 100644
index 48154f9..0000000
--- a/libs/audioflinger/A2dpAudioInterface.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef A2DP_AUDIO_HARDWARE_H
-#define A2DP_AUDIO_HARDWARE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/threads.h>
-
-#include <hardware_legacy/AudioHardwareBase.h>
-
-
-namespace android {
-
-class A2dpAudioInterface : public AudioHardwareBase
-{
- class A2dpAudioStreamOut;
-
-public:
- A2dpAudioInterface(AudioHardwareInterface* hw);
- virtual ~A2dpAudioInterface();
- virtual status_t initCheck();
-
- virtual status_t setVoiceVolume(float volume);
- virtual status_t setMasterVolume(float volume);
-
- virtual status_t setMode(int mode);
-
- // mic mute
- virtual status_t setMicMute(bool state);
- virtual status_t getMicMute(bool* state);
-
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys);
-
- virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
-
- // create I/O streams
- virtual AudioStreamOut* openOutputStream(
- uint32_t devices,
- int *format=0,
- uint32_t *channels=0,
- uint32_t *sampleRate=0,
- status_t *status=0);
- virtual void closeOutputStream(AudioStreamOut* out);
-
- virtual AudioStreamIn* openInputStream(
- uint32_t devices,
- int *format,
- uint32_t *channels,
- uint32_t *sampleRate,
- status_t *status,
- AudioSystem::audio_in_acoustics acoustics);
- virtual void closeInputStream(AudioStreamIn* in);
-// static AudioHardwareInterface* createA2dpInterface();
-
-protected:
- virtual status_t dump(int fd, const Vector<String16>& args);
-
-private:
- class A2dpAudioStreamOut : public AudioStreamOut {
- public:
- A2dpAudioStreamOut();
- virtual ~A2dpAudioStreamOut();
- status_t set(uint32_t device,
- int *pFormat,
- uint32_t *pChannels,
- uint32_t *pRate);
- virtual uint32_t sampleRate() const { return 44100; }
- // SBC codec wants a multiple of 512
- virtual size_t bufferSize() const { return 512 * 20; }
- virtual uint32_t channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
- virtual int format() const { return AudioSystem::PCM_16_BIT; }
- virtual uint32_t latency() const { return ((1000*bufferSize())/frameSize())/sampleRate() + 200; }
- virtual status_t setVolume(float left, float right) { return INVALID_OPERATION; }
- virtual ssize_t write(const void* buffer, size_t bytes);
- status_t standby();
- virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys);
- virtual status_t getRenderPosition(uint32_t *dspFrames);
-
- private:
- friend class A2dpAudioInterface;
- status_t init();
- status_t close();
- status_t close_l();
- status_t setAddress(const char* address);
- status_t setBluetoothEnabled(bool enabled);
- status_t setSuspended(bool onOff);
-
- private:
- int mFd;
- bool mStandby;
- int mStartCount;
- int mRetryCount;
- char mA2dpAddress[20];
- void* mData;
- Mutex mLock;
- bool mBluetoothEnabled;
- uint32_t mDevice;
- bool mClosing;
- bool mSuspended;
- };
-
- friend class A2dpAudioStreamOut;
-
- A2dpAudioStreamOut* mOutput;
- AudioHardwareInterface *mHardwareInterface;
- char mA2dpAddress[20];
- bool mBluetoothEnabled;
- bool mSuspended;
-};
-
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // A2DP_AUDIO_HARDWARE_H
diff --git a/libs/audioflinger/Android.mk b/libs/audioflinger/Android.mk
deleted file mode 100644
index 22ecc54..0000000
--- a/libs/audioflinger/Android.mk
+++ /dev/null
@@ -1,131 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-#AUDIO_POLICY_TEST := true
-#ENABLE_AUDIO_DUMP := true
-
-include $(CLEAR_VARS)
-
-
-ifeq ($(AUDIO_POLICY_TEST),true)
- ENABLE_AUDIO_DUMP := true
-endif
-
-
-LOCAL_SRC_FILES:= \
- AudioHardwareGeneric.cpp \
- AudioHardwareStub.cpp \
- AudioHardwareInterface.cpp
-
-ifeq ($(ENABLE_AUDIO_DUMP),true)
- LOCAL_SRC_FILES += AudioDumpInterface.cpp
- LOCAL_CFLAGS += -DENABLE_AUDIO_DUMP
-endif
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- libbinder \
- libmedia \
- libhardware_legacy
-
-ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
- LOCAL_CFLAGS += -DGENERIC_AUDIO
-endif
-
-LOCAL_MODULE:= libaudiointerface
-
-ifeq ($(BOARD_HAVE_BLUETOOTH),true)
- LOCAL_SRC_FILES += A2dpAudioInterface.cpp
- LOCAL_SHARED_LIBRARIES += liba2dp
- LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
- LOCAL_C_INCLUDES += $(call include-path-for, bluez)
-endif
-
-include $(BUILD_STATIC_LIBRARY)
-
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- AudioPolicyManagerBase.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- libmedia
-
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -ldl
-else
- LOCAL_SHARED_LIBRARIES += libdl
-endif
-
-LOCAL_MODULE:= libaudiopolicybase
-
-ifeq ($(BOARD_HAVE_BLUETOOTH),true)
- LOCAL_CFLAGS += -DWITH_A2DP
-endif
-
-ifeq ($(AUDIO_POLICY_TEST),true)
- LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
-endif
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- AudioFlinger.cpp \
- AudioMixer.cpp.arm \
- AudioResampler.cpp.arm \
- AudioResamplerSinc.cpp.arm \
- AudioResamplerCubic.cpp.arm \
- AudioPolicyService.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- libbinder \
- libmedia \
- libhardware_legacy \
- libeffects
-
-ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
- LOCAL_STATIC_LIBRARIES += libaudiointerface libaudiopolicybase
- LOCAL_CFLAGS += -DGENERIC_AUDIO
-else
- LOCAL_SHARED_LIBRARIES += libaudio libaudiopolicy
-endif
-
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -ldl
-else
- LOCAL_SHARED_LIBRARIES += libdl
-endif
-
-LOCAL_MODULE:= libaudioflinger
-
-ifeq ($(BOARD_HAVE_BLUETOOTH),true)
- LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
- LOCAL_SHARED_LIBRARIES += liba2dp
-endif
-
-ifeq ($(AUDIO_POLICY_TEST),true)
- LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
-endif
-
-ifeq ($(TARGET_SIMULATOR),true)
- ifeq ($(HOST_OS),linux)
- LOCAL_LDLIBS += -lrt -lpthread
- endif
-endif
-
-ifeq ($(BOARD_USE_LVMX),true)
- LOCAL_CFLAGS += -DLVMX
- LOCAL_C_INCLUDES += vendor/nxp
- LOCAL_STATIC_LIBRARIES += liblifevibes
- LOCAL_SHARED_LIBRARIES += liblvmxservice
-# LOCAL_SHARED_LIBRARIES += liblvmxipc
-endif
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/audioflinger/AudioBufferProvider.h b/libs/audioflinger/AudioBufferProvider.h
deleted file mode 100644
index 81c5c39..0000000
--- a/libs/audioflinger/AudioBufferProvider.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_AUDIO_BUFFER_PROVIDER_H
-#define ANDROID_AUDIO_BUFFER_PROVIDER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <utils/Errors.h>
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class AudioBufferProvider
-{
-public:
-
- struct Buffer {
- union {
- void* raw;
- short* i16;
- int8_t* i8;
- };
- size_t frameCount;
- };
-
- virtual ~AudioBufferProvider() {}
-
- virtual status_t getNextBuffer(Buffer* buffer) = 0;
- virtual void releaseBuffer(Buffer* buffer) = 0;
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_AUDIO_BUFFER_PROVIDER_H
diff --git a/libs/audioflinger/AudioDumpInterface.cpp b/libs/audioflinger/AudioDumpInterface.cpp
deleted file mode 100644
index 6c11114..0000000
--- a/libs/audioflinger/AudioDumpInterface.cpp
+++ /dev/null
@@ -1,573 +0,0 @@
-/* //device/servers/AudioFlinger/AudioDumpInterface.cpp
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "AudioFlingerDump"
-//#define LOG_NDEBUG 0
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <utils/Log.h>
-
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "AudioDumpInterface.h"
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-AudioDumpInterface::AudioDumpInterface(AudioHardwareInterface* hw)
- : mPolicyCommands(String8("")), mFileName(String8(""))
-{
- if(hw == 0) {
- LOGE("Dump construct hw = 0");
- }
- mFinalInterface = hw;
- LOGV("Constructor %p, mFinalInterface %p", this, mFinalInterface);
-}
-
-
-AudioDumpInterface::~AudioDumpInterface()
-{
- for (size_t i = 0; i < mOutputs.size(); i++) {
- closeOutputStream((AudioStreamOut *)mOutputs[i]);
- }
-
- for (size_t i = 0; i < mInputs.size(); i++) {
- closeInputStream((AudioStreamIn *)mInputs[i]);
- }
-
- if(mFinalInterface) delete mFinalInterface;
-}
-
-
-AudioStreamOut* AudioDumpInterface::openOutputStream(
- uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
-{
- AudioStreamOut* outFinal = NULL;
- int lFormat = AudioSystem::PCM_16_BIT;
- uint32_t lChannels = AudioSystem::CHANNEL_OUT_STEREO;
- uint32_t lRate = 44100;
-
-
- outFinal = mFinalInterface->openOutputStream(devices, format, channels, sampleRate, status);
- if (outFinal != 0) {
- lFormat = outFinal->format();
- lChannels = outFinal->channels();
- lRate = outFinal->sampleRate();
- } else {
- if (format != 0) {
- if (*format != 0) {
- lFormat = *format;
- } else {
- *format = lFormat;
- }
- }
- if (channels != 0) {
- if (*channels != 0) {
- lChannels = *channels;
- } else {
- *channels = lChannels;
- }
- }
- if (sampleRate != 0) {
- if (*sampleRate != 0) {
- lRate = *sampleRate;
- } else {
- *sampleRate = lRate;
- }
- }
- if (status) *status = NO_ERROR;
- }
- LOGV("openOutputStream(), outFinal %p", outFinal);
-
- AudioStreamOutDump *dumOutput = new AudioStreamOutDump(this, mOutputs.size(), outFinal,
- devices, lFormat, lChannels, lRate);
- mOutputs.add(dumOutput);
-
- return dumOutput;
-}
-
-void AudioDumpInterface::closeOutputStream(AudioStreamOut* out)
-{
- AudioStreamOutDump *dumpOut = (AudioStreamOutDump *)out;
-
- if (mOutputs.indexOf(dumpOut) < 0) {
- LOGW("Attempt to close invalid output stream");
- return;
- }
-
- LOGV("closeOutputStream() output %p", out);
-
- dumpOut->standby();
- if (dumpOut->finalStream() != NULL) {
- mFinalInterface->closeOutputStream(dumpOut->finalStream());
- }
-
- mOutputs.remove(dumpOut);
- delete dumpOut;
-}
-
-AudioStreamIn* AudioDumpInterface::openInputStream(uint32_t devices, int *format, uint32_t *channels,
- uint32_t *sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics)
-{
- AudioStreamIn* inFinal = NULL;
- int lFormat = AudioSystem::PCM_16_BIT;
- uint32_t lChannels = AudioSystem::CHANNEL_IN_MONO;
- uint32_t lRate = 8000;
-
- inFinal = mFinalInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics);
- if (inFinal != 0) {
- lFormat = inFinal->format();
- lChannels = inFinal->channels();
- lRate = inFinal->sampleRate();
- } else {
- if (format != 0) {
- if (*format != 0) {
- lFormat = *format;
- } else {
- *format = lFormat;
- }
- }
- if (channels != 0) {
- if (*channels != 0) {
- lChannels = *channels;
- } else {
- *channels = lChannels;
- }
- }
- if (sampleRate != 0) {
- if (*sampleRate != 0) {
- lRate = *sampleRate;
- } else {
- *sampleRate = lRate;
- }
- }
- if (status) *status = NO_ERROR;
- }
- LOGV("openInputStream(), inFinal %p", inFinal);
-
- AudioStreamInDump *dumInput = new AudioStreamInDump(this, mInputs.size(), inFinal,
- devices, lFormat, lChannels, lRate);
- mInputs.add(dumInput);
-
- return dumInput;
-}
-void AudioDumpInterface::closeInputStream(AudioStreamIn* in)
-{
- AudioStreamInDump *dumpIn = (AudioStreamInDump *)in;
-
- if (mInputs.indexOf(dumpIn) < 0) {
- LOGW("Attempt to close invalid input stream");
- return;
- }
- dumpIn->standby();
- if (dumpIn->finalStream() != NULL) {
- mFinalInterface->closeInputStream(dumpIn->finalStream());
- }
-
- mInputs.remove(dumpIn);
- delete dumpIn;
-}
-
-
-status_t AudioDumpInterface::setParameters(const String8& keyValuePairs)
-{
- AudioParameter param = AudioParameter(keyValuePairs);
- String8 value;
- int valueInt;
- LOGV("setParameters %s", keyValuePairs.string());
-
- if (param.get(String8("test_cmd_file_name"), value) == NO_ERROR) {
- mFileName = value;
- param.remove(String8("test_cmd_file_name"));
- }
- if (param.get(String8("test_cmd_policy"), value) == NO_ERROR) {
- Mutex::Autolock _l(mLock);
- param.remove(String8("test_cmd_policy"));
- mPolicyCommands = param.toString();
- LOGV("test_cmd_policy command %s written", mPolicyCommands.string());
- return NO_ERROR;
- }
-
- if (mFinalInterface != 0 ) return mFinalInterface->setParameters(keyValuePairs);
- return NO_ERROR;
-}
-
-String8 AudioDumpInterface::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- AudioParameter response;
- String8 value;
-
-// LOGV("getParameters %s", keys.string());
- if (param.get(String8("test_cmd_policy"), value) == NO_ERROR) {
- Mutex::Autolock _l(mLock);
- if (mPolicyCommands.length() != 0) {
- response = AudioParameter(mPolicyCommands);
- response.addInt(String8("test_cmd_policy"), 1);
- } else {
- response.addInt(String8("test_cmd_policy"), 0);
- }
- param.remove(String8("test_cmd_policy"));
-// LOGV("test_cmd_policy command %s read", mPolicyCommands.string());
- }
-
- if (param.get(String8("test_cmd_file_name"), value) == NO_ERROR) {
- response.add(String8("test_cmd_file_name"), mFileName);
- param.remove(String8("test_cmd_file_name"));
- }
-
- String8 keyValuePairs = response.toString();
-
- if (param.size() && mFinalInterface != 0 ) {
- keyValuePairs += ";";
- keyValuePairs += mFinalInterface->getParameters(param.toString());
- }
-
- return keyValuePairs;
-}
-
-status_t AudioDumpInterface::setMode(int mode)
-{
- return mFinalInterface->setMode(mode);
-}
-
-size_t AudioDumpInterface::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
-{
- return mFinalInterface->getInputBufferSize(sampleRate, format, channelCount);
-}
-
-// ----------------------------------------------------------------------------
-
-AudioStreamOutDump::AudioStreamOutDump(AudioDumpInterface *interface,
- int id,
- AudioStreamOut* finalStream,
- uint32_t devices,
- int format,
- uint32_t channels,
- uint32_t sampleRate)
- : mInterface(interface), mId(id),
- mSampleRate(sampleRate), mFormat(format), mChannels(channels), mLatency(0), mDevice(devices),
- mBufferSize(1024), mFinalStream(finalStream), mFile(0), mFileCount(0)
-{
- LOGV("AudioStreamOutDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream);
-}
-
-
-AudioStreamOutDump::~AudioStreamOutDump()
-{
- LOGV("AudioStreamOutDump destructor");
- Close();
-}
-
-ssize_t AudioStreamOutDump::write(const void* buffer, size_t bytes)
-{
- ssize_t ret;
-
- if (mFinalStream) {
- ret = mFinalStream->write(buffer, bytes);
- } else {
- usleep((((bytes * 1000) / frameSize()) / sampleRate()) * 1000);
- ret = bytes;
- }
- if(!mFile) {
- if (mInterface->fileName() != "") {
- char name[255];
- sprintf(name, "%s_out_%d_%d.pcm", mInterface->fileName().string(), mId, ++mFileCount);
- mFile = fopen(name, "wb");
- LOGV("Opening dump file %s, fh %p", name, mFile);
- }
- }
- if (mFile) {
- fwrite(buffer, bytes, 1, mFile);
- }
- return ret;
-}
-
-status_t AudioStreamOutDump::standby()
-{
- LOGV("AudioStreamOutDump standby(), mFile %p, mFinalStream %p", mFile, mFinalStream);
-
- Close();
- if (mFinalStream != 0 ) return mFinalStream->standby();
- return NO_ERROR;
-}
-
-uint32_t AudioStreamOutDump::sampleRate() const
-{
- if (mFinalStream != 0 ) return mFinalStream->sampleRate();
- return mSampleRate;
-}
-
-size_t AudioStreamOutDump::bufferSize() const
-{
- if (mFinalStream != 0 ) return mFinalStream->bufferSize();
- return mBufferSize;
-}
-
-uint32_t AudioStreamOutDump::channels() const
-{
- if (mFinalStream != 0 ) return mFinalStream->channels();
- return mChannels;
-}
-int AudioStreamOutDump::format() const
-{
- if (mFinalStream != 0 ) return mFinalStream->format();
- return mFormat;
-}
-uint32_t AudioStreamOutDump::latency() const
-{
- if (mFinalStream != 0 ) return mFinalStream->latency();
- return 0;
-}
-status_t AudioStreamOutDump::setVolume(float left, float right)
-{
- if (mFinalStream != 0 ) return mFinalStream->setVolume(left, right);
- return NO_ERROR;
-}
-status_t AudioStreamOutDump::setParameters(const String8& keyValuePairs)
-{
- LOGV("AudioStreamOutDump::setParameters %s", keyValuePairs.string());
-
- if (mFinalStream != 0 ) {
- return mFinalStream->setParameters(keyValuePairs);
- }
-
- AudioParameter param = AudioParameter(keyValuePairs);
- String8 value;
- int valueInt;
- status_t status = NO_ERROR;
-
- if (param.getInt(String8("set_id"), valueInt) == NO_ERROR) {
- mId = valueInt;
- }
-
- if (param.getInt(String8("format"), valueInt) == NO_ERROR) {
- if (mFile == 0) {
- mFormat = valueInt;
- } else {
- status = INVALID_OPERATION;
- }
- }
- if (param.getInt(String8("channels"), valueInt) == NO_ERROR) {
- if (valueInt == AudioSystem::CHANNEL_OUT_STEREO || valueInt == AudioSystem::CHANNEL_OUT_MONO) {
- mChannels = valueInt;
- } else {
- status = BAD_VALUE;
- }
- }
- if (param.getInt(String8("sampling_rate"), valueInt) == NO_ERROR) {
- if (valueInt > 0 && valueInt <= 48000) {
- if (mFile == 0) {
- mSampleRate = valueInt;
- } else {
- status = INVALID_OPERATION;
- }
- } else {
- status = BAD_VALUE;
- }
- }
- return status;
-}
-
-String8 AudioStreamOutDump::getParameters(const String8& keys)
-{
- if (mFinalStream != 0 ) return mFinalStream->getParameters(keys);
-
- AudioParameter param = AudioParameter(keys);
- return param.toString();
-}
-
-status_t AudioStreamOutDump::dump(int fd, const Vector<String16>& args)
-{
- if (mFinalStream != 0 ) return mFinalStream->dump(fd, args);
- return NO_ERROR;
-}
-
-void AudioStreamOutDump::Close()
-{
- if(mFile) {
- fclose(mFile);
- mFile = 0;
- }
-}
-
-status_t AudioStreamOutDump::getRenderPosition(uint32_t *dspFrames)
-{
- if (mFinalStream != 0 ) return mFinalStream->getRenderPosition(dspFrames);
- return INVALID_OPERATION;
-}
-
-// ----------------------------------------------------------------------------
-
-AudioStreamInDump::AudioStreamInDump(AudioDumpInterface *interface,
- int id,
- AudioStreamIn* finalStream,
- uint32_t devices,
- int format,
- uint32_t channels,
- uint32_t sampleRate)
- : mInterface(interface), mId(id),
- mSampleRate(sampleRate), mFormat(format), mChannels(channels), mDevice(devices),
- mBufferSize(1024), mFinalStream(finalStream), mFile(0), mFileCount(0)
-{
- LOGV("AudioStreamInDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream);
-}
-
-
-AudioStreamInDump::~AudioStreamInDump()
-{
- Close();
-}
-
-ssize_t AudioStreamInDump::read(void* buffer, ssize_t bytes)
-{
- ssize_t ret;
-
- if (mFinalStream) {
- ret = mFinalStream->read(buffer, bytes);
- if(!mFile) {
- if (mInterface->fileName() != "") {
- char name[255];
- sprintf(name, "%s_in_%d_%d.pcm", mInterface->fileName().string(), mId, ++mFileCount);
- mFile = fopen(name, "wb");
- LOGV("Opening input dump file %s, fh %p", name, mFile);
- }
- }
- if (mFile) {
- fwrite(buffer, bytes, 1, mFile);
- }
- } else {
- usleep((((bytes * 1000) / frameSize()) / sampleRate()) * 1000);
- ret = bytes;
- if(!mFile) {
- char name[255];
- strcpy(name, "/sdcard/music/sine440");
- if (channels() == AudioSystem::CHANNEL_IN_MONO) {
- strcat(name, "_mo");
- } else {
- strcat(name, "_st");
- }
- if (format() == AudioSystem::PCM_16_BIT) {
- strcat(name, "_16b");
- } else {
- strcat(name, "_8b");
- }
- if (sampleRate() < 16000) {
- strcat(name, "_8k");
- } else if (sampleRate() < 32000) {
- strcat(name, "_22k");
- } else if (sampleRate() < 48000) {
- strcat(name, "_44k");
- } else {
- strcat(name, "_48k");
- }
- strcat(name, ".wav");
- mFile = fopen(name, "rb");
- LOGV("Opening input read file %s, fh %p", name, mFile);
- if (mFile) {
- fseek(mFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
- }
- }
- if (mFile) {
- ssize_t bytesRead = fread(buffer, bytes, 1, mFile);
- if (bytesRead >=0 && bytesRead < bytes) {
- fseek(mFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
- fread((uint8_t *)buffer+bytesRead, bytes-bytesRead, 1, mFile);
- }
- }
- }
-
- return ret;
-}
-
-status_t AudioStreamInDump::standby()
-{
- LOGV("AudioStreamInDump standby(), mFile %p, mFinalStream %p", mFile, mFinalStream);
-
- Close();
- if (mFinalStream != 0 ) return mFinalStream->standby();
- return NO_ERROR;
-}
-
-status_t AudioStreamInDump::setGain(float gain)
-{
- if (mFinalStream != 0 ) return mFinalStream->setGain(gain);
- return NO_ERROR;
-}
-
-uint32_t AudioStreamInDump::sampleRate() const
-{
- if (mFinalStream != 0 ) return mFinalStream->sampleRate();
- return mSampleRate;
-}
-
-size_t AudioStreamInDump::bufferSize() const
-{
- if (mFinalStream != 0 ) return mFinalStream->bufferSize();
- return mBufferSize;
-}
-
-uint32_t AudioStreamInDump::channels() const
-{
- if (mFinalStream != 0 ) return mFinalStream->channels();
- return mChannels;
-}
-
-int AudioStreamInDump::format() const
-{
- if (mFinalStream != 0 ) return mFinalStream->format();
- return mFormat;
-}
-
-status_t AudioStreamInDump::setParameters(const String8& keyValuePairs)
-{
- LOGV("AudioStreamInDump::setParameters()");
- if (mFinalStream != 0 ) return mFinalStream->setParameters(keyValuePairs);
- return NO_ERROR;
-}
-
-String8 AudioStreamInDump::getParameters(const String8& keys)
-{
- if (mFinalStream != 0 ) return mFinalStream->getParameters(keys);
-
- AudioParameter param = AudioParameter(keys);
- return param.toString();
-}
-
-unsigned int AudioStreamInDump::getInputFramesLost() const
-{
- if (mFinalStream != 0 ) return mFinalStream->getInputFramesLost();
- return 0;
-}
-
-status_t AudioStreamInDump::dump(int fd, const Vector<String16>& args)
-{
- if (mFinalStream != 0 ) return mFinalStream->dump(fd, args);
- return NO_ERROR;
-}
-
-void AudioStreamInDump::Close()
-{
- if(mFile) {
- fclose(mFile);
- mFile = 0;
- }
-}
-}; // namespace android
diff --git a/libs/audioflinger/AudioDumpInterface.h b/libs/audioflinger/AudioDumpInterface.h
deleted file mode 100644
index 814ce5f..0000000
--- a/libs/audioflinger/AudioDumpInterface.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/* //device/servers/AudioFlinger/AudioDumpInterface.h
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_AUDIO_DUMP_INTERFACE_H
-#define ANDROID_AUDIO_DUMP_INTERFACE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <utils/String8.h>
-#include <utils/SortedVector.h>
-
-#include <hardware_legacy/AudioHardwareBase.h>
-
-namespace android {
-
-#define AUDIO_DUMP_WAVE_HDR_SIZE 44
-
-class AudioDumpInterface;
-
-class AudioStreamOutDump : public AudioStreamOut {
-public:
- AudioStreamOutDump(AudioDumpInterface *interface,
- int id,
- AudioStreamOut* finalStream,
- uint32_t devices,
- int format,
- uint32_t channels,
- uint32_t sampleRate);
- ~AudioStreamOutDump();
-
- virtual ssize_t write(const void* buffer, size_t bytes);
- virtual uint32_t sampleRate() const;
- virtual size_t bufferSize() const;
- virtual uint32_t channels() const;
- virtual int format() const;
- virtual uint32_t latency() const;
- virtual status_t setVolume(float left, float right);
- virtual status_t standby();
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys);
- virtual status_t dump(int fd, const Vector<String16>& args);
- void Close(void);
- AudioStreamOut* finalStream() { return mFinalStream; }
- uint32_t device() { return mDevice; }
- int getId() { return mId; }
- virtual status_t getRenderPosition(uint32_t *dspFrames);
-
-private:
- AudioDumpInterface *mInterface;
- int mId;
- uint32_t mSampleRate; //
- uint32_t mFormat; //
- uint32_t mChannels; // output configuration
- uint32_t mLatency; //
- uint32_t mDevice; // current device this output is routed to
- size_t mBufferSize;
- AudioStreamOut *mFinalStream;
- FILE *mFile; // output file
- int mFileCount;
-};
-
-class AudioStreamInDump : public AudioStreamIn {
-public:
- AudioStreamInDump(AudioDumpInterface *interface,
- int id,
- AudioStreamIn* finalStream,
- uint32_t devices,
- int format,
- uint32_t channels,
- uint32_t sampleRate);
- ~AudioStreamInDump();
-
- virtual uint32_t sampleRate() const;
- virtual size_t bufferSize() const;
- virtual uint32_t channels() const;
- virtual int format() const;
-
- virtual status_t setGain(float gain);
- virtual ssize_t read(void* buffer, ssize_t bytes);
- virtual status_t standby();
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys);
- virtual unsigned int getInputFramesLost() const;
- virtual status_t dump(int fd, const Vector<String16>& args);
- void Close(void);
- AudioStreamIn* finalStream() { return mFinalStream; }
- uint32_t device() { return mDevice; }
-
-private:
- AudioDumpInterface *mInterface;
- int mId;
- uint32_t mSampleRate; //
- uint32_t mFormat; //
- uint32_t mChannels; // output configuration
- uint32_t mDevice; // current device this output is routed to
- size_t mBufferSize;
- AudioStreamIn *mFinalStream;
- FILE *mFile; // output file
- int mFileCount;
-};
-
-class AudioDumpInterface : public AudioHardwareBase
-{
-
-public:
- AudioDumpInterface(AudioHardwareInterface* hw);
- virtual AudioStreamOut* openOutputStream(
- uint32_t devices,
- int *format=0,
- uint32_t *channels=0,
- uint32_t *sampleRate=0,
- status_t *status=0);
- virtual void closeOutputStream(AudioStreamOut* out);
-
- virtual ~AudioDumpInterface();
-
- virtual status_t initCheck()
- {return mFinalInterface->initCheck();}
- virtual status_t setVoiceVolume(float volume)
- {return mFinalInterface->setVoiceVolume(volume);}
- virtual status_t setMasterVolume(float volume)
- {return mFinalInterface->setMasterVolume(volume);}
-
- virtual status_t setMode(int mode);
-
- // mic mute
- virtual status_t setMicMute(bool state)
- {return mFinalInterface->setMicMute(state);}
- virtual status_t getMicMute(bool* state)
- {return mFinalInterface->getMicMute(state);}
-
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys);
-
- virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
-
- virtual AudioStreamIn* openInputStream(uint32_t devices, int *format, uint32_t *channels,
- uint32_t *sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics);
- virtual void closeInputStream(AudioStreamIn* in);
-
- virtual status_t dump(int fd, const Vector<String16>& args) { return mFinalInterface->dumpState(fd, args); }
-
- String8 fileName() const { return mFileName; }
-protected:
-
- AudioHardwareInterface *mFinalInterface;
- SortedVector<AudioStreamOutDump *> mOutputs;
- SortedVector<AudioStreamInDump *> mInputs;
- Mutex mLock;
- String8 mPolicyCommands;
- String8 mFileName;
-};
-
-}; // namespace android
-
-#endif // ANDROID_AUDIO_DUMP_INTERFACE_H
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
deleted file mode 100644
index 97eb6c0..0000000
--- a/libs/audioflinger/AudioFlinger.cpp
+++ /dev/null
@@ -1,6078 +0,0 @@
-/* //device/include/server/AudioFlinger/AudioFlinger.cpp
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-
-#define LOG_TAG "AudioFlinger"
-//#define LOG_NDEBUG 0
-
-#include <math.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-
-#include <binder/IServiceManager.h>
-#include <utils/Log.h>
-#include <binder/Parcel.h>
-#include <binder/IPCThreadState.h>
-#include <utils/String16.h>
-#include <utils/threads.h>
-
-#include <cutils/properties.h>
-
-#include <media/AudioTrack.h>
-#include <media/AudioRecord.h>
-
-#include <private/media/AudioTrackShared.h>
-#include <private/media/AudioEffectShared.h>
-#include <hardware_legacy/AudioHardwareInterface.h>
-
-#include "AudioMixer.h"
-#include "AudioFlinger.h"
-
-#ifdef WITH_A2DP
-#include "A2dpAudioInterface.h"
-#endif
-
-#ifdef LVMX
-#include "lifevibes.h"
-#endif
-
-#include <media/EffectsFactoryApi.h>
-#include <media/EffectVisualizerApi.h>
-
-// ----------------------------------------------------------------------------
-// the sim build doesn't have gettid
-
-#ifndef HAVE_GETTID
-# define gettid getpid
-#endif
-
-// ----------------------------------------------------------------------------
-
-namespace android {
-
-static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n";
-static const char* kHardwareLockedString = "Hardware lock is taken\n";
-
-//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
-static const float MAX_GAIN = 4096.0f;
-static const float MAX_GAIN_INT = 0x1000;
-
-// retry counts for buffer fill timeout
-// 50 * ~20msecs = 1 second
-static const int8_t kMaxTrackRetries = 50;
-static const int8_t kMaxTrackStartupRetries = 50;
-// allow less retry attempts on direct output thread.
-// direct outputs can be a scarce resource in audio hardware and should
-// be released as quickly as possible.
-static const int8_t kMaxTrackRetriesDirect = 2;
-
-static const int kDumpLockRetries = 50;
-static const int kDumpLockSleep = 20000;
-
-static const nsecs_t kWarningThrottle = seconds(5);
-
-
-#define AUDIOFLINGER_SECURITY_ENABLED 1
-
-// ----------------------------------------------------------------------------
-
-static bool recordingAllowed() {
-#ifndef HAVE_ANDROID_OS
- return true;
-#endif
-#if AUDIOFLINGER_SECURITY_ENABLED
- if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
- bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
- if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
- return ok;
-#else
- if (!checkCallingPermission(String16("android.permission.RECORD_AUDIO")))
- LOGW("WARNING: Need to add android.permission.RECORD_AUDIO to manifest");
- return true;
-#endif
-}
-
-static bool settingsAllowed() {
-#ifndef HAVE_ANDROID_OS
- return true;
-#endif
-#if AUDIOFLINGER_SECURITY_ENABLED
- if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
- bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
- if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
- return ok;
-#else
- if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")))
- LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest");
- return true;
-#endif
-}
-
-// ----------------------------------------------------------------------------
-
-AudioFlinger::AudioFlinger()
- : BnAudioFlinger(),
- mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1),
- mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0)
-{
- mHardwareStatus = AUDIO_HW_IDLE;
-
- mAudioHardware = AudioHardwareInterface::create();
-
- mHardwareStatus = AUDIO_HW_INIT;
- if (mAudioHardware->initCheck() == NO_ERROR) {
- // open 16-bit output stream for s/w mixer
- mMode = AudioSystem::MODE_NORMAL;
- setMode(mMode);
-
- setMasterVolume(1.0f);
- setMasterMute(false);
- } else {
- LOGE("Couldn't even initialize the stubbed audio hardware!");
- }
-#ifdef LVMX
- LifeVibes::init();
- mLifeVibesClientPid = -1;
-#endif
-}
-
-AudioFlinger::~AudioFlinger()
-{
- while (!mRecordThreads.isEmpty()) {
- // closeInput() will remove first entry from mRecordThreads
- closeInput(mRecordThreads.keyAt(0));
- }
- while (!mPlaybackThreads.isEmpty()) {
- // closeOutput() will remove first entry from mPlaybackThreads
- closeOutput(mPlaybackThreads.keyAt(0));
- }
- if (mAudioHardware) {
- delete mAudioHardware;
- }
-}
-
-
-
-status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- result.append("Clients:\n");
- for (size_t i = 0; i < mClients.size(); ++i) {
- wp<Client> wClient = mClients.valueAt(i);
- if (wClient != 0) {
- sp<Client> client = wClient.promote();
- if (client != 0) {
- snprintf(buffer, SIZE, " pid: %d\n", client->pid());
- result.append(buffer);
- }
- }
- }
- write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-
-status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- int hardwareStatus = mHardwareStatus;
-
- snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
- result.append(buffer);
- write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- snprintf(buffer, SIZE, "Permission Denial: "
- "can't dump AudioFlinger from pid=%d, uid=%d\n",
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid());
- result.append(buffer);
- write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-static bool tryLock(Mutex& mutex)
-{
- bool locked = false;
- for (int i = 0; i < kDumpLockRetries; ++i) {
- if (mutex.tryLock() == NO_ERROR) {
- locked = true;
- break;
- }
- usleep(kDumpLockSleep);
- }
- return locked;
-}
-
-status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
-{
- if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
- dumpPermissionDenial(fd, args);
- } else {
- // get state of hardware lock
- bool hardwareLocked = tryLock(mHardwareLock);
- if (!hardwareLocked) {
- String8 result(kHardwareLockedString);
- write(fd, result.string(), result.size());
- } else {
- mHardwareLock.unlock();
- }
-
- bool locked = tryLock(mLock);
-
- // failed to lock - AudioFlinger is probably deadlocked
- if (!locked) {
- String8 result(kDeadlockedString);
- write(fd, result.string(), result.size());
- }
-
- dumpClients(fd, args);
- dumpInternals(fd, args);
-
- // dump playback threads
- for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- mPlaybackThreads.valueAt(i)->dump(fd, args);
- }
-
- // dump record threads
- for (size_t i = 0; i < mRecordThreads.size(); i++) {
- mRecordThreads.valueAt(i)->dump(fd, args);
- }
-
- if (mAudioHardware) {
- mAudioHardware->dumpState(fd, args);
- }
- if (locked) mLock.unlock();
- }
- return NO_ERROR;
-}
-
-
-// IAudioFlinger interface
-
-
-sp<IAudioTrack> AudioFlinger::createTrack(
- pid_t pid,
- int streamType,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- uint32_t flags,
- const sp<IMemory>& sharedBuffer,
- int output,
- int *sessionId,
- status_t *status)
-{
- sp<PlaybackThread::Track> track;
- sp<TrackHandle> trackHandle;
- sp<Client> client;
- wp<Client> wclient;
- status_t lStatus;
- int lSessionId;
-
- if (streamType >= AudioSystem::NUM_STREAM_TYPES) {
- LOGE("invalid stream type");
- lStatus = BAD_VALUE;
- goto Exit;
- }
-
- {
- Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
- if (thread == NULL) {
- LOGE("unknown output thread");
- lStatus = BAD_VALUE;
- goto Exit;
- }
-
- wclient = mClients.valueFor(pid);
-
- if (wclient != NULL) {
- client = wclient.promote();
- } else {
- client = new Client(this, pid);
- mClients.add(pid, client);
- }
-
- // If no audio session id is provided, create one here
- // TODO: enforce same stream type for all tracks in same audio session?
- // TODO: prevent same audio session on different output threads
- LOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
- if (sessionId != NULL && *sessionId != 0) {
- lSessionId = *sessionId;
- } else {
- lSessionId = nextUniqueId();
- if (sessionId != NULL) {
- *sessionId = lSessionId;
- }
- }
- LOGV("createTrack() lSessionId: %d", lSessionId);
-
- track = thread->createTrack_l(client, streamType, sampleRate, format,
- channelCount, frameCount, sharedBuffer, lSessionId, &lStatus);
- }
- if (lStatus == NO_ERROR) {
- trackHandle = new TrackHandle(track);
- } else {
- // remove local strong reference to Client before deleting the Track so that the Client
- // destructor is called by the TrackBase destructor with mLock held
- client.clear();
- track.clear();
- }
-
-Exit:
- if(status) {
- *status = lStatus;
- }
- return trackHandle;
-}
-
-uint32_t AudioFlinger::sampleRate(int output) const
-{
- Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
- if (thread == NULL) {
- LOGW("sampleRate() unknown thread %d", output);
- return 0;
- }
- return thread->sampleRate();
-}
-
-int AudioFlinger::channelCount(int output) const
-{
- Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
- if (thread == NULL) {
- LOGW("channelCount() unknown thread %d", output);
- return 0;
- }
- return thread->channelCount();
-}
-
-int AudioFlinger::format(int output) const
-{
- Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
- if (thread == NULL) {
- LOGW("format() unknown thread %d", output);
- return 0;
- }
- return thread->format();
-}
-
-size_t AudioFlinger::frameCount(int output) const
-{
- Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
- if (thread == NULL) {
- LOGW("frameCount() unknown thread %d", output);
- return 0;
- }
- return thread->frameCount();
-}
-
-uint32_t AudioFlinger::latency(int output) const
-{
- Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
- if (thread == NULL) {
- LOGW("latency() unknown thread %d", output);
- return 0;
- }
- return thread->latency();
-}
-
-status_t AudioFlinger::setMasterVolume(float value)
-{
- // check calling permissions
- if (!settingsAllowed()) {
- return PERMISSION_DENIED;
- }
-
- // when hw supports master volume, don't scale in sw mixer
- AutoMutex lock(mHardwareLock);
- mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
- if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
- value = 1.0f;
- }
- mHardwareStatus = AUDIO_HW_IDLE;
-
- mMasterVolume = value;
- for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
- mPlaybackThreads.valueAt(i)->setMasterVolume(value);
-
- return NO_ERROR;
-}
-
-status_t AudioFlinger::setMode(int mode)
-{
- status_t ret;
-
- // check calling permissions
- if (!settingsAllowed()) {
- return PERMISSION_DENIED;
- }
- if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) {
- LOGW("Illegal value: setMode(%d)", mode);
- return BAD_VALUE;
- }
-
- { // scope for the lock
- AutoMutex lock(mHardwareLock);
- mHardwareStatus = AUDIO_HW_SET_MODE;
- ret = mAudioHardware->setMode(mode);
- mHardwareStatus = AUDIO_HW_IDLE;
- }
-
- if (NO_ERROR == ret) {
- Mutex::Autolock _l(mLock);
- mMode = mode;
- for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
- mPlaybackThreads.valueAt(i)->setMode(mode);
-#ifdef LVMX
- LifeVibes::setMode(mode);
-#endif
- }
-
- return ret;
-}
-
-status_t AudioFlinger::setMicMute(bool state)
-{
- // check calling permissions
- if (!settingsAllowed()) {
- return PERMISSION_DENIED;
- }
-
- AutoMutex lock(mHardwareLock);
- mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
- status_t ret = mAudioHardware->setMicMute(state);
- mHardwareStatus = AUDIO_HW_IDLE;
- return ret;
-}
-
-bool AudioFlinger::getMicMute() const
-{
- bool state = AudioSystem::MODE_INVALID;
- mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
- mAudioHardware->getMicMute(&state);
- mHardwareStatus = AUDIO_HW_IDLE;
- return state;
-}
-
-status_t AudioFlinger::setMasterMute(bool muted)
-{
- // check calling permissions
- if (!settingsAllowed()) {
- return PERMISSION_DENIED;
- }
-
- mMasterMute = muted;
- for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
- mPlaybackThreads.valueAt(i)->setMasterMute(muted);
-
- return NO_ERROR;
-}
-
-float AudioFlinger::masterVolume() const
-{
- return mMasterVolume;
-}
-
-bool AudioFlinger::masterMute() const
-{
- return mMasterMute;
-}
-
-status_t AudioFlinger::setStreamVolume(int stream, float value, int output)
-{
- // check calling permissions
- if (!settingsAllowed()) {
- return PERMISSION_DENIED;
- }
-
- if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
- return BAD_VALUE;
- }
-
- AutoMutex lock(mLock);
- PlaybackThread *thread = NULL;
- if (output) {
- thread = checkPlaybackThread_l(output);
- if (thread == NULL) {
- return BAD_VALUE;
- }
- }
-
- mStreamTypes[stream].volume = value;
-
- if (thread == NULL) {
- for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
- mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
- }
- } else {
- thread->setStreamVolume(stream, value);
- }
-
- return NO_ERROR;
-}
-
-status_t AudioFlinger::setStreamMute(int stream, bool muted)
-{
- // check calling permissions
- if (!settingsAllowed()) {
- return PERMISSION_DENIED;
- }
-
- if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
- uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) {
- return BAD_VALUE;
- }
-
- mStreamTypes[stream].mute = muted;
- for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
- mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
-
- return NO_ERROR;
-}
-
-float AudioFlinger::streamVolume(int stream, int output) const
-{
- if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
- return 0.0f;
- }
-
- AutoMutex lock(mLock);
- float volume;
- if (output) {
- PlaybackThread *thread = checkPlaybackThread_l(output);
- if (thread == NULL) {
- return 0.0f;
- }
- volume = thread->streamVolume(stream);
- } else {
- volume = mStreamTypes[stream].volume;
- }
-
- return volume;
-}
-
-bool AudioFlinger::streamMute(int stream) const
-{
- if (stream < 0 || stream >= (int)AudioSystem::NUM_STREAM_TYPES) {
- return true;
- }
-
- return mStreamTypes[stream].mute;
-}
-
-bool AudioFlinger::isStreamActive(int stream) const
-{
- Mutex::Autolock _l(mLock);
- for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
- if (mPlaybackThreads.valueAt(i)->isStreamActive(stream)) {
- return true;
- }
- }
- return false;
-}
-
-status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
-{
- status_t result;
-
- LOGV("setParameters(): io %d, keyvalue %s, tid %d, calling tid %d",
- ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
- // check calling permissions
- if (!settingsAllowed()) {
- return PERMISSION_DENIED;
- }
-
-#ifdef LVMX
- AudioParameter param = AudioParameter(keyValuePairs);
- LifeVibes::setParameters(ioHandle,keyValuePairs);
- String8 key = String8(AudioParameter::keyRouting);
- int device;
- if (NO_ERROR != param.getInt(key, device)) {
- device = -1;
- }
-
- key = String8(LifevibesTag);
- String8 value;
- int musicEnabled = -1;
- if (NO_ERROR == param.get(key, value)) {
- if (value == LifevibesEnable) {
- mLifeVibesClientPid = IPCThreadState::self()->getCallingPid();
- musicEnabled = 1;
- } else if (value == LifevibesDisable) {
- mLifeVibesClientPid = -1;
- musicEnabled = 0;
- }
- }
-#endif
-
- // ioHandle == 0 means the parameters are global to the audio hardware interface
- if (ioHandle == 0) {
- AutoMutex lock(mHardwareLock);
- mHardwareStatus = AUDIO_SET_PARAMETER;
- result = mAudioHardware->setParameters(keyValuePairs);
-#ifdef LVMX
- if (musicEnabled != -1) {
- LifeVibes::enableMusic((bool) musicEnabled);
- }
-#endif
- mHardwareStatus = AUDIO_HW_IDLE;
- return result;
- }
-
- // hold a strong ref on thread in case closeOutput() or closeInput() is called
- // and the thread is exited once the lock is released
- sp<ThreadBase> thread;
- {
- Mutex::Autolock _l(mLock);
- thread = checkPlaybackThread_l(ioHandle);
- if (thread == NULL) {
- thread = checkRecordThread_l(ioHandle);
- }
- }
- if (thread != NULL) {
- result = thread->setParameters(keyValuePairs);
-#ifdef LVMX
- if ((NO_ERROR == result) && (device != -1)) {
- LifeVibes::setDevice(LifeVibes::threadIdToAudioOutputType(thread->id()), device);
- }
-#endif
- return result;
- }
- return BAD_VALUE;
-}
-
-String8 AudioFlinger::getParameters(int ioHandle, const String8& keys)
-{
-// LOGV("getParameters() io %d, keys %s, tid %d, calling tid %d",
-// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
-
- if (ioHandle == 0) {
- return mAudioHardware->getParameters(keys);
- }
-
- Mutex::Autolock _l(mLock);
-
- PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
- if (playbackThread != NULL) {
- return playbackThread->getParameters(keys);
- }
- RecordThread *recordThread = checkRecordThread_l(ioHandle);
- if (recordThread != NULL) {
- return recordThread->getParameters(keys);
- }
- return String8("");
-}
-
-size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
-{
- return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
-}
-
-unsigned int AudioFlinger::getInputFramesLost(int ioHandle)
-{
- if (ioHandle == 0) {
- return 0;
- }
-
- Mutex::Autolock _l(mLock);
-
- RecordThread *recordThread = checkRecordThread_l(ioHandle);
- if (recordThread != NULL) {
- return recordThread->getInputFramesLost();
- }
- return 0;
-}
-
-status_t AudioFlinger::setVoiceVolume(float value)
-{
- // check calling permissions
- if (!settingsAllowed()) {
- return PERMISSION_DENIED;
- }
-
- AutoMutex lock(mHardwareLock);
- mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
- status_t ret = mAudioHardware->setVoiceVolume(value);
- mHardwareStatus = AUDIO_HW_IDLE;
-
- return ret;
-}
-
-status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output)
-{
- status_t status;
-
- Mutex::Autolock _l(mLock);
-
- PlaybackThread *playbackThread = checkPlaybackThread_l(output);
- if (playbackThread != NULL) {
- return playbackThread->getRenderPosition(halFrames, dspFrames);
- }
-
- return BAD_VALUE;
-}
-
-void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
-{
-
- Mutex::Autolock _l(mLock);
-
- int pid = IPCThreadState::self()->getCallingPid();
- if (mNotificationClients.indexOfKey(pid) < 0) {
- sp<NotificationClient> notificationClient = new NotificationClient(this,
- client,
- pid);
- LOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
-
- mNotificationClients.add(pid, notificationClient);
-
- sp<IBinder> binder = client->asBinder();
- binder->linkToDeath(notificationClient);
-
- // the config change is always sent from playback or record threads to avoid deadlock
- // with AudioSystem::gLock
- for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
- }
-
- for (size_t i = 0; i < mRecordThreads.size(); i++) {
- mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
- }
- }
-}
-
-void AudioFlinger::removeNotificationClient(pid_t pid)
-{
- Mutex::Autolock _l(mLock);
-
- int index = mNotificationClients.indexOfKey(pid);
- if (index >= 0) {
- sp <NotificationClient> client = mNotificationClients.valueFor(pid);
- LOGV("removeNotificationClient() %p, pid %d", client.get(), pid);
-#ifdef LVMX
- if (pid == mLifeVibesClientPid) {
- LOGV("Disabling lifevibes");
- LifeVibes::enableMusic(false);
- mLifeVibesClientPid = -1;
- }
-#endif
- mNotificationClients.removeItem(pid);
- }
-}
-
-// audioConfigChanged_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2)
-{
- size_t size = mNotificationClients.size();
- for (size_t i = 0; i < size; i++) {
- mNotificationClients.valueAt(i)->client()->ioConfigChanged(event, ioHandle, param2);
- }
-}
-
-// removeClient_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::removeClient_l(pid_t pid)
-{
- LOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
- mClients.removeItem(pid);
-}
-
-
-// ----------------------------------------------------------------------------
-
-AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id)
- : Thread(false),
- mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
- mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false)
-{
-}
-
-AudioFlinger::ThreadBase::~ThreadBase()
-{
- mParamCond.broadcast();
- mNewParameters.clear();
-}
-
-void AudioFlinger::ThreadBase::exit()
-{
- // keep a strong ref on ourself so that we wont get
- // destroyed in the middle of requestExitAndWait()
- sp <ThreadBase> strongMe = this;
-
- LOGV("ThreadBase::exit");
- {
- AutoMutex lock(&mLock);
- mExiting = true;
- requestExit();
- mWaitWorkCV.signal();
- }
- requestExitAndWait();
-}
-
-uint32_t AudioFlinger::ThreadBase::sampleRate() const
-{
- return mSampleRate;
-}
-
-int AudioFlinger::ThreadBase::channelCount() const
-{
- return (int)mChannelCount;
-}
-
-int AudioFlinger::ThreadBase::format() const
-{
- return mFormat;
-}
-
-size_t AudioFlinger::ThreadBase::frameCount() const
-{
- return mFrameCount;
-}
-
-status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
-{
- status_t status;
-
- LOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
- Mutex::Autolock _l(mLock);
-
- mNewParameters.add(keyValuePairs);
- mWaitWorkCV.signal();
- // wait condition with timeout in case the thread loop has exited
- // before the request could be processed
- if (mParamCond.waitRelative(mLock, seconds(2)) == NO_ERROR) {
- status = mParamStatus;
- mWaitWorkCV.signal();
- } else {
- status = TIMED_OUT;
- }
- return status;
-}
-
-void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
-{
- Mutex::Autolock _l(mLock);
- sendConfigEvent_l(event, param);
-}
-
-// sendConfigEvent_l() must be called with ThreadBase::mLock held
-void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
-{
- ConfigEvent *configEvent = new ConfigEvent();
- configEvent->mEvent = event;
- configEvent->mParam = param;
- mConfigEvents.add(configEvent);
- LOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
- mWaitWorkCV.signal();
-}
-
-void AudioFlinger::ThreadBase::processConfigEvents()
-{
- mLock.lock();
- while(!mConfigEvents.isEmpty()) {
- LOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
- ConfigEvent *configEvent = mConfigEvents[0];
- mConfigEvents.removeAt(0);
- // release mLock before locking AudioFlinger mLock: lock order is always
- // AudioFlinger then ThreadBase to avoid cross deadlock
- mLock.unlock();
- mAudioFlinger->mLock.lock();
- audioConfigChanged_l(configEvent->mEvent, configEvent->mParam);
- mAudioFlinger->mLock.unlock();
- delete configEvent;
- mLock.lock();
- }
- mLock.unlock();
-}
-
-status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- bool locked = tryLock(mLock);
- if (!locked) {
- snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
- write(fd, buffer, strlen(buffer));
- }
-
- snprintf(buffer, SIZE, "standby: %d\n", mStandby);
- result.append(buffer);
- snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
- result.append(buffer);
- snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
- result.append(buffer);
- snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
- result.append(buffer);
- snprintf(buffer, SIZE, "Format: %d\n", mFormat);
- result.append(buffer);
- snprintf(buffer, SIZE, "Frame size: %d\n", mFrameSize);
- result.append(buffer);
-
- snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
- result.append(buffer);
- result.append(" Index Command");
- for (size_t i = 0; i < mNewParameters.size(); ++i) {
- snprintf(buffer, SIZE, "\n %02d ", i);
- result.append(buffer);
- result.append(mNewParameters[i]);
- }
-
- snprintf(buffer, SIZE, "\n\nPending config events: \n");
- result.append(buffer);
- snprintf(buffer, SIZE, " Index event param\n");
- result.append(buffer);
- for (size_t i = 0; i < mConfigEvents.size(); i++) {
- snprintf(buffer, SIZE, " %02d %02d %d\n", i, mConfigEvents[i]->mEvent, mConfigEvents[i]->mParam);
- result.append(buffer);
- }
- result.append("\n");
-
- write(fd, result.string(), result.size());
-
- if (locked) {
- mLock.unlock();
- }
- return NO_ERROR;
-}
-
-
-// ----------------------------------------------------------------------------
-
-AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
- : ThreadBase(audioFlinger, id),
- mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
- mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
- mDevice(device)
-{
- readOutputParameters();
-
- mMasterVolume = mAudioFlinger->masterVolume();
- mMasterMute = mAudioFlinger->masterMute();
-
- for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
- mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
- mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
- }
-}
-
-AudioFlinger::PlaybackThread::~PlaybackThread()
-{
- delete [] mMixBuffer;
-}
-
-status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
-{
- dumpInternals(fd, args);
- dumpTracks(fd, args);
- dumpEffectChains(fd, args);
- return NO_ERROR;
-}
-
-status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
- result.append(buffer);
- result.append(" Name Clien Typ Fmt Chn Session Buf S M F SRate LeftV RighV Serv User Main buf Aux Buf\n");
- for (size_t i = 0; i < mTracks.size(); ++i) {
- sp<Track> track = mTracks[i];
- if (track != 0) {
- track->dump(buffer, SIZE);
- result.append(buffer);
- }
- }
-
- snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
- result.append(buffer);
- result.append(" Name Clien Typ Fmt Chn Session Buf S M F SRate LeftV RighV Serv User Main buf Aux Buf\n");
- for (size_t i = 0; i < mActiveTracks.size(); ++i) {
- wp<Track> wTrack = mActiveTracks[i];
- if (wTrack != 0) {
- sp<Track> track = wTrack.promote();
- if (track != 0) {
- track->dump(buffer, SIZE);
- result.append(buffer);
- }
- }
- }
- write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-status_t AudioFlinger::PlaybackThread::dumpEffectChains(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
- write(fd, buffer, strlen(buffer));
-
- for (size_t i = 0; i < mEffectChains.size(); ++i) {
- sp<EffectChain> chain = mEffectChains[i];
- if (chain != 0) {
- chain->dump(fd, args);
- }
- }
- return NO_ERROR;
-}
-
-status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
- result.append(buffer);
- snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
- result.append(buffer);
- snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
- result.append(buffer);
- snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
- result.append(buffer);
- snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
- result.append(buffer);
- snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
- result.append(buffer);
- snprintf(buffer, SIZE, "mix buffer : %p\n", mMixBuffer);
- result.append(buffer);
- write(fd, result.string(), result.size());
-
- dumpBase(fd, args);
-
- return NO_ERROR;
-}
-
-// Thread virtuals
-status_t AudioFlinger::PlaybackThread::readyToRun()
-{
- if (mSampleRate == 0) {
- LOGE("No working audio driver found.");
- return NO_INIT;
- }
- LOGI("AudioFlinger's thread %p ready to run", this);
- return NO_ERROR;
-}
-
-void AudioFlinger::PlaybackThread::onFirstRef()
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
-
- snprintf(buffer, SIZE, "Playback Thread %p", this);
-
- run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
-}
-
-// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
- const sp<AudioFlinger::Client>& client,
- int streamType,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- const sp<IMemory>& sharedBuffer,
- int sessionId,
- status_t *status)
-{
- sp<Track> track;
- status_t lStatus;
-
- if (mType == DIRECT) {
- if (sampleRate != mSampleRate || format != mFormat || channelCount != (int)mChannelCount) {
- LOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelCount %d for output %p",
- sampleRate, format, channelCount, mOutput);
- lStatus = BAD_VALUE;
- goto Exit;
- }
- } else {
- // Resampler implementation limits input sampling rate to 2 x output sampling rate.
- if (sampleRate > mSampleRate*2) {
- LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
- lStatus = BAD_VALUE;
- goto Exit;
- }
- }
-
- if (mOutput == 0) {
- LOGE("Audio driver not initialized.");
- lStatus = NO_INIT;
- goto Exit;
- }
-
- { // scope for mLock
- Mutex::Autolock _l(mLock);
- track = new Track(this, client, streamType, sampleRate, format,
- channelCount, frameCount, sharedBuffer, sessionId);
- if (track->getCblk() == NULL || track->name() < 0) {
- lStatus = NO_MEMORY;
- goto Exit;
- }
- mTracks.add(track);
-
- sp<EffectChain> chain = getEffectChain_l(sessionId);
- if (chain != 0) {
- LOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
- track->setMainBuffer(chain->inBuffer());
- }
- }
- lStatus = NO_ERROR;
-
-Exit:
- if(status) {
- *status = lStatus;
- }
- return track;
-}
-
-uint32_t AudioFlinger::PlaybackThread::latency() const
-{
- if (mOutput) {
- return mOutput->latency();
- }
- else {
- return 0;
- }
-}
-
-status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
-{
-#ifdef LVMX
- int audioOutputType = LifeVibes::getMixerType(mId, mType);
- if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
- LifeVibes::setMasterVolume(audioOutputType, value);
- }
-#endif
- mMasterVolume = value;
- return NO_ERROR;
-}
-
-status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
-{
-#ifdef LVMX
- int audioOutputType = LifeVibes::getMixerType(mId, mType);
- if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
- LifeVibes::setMasterMute(audioOutputType, muted);
- }
-#endif
- mMasterMute = muted;
- return NO_ERROR;
-}
-
-float AudioFlinger::PlaybackThread::masterVolume() const
-{
- return mMasterVolume;
-}
-
-bool AudioFlinger::PlaybackThread::masterMute() const
-{
- return mMasterMute;
-}
-
-status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value)
-{
-#ifdef LVMX
- int audioOutputType = LifeVibes::getMixerType(mId, mType);
- if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
- LifeVibes::setStreamVolume(audioOutputType, stream, value);
- }
-#endif
- mStreamTypes[stream].volume = value;
- return NO_ERROR;
-}
-
-status_t AudioFlinger::PlaybackThread::setStreamMute(int stream, bool muted)
-{
-#ifdef LVMX
- int audioOutputType = LifeVibes::getMixerType(mId, mType);
- if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
- LifeVibes::setStreamMute(audioOutputType, stream, muted);
- }
-#endif
- mStreamTypes[stream].mute = muted;
- return NO_ERROR;
-}
-
-float AudioFlinger::PlaybackThread::streamVolume(int stream) const
-{
- return mStreamTypes[stream].volume;
-}
-
-bool AudioFlinger::PlaybackThread::streamMute(int stream) const
-{
- return mStreamTypes[stream].mute;
-}
-
-bool AudioFlinger::PlaybackThread::isStreamActive(int stream) const
-{
- Mutex::Autolock _l(mLock);
- size_t count = mActiveTracks.size();
- for (size_t i = 0 ; i < count ; ++i) {
- sp<Track> t = mActiveTracks[i].promote();
- if (t == 0) continue;
- Track* const track = t.get();
- if (t->type() == stream)
- return true;
- }
- return false;
-}
-
-// addTrack_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
-{
- status_t status = ALREADY_EXISTS;
-
- // set retry count for buffer fill
- track->mRetryCount = kMaxTrackStartupRetries;
- if (mActiveTracks.indexOf(track) < 0) {
- // the track is newly added, make sure it fills up all its
- // buffers before playing. This is to ensure the client will
- // effectively get the latency it requested.
- track->mFillingUpStatus = Track::FS_FILLING;
- track->mResetDone = false;
- mActiveTracks.add(track);
- if (track->mainBuffer() != mMixBuffer) {
- sp<EffectChain> chain = getEffectChain_l(track->sessionId());
- if (chain != 0) {
- LOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), track->sessionId());
- chain->startTrack();
- }
- }
-
- status = NO_ERROR;
- }
-
- LOGV("mWaitWorkCV.broadcast");
- mWaitWorkCV.broadcast();
-
- return status;
-}
-
-// destroyTrack_l() must be called with ThreadBase::mLock held
-void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
-{
- track->mState = TrackBase::TERMINATED;
- if (mActiveTracks.indexOf(track) < 0) {
- mTracks.remove(track);
- deleteTrackName_l(track->name());
- }
-}
-
-String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
-{
- return mOutput->getParameters(keys);
-}
-
-// destroyTrack_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
- AudioSystem::OutputDescriptor desc;
- void *param2 = 0;
-
- LOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param);
-
- switch (event) {
- case AudioSystem::OUTPUT_OPENED:
- case AudioSystem::OUTPUT_CONFIG_CHANGED:
- desc.channels = mChannels;
- desc.samplingRate = mSampleRate;
- desc.format = mFormat;
- desc.frameCount = mFrameCount;
- desc.latency = latency();
- param2 = &desc;
- break;
-
- case AudioSystem::STREAM_CONFIG_CHANGED:
- param2 = &param;
- case AudioSystem::OUTPUT_CLOSED:
- default:
- break;
- }
- mAudioFlinger->audioConfigChanged_l(event, mId, param2);
-}
-
-void AudioFlinger::PlaybackThread::readOutputParameters()
-{
- mSampleRate = mOutput->sampleRate();
- mChannels = mOutput->channels();
- mChannelCount = (uint16_t)AudioSystem::popCount(mChannels);
- mFormat = mOutput->format();
- mFrameSize = (uint16_t)mOutput->frameSize();
- mFrameCount = mOutput->bufferSize() / mFrameSize;
-
- // FIXME - Current mixer implementation only supports stereo output: Always
- // Allocate a stereo buffer even if HW output is mono.
- if (mMixBuffer != NULL) delete[] mMixBuffer;
- mMixBuffer = new int16_t[mFrameCount * 2];
- memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
-
- //TODO handle effects reconfig
-}
-
-status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
-{
- if (halFrames == 0 || dspFrames == 0) {
- return BAD_VALUE;
- }
- if (mOutput == 0) {
- return INVALID_OPERATION;
- }
- *halFrames = mBytesWritten/mOutput->frameSize();
-
- return mOutput->getRenderPosition(dspFrames);
-}
-
-bool AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
-{
- Mutex::Autolock _l(mLock);
- if (getEffectChain_l(sessionId) != 0) {
- return true;
- }
-
- for (size_t i = 0; i < mTracks.size(); ++i) {
- sp<Track> track = mTracks[i];
- if (sessionId == track->sessionId()) {
- return true;
- }
- }
-
- return false;
-}
-
-sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain(int sessionId)
-{
- Mutex::Autolock _l(mLock);
- return getEffectChain_l(sessionId);
-}
-
-sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain_l(int sessionId)
-{
- sp<EffectChain> chain;
-
- size_t size = mEffectChains.size();
- for (size_t i = 0; i < size; i++) {
- if (mEffectChains[i]->sessionId() == sessionId) {
- chain = mEffectChains[i];
- break;
- }
- }
- return chain;
-}
-
-void AudioFlinger::PlaybackThread::setMode(uint32_t mode)
-{
- Mutex::Autolock _l(mLock);
- size_t size = mEffectChains.size();
- for (size_t i = 0; i < size; i++) {
- mEffectChains[i]->setMode(mode);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
- : PlaybackThread(audioFlinger, output, id, device),
- mAudioMixer(0)
-{
- mType = PlaybackThread::MIXER;
- mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
-
- // FIXME - Current mixer implementation only supports stereo output
- if (mChannelCount == 1) {
- LOGE("Invalid audio hardware channel count");
- }
-}
-
-AudioFlinger::MixerThread::~MixerThread()
-{
- delete mAudioMixer;
-}
-
-bool AudioFlinger::MixerThread::threadLoop()
-{
- Vector< sp<Track> > tracksToRemove;
- uint32_t mixerStatus = MIXER_IDLE;
- nsecs_t standbyTime = systemTime();
- size_t mixBufferSize = mFrameCount * mFrameSize;
- // FIXME: Relaxed timing because of a certain device that can't meet latency
- // Should be reduced to 2x after the vendor fixes the driver issue
- nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
- nsecs_t lastWarning = 0;
- bool longStandbyExit = false;
- uint32_t activeSleepTime = activeSleepTimeUs();
- uint32_t idleSleepTime = idleSleepTimeUs();
- uint32_t sleepTime = idleSleepTime;
- Vector< sp<EffectChain> > effectChains;
-
- while (!exitPending())
- {
- processConfigEvents();
-
- mixerStatus = MIXER_IDLE;
- { // scope for mLock
-
- Mutex::Autolock _l(mLock);
-
- if (checkForNewParameters_l()) {
- mixBufferSize = mFrameCount * mFrameSize;
- // FIXME: Relaxed timing because of a certain device that can't meet latency
- // Should be reduced to 2x after the vendor fixes the driver issue
- maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
- activeSleepTime = activeSleepTimeUs();
- idleSleepTime = idleSleepTimeUs();
- }
-
- const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
-
- // put audio hardware into standby after short delay
- if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
- mSuspended) {
- if (!mStandby) {
- LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
- mOutput->standby();
- mStandby = true;
- mBytesWritten = 0;
- }
-
- if (!activeTracks.size() && mConfigEvents.isEmpty()) {
- // we're about to wait, flush the binder command buffer
- IPCThreadState::self()->flushCommands();
-
- if (exitPending()) break;
-
- // wait until we have something to do...
- LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
- mWaitWorkCV.wait(mLock);
- LOGV("MixerThread %p TID %d waking up\n", this, gettid());
-
- if (mMasterMute == false) {
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.audio.silent", value, "0");
- if (atoi(value)) {
- LOGD("Silence is golden");
- setMasterMute(true);
- }
- }
-
- standbyTime = systemTime() + kStandbyTimeInNsecs;
- sleepTime = idleSleepTime;
- continue;
- }
- }
-
- mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
-
- // prevent any changes in effect chain list and in each effect chain
- // during mixing and effect process as the audio buffers could be deleted
- // or modified if an effect is created or deleted
- effectChains = mEffectChains;
- lockEffectChains_l();
- }
-
- if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
- // mix buffers...
- mAudioMixer->process();
- sleepTime = 0;
- standbyTime = systemTime() + kStandbyTimeInNsecs;
- //TODO: delay standby when effects have a tail
- } else {
- // If no tracks are ready, sleep once for the duration of an output
- // buffer size, then write 0s to the output
- if (sleepTime == 0) {
- if (mixerStatus == MIXER_TRACKS_ENABLED) {
- sleepTime = activeSleepTime;
- } else {
- sleepTime = idleSleepTime;
- }
- } else if (mBytesWritten != 0 ||
- (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
- memset (mMixBuffer, 0, mixBufferSize);
- sleepTime = 0;
- LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
- }
- // TODO add standby time extension fct of effect tail
- }
-
- if (mSuspended) {
- sleepTime = idleSleepTime;
- }
- // sleepTime == 0 means we must write to audio hardware
- if (sleepTime == 0) {
- for (size_t i = 0; i < effectChains.size(); i ++) {
- effectChains[i]->process_l();
- }
- // enable changes in effect chain
- unlockEffectChains();
-#ifdef LVMX
- int audioOutputType = LifeVibes::getMixerType(mId, mType);
- if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
- LifeVibes::process(audioOutputType, mMixBuffer, mixBufferSize);
- }
-#endif
- mLastWriteTime = systemTime();
- mInWrite = true;
- mBytesWritten += mixBufferSize;
-
- int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
- if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
- mNumWrites++;
- mInWrite = false;
- nsecs_t now = systemTime();
- nsecs_t delta = now - mLastWriteTime;
- if (delta > maxPeriod) {
- mNumDelayedWrites++;
- if ((now - lastWarning) > kWarningThrottle) {
- LOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
- ns2ms(delta), mNumDelayedWrites, this);
- lastWarning = now;
- }
- if (mStandby) {
- longStandbyExit = true;
- }
- }
- mStandby = false;
- } else {
- // enable changes in effect chain
- unlockEffectChains();
- usleep(sleepTime);
- }
-
- // finally let go of all our tracks, without the lock held
- // since we can't guarantee the destructors won't acquire that
- // same lock.
- tracksToRemove.clear();
-
- // Effect chains will be actually deleted here if they were removed from
- // mEffectChains list during mixing or effects processing
- effectChains.clear();
- }
-
- if (!mStandby) {
- mOutput->standby();
- }
-
- LOGV("MixerThread %p exiting", this);
- return false;
-}
-
-// prepareTracks_l() must be called with ThreadBase::mLock held
-uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
-{
-
- uint32_t mixerStatus = MIXER_IDLE;
- // find out which tracks need to be processed
- size_t count = activeTracks.size();
- size_t mixedTracks = 0;
- size_t tracksWithEffect = 0;
-
- float masterVolume = mMasterVolume;
- bool masterMute = mMasterMute;
-
-#ifdef LVMX
- bool tracksConnectedChanged = false;
- bool stateChanged = false;
-
- int audioOutputType = LifeVibes::getMixerType(mId, mType);
- if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType))
- {
- int activeTypes = 0;
- for (size_t i=0 ; i<count ; i++) {
- sp<Track> t = activeTracks[i].promote();
- if (t == 0) continue;
- Track* const track = t.get();
- int iTracktype=track->type();
- activeTypes |= 1<<track->type();
- }
- LifeVibes::computeVolumes(audioOutputType, activeTypes, tracksConnectedChanged, stateChanged, masterVolume, masterMute);
- }
-#endif
- // Delegate master volume control to effect in output mix effect chain if needed
- sp<EffectChain> chain = getEffectChain_l(0);
- if (chain != 0) {
- uint32_t v = (uint32_t)(masterVolume * (1 << 24));
- chain->setVolume(&v, &v);
- masterVolume = (float)((v + (1 << 23)) >> 24);
- chain.clear();
- }
-
- for (size_t i=0 ; i<count ; i++) {
- sp<Track> t = activeTracks[i].promote();
- if (t == 0) continue;
-
- Track* const track = t.get();
- audio_track_cblk_t* cblk = track->cblk();
-
- // The first time a track is added we wait
- // for all its buffers to be filled before processing it
- mAudioMixer->setActiveTrack(track->name());
- if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
- !track->isPaused() && !track->isTerminated())
- {
- //LOGV("track %d u=%08x, s=%08x [OK] on thread %p", track->name(), cblk->user, cblk->server, this);
-
- mixedTracks++;
-
- // track->mainBuffer() != mMixBuffer means there is an effect chain
- // connected to the track
- chain.clear();
- if (track->mainBuffer() != mMixBuffer) {
- chain = getEffectChain_l(track->sessionId());
- // Delegate volume control to effect in track effect chain if needed
- if (chain != 0) {
- tracksWithEffect++;
- } else {
- LOGW("prepareTracks_l(): track %08x attached to effect but no chain found on session %d",
- track->name(), track->sessionId());
- }
- }
-
-
- int param = AudioMixer::VOLUME;
- if (track->mFillingUpStatus == Track::FS_FILLED) {
- // no ramp for the first volume setting
- track->mFillingUpStatus = Track::FS_ACTIVE;
- if (track->mState == TrackBase::RESUMING) {
- track->mState = TrackBase::ACTIVE;
- param = AudioMixer::RAMP_VOLUME;
- }
- } else if (cblk->server != 0) {
- // If the track is stopped before the first frame was mixed,
- // do not apply ramp
- param = AudioMixer::RAMP_VOLUME;
- }
-
- // compute volume for this track
- int16_t left, right, aux;
- if (track->isMuted() || masterMute || track->isPausing() ||
- mStreamTypes[track->type()].mute) {
- left = right = aux = 0;
- if (track->isPausing()) {
- track->setPaused();
- }
- } else {
- // read original volumes with volume control
- float typeVolume = mStreamTypes[track->type()].volume;
-#ifdef LVMX
- bool streamMute=false;
- // read the volume from the LivesVibes audio engine.
- if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType))
- {
- LifeVibes::getStreamVolumes(audioOutputType, track->type(), &typeVolume, &streamMute);
- if (streamMute) {
- typeVolume = 0;
- }
- }
-#endif
- float v = masterVolume * typeVolume;
- uint32_t vl = (uint32_t)(v * cblk->volume[0]) << 12;
- uint32_t vr = (uint32_t)(v * cblk->volume[1]) << 12;
-
- // Delegate volume control to effect in track effect chain if needed
- if (chain != 0 && chain->setVolume(&vl, &vr)) {
- // Do not ramp volume is volume is controlled by effect
- param = AudioMixer::VOLUME;
- }
-
- // Convert volumes from 8.24 to 4.12 format
- uint32_t v_clamped = (vl + (1 << 11)) >> 12;
- if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
- left = int16_t(v_clamped);
- v_clamped = (vr + (1 << 11)) >> 12;
- if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
- right = int16_t(v_clamped);
-
- v_clamped = (uint32_t)(v * cblk->sendLevel);
- if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
- aux = int16_t(v_clamped);
- }
-
-#ifdef LVMX
- if ( tracksConnectedChanged || stateChanged )
- {
- // only do the ramp when the volume is changed by the user / application
- param = AudioMixer::VOLUME;
- }
-#endif
-
- // XXX: these things DON'T need to be done each time
- mAudioMixer->setBufferProvider(track);
- mAudioMixer->enable(AudioMixer::MIXING);
-
- mAudioMixer->setParameter(param, AudioMixer::VOLUME0, (void *)left);
- mAudioMixer->setParameter(param, AudioMixer::VOLUME1, (void *)right);
- mAudioMixer->setParameter(param, AudioMixer::AUXLEVEL, (void *)aux);
- mAudioMixer->setParameter(
- AudioMixer::TRACK,
- AudioMixer::FORMAT, (void *)track->format());
- mAudioMixer->setParameter(
- AudioMixer::TRACK,
- AudioMixer::CHANNEL_COUNT, (void *)track->channelCount());
- mAudioMixer->setParameter(
- AudioMixer::RESAMPLE,
- AudioMixer::SAMPLE_RATE,
- (void *)(cblk->sampleRate));
- mAudioMixer->setParameter(
- AudioMixer::TRACK,
- AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
- mAudioMixer->setParameter(
- AudioMixer::TRACK,
- AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
-
- // reset retry count
- track->mRetryCount = kMaxTrackRetries;
- mixerStatus = MIXER_TRACKS_READY;
- } else {
- //LOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", track->name(), cblk->user, cblk->server, this);
- if (track->isStopped()) {
- track->reset();
- }
- if (track->isTerminated() || track->isStopped() || track->isPaused()) {
- // We have consumed all the buffers of this track.
- // Remove it from the list of active tracks.
- tracksToRemove->add(track);
- } else {
- // No buffers for this track. Give it a few chances to
- // fill a buffer, then remove it from active list.
- if (--(track->mRetryCount) <= 0) {
- LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
- tracksToRemove->add(track);
- } else if (mixerStatus != MIXER_TRACKS_READY) {
- mixerStatus = MIXER_TRACKS_ENABLED;
- }
- }
- mAudioMixer->disable(AudioMixer::MIXING);
- }
- }
-
- // remove all the tracks that need to be...
- count = tracksToRemove->size();
- if (UNLIKELY(count)) {
- for (size_t i=0 ; i<count ; i++) {
- const sp<Track>& track = tracksToRemove->itemAt(i);
- mActiveTracks.remove(track);
- if (track->mainBuffer() != mMixBuffer) {
- chain = getEffectChain_l(track->sessionId());
- if (chain != 0) {
- LOGV("stopping track on chain %p for session Id: %d", chain.get(), track->sessionId());
- chain->stopTrack();
- }
- }
- if (track->isTerminated()) {
- mTracks.remove(track);
- deleteTrackName_l(track->mName);
- }
- }
- }
-
- // mix buffer must be cleared if all tracks are connected to an
- // effect chain as in this case the mixer will not write to
- // mix buffer and track effects will accumulate into it
- if (mixedTracks != 0 && mixedTracks == tracksWithEffect) {
- memset(mMixBuffer, 0, mFrameCount * mChannelCount * sizeof(int16_t));
- }
-
- return mixerStatus;
-}
-
-void AudioFlinger::MixerThread::invalidateTracks(int streamType)
-{
- LOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d", this, streamType, mTracks.size());
- Mutex::Autolock _l(mLock);
- size_t size = mTracks.size();
- for (size_t i = 0; i < size; i++) {
- sp<Track> t = mTracks[i];
- if (t->type() == streamType) {
- t->mCblk->lock.lock();
- t->mCblk->flags |= CBLK_INVALID_ON;
- t->mCblk->cv.signal();
- t->mCblk->lock.unlock();
- }
- }
-}
-
-
-// getTrackName_l() must be called with ThreadBase::mLock held
-int AudioFlinger::MixerThread::getTrackName_l()
-{
- return mAudioMixer->getTrackName();
-}
-
-// deleteTrackName_l() must be called with ThreadBase::mLock held
-void AudioFlinger::MixerThread::deleteTrackName_l(int name)
-{
- LOGV("remove track (%d) and delete from mixer", name);
- mAudioMixer->deleteTrackName(name);
-}
-
-// checkForNewParameters_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::MixerThread::checkForNewParameters_l()
-{
- bool reconfig = false;
-
- while (!mNewParameters.isEmpty()) {
- status_t status = NO_ERROR;
- String8 keyValuePair = mNewParameters[0];
- AudioParameter param = AudioParameter(keyValuePair);
- int value;
-
- if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
- reconfig = true;
- }
- if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
- if (value != AudioSystem::PCM_16_BIT) {
- status = BAD_VALUE;
- } else {
- reconfig = true;
- }
- }
- if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
- if (value != AudioSystem::CHANNEL_OUT_STEREO) {
- status = BAD_VALUE;
- } else {
- reconfig = true;
- }
- }
- if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
- // do not accept frame count changes if tracks are open as the track buffer
- // size depends on frame count and correct behavior would not be garantied
- // if frame count is changed after track creation
- if (!mTracks.isEmpty()) {
- status = INVALID_OPERATION;
- } else {
- reconfig = true;
- }
- }
- if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
- // forward device change to effects that have requested to be
- // aware of attached audio device.
- mDevice = (uint32_t)value;
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setDevice(mDevice);
- }
- }
-
- if (status == NO_ERROR) {
- status = mOutput->setParameters(keyValuePair);
- if (!mStandby && status == INVALID_OPERATION) {
- mOutput->standby();
- mStandby = true;
- mBytesWritten = 0;
- status = mOutput->setParameters(keyValuePair);
- }
- if (status == NO_ERROR && reconfig) {
- delete mAudioMixer;
- readOutputParameters();
- mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
- for (size_t i = 0; i < mTracks.size() ; i++) {
- int name = getTrackName_l();
- if (name < 0) break;
- mTracks[i]->mName = name;
- // limit track sample rate to 2 x new output sample rate
- if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
- mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
- }
- }
- sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
- }
- }
-
- mNewParameters.removeAt(0);
-
- mParamStatus = status;
- mParamCond.signal();
- mWaitWorkCV.wait(mLock);
- }
- return reconfig;
-}
-
-status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- PlaybackThread::dumpInternals(fd, args);
-
- snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
- result.append(buffer);
- write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
-{
- return (uint32_t)(mOutput->latency() * 1000) / 2;
-}
-
-uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
-{
- return (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
-}
-
-// ----------------------------------------------------------------------------
-AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
- : PlaybackThread(audioFlinger, output, id, device)
-{
- mType = PlaybackThread::DIRECT;
-}
-
-AudioFlinger::DirectOutputThread::~DirectOutputThread()
-{
-}
-
-
-static inline int16_t clamp16(int32_t sample)
-{
- if ((sample>>15) ^ (sample>>31))
- sample = 0x7FFF ^ (sample>>31);
- return sample;
-}
-
-static inline
-int32_t mul(int16_t in, int16_t v)
-{
-#if defined(__arm__) && !defined(__thumb__)
- int32_t out;
- asm( "smulbb %[out], %[in], %[v] \n"
- : [out]"=r"(out)
- : [in]"%r"(in), [v]"r"(v)
- : );
- return out;
-#else
- return in * int32_t(v);
-#endif
-}
-
-void AudioFlinger::DirectOutputThread::applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp)
-{
- // Do not apply volume on compressed audio
- if (!AudioSystem::isLinearPCM(mFormat)) {
- return;
- }
-
- // convert to signed 16 bit before volume calculation
- if (mFormat == AudioSystem::PCM_8_BIT) {
- size_t count = mFrameCount * mChannelCount;
- uint8_t *src = (uint8_t *)mMixBuffer + count-1;
- int16_t *dst = mMixBuffer + count-1;
- while(count--) {
- *dst-- = (int16_t)(*src--^0x80) << 8;
- }
- }
-
- size_t frameCount = mFrameCount;
- int16_t *out = mMixBuffer;
- if (ramp) {
- if (mChannelCount == 1) {
- int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
- int32_t vlInc = d / (int32_t)frameCount;
- int32_t vl = ((int32_t)mLeftVolShort << 16);
- do {
- out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
- out++;
- vl += vlInc;
- } while (--frameCount);
-
- } else {
- int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
- int32_t vlInc = d / (int32_t)frameCount;
- d = ((int32_t)rightVol - (int32_t)mRightVolShort) << 16;
- int32_t vrInc = d / (int32_t)frameCount;
- int32_t vl = ((int32_t)mLeftVolShort << 16);
- int32_t vr = ((int32_t)mRightVolShort << 16);
- do {
- out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
- out[1] = clamp16(mul(out[1], vr >> 16) >> 12);
- out += 2;
- vl += vlInc;
- vr += vrInc;
- } while (--frameCount);
- }
- } else {
- if (mChannelCount == 1) {
- do {
- out[0] = clamp16(mul(out[0], leftVol) >> 12);
- out++;
- } while (--frameCount);
- } else {
- do {
- out[0] = clamp16(mul(out[0], leftVol) >> 12);
- out[1] = clamp16(mul(out[1], rightVol) >> 12);
- out += 2;
- } while (--frameCount);
- }
- }
-
- // convert back to unsigned 8 bit after volume calculation
- if (mFormat == AudioSystem::PCM_8_BIT) {
- size_t count = mFrameCount * mChannelCount;
- int16_t *src = mMixBuffer;
- uint8_t *dst = (uint8_t *)mMixBuffer;
- while(count--) {
- *dst++ = (uint8_t)(((int32_t)*src++ + (1<<7)) >> 8)^0x80;
- }
- }
-
- mLeftVolShort = leftVol;
- mRightVolShort = rightVol;
-}
-
-bool AudioFlinger::DirectOutputThread::threadLoop()
-{
- uint32_t mixerStatus = MIXER_IDLE;
- sp<Track> trackToRemove;
- sp<Track> activeTrack;
- nsecs_t standbyTime = systemTime();
- int8_t *curBuf;
- size_t mixBufferSize = mFrameCount*mFrameSize;
- uint32_t activeSleepTime = activeSleepTimeUs();
- uint32_t idleSleepTime = idleSleepTimeUs();
- uint32_t sleepTime = idleSleepTime;
- // use shorter standby delay as on normal output to release
- // hardware resources as soon as possible
- nsecs_t standbyDelay = microseconds(activeSleepTime*2);
-
-
- while (!exitPending())
- {
- bool rampVolume;
- uint16_t leftVol;
- uint16_t rightVol;
- Vector< sp<EffectChain> > effectChains;
-
- processConfigEvents();
-
- mixerStatus = MIXER_IDLE;
-
- { // scope for the mLock
-
- Mutex::Autolock _l(mLock);
-
- if (checkForNewParameters_l()) {
- mixBufferSize = mFrameCount*mFrameSize;
- activeSleepTime = activeSleepTimeUs();
- idleSleepTime = idleSleepTimeUs();
- standbyDelay = microseconds(activeSleepTime*2);
- }
-
- // put audio hardware into standby after short delay
- if UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
- mSuspended) {
- // wait until we have something to do...
- if (!mStandby) {
- LOGV("Audio hardware entering standby, mixer %p\n", this);
- mOutput->standby();
- mStandby = true;
- mBytesWritten = 0;
- }
-
- if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
- // we're about to wait, flush the binder command buffer
- IPCThreadState::self()->flushCommands();
-
- if (exitPending()) break;
-
- LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
- mWaitWorkCV.wait(mLock);
- LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
-
- if (mMasterMute == false) {
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.audio.silent", value, "0");
- if (atoi(value)) {
- LOGD("Silence is golden");
- setMasterMute(true);
- }
- }
-
- standbyTime = systemTime() + standbyDelay;
- sleepTime = idleSleepTime;
- continue;
- }
- }
-
- effectChains = mEffectChains;
-
- // find out which tracks need to be processed
- if (mActiveTracks.size() != 0) {
- sp<Track> t = mActiveTracks[0].promote();
- if (t == 0) continue;
-
- Track* const track = t.get();
- audio_track_cblk_t* cblk = track->cblk();
-
- // The first time a track is added we wait
- // for all its buffers to be filled before processing it
- if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
- !track->isPaused() && !track->isTerminated())
- {
- //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
-
- if (track->mFillingUpStatus == Track::FS_FILLED) {
- track->mFillingUpStatus = Track::FS_ACTIVE;
- mLeftVolFloat = mRightVolFloat = 0;
- mLeftVolShort = mRightVolShort = 0;
- if (track->mState == TrackBase::RESUMING) {
- track->mState = TrackBase::ACTIVE;
- rampVolume = true;
- }
- } else if (cblk->server != 0) {
- // If the track is stopped before the first frame was mixed,
- // do not apply ramp
- rampVolume = true;
- }
- // compute volume for this track
- float left, right;
- if (track->isMuted() || mMasterMute || track->isPausing() ||
- mStreamTypes[track->type()].mute) {
- left = right = 0;
- if (track->isPausing()) {
- track->setPaused();
- }
- } else {
- float typeVolume = mStreamTypes[track->type()].volume;
- float v = mMasterVolume * typeVolume;
- float v_clamped = v * cblk->volume[0];
- if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
- left = v_clamped/MAX_GAIN;
- v_clamped = v * cblk->volume[1];
- if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
- right = v_clamped/MAX_GAIN;
- }
-
- if (left != mLeftVolFloat || right != mRightVolFloat) {
- mLeftVolFloat = left;
- mRightVolFloat = right;
-
- // If audio HAL implements volume control,
- // force software volume to nominal value
- if (mOutput->setVolume(left, right) == NO_ERROR) {
- left = 1.0f;
- right = 1.0f;
- }
-
- // Convert volumes from float to 8.24
- uint32_t vl = (uint32_t)(left * (1 << 24));
- uint32_t vr = (uint32_t)(right * (1 << 24));
-
- // Delegate volume control to effect in track effect chain if needed
- // only one effect chain can be present on DirectOutputThread, so if
- // there is one, the track is connected to it
- if (!effectChains.isEmpty()) {
- // Do not ramp volume is volume is controlled by effect
- if(effectChains[0]->setVolume(&vl, &vr)) {
- rampVolume = false;
- }
- }
-
- // Convert volumes from 8.24 to 4.12 format
- uint32_t v_clamped = (vl + (1 << 11)) >> 12;
- if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
- leftVol = (uint16_t)v_clamped;
- v_clamped = (vr + (1 << 11)) >> 12;
- if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
- rightVol = (uint16_t)v_clamped;
- } else {
- leftVol = mLeftVolShort;
- rightVol = mRightVolShort;
- rampVolume = false;
- }
-
- // reset retry count
- track->mRetryCount = kMaxTrackRetriesDirect;
- activeTrack = t;
- mixerStatus = MIXER_TRACKS_READY;
- } else {
- //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
- if (track->isStopped()) {
- track->reset();
- }
- if (track->isTerminated() || track->isStopped() || track->isPaused()) {
- // We have consumed all the buffers of this track.
- // Remove it from the list of active tracks.
- trackToRemove = track;
- } else {
- // No buffers for this track. Give it a few chances to
- // fill a buffer, then remove it from active list.
- if (--(track->mRetryCount) <= 0) {
- LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
- trackToRemove = track;
- } else {
- mixerStatus = MIXER_TRACKS_ENABLED;
- }
- }
- }
- }
-
- // remove all the tracks that need to be...
- if (UNLIKELY(trackToRemove != 0)) {
- mActiveTracks.remove(trackToRemove);
- if (!effectChains.isEmpty()) {
- LOGV("stopping track on chain %p for session Id: %d", effectChains[0].get(), trackToRemove->sessionId());
- effectChains[0]->stopTrack();
- }
- if (trackToRemove->isTerminated()) {
- mTracks.remove(trackToRemove);
- deleteTrackName_l(trackToRemove->mName);
- }
- }
-
- lockEffectChains_l();
- }
-
- if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
- AudioBufferProvider::Buffer buffer;
- size_t frameCount = mFrameCount;
- curBuf = (int8_t *)mMixBuffer;
- // output audio to hardware
- while (frameCount) {
- buffer.frameCount = frameCount;
- activeTrack->getNextBuffer(&buffer);
- if (UNLIKELY(buffer.raw == 0)) {
- memset(curBuf, 0, frameCount * mFrameSize);
- break;
- }
- memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
- frameCount -= buffer.frameCount;
- curBuf += buffer.frameCount * mFrameSize;
- activeTrack->releaseBuffer(&buffer);
- }
- sleepTime = 0;
- standbyTime = systemTime() + standbyDelay;
- } else {
- if (sleepTime == 0) {
- if (mixerStatus == MIXER_TRACKS_ENABLED) {
- sleepTime = activeSleepTime;
- } else {
- sleepTime = idleSleepTime;
- }
- } else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) {
- memset (mMixBuffer, 0, mFrameCount * mFrameSize);
- sleepTime = 0;
- }
- }
-
- if (mSuspended) {
- sleepTime = idleSleepTime;
- }
- // sleepTime == 0 means we must write to audio hardware
- if (sleepTime == 0) {
- if (mixerStatus == MIXER_TRACKS_READY) {
- applyVolume(leftVol, rightVol, rampVolume);
- }
- for (size_t i = 0; i < effectChains.size(); i ++) {
- effectChains[i]->process_l();
- }
- unlockEffectChains();
-
- mLastWriteTime = systemTime();
- mInWrite = true;
- mBytesWritten += mixBufferSize;
- int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
- if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
- mNumWrites++;
- mInWrite = false;
- mStandby = false;
- } else {
- unlockEffectChains();
- usleep(sleepTime);
- }
-
- // finally let go of removed track, without the lock held
- // since we can't guarantee the destructors won't acquire that
- // same lock.
- trackToRemove.clear();
- activeTrack.clear();
-
- // Effect chains will be actually deleted here if they were removed from
- // mEffectChains list during mixing or effects processing
- effectChains.clear();
- }
-
- if (!mStandby) {
- mOutput->standby();
- }
-
- LOGV("DirectOutputThread %p exiting", this);
- return false;
-}
-
-// getTrackName_l() must be called with ThreadBase::mLock held
-int AudioFlinger::DirectOutputThread::getTrackName_l()
-{
- return 0;
-}
-
-// deleteTrackName_l() must be called with ThreadBase::mLock held
-void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
-{
-}
-
-// checkForNewParameters_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
-{
- bool reconfig = false;
-
- while (!mNewParameters.isEmpty()) {
- status_t status = NO_ERROR;
- String8 keyValuePair = mNewParameters[0];
- AudioParameter param = AudioParameter(keyValuePair);
- int value;
-
- if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
- // do not accept frame count changes if tracks are open as the track buffer
- // size depends on frame count and correct behavior would not be garantied
- // if frame count is changed after track creation
- if (!mTracks.isEmpty()) {
- status = INVALID_OPERATION;
- } else {
- reconfig = true;
- }
- }
- if (status == NO_ERROR) {
- status = mOutput->setParameters(keyValuePair);
- if (!mStandby && status == INVALID_OPERATION) {
- mOutput->standby();
- mStandby = true;
- mBytesWritten = 0;
- status = mOutput->setParameters(keyValuePair);
- }
- if (status == NO_ERROR && reconfig) {
- readOutputParameters();
- sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
- }
- }
-
- mNewParameters.removeAt(0);
-
- mParamStatus = status;
- mParamCond.signal();
- mWaitWorkCV.wait(mLock);
- }
- return reconfig;
-}
-
-uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
-{
- uint32_t time;
- if (AudioSystem::isLinearPCM(mFormat)) {
- time = (uint32_t)(mOutput->latency() * 1000) / 2;
- } else {
- time = 10000;
- }
- return time;
-}
-
-uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
-{
- uint32_t time;
- if (AudioSystem::isLinearPCM(mFormat)) {
- time = (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
- } else {
- time = 10000;
- }
- return time;
-}
-
-// ----------------------------------------------------------------------------
-
-AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
- : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device()), mWaitTimeMs(UINT_MAX)
-{
- mType = PlaybackThread::DUPLICATING;
- addOutputTrack(mainThread);
-}
-
-AudioFlinger::DuplicatingThread::~DuplicatingThread()
-{
- for (size_t i = 0; i < mOutputTracks.size(); i++) {
- mOutputTracks[i]->destroy();
- }
- mOutputTracks.clear();
-}
-
-bool AudioFlinger::DuplicatingThread::threadLoop()
-{
- Vector< sp<Track> > tracksToRemove;
- uint32_t mixerStatus = MIXER_IDLE;
- nsecs_t standbyTime = systemTime();
- size_t mixBufferSize = mFrameCount*mFrameSize;
- SortedVector< sp<OutputTrack> > outputTracks;
- uint32_t writeFrames = 0;
- uint32_t activeSleepTime = activeSleepTimeUs();
- uint32_t idleSleepTime = idleSleepTimeUs();
- uint32_t sleepTime = idleSleepTime;
- Vector< sp<EffectChain> > effectChains;
-
- while (!exitPending())
- {
- processConfigEvents();
-
- mixerStatus = MIXER_IDLE;
- { // scope for the mLock
-
- Mutex::Autolock _l(mLock);
-
- if (checkForNewParameters_l()) {
- mixBufferSize = mFrameCount*mFrameSize;
- updateWaitTime();
- activeSleepTime = activeSleepTimeUs();
- idleSleepTime = idleSleepTimeUs();
- }
-
- const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
-
- for (size_t i = 0; i < mOutputTracks.size(); i++) {
- outputTracks.add(mOutputTracks[i]);
- }
-
- // put audio hardware into standby after short delay
- if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
- mSuspended) {
- if (!mStandby) {
- for (size_t i = 0; i < outputTracks.size(); i++) {
- outputTracks[i]->stop();
- }
- mStandby = true;
- mBytesWritten = 0;
- }
-
- if (!activeTracks.size() && mConfigEvents.isEmpty()) {
- // we're about to wait, flush the binder command buffer
- IPCThreadState::self()->flushCommands();
- outputTracks.clear();
-
- if (exitPending()) break;
-
- LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
- mWaitWorkCV.wait(mLock);
- LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
- if (mMasterMute == false) {
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.audio.silent", value, "0");
- if (atoi(value)) {
- LOGD("Silence is golden");
- setMasterMute(true);
- }
- }
-
- standbyTime = systemTime() + kStandbyTimeInNsecs;
- sleepTime = idleSleepTime;
- continue;
- }
- }
-
- mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
-
- // prevent any changes in effect chain list and in each effect chain
- // during mixing and effect process as the audio buffers could be deleted
- // or modified if an effect is created or deleted
- effectChains = mEffectChains;
- lockEffectChains_l();
- }
-
- if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
- // mix buffers...
- if (outputsReady(outputTracks)) {
- mAudioMixer->process();
- } else {
- memset(mMixBuffer, 0, mixBufferSize);
- }
- sleepTime = 0;
- writeFrames = mFrameCount;
- } else {
- if (sleepTime == 0) {
- if (mixerStatus == MIXER_TRACKS_ENABLED) {
- sleepTime = activeSleepTime;
- } else {
- sleepTime = idleSleepTime;
- }
- } else if (mBytesWritten != 0) {
- // flush remaining overflow buffers in output tracks
- for (size_t i = 0; i < outputTracks.size(); i++) {
- if (outputTracks[i]->isActive()) {
- sleepTime = 0;
- writeFrames = 0;
- memset(mMixBuffer, 0, mixBufferSize);
- break;
- }
- }
- }
- }
-
- if (mSuspended) {
- sleepTime = idleSleepTime;
- }
- // sleepTime == 0 means we must write to audio hardware
- if (sleepTime == 0) {
- for (size_t i = 0; i < effectChains.size(); i ++) {
- effectChains[i]->process_l();
- }
- // enable changes in effect chain
- unlockEffectChains();
-
- standbyTime = systemTime() + kStandbyTimeInNsecs;
- for (size_t i = 0; i < outputTracks.size(); i++) {
- outputTracks[i]->write(mMixBuffer, writeFrames);
- }
- mStandby = false;
- mBytesWritten += mixBufferSize;
- } else {
- // enable changes in effect chain
- unlockEffectChains();
- usleep(sleepTime);
- }
-
- // finally let go of all our tracks, without the lock held
- // since we can't guarantee the destructors won't acquire that
- // same lock.
- tracksToRemove.clear();
- outputTracks.clear();
-
- // Effect chains will be actually deleted here if they were removed from
- // mEffectChains list during mixing or effects processing
- effectChains.clear();
- }
-
- return false;
-}
-
-void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
-{
- int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
- OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
- this,
- mSampleRate,
- mFormat,
- mChannelCount,
- frameCount);
- if (outputTrack->cblk() != NULL) {
- thread->setStreamVolume(AudioSystem::NUM_STREAM_TYPES, 1.0f);
- mOutputTracks.add(outputTrack);
- LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
- updateWaitTime();
- }
-}
-
-void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
-{
- Mutex::Autolock _l(mLock);
- for (size_t i = 0; i < mOutputTracks.size(); i++) {
- if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
- mOutputTracks[i]->destroy();
- mOutputTracks.removeAt(i);
- updateWaitTime();
- return;
- }
- }
- LOGV("removeOutputTrack(): unkonwn thread: %p", thread);
-}
-
-void AudioFlinger::DuplicatingThread::updateWaitTime()
-{
- mWaitTimeMs = UINT_MAX;
- for (size_t i = 0; i < mOutputTracks.size(); i++) {
- sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
- if (strong != NULL) {
- uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
- if (waitTimeMs < mWaitTimeMs) {
- mWaitTimeMs = waitTimeMs;
- }
- }
- }
-}
-
-
-bool AudioFlinger::DuplicatingThread::outputsReady(SortedVector< sp<OutputTrack> > &outputTracks)
-{
- for (size_t i = 0; i < outputTracks.size(); i++) {
- sp <ThreadBase> thread = outputTracks[i]->thread().promote();
- if (thread == 0) {
- LOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
- return false;
- }
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
- if (playbackThread->standby() && !playbackThread->isSuspended()) {
- LOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
- return false;
- }
- }
- return true;
-}
-
-uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
-{
- return (mWaitTimeMs * 1000) / 2;
-}
-
-// ----------------------------------------------------------------------------
-
-// TrackBase constructor must be called with AudioFlinger::mLock held
-AudioFlinger::ThreadBase::TrackBase::TrackBase(
- const wp<ThreadBase>& thread,
- const sp<Client>& client,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- uint32_t flags,
- const sp<IMemory>& sharedBuffer,
- int sessionId)
- : RefBase(),
- mThread(thread),
- mClient(client),
- mCblk(0),
- mFrameCount(0),
- mState(IDLE),
- mClientTid(-1),
- mFormat(format),
- mFlags(flags & ~SYSTEM_FLAGS_MASK),
- mSessionId(sessionId)
-{
- LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
-
- // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
- size_t size = sizeof(audio_track_cblk_t);
- size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
- if (sharedBuffer == 0) {
- size += bufferSize;
- }
-
- if (client != NULL) {
- mCblkMemory = client->heap()->allocate(size);
- if (mCblkMemory != 0) {
- mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
- if (mCblk) { // construct the shared structure in-place.
- new(mCblk) audio_track_cblk_t();
- // clear all buffers
- mCblk->frameCount = frameCount;
- mCblk->sampleRate = sampleRate;
- mCblk->channelCount = (uint8_t)channelCount;
- if (sharedBuffer == 0) {
- mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
- memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
- // Force underrun condition to avoid false underrun callback until first data is
- // written to buffer
- mCblk->flags = CBLK_UNDERRUN_ON;
- } else {
- mBuffer = sharedBuffer->pointer();
- }
- mBufferEnd = (uint8_t *)mBuffer + bufferSize;
- }
- } else {
- LOGE("not enough memory for AudioTrack size=%u", size);
- client->heap()->dump("AudioTrack");
- return;
- }
- } else {
- mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
- if (mCblk) { // construct the shared structure in-place.
- new(mCblk) audio_track_cblk_t();
- // clear all buffers
- mCblk->frameCount = frameCount;
- mCblk->sampleRate = sampleRate;
- mCblk->channelCount = (uint8_t)channelCount;
- mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
- memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
- // Force underrun condition to avoid false underrun callback until first data is
- // written to buffer
- mCblk->flags = CBLK_UNDERRUN_ON;
- mBufferEnd = (uint8_t *)mBuffer + bufferSize;
- }
- }
-}
-
-AudioFlinger::ThreadBase::TrackBase::~TrackBase()
-{
- if (mCblk) {
- mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
- if (mClient == NULL) {
- delete mCblk;
- }
- }
- mCblkMemory.clear(); // and free the shared memory
- if (mClient != NULL) {
- Mutex::Autolock _l(mClient->audioFlinger()->mLock);
- mClient.clear();
- }
-}
-
-void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
-{
- buffer->raw = 0;
- mFrameCount = buffer->frameCount;
- step();
- buffer->frameCount = 0;
-}
-
-bool AudioFlinger::ThreadBase::TrackBase::step() {
- bool result;
- audio_track_cblk_t* cblk = this->cblk();
-
- result = cblk->stepServer(mFrameCount);
- if (!result) {
- LOGV("stepServer failed acquiring cblk mutex");
- mFlags |= STEPSERVER_FAILED;
- }
- return result;
-}
-
-void AudioFlinger::ThreadBase::TrackBase::reset() {
- audio_track_cblk_t* cblk = this->cblk();
-
- cblk->user = 0;
- cblk->server = 0;
- cblk->userBase = 0;
- cblk->serverBase = 0;
- mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
- LOGV("TrackBase::reset");
-}
-
-sp<IMemory> AudioFlinger::ThreadBase::TrackBase::getCblk() const
-{
- return mCblkMemory;
-}
-
-int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
- return (int)mCblk->sampleRate;
-}
-
-int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
- return (int)mCblk->channelCount;
-}
-
-void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
- audio_track_cblk_t* cblk = this->cblk();
- int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
- int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
-
- // Check validity of returned pointer in case the track control block would have been corrupted.
- if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
- ((unsigned long)bufferStart & (unsigned long)(cblk->frameSize - 1))) {
- LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
- server %d, serverBase %d, user %d, userBase %d, channelCount %d",
- bufferStart, bufferEnd, mBuffer, mBufferEnd,
- cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channelCount);
- return 0;
- }
-
- return bufferStart;
-}
-
-// ----------------------------------------------------------------------------
-
-// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
-AudioFlinger::PlaybackThread::Track::Track(
- const wp<ThreadBase>& thread,
- const sp<Client>& client,
- int streamType,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- const sp<IMemory>& sharedBuffer,
- int sessionId)
- : TrackBase(thread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer, sessionId),
- mMute(false), mSharedBuffer(sharedBuffer), mName(-1), mMainBuffer(NULL), mAuxBuffer(NULL), mAuxEffectId(0)
-{
- if (mCblk != NULL) {
- sp<ThreadBase> baseThread = thread.promote();
- if (baseThread != 0) {
- PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
- mName = playbackThread->getTrackName_l();
- mMainBuffer = playbackThread->mixBuffer();
- }
- LOGV("Track constructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
- if (mName < 0) {
- LOGE("no more track names available");
- }
- mVolume[0] = 1.0f;
- mVolume[1] = 1.0f;
- mStreamType = streamType;
- // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
- // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
- mCblk->frameSize = AudioSystem::isLinearPCM(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
- }
-}
-
-AudioFlinger::PlaybackThread::Track::~Track()
-{
- LOGV("PlaybackThread::Track destructor");
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- Mutex::Autolock _l(thread->mLock);
- mState = TERMINATED;
- }
-}
-
-void AudioFlinger::PlaybackThread::Track::destroy()
-{
- // NOTE: destroyTrack_l() can remove a strong reference to this Track
- // by removing it from mTracks vector, so there is a risk that this Tracks's
- // desctructor is called. As the destructor needs to lock mLock,
- // we must acquire a strong reference on this Track before locking mLock
- // here so that the destructor is called only when exiting this function.
- // On the other hand, as long as Track::destroy() is only called by
- // TrackHandle destructor, the TrackHandle still holds a strong ref on
- // this Track with its member mTrack.
- sp<Track> keep(this);
- { // scope for mLock
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- if (!isOutputTrack()) {
- if (mState == ACTIVE || mState == RESUMING) {
- AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
- }
- AudioSystem::releaseOutput(thread->id());
- }
- Mutex::Autolock _l(thread->mLock);
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
- playbackThread->destroyTrack_l(this);
- }
- }
-}
-
-void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
-{
- snprintf(buffer, size, " %05d %05d %03u %03u %03u %05u %04u %1d %1d %1d %05u %05u %05u 0x%08x 0x%08x 0x%08x 0x%08x\n",
- mName - AudioMixer::TRACK0,
- (mClient == NULL) ? getpid() : mClient->pid(),
- mStreamType,
- mFormat,
- mCblk->channelCount,
- mSessionId,
- mFrameCount,
- mState,
- mMute,
- mFillingUpStatus,
- mCblk->sampleRate,
- mCblk->volume[0],
- mCblk->volume[1],
- mCblk->server,
- mCblk->user,
- (int)mMainBuffer,
- (int)mAuxBuffer);
-}
-
-status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
-{
- audio_track_cblk_t* cblk = this->cblk();
- uint32_t framesReady;
- uint32_t framesReq = buffer->frameCount;
-
- // Check if last stepServer failed, try to step now
- if (mFlags & TrackBase::STEPSERVER_FAILED) {
- if (!step()) goto getNextBuffer_exit;
- LOGV("stepServer recovered");
- mFlags &= ~TrackBase::STEPSERVER_FAILED;
- }
-
- framesReady = cblk->framesReady();
-
- if (LIKELY(framesReady)) {
- uint32_t s = cblk->server;
- uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
-
- bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
- if (framesReq > framesReady) {
- framesReq = framesReady;
- }
- if (s + framesReq > bufferEnd) {
- framesReq = bufferEnd - s;
- }
-
- buffer->raw = getBuffer(s, framesReq);
- if (buffer->raw == 0) goto getNextBuffer_exit;
-
- buffer->frameCount = framesReq;
- return NO_ERROR;
- }
-
-getNextBuffer_exit:
- buffer->raw = 0;
- buffer->frameCount = 0;
- LOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get());
- return NOT_ENOUGH_DATA;
-}
-
-bool AudioFlinger::PlaybackThread::Track::isReady() const {
- if (mFillingUpStatus != FS_FILLING) return true;
-
- if (mCblk->framesReady() >= mCblk->frameCount ||
- (mCblk->flags & CBLK_FORCEREADY_MSK)) {
- mFillingUpStatus = FS_FILLED;
- mCblk->flags &= ~CBLK_FORCEREADY_MSK;
- return true;
- }
- return false;
-}
-
-status_t AudioFlinger::PlaybackThread::Track::start()
-{
- status_t status = NO_ERROR;
- LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- Mutex::Autolock _l(thread->mLock);
- int state = mState;
- // here the track could be either new, or restarted
- // in both cases "unstop" the track
- if (mState == PAUSED) {
- mState = TrackBase::RESUMING;
- LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
- } else {
- mState = TrackBase::ACTIVE;
- LOGV("? => ACTIVE (%d) on thread %p", mName, this);
- }
-
- if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
- thread->mLock.unlock();
- status = AudioSystem::startOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
- thread->mLock.lock();
- }
- if (status == NO_ERROR) {
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
- playbackThread->addTrack_l(this);
- } else {
- mState = state;
- }
- } else {
- status = BAD_VALUE;
- }
- return status;
-}
-
-void AudioFlinger::PlaybackThread::Track::stop()
-{
- LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- Mutex::Autolock _l(thread->mLock);
- int state = mState;
- if (mState > STOPPED) {
- mState = STOPPED;
- // If the track is not active (PAUSED and buffers full), flush buffers
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
- if (playbackThread->mActiveTracks.indexOf(this) < 0) {
- reset();
- }
- LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
- }
- if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
- thread->mLock.unlock();
- AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
- thread->mLock.lock();
- }
- }
-}
-
-void AudioFlinger::PlaybackThread::Track::pause()
-{
- LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- Mutex::Autolock _l(thread->mLock);
- if (mState == ACTIVE || mState == RESUMING) {
- mState = PAUSING;
- LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
- if (!isOutputTrack()) {
- thread->mLock.unlock();
- AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
- thread->mLock.lock();
- }
- }
- }
-}
-
-void AudioFlinger::PlaybackThread::Track::flush()
-{
- LOGV("flush(%d)", mName);
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- Mutex::Autolock _l(thread->mLock);
- if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
- return;
- }
- // No point remaining in PAUSED state after a flush => go to
- // STOPPED state
- mState = STOPPED;
-
- mCblk->lock.lock();
- // NOTE: reset() will reset cblk->user and cblk->server with
- // the risk that at the same time, the AudioMixer is trying to read
- // data. In this case, getNextBuffer() would return a NULL pointer
- // as audio buffer => the AudioMixer code MUST always test that pointer
- // returned by getNextBuffer() is not NULL!
- reset();
- mCblk->lock.unlock();
- }
-}
-
-void AudioFlinger::PlaybackThread::Track::reset()
-{
- // Do not reset twice to avoid discarding data written just after a flush and before
- // the audioflinger thread detects the track is stopped.
- if (!mResetDone) {
- TrackBase::reset();
- // Force underrun condition to avoid false underrun callback until first data is
- // written to buffer
- mCblk->flags |= CBLK_UNDERRUN_ON;
- mCblk->flags &= ~CBLK_FORCEREADY_MSK;
- mFillingUpStatus = FS_FILLING;
- mResetDone = true;
- }
-}
-
-void AudioFlinger::PlaybackThread::Track::mute(bool muted)
-{
- mMute = muted;
-}
-
-void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right)
-{
- mVolume[0] = left;
- mVolume[1] = right;
-}
-
-status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
-{
- status_t status = DEAD_OBJECT;
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
- status = playbackThread->attachAuxEffect(this, EffectId);
- }
- return status;
-}
-
-void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
-{
- mAuxEffectId = EffectId;
- mAuxBuffer = buffer;
-}
-
-// ----------------------------------------------------------------------------
-
-// RecordTrack constructor must be called with AudioFlinger::mLock held
-AudioFlinger::RecordThread::RecordTrack::RecordTrack(
- const wp<ThreadBase>& thread,
- const sp<Client>& client,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- uint32_t flags,
- int sessionId)
- : TrackBase(thread, client, sampleRate, format,
- channelCount, frameCount, flags, 0, sessionId),
- mOverflow(false)
-{
- if (mCblk != NULL) {
- LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
- if (format == AudioSystem::PCM_16_BIT) {
- mCblk->frameSize = channelCount * sizeof(int16_t);
- } else if (format == AudioSystem::PCM_8_BIT) {
- mCblk->frameSize = channelCount * sizeof(int8_t);
- } else {
- mCblk->frameSize = sizeof(int8_t);
- }
- }
-}
-
-AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
-{
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- AudioSystem::releaseInput(thread->id());
- }
-}
-
-status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
-{
- audio_track_cblk_t* cblk = this->cblk();
- uint32_t framesAvail;
- uint32_t framesReq = buffer->frameCount;
-
- // Check if last stepServer failed, try to step now
- if (mFlags & TrackBase::STEPSERVER_FAILED) {
- if (!step()) goto getNextBuffer_exit;
- LOGV("stepServer recovered");
- mFlags &= ~TrackBase::STEPSERVER_FAILED;
- }
-
- framesAvail = cblk->framesAvailable_l();
-
- if (LIKELY(framesAvail)) {
- uint32_t s = cblk->server;
- uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
-
- if (framesReq > framesAvail) {
- framesReq = framesAvail;
- }
- if (s + framesReq > bufferEnd) {
- framesReq = bufferEnd - s;
- }
-
- buffer->raw = getBuffer(s, framesReq);
- if (buffer->raw == 0) goto getNextBuffer_exit;
-
- buffer->frameCount = framesReq;
- return NO_ERROR;
- }
-
-getNextBuffer_exit:
- buffer->raw = 0;
- buffer->frameCount = 0;
- return NOT_ENOUGH_DATA;
-}
-
-status_t AudioFlinger::RecordThread::RecordTrack::start()
-{
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- RecordThread *recordThread = (RecordThread *)thread.get();
- return recordThread->start(this);
- } else {
- return BAD_VALUE;
- }
-}
-
-void AudioFlinger::RecordThread::RecordTrack::stop()
-{
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- RecordThread *recordThread = (RecordThread *)thread.get();
- recordThread->stop(this);
- TrackBase::reset();
- // Force overerrun condition to avoid false overrun callback until first data is
- // read from buffer
- mCblk->flags |= CBLK_UNDERRUN_ON;
- }
-}
-
-void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
-{
- snprintf(buffer, size, " %05d %03u %03u %05d %04u %01d %05u %08x %08x\n",
- (mClient == NULL) ? getpid() : mClient->pid(),
- mFormat,
- mCblk->channelCount,
- mSessionId,
- mFrameCount,
- mState,
- mCblk->sampleRate,
- mCblk->server,
- mCblk->user);
-}
-
-
-// ----------------------------------------------------------------------------
-
-AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
- const wp<ThreadBase>& thread,
- DuplicatingThread *sourceThread,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount)
- : Track(thread, NULL, AudioSystem::NUM_STREAM_TYPES, sampleRate, format, channelCount, frameCount, NULL, 0),
- mActive(false), mSourceThread(sourceThread)
-{
-
- PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
- if (mCblk != NULL) {
- mCblk->flags |= CBLK_DIRECTION_OUT;
- mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
- mCblk->volume[0] = mCblk->volume[1] = 0x1000;
- mOutBuffer.frameCount = 0;
- playbackThread->mTracks.add(this);
- LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channelCount %d mBufferEnd %p",
- mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channelCount, mBufferEnd);
- } else {
- LOGW("Error creating output track on thread %p", playbackThread);
- }
-}
-
-AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
-{
- clearBufferQueue();
-}
-
-status_t AudioFlinger::PlaybackThread::OutputTrack::start()
-{
- status_t status = Track::start();
- if (status != NO_ERROR) {
- return status;
- }
-
- mActive = true;
- mRetryCount = 127;
- return status;
-}
-
-void AudioFlinger::PlaybackThread::OutputTrack::stop()
-{
- Track::stop();
- clearBufferQueue();
- mOutBuffer.frameCount = 0;
- mActive = false;
-}
-
-bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
-{
- Buffer *pInBuffer;
- Buffer inBuffer;
- uint32_t channelCount = mCblk->channelCount;
- bool outputBufferFull = false;
- inBuffer.frameCount = frames;
- inBuffer.i16 = data;
-
- uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
-
- if (!mActive && frames != 0) {
- start();
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- MixerThread *mixerThread = (MixerThread *)thread.get();
- if (mCblk->frameCount > frames){
- if (mBufferQueue.size() < kMaxOverFlowBuffers) {
- uint32_t startFrames = (mCblk->frameCount - frames);
- pInBuffer = new Buffer;
- pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
- pInBuffer->frameCount = startFrames;
- pInBuffer->i16 = pInBuffer->mBuffer;
- memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
- mBufferQueue.add(pInBuffer);
- } else {
- LOGW ("OutputTrack::write() %p no more buffers in queue", this);
- }
- }
- }
- }
-
- while (waitTimeLeftMs) {
- // First write pending buffers, then new data
- if (mBufferQueue.size()) {
- pInBuffer = mBufferQueue.itemAt(0);
- } else {
- pInBuffer = &inBuffer;
- }
-
- if (pInBuffer->frameCount == 0) {
- break;
- }
-
- if (mOutBuffer.frameCount == 0) {
- mOutBuffer.frameCount = pInBuffer->frameCount;
- nsecs_t startTime = systemTime();
- if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
- LOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
- outputBufferFull = true;
- break;
- }
- uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
- if (waitTimeLeftMs >= waitTimeMs) {
- waitTimeLeftMs -= waitTimeMs;
- } else {
- waitTimeLeftMs = 0;
- }
- }
-
- uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
- memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
- mCblk->stepUser(outFrames);
- pInBuffer->frameCount -= outFrames;
- pInBuffer->i16 += outFrames * channelCount;
- mOutBuffer.frameCount -= outFrames;
- mOutBuffer.i16 += outFrames * channelCount;
-
- if (pInBuffer->frameCount == 0) {
- if (mBufferQueue.size()) {
- mBufferQueue.removeAt(0);
- delete [] pInBuffer->mBuffer;
- delete pInBuffer;
- LOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
- } else {
- break;
- }
- }
- }
-
- // If we could not write all frames, allocate a buffer and queue it for next time.
- if (inBuffer.frameCount) {
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0 && !thread->standby()) {
- if (mBufferQueue.size() < kMaxOverFlowBuffers) {
- pInBuffer = new Buffer;
- pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
- pInBuffer->frameCount = inBuffer.frameCount;
- pInBuffer->i16 = pInBuffer->mBuffer;
- memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t));
- mBufferQueue.add(pInBuffer);
- LOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
- } else {
- LOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
- }
- }
- }
-
- // Calling write() with a 0 length buffer, means that no more data will be written:
- // If no more buffers are pending, fill output track buffer to make sure it is started
- // by output mixer.
- if (frames == 0 && mBufferQueue.size() == 0) {
- if (mCblk->user < mCblk->frameCount) {
- frames = mCblk->frameCount - mCblk->user;
- pInBuffer = new Buffer;
- pInBuffer->mBuffer = new int16_t[frames * channelCount];
- pInBuffer->frameCount = frames;
- pInBuffer->i16 = pInBuffer->mBuffer;
- memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
- mBufferQueue.add(pInBuffer);
- } else if (mActive) {
- stop();
- }
- }
-
- return outputBufferFull;
-}
-
-status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
-{
- int active;
- status_t result;
- audio_track_cblk_t* cblk = mCblk;
- uint32_t framesReq = buffer->frameCount;
-
-// LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
- buffer->frameCount = 0;
-
- uint32_t framesAvail = cblk->framesAvailable();
-
-
- if (framesAvail == 0) {
- Mutex::Autolock _l(cblk->lock);
- goto start_loop_here;
- while (framesAvail == 0) {
- active = mActive;
- if (UNLIKELY(!active)) {
- LOGV("Not active and NO_MORE_BUFFERS");
- return AudioTrack::NO_MORE_BUFFERS;
- }
- result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
- if (result != NO_ERROR) {
- return AudioTrack::NO_MORE_BUFFERS;
- }
- // read the server count again
- start_loop_here:
- framesAvail = cblk->framesAvailable_l();
- }
- }
-
-// if (framesAvail < framesReq) {
-// return AudioTrack::NO_MORE_BUFFERS;
-// }
-
- if (framesReq > framesAvail) {
- framesReq = framesAvail;
- }
-
- uint32_t u = cblk->user;
- uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
-
- if (u + framesReq > bufferEnd) {
- framesReq = bufferEnd - u;
- }
-
- buffer->frameCount = framesReq;
- buffer->raw = (void *)cblk->buffer(u);
- return NO_ERROR;
-}
-
-
-void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
-{
- size_t size = mBufferQueue.size();
- Buffer *pBuffer;
-
- for (size_t i = 0; i < size; i++) {
- pBuffer = mBufferQueue.itemAt(i);
- delete [] pBuffer->mBuffer;
- delete pBuffer;
- }
- mBufferQueue.clear();
-}
-
-// ----------------------------------------------------------------------------
-
-AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
- : RefBase(),
- mAudioFlinger(audioFlinger),
- mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
- mPid(pid)
-{
- // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
-}
-
-// Client destructor must be called with AudioFlinger::mLock held
-AudioFlinger::Client::~Client()
-{
- mAudioFlinger->removeClient_l(mPid);
-}
-
-const sp<MemoryDealer>& AudioFlinger::Client::heap() const
-{
- return mMemoryDealer;
-}
-
-// ----------------------------------------------------------------------------
-
-AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
- const sp<IAudioFlingerClient>& client,
- pid_t pid)
- : mAudioFlinger(audioFlinger), mPid(pid), mClient(client)
-{
-}
-
-AudioFlinger::NotificationClient::~NotificationClient()
-{
- mClient.clear();
-}
-
-void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
-{
- sp<NotificationClient> keep(this);
- {
- mAudioFlinger->removeNotificationClient(mPid);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
- : BnAudioTrack(),
- mTrack(track)
-{
-}
-
-AudioFlinger::TrackHandle::~TrackHandle() {
- // just stop the track on deletion, associated resources
- // will be freed from the main thread once all pending buffers have
- // been played. Unless it's not in the active track list, in which
- // case we free everything now...
- mTrack->destroy();
-}
-
-status_t AudioFlinger::TrackHandle::start() {
- return mTrack->start();
-}
-
-void AudioFlinger::TrackHandle::stop() {
- mTrack->stop();
-}
-
-void AudioFlinger::TrackHandle::flush() {
- mTrack->flush();
-}
-
-void AudioFlinger::TrackHandle::mute(bool e) {
- mTrack->mute(e);
-}
-
-void AudioFlinger::TrackHandle::pause() {
- mTrack->pause();
-}
-
-void AudioFlinger::TrackHandle::setVolume(float left, float right) {
- mTrack->setVolume(left, right);
-}
-
-sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
- return mTrack->getCblk();
-}
-
-status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
-{
- return mTrack->attachAuxEffect(EffectId);
-}
-
-status_t AudioFlinger::TrackHandle::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- return BnAudioTrack::onTransact(code, data, reply, flags);
-}
-
-// ----------------------------------------------------------------------------
-
-sp<IAudioRecord> AudioFlinger::openRecord(
- pid_t pid,
- int input,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- uint32_t flags,
- int *sessionId,
- status_t *status)
-{
- sp<RecordThread::RecordTrack> recordTrack;
- sp<RecordHandle> recordHandle;
- sp<Client> client;
- wp<Client> wclient;
- status_t lStatus;
- RecordThread *thread;
- size_t inFrameCount;
- int lSessionId;
-
- // check calling permissions
- if (!recordingAllowed()) {
- lStatus = PERMISSION_DENIED;
- goto Exit;
- }
-
- // add client to list
- { // scope for mLock
- Mutex::Autolock _l(mLock);
- thread = checkRecordThread_l(input);
- if (thread == NULL) {
- lStatus = BAD_VALUE;
- goto Exit;
- }
-
- wclient = mClients.valueFor(pid);
- if (wclient != NULL) {
- client = wclient.promote();
- } else {
- client = new Client(this, pid);
- mClients.add(pid, client);
- }
-
- // If no audio session id is provided, create one here
- if (sessionId != NULL && *sessionId != 0) {
- lSessionId = *sessionId;
- } else {
- lSessionId = nextUniqueId();
- if (sessionId != NULL) {
- *sessionId = lSessionId;
- }
- }
- // create new record track. The record track uses one track in mHardwareMixerThread by convention.
- recordTrack = new RecordThread::RecordTrack(thread, client, sampleRate,
- format, channelCount, frameCount, flags, lSessionId);
- }
- if (recordTrack->getCblk() == NULL) {
- // remove local strong reference to Client before deleting the RecordTrack so that the Client
- // destructor is called by the TrackBase destructor with mLock held
- client.clear();
- recordTrack.clear();
- lStatus = NO_MEMORY;
- goto Exit;
- }
-
- // return to handle to client
- recordHandle = new RecordHandle(recordTrack);
- lStatus = NO_ERROR;
-
-Exit:
- if (status) {
- *status = lStatus;
- }
- return recordHandle;
-}
-
-// ----------------------------------------------------------------------------
-
-AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
- : BnAudioRecord(),
- mRecordTrack(recordTrack)
-{
-}
-
-AudioFlinger::RecordHandle::~RecordHandle() {
- stop();
-}
-
-status_t AudioFlinger::RecordHandle::start() {
- LOGV("RecordHandle::start()");
- return mRecordTrack->start();
-}
-
-void AudioFlinger::RecordHandle::stop() {
- LOGV("RecordHandle::stop()");
- mRecordTrack->stop();
-}
-
-sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
- return mRecordTrack->getCblk();
-}
-
-status_t AudioFlinger::RecordHandle::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- return BnAudioRecord::onTransact(code, data, reply, flags);
-}
-
-// ----------------------------------------------------------------------------
-
-AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) :
- ThreadBase(audioFlinger, id),
- mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
-{
- mReqChannelCount = AudioSystem::popCount(channels);
- mReqSampleRate = sampleRate;
- readInputParameters();
-}
-
-
-AudioFlinger::RecordThread::~RecordThread()
-{
- delete[] mRsmpInBuffer;
- if (mResampler != 0) {
- delete mResampler;
- delete[] mRsmpOutBuffer;
- }
-}
-
-void AudioFlinger::RecordThread::onFirstRef()
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
-
- snprintf(buffer, SIZE, "Record Thread %p", this);
-
- run(buffer, PRIORITY_URGENT_AUDIO);
-}
-
-bool AudioFlinger::RecordThread::threadLoop()
-{
- AudioBufferProvider::Buffer buffer;
- sp<RecordTrack> activeTrack;
-
- // start recording
- while (!exitPending()) {
-
- processConfigEvents();
-
- { // scope for mLock
- Mutex::Autolock _l(mLock);
- checkForNewParameters_l();
- if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
- if (!mStandby) {
- mInput->standby();
- mStandby = true;
- }
-
- if (exitPending()) break;
-
- LOGV("RecordThread: loop stopping");
- // go to sleep
- mWaitWorkCV.wait(mLock);
- LOGV("RecordThread: loop starting");
- continue;
- }
- if (mActiveTrack != 0) {
- if (mActiveTrack->mState == TrackBase::PAUSING) {
- if (!mStandby) {
- mInput->standby();
- mStandby = true;
- }
- mActiveTrack.clear();
- mStartStopCond.broadcast();
- } else if (mActiveTrack->mState == TrackBase::RESUMING) {
- if (mReqChannelCount != mActiveTrack->channelCount()) {
- mActiveTrack.clear();
- mStartStopCond.broadcast();
- } else if (mBytesRead != 0) {
- // record start succeeds only if first read from audio input
- // succeeds
- if (mBytesRead > 0) {
- mActiveTrack->mState = TrackBase::ACTIVE;
- } else {
- mActiveTrack.clear();
- }
- mStartStopCond.broadcast();
- }
- mStandby = false;
- }
- }
- }
-
- if (mActiveTrack != 0) {
- if (mActiveTrack->mState != TrackBase::ACTIVE &&
- mActiveTrack->mState != TrackBase::RESUMING) {
- usleep(5000);
- continue;
- }
- buffer.frameCount = mFrameCount;
- if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
- size_t framesOut = buffer.frameCount;
- if (mResampler == 0) {
- // no resampling
- while (framesOut) {
- size_t framesIn = mFrameCount - mRsmpInIndex;
- if (framesIn) {
- int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
- int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
- if (framesIn > framesOut)
- framesIn = framesOut;
- mRsmpInIndex += framesIn;
- framesOut -= framesIn;
- if ((int)mChannelCount == mReqChannelCount ||
- mFormat != AudioSystem::PCM_16_BIT) {
- memcpy(dst, src, framesIn * mFrameSize);
- } else {
- int16_t *src16 = (int16_t *)src;
- int16_t *dst16 = (int16_t *)dst;
- if (mChannelCount == 1) {
- while (framesIn--) {
- *dst16++ = *src16;
- *dst16++ = *src16++;
- }
- } else {
- while (framesIn--) {
- *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
- src16 += 2;
- }
- }
- }
- }
- if (framesOut && mFrameCount == mRsmpInIndex) {
- if (framesOut == mFrameCount &&
- ((int)mChannelCount == mReqChannelCount || mFormat != AudioSystem::PCM_16_BIT)) {
- mBytesRead = mInput->read(buffer.raw, mInputBytes);
- framesOut = 0;
- } else {
- mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
- mRsmpInIndex = 0;
- }
- if (mBytesRead < 0) {
- LOGE("Error reading audio input");
- if (mActiveTrack->mState == TrackBase::ACTIVE) {
- // Force input into standby so that it tries to
- // recover at next read attempt
- mInput->standby();
- usleep(5000);
- }
- mRsmpInIndex = mFrameCount;
- framesOut = 0;
- buffer.frameCount = 0;
- }
- }
- }
- } else {
- // resampling
-
- memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
- // alter output frame count as if we were expecting stereo samples
- if (mChannelCount == 1 && mReqChannelCount == 1) {
- framesOut >>= 1;
- }
- mResampler->resample(mRsmpOutBuffer, framesOut, this);
- // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
- // are 32 bit aligned which should be always true.
- if (mChannelCount == 2 && mReqChannelCount == 1) {
- AudioMixer::ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
- // the resampler always outputs stereo samples: do post stereo to mono conversion
- int16_t *src = (int16_t *)mRsmpOutBuffer;
- int16_t *dst = buffer.i16;
- while (framesOut--) {
- *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
- src += 2;
- }
- } else {
- AudioMixer::ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
- }
-
- }
- mActiveTrack->releaseBuffer(&buffer);
- mActiveTrack->overflow();
- }
- // client isn't retrieving buffers fast enough
- else {
- if (!mActiveTrack->setOverflow())
- LOGW("RecordThread: buffer overflow");
- // Release the processor for a while before asking for a new buffer.
- // This will give the application more chance to read from the buffer and
- // clear the overflow.
- usleep(5000);
- }
- }
- }
-
- if (!mStandby) {
- mInput->standby();
- }
- mActiveTrack.clear();
-
- mStartStopCond.broadcast();
-
- LOGV("RecordThread %p exiting", this);
- return false;
-}
-
-status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
-{
- LOGV("RecordThread::start");
- sp <ThreadBase> strongMe = this;
- status_t status = NO_ERROR;
- {
- AutoMutex lock(&mLock);
- if (mActiveTrack != 0) {
- if (recordTrack != mActiveTrack.get()) {
- status = -EBUSY;
- } else if (mActiveTrack->mState == TrackBase::PAUSING) {
- mActiveTrack->mState = TrackBase::ACTIVE;
- }
- return status;
- }
-
- recordTrack->mState = TrackBase::IDLE;
- mActiveTrack = recordTrack;
- mLock.unlock();
- status_t status = AudioSystem::startInput(mId);
- mLock.lock();
- if (status != NO_ERROR) {
- mActiveTrack.clear();
- return status;
- }
- mActiveTrack->mState = TrackBase::RESUMING;
- mRsmpInIndex = mFrameCount;
- mBytesRead = 0;
- // signal thread to start
- LOGV("Signal record thread");
- mWaitWorkCV.signal();
- // do not wait for mStartStopCond if exiting
- if (mExiting) {
- mActiveTrack.clear();
- status = INVALID_OPERATION;
- goto startError;
- }
- mStartStopCond.wait(mLock);
- if (mActiveTrack == 0) {
- LOGV("Record failed to start");
- status = BAD_VALUE;
- goto startError;
- }
- LOGV("Record started OK");
- return status;
- }
-startError:
- AudioSystem::stopInput(mId);
- return status;
-}
-
-void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
- LOGV("RecordThread::stop");
- sp <ThreadBase> strongMe = this;
- {
- AutoMutex lock(&mLock);
- if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
- mActiveTrack->mState = TrackBase::PAUSING;
- // do not wait for mStartStopCond if exiting
- if (mExiting) {
- return;
- }
- mStartStopCond.wait(mLock);
- // if we have been restarted, recordTrack == mActiveTrack.get() here
- if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
- mLock.unlock();
- AudioSystem::stopInput(mId);
- mLock.lock();
- LOGV("Record stopped OK");
- }
- }
- }
-}
-
-status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- pid_t pid = 0;
-
- snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
- result.append(buffer);
-
- if (mActiveTrack != 0) {
- result.append("Active Track:\n");
- result.append(" Clien Fmt Chn Session Buf S SRate Serv User\n");
- mActiveTrack->dump(buffer, SIZE);
- result.append(buffer);
-
- snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
- result.append(buffer);
- snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
- result.append(buffer);
- snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != 0));
- result.append(buffer);
- snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
- result.append(buffer);
- snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
- result.append(buffer);
-
-
- } else {
- result.append("No record client\n");
- }
- write(fd, result.string(), result.size());
-
- dumpBase(fd, args);
-
- return NO_ERROR;
-}
-
-status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer)
-{
- size_t framesReq = buffer->frameCount;
- size_t framesReady = mFrameCount - mRsmpInIndex;
- int channelCount;
-
- if (framesReady == 0) {
- mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
- if (mBytesRead < 0) {
- LOGE("RecordThread::getNextBuffer() Error reading audio input");
- if (mActiveTrack->mState == TrackBase::ACTIVE) {
- // Force input into standby so that it tries to
- // recover at next read attempt
- mInput->standby();
- usleep(5000);
- }
- buffer->raw = 0;
- buffer->frameCount = 0;
- return NOT_ENOUGH_DATA;
- }
- mRsmpInIndex = 0;
- framesReady = mFrameCount;
- }
-
- if (framesReq > framesReady) {
- framesReq = framesReady;
- }
-
- if (mChannelCount == 1 && mReqChannelCount == 2) {
- channelCount = 1;
- } else {
- channelCount = 2;
- }
- buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
- buffer->frameCount = framesReq;
- return NO_ERROR;
-}
-
-void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
-{
- mRsmpInIndex += buffer->frameCount;
- buffer->frameCount = 0;
-}
-
-bool AudioFlinger::RecordThread::checkForNewParameters_l()
-{
- bool reconfig = false;
-
- while (!mNewParameters.isEmpty()) {
- status_t status = NO_ERROR;
- String8 keyValuePair = mNewParameters[0];
- AudioParameter param = AudioParameter(keyValuePair);
- int value;
- int reqFormat = mFormat;
- int reqSamplingRate = mReqSampleRate;
- int reqChannelCount = mReqChannelCount;
-
- if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
- reqSamplingRate = value;
- reconfig = true;
- }
- if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
- reqFormat = value;
- reconfig = true;
- }
- if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
- reqChannelCount = AudioSystem::popCount(value);
- reconfig = true;
- }
- if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
- // do not accept frame count changes if tracks are open as the track buffer
- // size depends on frame count and correct behavior would not be garantied
- // if frame count is changed after track creation
- if (mActiveTrack != 0) {
- status = INVALID_OPERATION;
- } else {
- reconfig = true;
- }
- }
- if (status == NO_ERROR) {
- status = mInput->setParameters(keyValuePair);
- if (status == INVALID_OPERATION) {
- mInput->standby();
- status = mInput->setParameters(keyValuePair);
- }
- if (reconfig) {
- if (status == BAD_VALUE &&
- reqFormat == mInput->format() && reqFormat == AudioSystem::PCM_16_BIT &&
- ((int)mInput->sampleRate() <= 2 * reqSamplingRate) &&
- (AudioSystem::popCount(mInput->channels()) < 3) && (reqChannelCount < 3)) {
- status = NO_ERROR;
- }
- if (status == NO_ERROR) {
- readInputParameters();
- sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
- }
- }
- }
-
- mNewParameters.removeAt(0);
-
- mParamStatus = status;
- mParamCond.signal();
- mWaitWorkCV.wait(mLock);
- }
- return reconfig;
-}
-
-String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
-{
- return mInput->getParameters(keys);
-}
-
-void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
- AudioSystem::OutputDescriptor desc;
- void *param2 = 0;
-
- switch (event) {
- case AudioSystem::INPUT_OPENED:
- case AudioSystem::INPUT_CONFIG_CHANGED:
- desc.channels = mChannels;
- desc.samplingRate = mSampleRate;
- desc.format = mFormat;
- desc.frameCount = mFrameCount;
- desc.latency = 0;
- param2 = &desc;
- break;
-
- case AudioSystem::INPUT_CLOSED:
- default:
- break;
- }
- mAudioFlinger->audioConfigChanged_l(event, mId, param2);
-}
-
-void AudioFlinger::RecordThread::readInputParameters()
-{
- if (mRsmpInBuffer) delete mRsmpInBuffer;
- if (mRsmpOutBuffer) delete mRsmpOutBuffer;
- if (mResampler) delete mResampler;
- mResampler = 0;
-
- mSampleRate = mInput->sampleRate();
- mChannels = mInput->channels();
- mChannelCount = (uint16_t)AudioSystem::popCount(mChannels);
- mFormat = mInput->format();
- mFrameSize = (uint16_t)mInput->frameSize();
- mInputBytes = mInput->bufferSize();
- mFrameCount = mInputBytes / mFrameSize;
- mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
-
- if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
- {
- int channelCount;
- // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
- // stereo to mono post process as the resampler always outputs stereo.
- if (mChannelCount == 1 && mReqChannelCount == 2) {
- channelCount = 1;
- } else {
- channelCount = 2;
- }
- mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
- mResampler->setSampleRate(mSampleRate);
- mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
- mRsmpOutBuffer = new int32_t[mFrameCount * 2];
-
- // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
- if (mChannelCount == 1 && mReqChannelCount == 1) {
- mFrameCount >>= 1;
- }
-
- }
- mRsmpInIndex = mFrameCount;
-}
-
-unsigned int AudioFlinger::RecordThread::getInputFramesLost()
-{
- return mInput->getInputFramesLost();
-}
-
-// ----------------------------------------------------------------------------
-
-int AudioFlinger::openOutput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t *pLatencyMs,
- uint32_t flags)
-{
- status_t status;
- PlaybackThread *thread = NULL;
- mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
- uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
- uint32_t format = pFormat ? *pFormat : 0;
- uint32_t channels = pChannels ? *pChannels : 0;
- uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
-
- LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
- pDevices ? *pDevices : 0,
- samplingRate,
- format,
- channels,
- flags);
-
- if (pDevices == NULL || *pDevices == 0) {
- return 0;
- }
- Mutex::Autolock _l(mLock);
-
- AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,
- (int *)&format,
- &channels,
- &samplingRate,
- &status);
- LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
- output,
- samplingRate,
- format,
- channels,
- status);
-
- mHardwareStatus = AUDIO_HW_IDLE;
- if (output != 0) {
- int id = nextUniqueId();
- if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
- (format != AudioSystem::PCM_16_BIT) ||
- (channels != AudioSystem::CHANNEL_OUT_STEREO)) {
- thread = new DirectOutputThread(this, output, id, *pDevices);
- LOGV("openOutput() created direct output: ID %d thread %p", id, thread);
- } else {
- thread = new MixerThread(this, output, id, *pDevices);
- LOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
-
-#ifdef LVMX
- unsigned bitsPerSample =
- (format == AudioSystem::PCM_16_BIT) ? 16 :
- ((format == AudioSystem::PCM_8_BIT) ? 8 : 0);
- unsigned channelCount = (channels == AudioSystem::CHANNEL_OUT_STEREO) ? 2 : 1;
- int audioOutputType = LifeVibes::threadIdToAudioOutputType(thread->id());
-
- LifeVibes::init_aot(audioOutputType, samplingRate, bitsPerSample, channelCount);
- LifeVibes::setDevice(audioOutputType, *pDevices);
-#endif
-
- }
- mPlaybackThreads.add(id, thread);
-
- if (pSamplingRate) *pSamplingRate = samplingRate;
- if (pFormat) *pFormat = format;
- if (pChannels) *pChannels = channels;
- if (pLatencyMs) *pLatencyMs = thread->latency();
-
- // notify client processes of the new output creation
- thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
- return id;
- }
-
- return 0;
-}
-
-int AudioFlinger::openDuplicateOutput(int output1, int output2)
-{
- Mutex::Autolock _l(mLock);
- MixerThread *thread1 = checkMixerThread_l(output1);
- MixerThread *thread2 = checkMixerThread_l(output2);
-
- if (thread1 == NULL || thread2 == NULL) {
- LOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
- return 0;
- }
-
- int id = nextUniqueId();
- DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
- thread->addOutputTrack(thread2);
- mPlaybackThreads.add(id, thread);
- // notify client processes of the new output creation
- thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
- return id;
-}
-
-status_t AudioFlinger::closeOutput(int output)
-{
- // keep strong reference on the playback thread so that
- // it is not destroyed while exit() is executed
- sp <PlaybackThread> thread;
- {
- Mutex::Autolock _l(mLock);
- thread = checkPlaybackThread_l(output);
- if (thread == NULL) {
- return BAD_VALUE;
- }
-
- LOGV("closeOutput() %d", output);
-
- if (thread->type() == PlaybackThread::MIXER) {
- for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- if (mPlaybackThreads.valueAt(i)->type() == PlaybackThread::DUPLICATING) {
- DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
- dupThread->removeOutputTrack((MixerThread *)thread.get());
- }
- }
- }
- void *param2 = 0;
- audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2);
- mPlaybackThreads.removeItem(output);
- }
- thread->exit();
-
- if (thread->type() != PlaybackThread::DUPLICATING) {
- mAudioHardware->closeOutputStream(thread->getOutput());
- }
- return NO_ERROR;
-}
-
-status_t AudioFlinger::suspendOutput(int output)
-{
- Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
-
- if (thread == NULL) {
- return BAD_VALUE;
- }
-
- LOGV("suspendOutput() %d", output);
- thread->suspend();
-
- return NO_ERROR;
-}
-
-status_t AudioFlinger::restoreOutput(int output)
-{
- Mutex::Autolock _l(mLock);
- PlaybackThread *thread = checkPlaybackThread_l(output);
-
- if (thread == NULL) {
- return BAD_VALUE;
- }
-
- LOGV("restoreOutput() %d", output);
-
- thread->restore();
-
- return NO_ERROR;
-}
-
-int AudioFlinger::openInput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t acoustics)
-{
- status_t status;
- RecordThread *thread = NULL;
- uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
- uint32_t format = pFormat ? *pFormat : 0;
- uint32_t channels = pChannels ? *pChannels : 0;
- uint32_t reqSamplingRate = samplingRate;
- uint32_t reqFormat = format;
- uint32_t reqChannels = channels;
-
- if (pDevices == NULL || *pDevices == 0) {
- return 0;
- }
- Mutex::Autolock _l(mLock);
-
- AudioStreamIn *input = mAudioHardware->openInputStream(*pDevices,
- (int *)&format,
- &channels,
- &samplingRate,
- &status,
- (AudioSystem::audio_in_acoustics)acoustics);
- LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
- input,
- samplingRate,
- format,
- channels,
- acoustics,
- status);
-
- // If the input could not be opened with the requested parameters and we can handle the conversion internally,
- // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
- // or stereo to mono conversions on 16 bit PCM inputs.
- if (input == 0 && status == BAD_VALUE &&
- reqFormat == format && format == AudioSystem::PCM_16_BIT &&
- (samplingRate <= 2 * reqSamplingRate) &&
- (AudioSystem::popCount(channels) < 3) && (AudioSystem::popCount(reqChannels) < 3)) {
- LOGV("openInput() reopening with proposed sampling rate and channels");
- input = mAudioHardware->openInputStream(*pDevices,
- (int *)&format,
- &channels,
- &samplingRate,
- &status,
- (AudioSystem::audio_in_acoustics)acoustics);
- }
-
- if (input != 0) {
- int id = nextUniqueId();
- // Start record thread
- thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id);
- mRecordThreads.add(id, thread);
- LOGV("openInput() created record thread: ID %d thread %p", id, thread);
- if (pSamplingRate) *pSamplingRate = reqSamplingRate;
- if (pFormat) *pFormat = format;
- if (pChannels) *pChannels = reqChannels;
-
- input->standby();
-
- // notify client processes of the new input creation
- thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
- return id;
- }
-
- return 0;
-}
-
-status_t AudioFlinger::closeInput(int input)
-{
- // keep strong reference on the record thread so that
- // it is not destroyed while exit() is executed
- sp <RecordThread> thread;
- {
- Mutex::Autolock _l(mLock);
- thread = checkRecordThread_l(input);
- if (thread == NULL) {
- return BAD_VALUE;
- }
-
- LOGV("closeInput() %d", input);
- void *param2 = 0;
- audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
- mRecordThreads.removeItem(input);
- }
- thread->exit();
-
- mAudioHardware->closeInputStream(thread->getInput());
-
- return NO_ERROR;
-}
-
-status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
-{
- Mutex::Autolock _l(mLock);
- MixerThread *dstThread = checkMixerThread_l(output);
- if (dstThread == NULL) {
- LOGW("setStreamOutput() bad output id %d", output);
- return BAD_VALUE;
- }
-
- LOGV("setStreamOutput() stream %d to output %d", stream, output);
- audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
-
- for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
- if (thread != dstThread &&
- thread->type() != PlaybackThread::DIRECT) {
- MixerThread *srcThread = (MixerThread *)thread;
- srcThread->invalidateTracks(stream);
- }
- }
-
- return NO_ERROR;
-}
-
-
-int AudioFlinger::newAudioSessionId()
-{
- return nextUniqueId();
-}
-
-// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
-{
- PlaybackThread *thread = NULL;
- if (mPlaybackThreads.indexOfKey(output) >= 0) {
- thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
- }
- return thread;
-}
-
-// checkMixerThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(int output) const
-{
- PlaybackThread *thread = checkPlaybackThread_l(output);
- if (thread != NULL) {
- if (thread->type() == PlaybackThread::DIRECT) {
- thread = NULL;
- }
- }
- return (MixerThread *)thread;
-}
-
-// checkRecordThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const
-{
- RecordThread *thread = NULL;
- if (mRecordThreads.indexOfKey(input) >= 0) {
- thread = (RecordThread *)mRecordThreads.valueFor(input).get();
- }
- return thread;
-}
-
-int AudioFlinger::nextUniqueId()
-{
- return android_atomic_inc(&mNextUniqueId);
-}
-
-// ----------------------------------------------------------------------------
-// Effect management
-// ----------------------------------------------------------------------------
-
-
-status_t AudioFlinger::loadEffectLibrary(const char *libPath, int *handle)
-{
- Mutex::Autolock _l(mLock);
- return EffectLoadLibrary(libPath, handle);
-}
-
-status_t AudioFlinger::unloadEffectLibrary(int handle)
-{
- Mutex::Autolock _l(mLock);
- return EffectUnloadLibrary(handle);
-}
-
-status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects)
-{
- Mutex::Autolock _l(mLock);
- return EffectQueryNumberEffects(numEffects);
-}
-
-status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
-{
- Mutex::Autolock _l(mLock);
- return EffectQueryEffect(index, descriptor);
-}
-
-status_t AudioFlinger::getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *descriptor)
-{
- Mutex::Autolock _l(mLock);
- return EffectGetDescriptor(pUuid, descriptor);
-}
-
-
-// this UUID must match the one defined in media/libeffects/EffectVisualizer.cpp
-static const effect_uuid_t VISUALIZATION_UUID_ =
- {0xd069d9e0, 0x8329, 0x11df, 0x9168, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
-
-sp<IEffect> AudioFlinger::createEffect(pid_t pid,
- effect_descriptor_t *pDesc,
- const sp<IEffectClient>& effectClient,
- int32_t priority,
- int output,
- int sessionId,
- status_t *status,
- int *id,
- int *enabled)
-{
- status_t lStatus = NO_ERROR;
- sp<EffectHandle> handle;
- effect_interface_t itfe;
- effect_descriptor_t desc;
- sp<Client> client;
- wp<Client> wclient;
-
- LOGV("createEffect pid %d, client %p, priority %d, sessionId %d, output %d", pid, effectClient.get(), priority, sessionId, output);
-
- if (pDesc == NULL) {
- lStatus = BAD_VALUE;
- goto Exit;
- }
-
- {
- Mutex::Autolock _l(mLock);
-
- // check recording permission for visualizer
- if (memcmp(&pDesc->type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0 ||
- memcmp(&pDesc->uuid, &VISUALIZATION_UUID_, sizeof(effect_uuid_t)) == 0) {
- if (!recordingAllowed()) {
- lStatus = PERMISSION_DENIED;
- goto Exit;
- }
- }
-
- if (!EffectIsNullUuid(&pDesc->uuid)) {
- // if uuid is specified, request effect descriptor
- lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
- if (lStatus < 0) {
- LOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
- goto Exit;
- }
- } else {
- // if uuid is not specified, look for an available implementation
- // of the required type in effect factory
- if (EffectIsNullUuid(&pDesc->type)) {
- LOGW("createEffect() no effect type");
- lStatus = BAD_VALUE;
- goto Exit;
- }
- uint32_t numEffects = 0;
- effect_descriptor_t d;
- bool found = false;
-
- lStatus = EffectQueryNumberEffects(&numEffects);
- if (lStatus < 0) {
- LOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
- goto Exit;
- }
- for (uint32_t i = 0; i < numEffects; i++) {
- lStatus = EffectQueryEffect(i, &desc);
- if (lStatus < 0) {
- LOGW("createEffect() error %d from EffectQueryEffect", lStatus);
- continue;
- }
- if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
- // If matching type found save effect descriptor. If the session is
- // 0 and the effect is not auxiliary, continue enumeration in case
- // an auxiliary version of this effect type is available
- found = true;
- memcpy(&d, &desc, sizeof(effect_descriptor_t));
- if (sessionId != 0 ||
- (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- break;
- }
- }
- }
- if (!found) {
- lStatus = BAD_VALUE;
- LOGW("createEffect() effect not found");
- goto Exit;
- }
- // For same effect type, chose auxiliary version over insert version if
- // connect to output mix (Compliance to OpenSL ES)
- if (sessionId == 0 &&
- (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
- memcpy(&desc, &d, sizeof(effect_descriptor_t));
- }
- }
-
- // Do not allow auxiliary effects on a session different from 0 (output mix)
- if (sessionId != 0 &&
- (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- lStatus = INVALID_OPERATION;
- goto Exit;
- }
-
- // Session -1 is reserved for output stage effects that can only be created
- // by audio policy manager (running in same process)
- if (sessionId == -1 && getpid() != IPCThreadState::self()->getCallingPid()) {
- lStatus = INVALID_OPERATION;
- goto Exit;
- }
-
- // return effect descriptor
- memcpy(pDesc, &desc, sizeof(effect_descriptor_t));
-
- // If output is not specified try to find a matching audio session ID in one of the
- // output threads.
- // TODO: allow attachment of effect to inputs
- if (output == 0) {
- if (sessionId <= 0) {
- // default to first output
- // TODO: define criteria to choose output when not specified. Or
- // receive output from audio policy manager
- if (mPlaybackThreads.size() != 0) {
- output = mPlaybackThreads.keyAt(0);
- }
- } else {
- // look for the thread where the specified audio session is present
- for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId)) {
- output = mPlaybackThreads.keyAt(i);
- break;
- }
- }
- }
- }
- PlaybackThread *thread = checkPlaybackThread_l(output);
- if (thread == NULL) {
- LOGE("unknown output thread");
- lStatus = BAD_VALUE;
- goto Exit;
- }
-
- wclient = mClients.valueFor(pid);
-
- if (wclient != NULL) {
- client = wclient.promote();
- } else {
- client = new Client(this, pid);
- mClients.add(pid, client);
- }
-
- // create effect on selected output trhead
- handle = thread->createEffect_l(client, effectClient, priority, sessionId, &desc, enabled, &lStatus);
- if (handle != 0 && id != NULL) {
- *id = handle->id();
- }
- }
-
-Exit:
- if(status) {
- *status = lStatus;
- }
- return handle;
-}
-
-status_t AudioFlinger::registerEffectResource_l(effect_descriptor_t *desc) {
- if (mTotalEffectsCpuLoad + desc->cpuLoad > MAX_EFFECTS_CPU_LOAD) {
- LOGW("registerEffectResource() CPU Load limit exceeded for Fx %s, CPU %f MIPS",
- desc->name, (float)desc->cpuLoad/10);
- return INVALID_OPERATION;
- }
- if (mTotalEffectsMemory + desc->memoryUsage > MAX_EFFECTS_MEMORY) {
- LOGW("registerEffectResource() memory limit exceeded for Fx %s, Memory %d KB",
- desc->name, desc->memoryUsage);
- return INVALID_OPERATION;
- }
- mTotalEffectsCpuLoad += desc->cpuLoad;
- mTotalEffectsMemory += desc->memoryUsage;
- LOGV("registerEffectResource_l() effect %s, CPU %d, memory %d",
- desc->name, desc->cpuLoad, desc->memoryUsage);
- LOGV(" total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
- return NO_ERROR;
-}
-
-void AudioFlinger::unregisterEffectResource_l(effect_descriptor_t *desc) {
- mTotalEffectsCpuLoad -= desc->cpuLoad;
- mTotalEffectsMemory -= desc->memoryUsage;
- LOGV("unregisterEffectResource_l() effect %s, CPU %d, memory %d",
- desc->name, desc->cpuLoad, desc->memoryUsage);
- LOGV(" total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
-}
-
-// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(
- const sp<AudioFlinger::Client>& client,
- const sp<IEffectClient>& effectClient,
- int32_t priority,
- int sessionId,
- effect_descriptor_t *desc,
- int *enabled,
- status_t *status
- )
-{
- sp<EffectModule> effect;
- sp<EffectHandle> handle;
- status_t lStatus;
- sp<Track> track;
- sp<EffectChain> chain;
- bool effectCreated = false;
- bool effectRegistered = false;
-
- if (mOutput == 0) {
- LOGW("createEffect_l() Audio driver not initialized.");
- lStatus = NO_INIT;
- goto Exit;
- }
-
- // Do not allow auxiliary effect on session other than 0
- if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY &&
- sessionId != 0) {
- LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d", desc->name, sessionId);
- lStatus = BAD_VALUE;
- goto Exit;
- }
-
- // Do not allow effects with session ID 0 on direct output or duplicating threads
- // TODO: add rule for hw accelerated effects on direct outputs with non PCM format
- if (sessionId == 0 && mType != MIXER) {
- LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d", desc->name, sessionId);
- lStatus = BAD_VALUE;
- goto Exit;
- }
-
- LOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
-
- { // scope for mLock
- Mutex::Autolock _l(mLock);
-
- // check for existing effect chain with the requested audio session
- chain = getEffectChain_l(sessionId);
- if (chain == 0) {
- // create a new chain for this session
- LOGV("createEffect_l() new effect chain for session %d", sessionId);
- chain = new EffectChain(this, sessionId);
- addEffectChain_l(chain);
- } else {
- effect = chain->getEffectFromDesc(desc);
- }
-
- LOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get());
-
- if (effect == 0) {
- // Check CPU and memory usage
- lStatus = mAudioFlinger->registerEffectResource_l(desc);
- if (lStatus != NO_ERROR) {
- goto Exit;
- }
- effectRegistered = true;
- // create a new effect module if none present in the chain
- effect = new EffectModule(this, chain, desc, mAudioFlinger->nextUniqueId(), sessionId);
- lStatus = effect->status();
- if (lStatus != NO_ERROR) {
- goto Exit;
- }
- lStatus = chain->addEffect(effect);
- if (lStatus != NO_ERROR) {
- goto Exit;
- }
- effectCreated = true;
-
- effect->setDevice(mDevice);
- effect->setMode(mAudioFlinger->getMode());
- }
- // create effect handle and connect it to effect module
- handle = new EffectHandle(effect, client, effectClient, priority);
- lStatus = effect->addHandle(handle);
- if (enabled) {
- *enabled = (int)effect->isEnabled();
- }
- }
-
-Exit:
- if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
- if (effectCreated) {
- if (chain->removeEffect(effect) == 0) {
- removeEffectChain_l(chain);
- }
- }
- if (effectRegistered) {
- mAudioFlinger->unregisterEffectResource_l(desc);
- }
- handle.clear();
- }
-
- if(status) {
- *status = lStatus;
- }
- return handle;
-}
-
-void AudioFlinger::PlaybackThread::disconnectEffect(const sp< EffectModule>& effect,
- const wp<EffectHandle>& handle) {
- effect_descriptor_t desc = effect->desc();
- Mutex::Autolock _l(mLock);
- // delete the effect module if removing last handle on it
- if (effect->removeHandle(handle) == 0) {
- if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- detachAuxEffect_l(effect->id());
- }
- sp<EffectChain> chain = effect->chain().promote();
- if (chain != 0) {
- // remove effect chain if remove last effect
- if (chain->removeEffect(effect) == 0) {
- removeEffectChain_l(chain);
- }
- }
- mLock.unlock();
- mAudioFlinger->mLock.lock();
- mAudioFlinger->unregisterEffectResource_l(&desc);
- mAudioFlinger->mLock.unlock();
- }
-}
-
-status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
-{
- int session = chain->sessionId();
- int16_t *buffer = mMixBuffer;
- bool ownsBuffer = false;
-
- LOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
- if (session > 0) {
- // Only one effect chain can be present in direct output thread and it uses
- // the mix buffer as input
- if (mType != DIRECT) {
- size_t numSamples = mFrameCount * mChannelCount;
- buffer = new int16_t[numSamples];
- memset(buffer, 0, numSamples * sizeof(int16_t));
- LOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);
- ownsBuffer = true;
- }
-
- // Attach all tracks with same session ID to this chain.
- for (size_t i = 0; i < mTracks.size(); ++i) {
- sp<Track> track = mTracks[i];
- if (session == track->sessionId()) {
- LOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);
- track->setMainBuffer(buffer);
- }
- }
-
- // indicate all active tracks in the chain
- for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
- sp<Track> track = mActiveTracks[i].promote();
- if (track == 0) continue;
- if (session == track->sessionId()) {
- LOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
- chain->startTrack();
- }
- }
- }
-
- chain->setInBuffer(buffer, ownsBuffer);
- chain->setOutBuffer(mMixBuffer);
- // Effect chain for session -1 is inserted at end of effect chains list
- // in order to be processed last as it contains output stage effects
- // Effect chain for session 0 is inserted before session -1 to be processed
- // after track specific effects and before output stage
- // Effect chain for session other than 0 is inserted at beginning of effect
- // chains list to be processed before output mix effects. Relative order between
- // sessions other than 0 is not important
- size_t size = mEffectChains.size();
- size_t i = 0;
- for (i = 0; i < size; i++) {
- if (mEffectChains[i]->sessionId() < session) break;
- }
- mEffectChains.insertAt(chain, i);
-
- return NO_ERROR;
-}
-
-size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
-{
- int session = chain->sessionId();
-
- LOGV("removeEffectChain_l() %p from thread %p for session %d", chain.get(), this, session);
-
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- if (chain == mEffectChains[i]) {
- mEffectChains.removeAt(i);
- // detach all tracks with same session ID from this chain
- for (size_t i = 0; i < mTracks.size(); ++i) {
- sp<Track> track = mTracks[i];
- if (session == track->sessionId()) {
- track->setMainBuffer(mMixBuffer);
- }
- }
- }
- }
- return mEffectChains.size();
-}
-
-void AudioFlinger::PlaybackThread::lockEffectChains_l()
-{
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->lock();
- }
-}
-
-void AudioFlinger::PlaybackThread::unlockEffectChains()
-{
- Mutex::Autolock _l(mLock);
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->unlock();
- }
-}
-
-sp<AudioFlinger::EffectModule> AudioFlinger::PlaybackThread::getEffect_l(int sessionId, int effectId)
-{
- sp<EffectModule> effect;
-
- sp<EffectChain> chain = getEffectChain_l(sessionId);
- if (chain != 0) {
- effect = chain->getEffectFromId(effectId);
- }
- return effect;
-}
-
-status_t AudioFlinger::PlaybackThread::attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
-{
- Mutex::Autolock _l(mLock);
- return attachAuxEffect_l(track, EffectId);
-}
-
-status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
-{
- status_t status = NO_ERROR;
-
- if (EffectId == 0) {
- track->setAuxBuffer(0, NULL);
- } else {
- // Auxiliary effects are always in audio session 0
- sp<EffectModule> effect = getEffect_l(0, EffectId);
- if (effect != 0) {
- if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
- } else {
- status = INVALID_OPERATION;
- }
- } else {
- status = BAD_VALUE;
- }
- }
- return status;
-}
-
-void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
-{
- for (size_t i = 0; i < mTracks.size(); ++i) {
- sp<Track> track = mTracks[i];
- if (track->auxEffectId() == effectId) {
- attachAuxEffect_l(track, 0);
- }
- }
-}
-
-// ----------------------------------------------------------------------------
-// EffectModule implementation
-// ----------------------------------------------------------------------------
-
-#undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectModule"
-
-AudioFlinger::EffectModule::EffectModule(const wp<ThreadBase>& wThread,
- const wp<AudioFlinger::EffectChain>& chain,
- effect_descriptor_t *desc,
- int id,
- int sessionId)
- : mThread(wThread), mChain(chain), mId(id), mSessionId(sessionId), mEffectInterface(NULL),
- mStatus(NO_INIT), mState(IDLE)
-{
- LOGV("Constructor %p", this);
- int lStatus;
- sp<ThreadBase> thread = mThread.promote();
- if (thread == 0) {
- return;
- }
- PlaybackThread *p = (PlaybackThread *)thread.get();
-
- memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
-
- // create effect engine from effect factory
- mStatus = EffectCreate(&desc->uuid, sessionId, p->id(), &mEffectInterface);
-
- if (mStatus != NO_ERROR) {
- return;
- }
- lStatus = init();
- if (lStatus < 0) {
- mStatus = lStatus;
- goto Error;
- }
-
- LOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
- return;
-Error:
- EffectRelease(mEffectInterface);
- mEffectInterface = NULL;
- LOGV("Constructor Error %d", mStatus);
-}
-
-AudioFlinger::EffectModule::~EffectModule()
-{
- LOGV("Destructor %p", this);
- if (mEffectInterface != NULL) {
- // release effect engine
- EffectRelease(mEffectInterface);
- }
-}
-
-status_t AudioFlinger::EffectModule::addHandle(sp<EffectHandle>& handle)
-{
- status_t status;
-
- Mutex::Autolock _l(mLock);
- // First handle in mHandles has highest priority and controls the effect module
- int priority = handle->priority();
- size_t size = mHandles.size();
- sp<EffectHandle> h;
- size_t i;
- for (i = 0; i < size; i++) {
- h = mHandles[i].promote();
- if (h == 0) continue;
- if (h->priority() <= priority) break;
- }
- // if inserted in first place, move effect control from previous owner to this handle
- if (i == 0) {
- if (h != 0) {
- h->setControl(false, true);
- }
- handle->setControl(true, false);
- status = NO_ERROR;
- } else {
- status = ALREADY_EXISTS;
- }
- mHandles.insertAt(handle, i);
- return status;
-}
-
-size_t AudioFlinger::EffectModule::removeHandle(const wp<EffectHandle>& handle)
-{
- Mutex::Autolock _l(mLock);
- size_t size = mHandles.size();
- size_t i;
- for (i = 0; i < size; i++) {
- if (mHandles[i] == handle) break;
- }
- if (i == size) {
- return size;
- }
- mHandles.removeAt(i);
- size = mHandles.size();
- // if removed from first place, move effect control from this handle to next in line
- if (i == 0 && size != 0) {
- sp<EffectHandle> h = mHandles[0].promote();
- if (h != 0) {
- h->setControl(true, true);
- }
- }
-
- return size;
-}
-
-void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle)
-{
- // keep a strong reference on this EffectModule to avoid calling the
- // destructor before we exit
- sp<EffectModule> keep(this);
- {
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
- playbackThread->disconnectEffect(keep, handle);
- }
- }
-}
-
-void AudioFlinger::EffectModule::updateState() {
- Mutex::Autolock _l(mLock);
-
- switch (mState) {
- case RESTART:
- reset_l();
- // FALL THROUGH
-
- case STARTING:
- // clear auxiliary effect input buffer for next accumulation
- if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- memset(mConfig.inputCfg.buffer.raw,
- 0,
- mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
- }
- start_l();
- mState = ACTIVE;
- break;
- case STOPPING:
- stop_l();
- mDisableWaitCnt = mMaxDisableWaitCnt;
- mState = STOPPED;
- break;
- case STOPPED:
- // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
- // turn off sequence.
- if (--mDisableWaitCnt == 0) {
- reset_l();
- mState = IDLE;
- }
- break;
- default: //IDLE , ACTIVE
- break;
- }
-}
-
-void AudioFlinger::EffectModule::process()
-{
- Mutex::Autolock _l(mLock);
-
- if (mEffectInterface == NULL ||
- mConfig.inputCfg.buffer.raw == NULL ||
- mConfig.outputCfg.buffer.raw == NULL) {
- return;
- }
-
- if (mState == ACTIVE || mState == STOPPING || mState == STOPPED) {
- // do 32 bit to 16 bit conversion for auxiliary effect input buffer
- if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- AudioMixer::ditherAndClamp(mConfig.inputCfg.buffer.s32,
- mConfig.inputCfg.buffer.s32,
- mConfig.inputCfg.buffer.frameCount);
- }
-
- // do the actual processing in the effect engine
- int ret = (*mEffectInterface)->process(mEffectInterface,
- &mConfig.inputCfg.buffer,
- &mConfig.outputCfg.buffer);
-
- // force transition to IDLE state when engine is ready
- if (mState == STOPPED && ret == -ENODATA) {
- mDisableWaitCnt = 1;
- }
-
- // clear auxiliary effect input buffer for next accumulation
- if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- memset(mConfig.inputCfg.buffer.raw, 0, mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
- }
- } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
- mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw){
- // If an insert effect is idle and input buffer is different from output buffer, copy input to
- // output
- sp<EffectChain> chain = mChain.promote();
- if (chain != 0 && chain->activeTracks() != 0) {
- size_t size = mConfig.inputCfg.buffer.frameCount * sizeof(int16_t);
- if (mConfig.inputCfg.channels == CHANNEL_STEREO) {
- size *= 2;
- }
- memcpy(mConfig.outputCfg.buffer.raw, mConfig.inputCfg.buffer.raw, size);
- }
- }
-}
-
-void AudioFlinger::EffectModule::reset_l()
-{
- if (mEffectInterface == NULL) {
- return;
- }
- (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
-}
-
-status_t AudioFlinger::EffectModule::configure()
-{
- uint32_t channels;
- if (mEffectInterface == NULL) {
- return NO_INIT;
- }
-
- sp<ThreadBase> thread = mThread.promote();
- if (thread == 0) {
- return DEAD_OBJECT;
- }
-
- // TODO: handle configuration of effects replacing track process
- if (thread->channelCount() == 1) {
- channels = CHANNEL_MONO;
- } else {
- channels = CHANNEL_STEREO;
- }
-
- if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- mConfig.inputCfg.channels = CHANNEL_MONO;
- } else {
- mConfig.inputCfg.channels = channels;
- }
- mConfig.outputCfg.channels = channels;
- mConfig.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
- mConfig.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
- mConfig.inputCfg.samplingRate = thread->sampleRate();
- mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
- mConfig.inputCfg.bufferProvider.cookie = NULL;
- mConfig.inputCfg.bufferProvider.getBuffer = NULL;
- mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
- mConfig.outputCfg.bufferProvider.cookie = NULL;
- mConfig.outputCfg.bufferProvider.getBuffer = NULL;
- mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
- mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
- // Insert effect:
- // - in session 0 or -1, always overwrites output buffer: input buffer == output buffer
- // - in other sessions:
- // last effect in the chain accumulates in output buffer: input buffer != output buffer
- // other effect: overwrites output buffer: input buffer == output buffer
- // Auxiliary effect:
- // accumulates in output buffer: input buffer != output buffer
- // Therefore: accumulate <=> input buffer != output buffer
- if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
- mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
- } else {
- mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
- }
- mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
- mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
- mConfig.inputCfg.buffer.frameCount = thread->frameCount();
- mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
-
- status_t cmdStatus;
- int size = sizeof(int);
- status_t status = (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_CONFIGURE, sizeof(effect_config_t), &mConfig, &size, &cmdStatus);
- if (status == 0) {
- status = cmdStatus;
- }
-
- mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
- (1000 * mConfig.outputCfg.buffer.frameCount);
-
- return status;
-}
-
-status_t AudioFlinger::EffectModule::init()
-{
- Mutex::Autolock _l(mLock);
- if (mEffectInterface == NULL) {
- return NO_INIT;
- }
- status_t cmdStatus;
- int size = sizeof(status_t);
- status_t status = (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_INIT, 0, NULL, &size, &cmdStatus);
- if (status == 0) {
- status = cmdStatus;
- }
- return status;
-}
-
-status_t AudioFlinger::EffectModule::start_l()
-{
- if (mEffectInterface == NULL) {
- return NO_INIT;
- }
- status_t cmdStatus;
- int size = sizeof(status_t);
- status_t status = (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_ENABLE, 0, NULL, &size, &cmdStatus);
- if (status == 0) {
- status = cmdStatus;
- }
- return status;
-}
-
-status_t AudioFlinger::EffectModule::stop_l()
-{
- if (mEffectInterface == NULL) {
- return NO_INIT;
- }
- status_t cmdStatus;
- int size = sizeof(status_t);
- status_t status = (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_DISABLE, 0, NULL, &size, &cmdStatus);
- if (status == 0) {
- status = cmdStatus;
- }
- return status;
-}
-
-status_t AudioFlinger::EffectModule::command(int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData)
-{
- Mutex::Autolock _l(mLock);
-// LOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
-
- if (mEffectInterface == NULL) {
- return NO_INIT;
- }
- status_t status = (*mEffectInterface)->command(mEffectInterface, cmdCode, cmdSize, pCmdData, replySize, pReplyData);
- if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
- int size = (replySize == NULL) ? 0 : *replySize;
- for (size_t i = 1; i < mHandles.size(); i++) {
- sp<EffectHandle> h = mHandles[i].promote();
- if (h != 0) {
- h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
- }
- }
- }
- return status;
-}
-
-status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
-{
- Mutex::Autolock _l(mLock);
- LOGV("setEnabled %p enabled %d", this, enabled);
-
- if (enabled != isEnabled()) {
- switch (mState) {
- // going from disabled to enabled
- case IDLE:
- mState = STARTING;
- break;
- case STOPPED:
- mState = RESTART;
- break;
- case STOPPING:
- mState = ACTIVE;
- break;
-
- // going from enabled to disabled
- case RESTART:
- case STARTING:
- mState = IDLE;
- break;
- case ACTIVE:
- mState = STOPPING;
- break;
- }
- for (size_t i = 1; i < mHandles.size(); i++) {
- sp<EffectHandle> h = mHandles[i].promote();
- if (h != 0) {
- h->setEnabled(enabled);
- }
- }
- }
- return NO_ERROR;
-}
-
-bool AudioFlinger::EffectModule::isEnabled()
-{
- switch (mState) {
- case RESTART:
- case STARTING:
- case ACTIVE:
- return true;
- case IDLE:
- case STOPPING:
- case STOPPED:
- default:
- return false;
- }
-}
-
-status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
-{
- Mutex::Autolock _l(mLock);
- status_t status = NO_ERROR;
-
- // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
- // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
- if ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) & (EFFECT_FLAG_VOLUME_CTRL|EFFECT_FLAG_VOLUME_IND)) {
- status_t cmdStatus;
- uint32_t volume[2];
- uint32_t *pVolume = NULL;
- int size = sizeof(volume);
- volume[0] = *left;
- volume[1] = *right;
- if (controller) {
- pVolume = volume;
- }
- status = (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_SET_VOLUME, size, volume, &size, pVolume);
- if (controller && status == NO_ERROR && size == sizeof(volume)) {
- *left = volume[0];
- *right = volume[1];
- }
- }
- return status;
-}
-
-status_t AudioFlinger::EffectModule::setDevice(uint32_t device)
-{
- Mutex::Autolock _l(mLock);
- status_t status = NO_ERROR;
- if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
- // convert device bit field from AudioSystem to EffectApi format.
- device = deviceAudioSystemToEffectApi(device);
- if (device == 0) {
- return BAD_VALUE;
- }
- status_t cmdStatus;
- int size = sizeof(status_t);
- status = (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_SET_DEVICE, sizeof(uint32_t), &device, &size, &cmdStatus);
- if (status == NO_ERROR) {
- status = cmdStatus;
- }
- }
- return status;
-}
-
-status_t AudioFlinger::EffectModule::setMode(uint32_t mode)
-{
- Mutex::Autolock _l(mLock);
- status_t status = NO_ERROR;
- if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
- // convert audio mode from AudioSystem to EffectApi format.
- int effectMode = modeAudioSystemToEffectApi(mode);
- if (effectMode < 0) {
- return BAD_VALUE;
- }
- status_t cmdStatus;
- int size = sizeof(status_t);
- status = (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_SET_AUDIO_MODE, sizeof(int), &effectMode, &size, &cmdStatus);
- if (status == NO_ERROR) {
- status = cmdStatus;
- }
- }
- return status;
-}
-
-// update this table when AudioSystem::audio_devices or audio_device_e (in EffectApi.h) are modified
-const uint32_t AudioFlinger::EffectModule::sDeviceConvTable[] = {
- DEVICE_EARPIECE, // AudioSystem::DEVICE_OUT_EARPIECE
- DEVICE_SPEAKER, // AudioSystem::DEVICE_OUT_SPEAKER
- DEVICE_WIRED_HEADSET, // case AudioSystem::DEVICE_OUT_WIRED_HEADSET
- DEVICE_WIRED_HEADPHONE, // AudioSystem::DEVICE_OUT_WIRED_HEADPHONE
- DEVICE_BLUETOOTH_SCO, // AudioSystem::DEVICE_OUT_BLUETOOTH_SCO
- DEVICE_BLUETOOTH_SCO_HEADSET, // AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET
- DEVICE_BLUETOOTH_SCO_CARKIT, // AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT
- DEVICE_BLUETOOTH_A2DP, // AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP
- DEVICE_BLUETOOTH_A2DP_HEADPHONES, // AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES
- DEVICE_BLUETOOTH_A2DP_SPEAKER, // AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER
- DEVICE_AUX_DIGITAL // AudioSystem::DEVICE_OUT_AUX_DIGITAL
-};
-
-uint32_t AudioFlinger::EffectModule::deviceAudioSystemToEffectApi(uint32_t device)
-{
- uint32_t deviceOut = 0;
- while (device) {
- const uint32_t i = 31 - __builtin_clz(device);
- device &= ~(1 << i);
- if (i >= sizeof(sDeviceConvTable)/sizeof(uint32_t)) {
- LOGE("device convertion error for AudioSystem device 0x%08x", device);
- return 0;
- }
- deviceOut |= (uint32_t)sDeviceConvTable[i];
- }
- return deviceOut;
-}
-
-// update this table when AudioSystem::audio_mode or audio_mode_e (in EffectApi.h) are modified
-const uint32_t AudioFlinger::EffectModule::sModeConvTable[] = {
- AUDIO_MODE_NORMAL, // AudioSystem::MODE_NORMAL
- AUDIO_MODE_RINGTONE, // AudioSystem::MODE_RINGTONE
- AUDIO_MODE_IN_CALL // AudioSystem::MODE_IN_CALL
-};
-
-int AudioFlinger::EffectModule::modeAudioSystemToEffectApi(uint32_t mode)
-{
- int modeOut = -1;
- if (mode < sizeof(sModeConvTable) / sizeof(uint32_t)) {
- modeOut = (int)sModeConvTable[mode];
- }
- return modeOut;
-}
-
-status_t AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "\tEffect ID %d:\n", mId);
- result.append(buffer);
-
- bool locked = tryLock(mLock);
- // failed to lock - AudioFlinger is probably deadlocked
- if (!locked) {
- result.append("\t\tCould not lock Fx mutex:\n");
- }
-
- result.append("\t\tSession Status State Engine:\n");
- snprintf(buffer, SIZE, "\t\t%05d %03d %03d 0x%08x\n",
- mSessionId, mStatus, mState, (uint32_t)mEffectInterface);
- result.append(buffer);
-
- result.append("\t\tDescriptor:\n");
- snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
- mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
- mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],mDescriptor.uuid.node[2],
- mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
- result.append(buffer);
- snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
- mDescriptor.type.timeLow, mDescriptor.type.timeMid, mDescriptor.type.timeHiAndVersion,
- mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],mDescriptor.type.node[2],
- mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
- result.append(buffer);
- snprintf(buffer, SIZE, "\t\t- apiVersion: %04X\n\t\t- flags: %08X\n",
- mDescriptor.apiVersion,
- mDescriptor.flags);
- result.append(buffer);
- snprintf(buffer, SIZE, "\t\t- name: %s\n",
- mDescriptor.name);
- result.append(buffer);
- snprintf(buffer, SIZE, "\t\t- implementor: %s\n",
- mDescriptor.implementor);
- result.append(buffer);
-
- result.append("\t\t- Input configuration:\n");
- result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
- snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
- (uint32_t)mConfig.inputCfg.buffer.raw,
- mConfig.inputCfg.buffer.frameCount,
- mConfig.inputCfg.samplingRate,
- mConfig.inputCfg.channels,
- mConfig.inputCfg.format);
- result.append(buffer);
-
- result.append("\t\t- Output configuration:\n");
- result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
- snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
- (uint32_t)mConfig.outputCfg.buffer.raw,
- mConfig.outputCfg.buffer.frameCount,
- mConfig.outputCfg.samplingRate,
- mConfig.outputCfg.channels,
- mConfig.outputCfg.format);
- result.append(buffer);
-
- snprintf(buffer, SIZE, "\t\t%d Clients:\n", mHandles.size());
- result.append(buffer);
- result.append("\t\t\tPid Priority Ctrl Locked client server\n");
- for (size_t i = 0; i < mHandles.size(); ++i) {
- sp<EffectHandle> handle = mHandles[i].promote();
- if (handle != 0) {
- handle->dump(buffer, SIZE);
- result.append(buffer);
- }
- }
-
- result.append("\n");
-
- write(fd, result.string(), result.length());
-
- if (locked) {
- mLock.unlock();
- }
-
- return NO_ERROR;
-}
-
-// ----------------------------------------------------------------------------
-// EffectHandle implementation
-// ----------------------------------------------------------------------------
-
-#undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectHandle"
-
-AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
- const sp<AudioFlinger::Client>& client,
- const sp<IEffectClient>& effectClient,
- int32_t priority)
- : BnEffect(),
- mEffect(effect), mEffectClient(effectClient), mClient(client), mPriority(priority), mHasControl(false)
-{
- LOGV("constructor %p", this);
-
- int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
- mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
- if (mCblkMemory != 0) {
- mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer());
-
- if (mCblk) {
- new(mCblk) effect_param_cblk_t();
- mBuffer = (uint8_t *)mCblk + bufOffset;
- }
- } else {
- LOGE("not enough memory for Effect size=%u", EFFECT_PARAM_BUFFER_SIZE + sizeof(effect_param_cblk_t));
- return;
- }
-}
-
-AudioFlinger::EffectHandle::~EffectHandle()
-{
- LOGV("Destructor %p", this);
- disconnect();
-}
-
-status_t AudioFlinger::EffectHandle::enable()
-{
- if (!mHasControl) return INVALID_OPERATION;
- if (mEffect == 0) return DEAD_OBJECT;
-
- return mEffect->setEnabled(true);
-}
-
-status_t AudioFlinger::EffectHandle::disable()
-{
- if (!mHasControl) return INVALID_OPERATION;
- if (mEffect == NULL) return DEAD_OBJECT;
-
- return mEffect->setEnabled(false);
-}
-
-void AudioFlinger::EffectHandle::disconnect()
-{
- if (mEffect == 0) {
- return;
- }
- mEffect->disconnect(this);
- // release sp on module => module destructor can be called now
- mEffect.clear();
- if (mCblk) {
- mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
- }
- mCblkMemory.clear(); // and free the shared memory
- if (mClient != 0) {
- Mutex::Autolock _l(mClient->audioFlinger()->mLock);
- mClient.clear();
- }
-}
-
-status_t AudioFlinger::EffectHandle::command(int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData)
-{
-// LOGV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p", cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
-
- // only get parameter command is permitted for applications not controlling the effect
- if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
- return INVALID_OPERATION;
- }
- if (mEffect == 0) return DEAD_OBJECT;
-
- // handle commands that are not forwarded transparently to effect engine
- if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
- // No need to trylock() here as this function is executed in the binder thread serving a particular client process:
- // no risk to block the whole media server process or mixer threads is we are stuck here
- Mutex::Autolock _l(mCblk->lock);
- if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
- mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
- mCblk->serverIndex = 0;
- mCblk->clientIndex = 0;
- return BAD_VALUE;
- }
- status_t status = NO_ERROR;
- while (mCblk->serverIndex < mCblk->clientIndex) {
- int reply;
- int rsize = sizeof(int);
- int *p = (int *)(mBuffer + mCblk->serverIndex);
- int size = *p++;
- if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
- LOGW("command(): invalid parameter block size");
- break;
- }
- effect_param_t *param = (effect_param_t *)p;
- if (param->psize == 0 || param->vsize == 0) {
- LOGW("command(): null parameter or value size");
- mCblk->serverIndex += size;
- continue;
- }
- int psize = sizeof(effect_param_t) + ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
- status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM, psize, p, &rsize, &reply);
- if (ret == NO_ERROR) {
- if (reply != NO_ERROR) {
- status = reply;
- }
- } else {
- status = ret;
- }
- mCblk->serverIndex += size;
- }
- mCblk->serverIndex = 0;
- mCblk->clientIndex = 0;
- return status;
- } else if (cmdCode == EFFECT_CMD_ENABLE) {
- return enable();
- } else if (cmdCode == EFFECT_CMD_DISABLE) {
- return disable();
- }
-
- return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
-}
-
-sp<IMemory> AudioFlinger::EffectHandle::getCblk() const {
- return mCblkMemory;
-}
-
-void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal)
-{
- LOGV("setControl %p control %d", this, hasControl);
-
- mHasControl = hasControl;
- if (signal && mEffectClient != 0) {
- mEffectClient->controlStatusChanged(hasControl);
- }
-}
-
-void AudioFlinger::EffectHandle::commandExecuted(int cmdCode, int cmdSize, void *pCmdData, int replySize, void *pReplyData)
-{
- if (mEffectClient != 0) {
- mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
- }
-}
-
-
-
-void AudioFlinger::EffectHandle::setEnabled(bool enabled)
-{
- if (mEffectClient != 0) {
- mEffectClient->enableStatusChanged(enabled);
- }
-}
-
-status_t AudioFlinger::EffectHandle::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- return BnEffect::onTransact(code, data, reply, flags);
-}
-
-
-void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
-{
- bool locked = tryLock(mCblk->lock);
-
- snprintf(buffer, size, "\t\t\t%05d %05d %01u %01u %05u %05u\n",
- (mClient == NULL) ? getpid() : mClient->pid(),
- mPriority,
- mHasControl,
- !locked,
- mCblk->clientIndex,
- mCblk->serverIndex
- );
-
- if (locked) {
- mCblk->lock.unlock();
- }
-}
-
-#undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectChain"
-
-AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& wThread,
- int sessionId)
- : mThread(wThread), mSessionId(sessionId), mVolumeCtrlIdx(-1), mActiveTrackCnt(0), mOwnInBuffer(false)
-{
-
-}
-
-AudioFlinger::EffectChain::~EffectChain()
-{
- if (mOwnInBuffer) {
- delete mInBuffer;
- }
-
-}
-
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc(effect_descriptor_t *descriptor)
-{
- sp<EffectModule> effect;
- size_t size = mEffects.size();
-
- for (size_t i = 0; i < size; i++) {
- if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
- effect = mEffects[i];
- break;
- }
- }
- return effect;
-}
-
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId(int id)
-{
- sp<EffectModule> effect;
- size_t size = mEffects.size();
-
- for (size_t i = 0; i < size; i++) {
- if (mEffects[i]->id() == id) {
- effect = mEffects[i];
- break;
- }
- }
- return effect;
-}
-
-// Must be called with EffectChain::mLock locked
-void AudioFlinger::EffectChain::process_l()
-{
- size_t size = mEffects.size();
- for (size_t i = 0; i < size; i++) {
- mEffects[i]->process();
- }
- for (size_t i = 0; i < size; i++) {
- mEffects[i]->updateState();
- }
- // if no track is active, input buffer must be cleared here as the mixer process
- // will not do it
- if (mSessionId > 0 && activeTracks() == 0) {
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- size_t numSamples = thread->frameCount() * thread->channelCount();
- memset(mInBuffer, 0, numSamples * sizeof(int16_t));
- }
- }
-}
-
-status_t AudioFlinger::EffectChain::addEffect(sp<EffectModule>& effect)
-{
- effect_descriptor_t desc = effect->desc();
- uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
-
- Mutex::Autolock _l(mLock);
-
- if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- // Auxiliary effects are inserted at the beginning of mEffects vector as
- // they are processed first and accumulated in chain input buffer
- mEffects.insertAt(effect, 0);
- sp<ThreadBase> thread = mThread.promote();
- if (thread == 0) {
- return NO_INIT;
- }
- // the input buffer for auxiliary effect contains mono samples in
- // 32 bit format. This is to avoid saturation in AudoMixer
- // accumulation stage. Saturation is done in EffectModule::process() before
- // calling the process in effect engine
- size_t numSamples = thread->frameCount();
- int32_t *buffer = new int32_t[numSamples];
- memset(buffer, 0, numSamples * sizeof(int32_t));
- effect->setInBuffer((int16_t *)buffer);
- // auxiliary effects output samples to chain input buffer for further processing
- // by insert effects
- effect->setOutBuffer(mInBuffer);
- } else {
- // Insert effects are inserted at the end of mEffects vector as they are processed
- // after track and auxiliary effects.
- // Insert effect order as a function of indicated preference:
- // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
- // another effect is present
- // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
- // last effect claiming first position
- // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
- // first effect claiming last position
- // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
- // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
- // already present
-
- int size = (int)mEffects.size();
- int idx_insert = size;
- int idx_insert_first = -1;
- int idx_insert_last = -1;
-
- for (int i = 0; i < size; i++) {
- effect_descriptor_t d = mEffects[i]->desc();
- uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
- uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
- if (iMode == EFFECT_FLAG_TYPE_INSERT) {
- // check invalid effect chaining combinations
- if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
- iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
- LOGW("addEffect() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
- return INVALID_OPERATION;
- }
- // remember position of first insert effect and by default
- // select this as insert position for new effect
- if (idx_insert == size) {
- idx_insert = i;
- }
- // remember position of last insert effect claiming
- // first position
- if (iPref == EFFECT_FLAG_INSERT_FIRST) {
- idx_insert_first = i;
- }
- // remember position of first insert effect claiming
- // last position
- if (iPref == EFFECT_FLAG_INSERT_LAST &&
- idx_insert_last == -1) {
- idx_insert_last = i;
- }
- }
- }
-
- // modify idx_insert from first position if needed
- if (insertPref == EFFECT_FLAG_INSERT_LAST) {
- if (idx_insert_last != -1) {
- idx_insert = idx_insert_last;
- } else {
- idx_insert = size;
- }
- } else {
- if (idx_insert_first != -1) {
- idx_insert = idx_insert_first + 1;
- }
- }
-
- // always read samples from chain input buffer
- effect->setInBuffer(mInBuffer);
-
- // if last effect in the chain, output samples to chain
- // output buffer, otherwise to chain input buffer
- if (idx_insert == size) {
- if (idx_insert != 0) {
- mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
- mEffects[idx_insert-1]->configure();
- }
- effect->setOutBuffer(mOutBuffer);
- } else {
- effect->setOutBuffer(mInBuffer);
- }
- mEffects.insertAt(effect, idx_insert);
- // Always give volume control to last effect in chain with volume control capability
- if (((desc.flags & EFFECT_FLAG_VOLUME_MASK) & EFFECT_FLAG_VOLUME_CTRL) &&
- mVolumeCtrlIdx < idx_insert) {
- mVolumeCtrlIdx = idx_insert;
- }
-
- LOGV("addEffect() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
- }
- effect->configure();
- return NO_ERROR;
-}
-
-size_t AudioFlinger::EffectChain::removeEffect(const sp<EffectModule>& effect)
-{
- Mutex::Autolock _l(mLock);
-
- int size = (int)mEffects.size();
- int i;
- uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
-
- for (i = 0; i < size; i++) {
- if (effect == mEffects[i]) {
- if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
- delete[] effect->inBuffer();
- } else {
- if (i == size - 1 && i != 0) {
- mEffects[i - 1]->setOutBuffer(mOutBuffer);
- mEffects[i - 1]->configure();
- }
- }
- mEffects.removeAt(i);
- LOGV("removeEffect() effect %p, removed from chain %p at rank %d", effect.get(), this, i);
- break;
- }
- }
- // Return volume control to last effect in chain with volume control capability
- if (mVolumeCtrlIdx == i) {
- size = (int)mEffects.size();
- for (i = size; i > 0; i--) {
- if ((mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) & EFFECT_FLAG_VOLUME_CTRL) {
- break;
- }
- }
- // mVolumeCtrlIdx reset to -1 if no effect found with volume control flag set
- mVolumeCtrlIdx = i - 1;
- }
-
- return mEffects.size();
-}
-
-void AudioFlinger::EffectChain::setDevice(uint32_t device)
-{
- size_t size = mEffects.size();
- for (size_t i = 0; i < size; i++) {
- mEffects[i]->setDevice(device);
- }
-}
-
-void AudioFlinger::EffectChain::setMode(uint32_t mode)
-{
- size_t size = mEffects.size();
- for (size_t i = 0; i < size; i++) {
- mEffects[i]->setMode(mode);
- }
-}
-
-bool AudioFlinger::EffectChain::setVolume(uint32_t *left, uint32_t *right)
-{
- uint32_t newLeft = *left;
- uint32_t newRight = *right;
- bool hasControl = false;
-
- // first get volume update from volume controller
- if (mVolumeCtrlIdx >= 0) {
- mEffects[mVolumeCtrlIdx]->setVolume(&newLeft, &newRight, true);
- hasControl = true;
- }
- // then indicate volume to all other effects in chain.
- // Pass altered volume to effects before volume controller
- // and requested volume to effects after controller
- uint32_t lVol = newLeft;
- uint32_t rVol = newRight;
- size_t size = mEffects.size();
- for (size_t i = 0; i < size; i++) {
- if ((int)i == mVolumeCtrlIdx) continue;
- // this also works for mVolumeCtrlIdx == -1 when there is no volume controller
- if ((int)i > mVolumeCtrlIdx) {
- lVol = *left;
- rVol = *right;
- }
- mEffects[i]->setVolume(&lVol, &rVol, false);
- }
- *left = newLeft;
- *right = newRight;
-
- return hasControl;
-}
-
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getVolumeController()
-{
- sp<EffectModule> effect;
- if (mVolumeCtrlIdx >= 0) {
- effect = mEffects[mVolumeCtrlIdx];
- }
- return effect;
-}
-
-
-status_t AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "Effects for session %d:\n", mSessionId);
- result.append(buffer);
-
- bool locked = tryLock(mLock);
- // failed to lock - AudioFlinger is probably deadlocked
- if (!locked) {
- result.append("\tCould not lock mutex:\n");
- }
-
- result.append("\tNum fx In buffer Out buffer Vol ctrl Active tracks:\n");
- snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %02d %d\n",
- mEffects.size(),
- (uint32_t)mInBuffer,
- (uint32_t)mOutBuffer,
- (mVolumeCtrlIdx == -1) ? 0 : mEffects[mVolumeCtrlIdx]->id(),
- mActiveTrackCnt);
- result.append(buffer);
- write(fd, result.string(), result.size());
-
- for (size_t i = 0; i < mEffects.size(); ++i) {
- sp<EffectModule> effect = mEffects[i];
- if (effect != 0) {
- effect->dump(fd, args);
- }
- }
-
- if (locked) {
- mLock.unlock();
- }
-
- return NO_ERROR;
-}
-
-#undef LOG_TAG
-#define LOG_TAG "AudioFlinger"
-
-// ----------------------------------------------------------------------------
-
-status_t AudioFlinger::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- return BnAudioFlinger::onTransact(code, data, reply, flags);
-}
-
-// ----------------------------------------------------------------------------
-
-void AudioFlinger::instantiate() {
- defaultServiceManager()->addService(
- String16("media.audio_flinger"), new AudioFlinger());
-}
-
-}; // namespace android
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
deleted file mode 100644
index 507c9ac..0000000
--- a/libs/audioflinger/AudioFlinger.h
+++ /dev/null
@@ -1,1148 +0,0 @@
-/* //device/include/server/AudioFlinger/AudioFlinger.h
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_AUDIO_FLINGER_H
-#define ANDROID_AUDIO_FLINGER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <limits.h>
-
-#include <media/IAudioFlinger.h>
-#include <media/IAudioFlingerClient.h>
-#include <media/IAudioTrack.h>
-#include <media/IAudioRecord.h>
-#include <media/AudioTrack.h>
-
-#include <utils/Atomic.h>
-#include <utils/Errors.h>
-#include <utils/threads.h>
-#include <binder/MemoryDealer.h>
-#include <utils/SortedVector.h>
-#include <utils/Vector.h>
-
-#include <hardware_legacy/AudioHardwareInterface.h>
-
-#include "AudioBufferProvider.h"
-
-namespace android {
-
-class audio_track_cblk_t;
-class effect_param_cblk_t;
-class AudioMixer;
-class AudioBuffer;
-class AudioResampler;
-
-
-// ----------------------------------------------------------------------------
-
-#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
-#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
-
-
-// ----------------------------------------------------------------------------
-
-static const nsecs_t kStandbyTimeInNsecs = seconds(3);
-
-class AudioFlinger : public BnAudioFlinger
-{
-public:
- static void instantiate();
-
- virtual status_t dump(int fd, const Vector<String16>& args);
-
- // IAudioFlinger interface
- virtual sp<IAudioTrack> createTrack(
- pid_t pid,
- int streamType,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- uint32_t flags,
- const sp<IMemory>& sharedBuffer,
- int output,
- int *sessionId,
- status_t *status);
-
- virtual uint32_t sampleRate(int output) const;
- virtual int channelCount(int output) const;
- virtual int format(int output) const;
- virtual size_t frameCount(int output) const;
- virtual uint32_t latency(int output) const;
-
- virtual status_t setMasterVolume(float value);
- virtual status_t setMasterMute(bool muted);
-
- virtual float masterVolume() const;
- virtual bool masterMute() const;
-
- virtual status_t setStreamVolume(int stream, float value, int output);
- virtual status_t setStreamMute(int stream, bool muted);
-
- virtual float streamVolume(int stream, int output) const;
- virtual bool streamMute(int stream) const;
-
- virtual status_t setMode(int mode);
-
- virtual status_t setMicMute(bool state);
- virtual bool getMicMute() const;
-
- virtual bool isStreamActive(int stream) const;
-
- virtual status_t setParameters(int ioHandle, const String8& keyValuePairs);
- virtual String8 getParameters(int ioHandle, const String8& keys);
-
- virtual void registerClient(const sp<IAudioFlingerClient>& client);
-
- virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
- virtual unsigned int getInputFramesLost(int ioHandle);
-
- virtual int openOutput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t *pLatencyMs,
- uint32_t flags);
-
- virtual int openDuplicateOutput(int output1, int output2);
-
- virtual status_t closeOutput(int output);
-
- virtual status_t suspendOutput(int output);
-
- virtual status_t restoreOutput(int output);
-
- virtual int openInput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t acoustics);
-
- virtual status_t closeInput(int input);
-
- virtual status_t setStreamOutput(uint32_t stream, int output);
-
- virtual status_t setVoiceVolume(float volume);
-
- virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output);
-
- virtual int newAudioSessionId();
-
- virtual status_t loadEffectLibrary(const char *libPath, int *handle);
-
- virtual status_t unloadEffectLibrary(int handle);
-
- virtual status_t queryNumberEffects(uint32_t *numEffects);
-
- virtual status_t queryEffect(uint32_t index, effect_descriptor_t *descriptor);
-
- virtual status_t getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *descriptor);
-
- virtual sp<IEffect> createEffect(pid_t pid,
- effect_descriptor_t *pDesc,
- const sp<IEffectClient>& effectClient,
- int32_t priority,
- int output,
- int sessionId,
- status_t *status,
- int *id,
- int *enabled);
-
- status_t registerEffectResource_l(effect_descriptor_t *desc);
- void unregisterEffectResource_l(effect_descriptor_t *desc);
-
- enum hardware_call_state {
- AUDIO_HW_IDLE = 0,
- AUDIO_HW_INIT,
- AUDIO_HW_OUTPUT_OPEN,
- AUDIO_HW_OUTPUT_CLOSE,
- AUDIO_HW_INPUT_OPEN,
- AUDIO_HW_INPUT_CLOSE,
- AUDIO_HW_STANDBY,
- AUDIO_HW_SET_MASTER_VOLUME,
- AUDIO_HW_GET_ROUTING,
- AUDIO_HW_SET_ROUTING,
- AUDIO_HW_GET_MODE,
- AUDIO_HW_SET_MODE,
- AUDIO_HW_GET_MIC_MUTE,
- AUDIO_HW_SET_MIC_MUTE,
- AUDIO_SET_VOICE_VOLUME,
- AUDIO_SET_PARAMETER,
- };
-
- // record interface
- virtual sp<IAudioRecord> openRecord(
- pid_t pid,
- int input,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- uint32_t flags,
- int *sessionId,
- status_t *status);
-
- virtual status_t onTransact(
- uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags);
-
- uint32_t getMode() { return mMode; }
-
-private:
- AudioFlinger();
- virtual ~AudioFlinger();
-
-
- // Internal dump utilites.
- status_t dumpPermissionDenial(int fd, const Vector<String16>& args);
- status_t dumpClients(int fd, const Vector<String16>& args);
- status_t dumpInternals(int fd, const Vector<String16>& args);
-
- // --- Client ---
- class Client : public RefBase {
- public:
- Client(const sp<AudioFlinger>& audioFlinger, pid_t pid);
- virtual ~Client();
- const sp<MemoryDealer>& heap() const;
- pid_t pid() const { return mPid; }
- sp<AudioFlinger> audioFlinger() { return mAudioFlinger; }
-
- private:
- Client(const Client&);
- Client& operator = (const Client&);
- sp<AudioFlinger> mAudioFlinger;
- sp<MemoryDealer> mMemoryDealer;
- pid_t mPid;
- };
-
- // --- Notification Client ---
- class NotificationClient : public IBinder::DeathRecipient {
- public:
- NotificationClient(const sp<AudioFlinger>& audioFlinger,
- const sp<IAudioFlingerClient>& client,
- pid_t pid);
- virtual ~NotificationClient();
-
- sp<IAudioFlingerClient> client() { return mClient; }
-
- // IBinder::DeathRecipient
- virtual void binderDied(const wp<IBinder>& who);
-
- private:
- NotificationClient(const NotificationClient&);
- NotificationClient& operator = (const NotificationClient&);
-
- sp<AudioFlinger> mAudioFlinger;
- pid_t mPid;
- sp<IAudioFlingerClient> mClient;
- };
-
- class TrackHandle;
- class RecordHandle;
- class RecordThread;
- class PlaybackThread;
- class MixerThread;
- class DirectOutputThread;
- class DuplicatingThread;
- class Track;
- class RecordTrack;
- class EffectModule;
- class EffectHandle;
- class EffectChain;
-
- class ThreadBase : public Thread {
- public:
- ThreadBase (const sp<AudioFlinger>& audioFlinger, int id);
- virtual ~ThreadBase();
-
- status_t dumpBase(int fd, const Vector<String16>& args);
-
- // base for record and playback
- class TrackBase : public AudioBufferProvider, public RefBase {
-
- public:
- enum track_state {
- IDLE,
- TERMINATED,
- STOPPED,
- RESUMING,
- ACTIVE,
- PAUSING,
- PAUSED
- };
-
- enum track_flags {
- STEPSERVER_FAILED = 0x01, // StepServer could not acquire cblk->lock mutex
- SYSTEM_FLAGS_MASK = 0x0000ffffUL,
- // The upper 16 bits are used for track-specific flags.
- };
-
- TrackBase(const wp<ThreadBase>& thread,
- const sp<Client>& client,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- uint32_t flags,
- const sp<IMemory>& sharedBuffer,
- int sessionId);
- ~TrackBase();
-
- virtual status_t start() = 0;
- virtual void stop() = 0;
- sp<IMemory> getCblk() const;
- audio_track_cblk_t* cblk() const { return mCblk; }
- int sessionId() { return mSessionId; }
-
- protected:
- friend class ThreadBase;
- friend class RecordHandle;
- friend class PlaybackThread;
- friend class RecordThread;
- friend class MixerThread;
- friend class DirectOutputThread;
-
- TrackBase(const TrackBase&);
- TrackBase& operator = (const TrackBase&);
-
- virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0;
- virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
-
- int format() const {
- return mFormat;
- }
-
- int channelCount() const ;
-
- int sampleRate() const;
-
- void* getBuffer(uint32_t offset, uint32_t frames) const;
-
- bool isStopped() const {
- return mState == STOPPED;
- }
-
- bool isTerminated() const {
- return mState == TERMINATED;
- }
-
- bool step();
- void reset();
-
- wp<ThreadBase> mThread;
- sp<Client> mClient;
- sp<IMemory> mCblkMemory;
- audio_track_cblk_t* mCblk;
- void* mBuffer;
- void* mBufferEnd;
- uint32_t mFrameCount;
- // we don't really need a lock for these
- int mState;
- int mClientTid;
- uint8_t mFormat;
- uint32_t mFlags;
- int mSessionId;
- };
-
- class ConfigEvent {
- public:
- ConfigEvent() : mEvent(0), mParam(0) {}
-
- int mEvent;
- int mParam;
- };
-
- uint32_t sampleRate() const;
- int channelCount() const;
- int format() const;
- size_t frameCount() const;
- void wakeUp() { mWaitWorkCV.broadcast(); }
- void exit();
- virtual bool checkForNewParameters_l() = 0;
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys) = 0;
- virtual void audioConfigChanged_l(int event, int param = 0) = 0;
- void sendConfigEvent(int event, int param = 0);
- void sendConfigEvent_l(int event, int param = 0);
- void processConfigEvents();
- int id() const { return mId;}
- bool standby() { return mStandby; }
-
- mutable Mutex mLock;
-
- protected:
-
- friend class Track;
- friend class TrackBase;
- friend class PlaybackThread;
- friend class MixerThread;
- friend class DirectOutputThread;
- friend class DuplicatingThread;
- friend class RecordThread;
- friend class RecordTrack;
-
- Condition mWaitWorkCV;
- sp<AudioFlinger> mAudioFlinger;
- uint32_t mSampleRate;
- size_t mFrameCount;
- uint32_t mChannels;
- uint16_t mChannelCount;
- uint16_t mFrameSize;
- int mFormat;
- Condition mParamCond;
- Vector<String8> mNewParameters;
- status_t mParamStatus;
- Vector<ConfigEvent *> mConfigEvents;
- bool mStandby;
- int mId;
- bool mExiting;
- };
-
- // --- PlaybackThread ---
- class PlaybackThread : public ThreadBase {
- public:
-
- enum type {
- MIXER,
- DIRECT,
- DUPLICATING
- };
-
- enum mixer_state {
- MIXER_IDLE,
- MIXER_TRACKS_ENABLED,
- MIXER_TRACKS_READY
- };
-
- // playback track
- class Track : public TrackBase {
- public:
- Track( const wp<ThreadBase>& thread,
- const sp<Client>& client,
- int streamType,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- const sp<IMemory>& sharedBuffer,
- int sessionId);
- ~Track();
-
- void dump(char* buffer, size_t size);
- virtual status_t start();
- virtual void stop();
- void pause();
-
- void flush();
- void destroy();
- void mute(bool);
- void setVolume(float left, float right);
- int name() const {
- return mName;
- }
-
- int type() const {
- return mStreamType;
- }
- status_t attachAuxEffect(int EffectId);
- void setAuxBuffer(int EffectId, int32_t *buffer);
- int32_t *auxBuffer() { return mAuxBuffer; }
- void setMainBuffer(int16_t *buffer) { mMainBuffer = buffer; }
- int16_t *mainBuffer() { return mMainBuffer; }
- int auxEffectId() { return mAuxEffectId; }
-
-
- protected:
- friend class ThreadBase;
- friend class AudioFlinger;
- friend class TrackHandle;
- friend class PlaybackThread;
- friend class MixerThread;
- friend class DirectOutputThread;
-
- Track(const Track&);
- Track& operator = (const Track&);
-
- virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
- bool isMuted() { return mMute; }
- bool isPausing() const {
- return mState == PAUSING;
- }
- bool isPaused() const {
- return mState == PAUSED;
- }
- bool isReady() const;
- void setPaused() { mState = PAUSED; }
- void reset();
-
- bool isOutputTrack() const {
- return (mStreamType == AudioSystem::NUM_STREAM_TYPES);
- }
-
- // we don't really need a lock for these
- float mVolume[2];
- volatile bool mMute;
- // FILLED state is used for suppressing volume ramp at begin of playing
- enum {FS_FILLING, FS_FILLED, FS_ACTIVE};
- mutable uint8_t mFillingUpStatus;
- int8_t mRetryCount;
- sp<IMemory> mSharedBuffer;
- bool mResetDone;
- int mStreamType;
- int mName;
- int16_t *mMainBuffer;
- int32_t *mAuxBuffer;
- int mAuxEffectId;
- }; // end of Track
-
-
- // playback track
- class OutputTrack : public Track {
- public:
-
- class Buffer: public AudioBufferProvider::Buffer {
- public:
- int16_t *mBuffer;
- };
-
- OutputTrack( const wp<ThreadBase>& thread,
- DuplicatingThread *sourceThread,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount);
- ~OutputTrack();
-
- virtual status_t start();
- virtual void stop();
- bool write(int16_t* data, uint32_t frames);
- bool bufferQueueEmpty() { return (mBufferQueue.size() == 0) ? true : false; }
- bool isActive() { return mActive; }
- wp<ThreadBase>& thread() { return mThread; }
-
- private:
-
- status_t obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs);
- void clearBufferQueue();
-
- // Maximum number of pending buffers allocated by OutputTrack::write()
- static const uint8_t kMaxOverFlowBuffers = 10;
-
- Vector < Buffer* > mBufferQueue;
- AudioBufferProvider::Buffer mOutBuffer;
- bool mActive;
- DuplicatingThread* mSourceThread;
- }; // end of OutputTrack
-
- PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device);
- virtual ~PlaybackThread();
-
- virtual status_t dump(int fd, const Vector<String16>& args);
-
- // Thread virtuals
- virtual status_t readyToRun();
- virtual void onFirstRef();
-
- virtual uint32_t latency() const;
-
- virtual status_t setMasterVolume(float value);
- virtual status_t setMasterMute(bool muted);
-
- virtual float masterVolume() const;
- virtual bool masterMute() const;
-
- virtual status_t setStreamVolume(int stream, float value);
- virtual status_t setStreamMute(int stream, bool muted);
-
- virtual float streamVolume(int stream) const;
- virtual bool streamMute(int stream) const;
-
- bool isStreamActive(int stream) const;
-
- sp<Track> createTrack_l(
- const sp<AudioFlinger::Client>& client,
- int streamType,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- const sp<IMemory>& sharedBuffer,
- int sessionId,
- status_t *status);
-
- AudioStreamOut* getOutput() { return mOutput; }
-
- virtual int type() const { return mType; }
- void suspend() { mSuspended++; }
- void restore() { if (mSuspended) mSuspended--; }
- bool isSuspended() { return (mSuspended != 0); }
- virtual String8 getParameters(const String8& keys);
- virtual void audioConfigChanged_l(int event, int param = 0);
- virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
- int16_t *mixBuffer() { return mMixBuffer; };
-
- sp<EffectHandle> createEffect_l(
- const sp<AudioFlinger::Client>& client,
- const sp<IEffectClient>& effectClient,
- int32_t priority,
- int sessionId,
- effect_descriptor_t *desc,
- int *enabled,
- status_t *status);
- void disconnectEffect(const sp< EffectModule>& effect,
- const wp<EffectHandle>& handle);
-
- bool hasAudioSession(int sessionId);
- sp<EffectChain> getEffectChain(int sessionId);
- sp<EffectChain> getEffectChain_l(int sessionId);
- status_t addEffectChain_l(const sp<EffectChain>& chain);
- size_t removeEffectChain_l(const sp<EffectChain>& chain);
- void lockEffectChains_l();
- void unlockEffectChains();
-
- sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId);
- void detachAuxEffect_l(int effectId);
- status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId);
- status_t attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId);
- void setMode(uint32_t mode);
-
- struct stream_type_t {
- stream_type_t()
- : volume(1.0f),
- mute(false)
- {
- }
- float volume;
- bool mute;
- };
-
- protected:
- int mType;
- int16_t* mMixBuffer;
- int mSuspended;
- int mBytesWritten;
- bool mMasterMute;
- SortedVector< wp<Track> > mActiveTracks;
-
- virtual int getTrackName_l() = 0;
- virtual void deleteTrackName_l(int name) = 0;
- virtual uint32_t activeSleepTimeUs() = 0;
- virtual uint32_t idleSleepTimeUs() = 0;
-
- private:
-
- friend class AudioFlinger;
- friend class OutputTrack;
- friend class Track;
- friend class TrackBase;
- friend class MixerThread;
- friend class DirectOutputThread;
- friend class DuplicatingThread;
-
- PlaybackThread(const Client&);
- PlaybackThread& operator = (const PlaybackThread&);
-
- status_t addTrack_l(const sp<Track>& track);
- void destroyTrack_l(const sp<Track>& track);
-
- void readOutputParameters();
-
- uint32_t device() { return mDevice; }
-
- virtual status_t dumpInternals(int fd, const Vector<String16>& args);
- status_t dumpTracks(int fd, const Vector<String16>& args);
- status_t dumpEffectChains(int fd, const Vector<String16>& args);
-
- SortedVector< sp<Track> > mTracks;
- // mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread
- stream_type_t mStreamTypes[AudioSystem::NUM_STREAM_TYPES + 1];
- AudioStreamOut* mOutput;
- float mMasterVolume;
- nsecs_t mLastWriteTime;
- int mNumWrites;
- int mNumDelayedWrites;
- bool mInWrite;
- Vector< sp<EffectChain> > mEffectChains;
- uint32_t mDevice;
- };
-
- class MixerThread : public PlaybackThread {
- public:
- MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device);
- virtual ~MixerThread();
-
- // Thread virtuals
- virtual bool threadLoop();
-
- void invalidateTracks(int streamType);
- virtual bool checkForNewParameters_l();
- virtual status_t dumpInternals(int fd, const Vector<String16>& args);
-
- protected:
- uint32_t prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove);
- virtual int getTrackName_l();
- virtual void deleteTrackName_l(int name);
- virtual uint32_t activeSleepTimeUs();
- virtual uint32_t idleSleepTimeUs();
-
- AudioMixer* mAudioMixer;
- };
-
- class DirectOutputThread : public PlaybackThread {
- public:
-
- DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device);
- ~DirectOutputThread();
-
- // Thread virtuals
- virtual bool threadLoop();
-
- virtual bool checkForNewParameters_l();
-
- protected:
- virtual int getTrackName_l();
- virtual void deleteTrackName_l(int name);
- virtual uint32_t activeSleepTimeUs();
- virtual uint32_t idleSleepTimeUs();
-
- private:
- void applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp);
-
- float mLeftVolFloat;
- float mRightVolFloat;
- uint16_t mLeftVolShort;
- uint16_t mRightVolShort;
- };
-
- class DuplicatingThread : public MixerThread {
- public:
- DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread, int id);
- ~DuplicatingThread();
-
- // Thread virtuals
- virtual bool threadLoop();
- void addOutputTrack(MixerThread* thread);
- void removeOutputTrack(MixerThread* thread);
- uint32_t waitTimeMs() { return mWaitTimeMs; }
- protected:
- virtual uint32_t activeSleepTimeUs();
-
- private:
- bool outputsReady(SortedVector< sp<OutputTrack> > &outputTracks);
- void updateWaitTime();
-
- SortedVector < sp<OutputTrack> > mOutputTracks;
- uint32_t mWaitTimeMs;
- };
-
- PlaybackThread *checkPlaybackThread_l(int output) const;
- MixerThread *checkMixerThread_l(int output) const;
- RecordThread *checkRecordThread_l(int input) const;
- float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; }
- void audioConfigChanged_l(int event, int ioHandle, void *param2);
-
- int nextUniqueId();
-
- friend class AudioBuffer;
-
- class TrackHandle : public android::BnAudioTrack {
- public:
- TrackHandle(const sp<PlaybackThread::Track>& track);
- virtual ~TrackHandle();
- virtual status_t start();
- virtual void stop();
- virtual void flush();
- virtual void mute(bool);
- virtual void pause();
- virtual void setVolume(float left, float right);
- virtual sp<IMemory> getCblk() const;
- virtual status_t attachAuxEffect(int effectId);
- virtual status_t onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
- private:
- sp<PlaybackThread::Track> mTrack;
- };
-
- friend class Client;
- friend class PlaybackThread::Track;
-
-
- void removeClient_l(pid_t pid);
- void removeNotificationClient(pid_t pid);
-
-
- // record thread
- class RecordThread : public ThreadBase, public AudioBufferProvider
- {
- public:
-
- // record track
- class RecordTrack : public TrackBase {
- public:
- RecordTrack(const wp<ThreadBase>& thread,
- const sp<Client>& client,
- uint32_t sampleRate,
- int format,
- int channelCount,
- int frameCount,
- uint32_t flags,
- int sessionId);
- ~RecordTrack();
-
- virtual status_t start();
- virtual void stop();
-
- bool overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; }
- bool setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; }
-
- void dump(char* buffer, size_t size);
- private:
- friend class AudioFlinger;
- friend class RecordThread;
-
- RecordTrack(const RecordTrack&);
- RecordTrack& operator = (const RecordTrack&);
-
- virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
-
- bool mOverflow;
- };
-
-
- RecordThread(const sp<AudioFlinger>& audioFlinger,
- AudioStreamIn *input,
- uint32_t sampleRate,
- uint32_t channels,
- int id);
- ~RecordThread();
-
- virtual bool threadLoop();
- virtual status_t readyToRun() { return NO_ERROR; }
- virtual void onFirstRef();
-
- status_t start(RecordTrack* recordTrack);
- void stop(RecordTrack* recordTrack);
- status_t dump(int fd, const Vector<String16>& args);
- AudioStreamIn* getInput() { return mInput; }
-
- virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
- virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
- virtual bool checkForNewParameters_l();
- virtual String8 getParameters(const String8& keys);
- virtual void audioConfigChanged_l(int event, int param = 0);
- void readInputParameters();
- virtual unsigned int getInputFramesLost();
-
- private:
- RecordThread();
- AudioStreamIn *mInput;
- sp<RecordTrack> mActiveTrack;
- Condition mStartStopCond;
- AudioResampler *mResampler;
- int32_t *mRsmpOutBuffer;
- int16_t *mRsmpInBuffer;
- size_t mRsmpInIndex;
- size_t mInputBytes;
- int mReqChannelCount;
- uint32_t mReqSampleRate;
- ssize_t mBytesRead;
- };
-
- class RecordHandle : public android::BnAudioRecord {
- public:
- RecordHandle(const sp<RecordThread::RecordTrack>& recordTrack);
- virtual ~RecordHandle();
- virtual status_t start();
- virtual void stop();
- virtual sp<IMemory> getCblk() const;
- virtual status_t onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
- private:
- sp<RecordThread::RecordTrack> mRecordTrack;
- };
-
- //--- Audio Effect Management
-
- // EffectModule and EffectChain classes both have their own mutex to protect
- // state changes or resource modifications. Always respect the following order
- // if multiple mutexes must be acquired to avoid cross deadlock:
- // AudioFlinger -> ThreadBase -> EffectChain -> EffectModule
-
- // The EffectModule class is a wrapper object controlling the effect engine implementation
- // in the effect library. It prevents concurrent calls to process() and command() functions
- // from different client threads. It keeps a list of EffectHandle objects corresponding
- // to all client applications using this effect and notifies applications of effect state,
- // control or parameter changes. It manages the activation state machine to send appropriate
- // reset, enable, disable commands to effect engine and provide volume
- // ramping when effects are activated/deactivated.
- // When controlling an auxiliary effect, the EffectModule also provides an input buffer used by
- // the attached track(s) to accumulate their auxiliary channel.
- class EffectModule: public RefBase {
- public:
- EffectModule(const wp<ThreadBase>& wThread,
- const wp<AudioFlinger::EffectChain>& chain,
- effect_descriptor_t *desc,
- int id,
- int sessionId);
- ~EffectModule();
-
- enum effect_state {
- IDLE,
- RESTART,
- STARTING,
- ACTIVE,
- STOPPING,
- STOPPED
- };
-
- int id() { return mId; }
- void process();
- void updateState();
- status_t command(int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData);
-
- void reset_l();
- status_t configure();
- status_t init();
- uint32_t state() {
- return mState;
- }
- uint32_t status() {
- return mStatus;
- }
- status_t setEnabled(bool enabled);
- bool isEnabled();
-
- void setInBuffer(int16_t *buffer) { mConfig.inputCfg.buffer.s16 = buffer; }
- int16_t *inBuffer() { return mConfig.inputCfg.buffer.s16; }
- void setOutBuffer(int16_t *buffer) { mConfig.outputCfg.buffer.s16 = buffer; }
- int16_t *outBuffer() { return mConfig.outputCfg.buffer.s16; }
-
- status_t addHandle(sp<EffectHandle>& handle);
- void disconnect(const wp<EffectHandle>& handle);
- size_t removeHandle (const wp<EffectHandle>& handle);
-
- effect_descriptor_t& desc() { return mDescriptor; }
- wp<EffectChain>& chain() { return mChain; }
-
- status_t setDevice(uint32_t device);
- status_t setVolume(uint32_t *left, uint32_t *right, bool controller);
- status_t setMode(uint32_t mode);
-
- status_t dump(int fd, const Vector<String16>& args);
-
- protected:
-
- // Maximum time allocated to effect engines to complete the turn off sequence
- static const uint32_t MAX_DISABLE_TIME_MS = 10000;
-
- EffectModule(const EffectModule&);
- EffectModule& operator = (const EffectModule&);
-
- status_t start_l();
- status_t stop_l();
-
- // update this table when AudioSystem::audio_devices or audio_device_e (in EffectApi.h) are modified
- static const uint32_t sDeviceConvTable[];
- static uint32_t deviceAudioSystemToEffectApi(uint32_t device);
-
- // update this table when AudioSystem::audio_mode or audio_mode_e (in EffectApi.h) are modified
- static const uint32_t sModeConvTable[];
- static int modeAudioSystemToEffectApi(uint32_t mode);
-
- Mutex mLock; // mutex for process, commands and handles list protection
- wp<ThreadBase> mThread; // parent thread
- wp<EffectChain> mChain; // parent effect chain
- int mId; // this instance unique ID
- int mSessionId; // audio session ID
- effect_descriptor_t mDescriptor;// effect descriptor received from effect engine
- effect_config_t mConfig; // input and output audio configuration
- effect_interface_t mEffectInterface; // Effect module C API
- status_t mStatus; // initialization status
- uint32_t mState; // current activation state (effect_state)
- Vector< wp<EffectHandle> > mHandles; // list of client handles
- uint32_t mMaxDisableWaitCnt; // maximum grace period before forcing an effect off after
- // sending disable command.
- uint32_t mDisableWaitCnt; // current process() calls count during disable period.
- };
-
- // The EffectHandle class implements the IEffect interface. It provides resources
- // to receive parameter updates, keeps track of effect control
- // ownership and state and has a pointer to the EffectModule object it is controlling.
- // There is one EffectHandle object for each application controlling (or using)
- // an effect module.
- // The EffectHandle is obtained by calling AudioFlinger::createEffect().
- class EffectHandle: public android::BnEffect {
- public:
-
- EffectHandle(const sp<EffectModule>& effect,
- const sp<AudioFlinger::Client>& client,
- const sp<IEffectClient>& effectClient,
- int32_t priority);
- virtual ~EffectHandle();
-
- // IEffect
- virtual status_t enable();
- virtual status_t disable();
- virtual status_t command(int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData);
- virtual void disconnect();
- virtual sp<IMemory> getCblk() const;
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags);
-
-
- // Give or take control of effect module
- void setControl(bool hasControl, bool signal);
- void commandExecuted(int cmdCode, int cmdSize, void *pCmdData, int replySize, void *pReplyData);
- void setEnabled(bool enabled);
-
- // Getters
- int id() { return mEffect->id(); }
- int priority() { return mPriority; }
- bool hasControl() { return mHasControl; }
- sp<EffectModule> effect() { return mEffect; }
-
- void dump(char* buffer, size_t size);
-
- protected:
-
- EffectHandle(const EffectHandle&);
- EffectHandle& operator =(const EffectHandle&);
-
- sp<EffectModule> mEffect; // pointer to controlled EffectModule
- sp<IEffectClient> mEffectClient; // callback interface for client notifications
- sp<Client> mClient; // client for shared memory allocation
- sp<IMemory> mCblkMemory; // shared memory for control block
- effect_param_cblk_t* mCblk; // control block for deferred parameter setting via shared memory
- uint8_t* mBuffer; // pointer to parameter area in shared memory
- int mPriority; // client application priority to control the effect
- bool mHasControl; // true if this handle is controlling the effect
- };
-
- // the EffectChain class represents a group of effects associated to one audio session.
- // There can be any number of EffectChain objects per output mixer thread (PlaybackThread).
- // The EffecChain with session ID 0 contains global effects applied to the output mix.
- // Effects in this chain can be insert or auxiliary. Effects in other chains (attached to tracks)
- // are insert only. The EffectChain maintains an ordered list of effect module, the order corresponding
- // in the effect process order. When attached to a track (session ID != 0), it also provide it's own
- // input buffer used by the track as accumulation buffer.
- class EffectChain: public RefBase {
- public:
- EffectChain(const wp<ThreadBase>& wThread, int sessionId);
- ~EffectChain();
-
- void process_l();
-
- void lock() {
- mLock.lock();
- }
- void unlock() {
- mLock.unlock();
- }
-
- status_t addEffect(sp<EffectModule>& handle);
- size_t removeEffect(const sp<EffectModule>& handle);
-
- int sessionId() {
- return mSessionId;
- }
- sp<EffectModule> getEffectFromDesc(effect_descriptor_t *descriptor);
- sp<EffectModule> getEffectFromId(int id);
- sp<EffectModule> getVolumeController();
- bool setVolume(uint32_t *left, uint32_t *right);
- void setDevice(uint32_t device);
- void setMode(uint32_t mode);
-
-
- void setInBuffer(int16_t *buffer, bool ownsBuffer = false) {
- mInBuffer = buffer;
- mOwnInBuffer = ownsBuffer;
- }
- int16_t *inBuffer() {
- return mInBuffer;
- }
- void setOutBuffer(int16_t *buffer) {
- mOutBuffer = buffer;
- }
- int16_t *outBuffer() {
- return mOutBuffer;
- }
-
- void startTrack() {mActiveTrackCnt++;}
- void stopTrack() {mActiveTrackCnt--;}
- int activeTracks() { return mActiveTrackCnt;}
-
- status_t dump(int fd, const Vector<String16>& args);
-
- protected:
-
- EffectChain(const EffectChain&);
- EffectChain& operator =(const EffectChain&);
-
- wp<ThreadBase> mThread; // parent mixer thread
- Mutex mLock; // mutex protecting effect list
- Vector<sp<EffectModule> > mEffects; // list of effect modules
- int mSessionId; // audio session ID
- int16_t *mInBuffer; // chain input buffer
- int16_t *mOutBuffer; // chain output buffer
- int mVolumeCtrlIdx; // index of insert effect having control over volume
- int mActiveTrackCnt; // number of active tracks connected
- bool mOwnInBuffer; // true if the chain owns its input buffer
- };
-
- friend class RecordThread;
- friend class PlaybackThread;
-
-
- mutable Mutex mLock;
-
- DefaultKeyedVector< pid_t, wp<Client> > mClients;
-
- mutable Mutex mHardwareLock;
- AudioHardwareInterface* mAudioHardware;
- mutable int mHardwareStatus;
-
-
- DefaultKeyedVector< int, sp<PlaybackThread> > mPlaybackThreads;
- PlaybackThread::stream_type_t mStreamTypes[AudioSystem::NUM_STREAM_TYPES];
- float mMasterVolume;
- bool mMasterMute;
-
- DefaultKeyedVector< int, sp<RecordThread> > mRecordThreads;
-
- DefaultKeyedVector< pid_t, sp<NotificationClient> > mNotificationClients;
- volatile int32_t mNextUniqueId;
-#ifdef LVMX
- int mLifeVibesClientPid;
-#endif
- uint32_t mMode;
-
- // Maximum CPU load allocated to audio effects in 0.1 MIPS (ARMv5TE, 0 WS memory) units
- static const uint32_t MAX_EFFECTS_CPU_LOAD = 1000;
- // Maximum memory allocated to audio effects in KB
- static const uint32_t MAX_EFFECTS_MEMORY = 512;
- uint32_t mTotalEffectsCpuLoad; // current CPU load used by effects
- uint32_t mTotalEffectsMemory; // current memory used by effects
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_AUDIO_FLINGER_H
diff --git a/libs/audioflinger/AudioHardwareGeneric.cpp b/libs/audioflinger/AudioHardwareGeneric.cpp
deleted file mode 100644
index d63c031..0000000
--- a/libs/audioflinger/AudioHardwareGeneric.cpp
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sched.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-#define LOG_TAG "AudioHardware"
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include "AudioHardwareGeneric.h"
-#include <media/AudioRecord.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-static char const * const kAudioDeviceName = "/dev/eac";
-
-// ----------------------------------------------------------------------------
-
-AudioHardwareGeneric::AudioHardwareGeneric()
- : mOutput(0), mInput(0), mFd(-1), mMicMute(false)
-{
- mFd = ::open(kAudioDeviceName, O_RDWR);
-}
-
-AudioHardwareGeneric::~AudioHardwareGeneric()
-{
- if (mFd >= 0) ::close(mFd);
- closeOutputStream((AudioStreamOut *)mOutput);
- closeInputStream((AudioStreamIn *)mInput);
-}
-
-status_t AudioHardwareGeneric::initCheck()
-{
- if (mFd >= 0) {
- if (::access(kAudioDeviceName, O_RDWR) == NO_ERROR)
- return NO_ERROR;
- }
- return NO_INIT;
-}
-
-AudioStreamOut* AudioHardwareGeneric::openOutputStream(
- uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
-{
- AutoMutex lock(mLock);
-
- // only one output stream allowed
- if (mOutput) {
- if (status) {
- *status = INVALID_OPERATION;
- }
- return 0;
- }
-
- // create new output stream
- AudioStreamOutGeneric* out = new AudioStreamOutGeneric();
- status_t lStatus = out->set(this, mFd, devices, format, channels, sampleRate);
- if (status) {
- *status = lStatus;
- }
- if (lStatus == NO_ERROR) {
- mOutput = out;
- } else {
- delete out;
- }
- return mOutput;
-}
-
-void AudioHardwareGeneric::closeOutputStream(AudioStreamOut* out) {
- if (mOutput && out == mOutput) {
- delete mOutput;
- mOutput = 0;
- }
-}
-
-AudioStreamIn* AudioHardwareGeneric::openInputStream(
- uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate,
- status_t *status, AudioSystem::audio_in_acoustics acoustics)
-{
- // check for valid input source
- if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
- return 0;
- }
-
- AutoMutex lock(mLock);
-
- // only one input stream allowed
- if (mInput) {
- if (status) {
- *status = INVALID_OPERATION;
- }
- return 0;
- }
-
- // create new output stream
- AudioStreamInGeneric* in = new AudioStreamInGeneric();
- status_t lStatus = in->set(this, mFd, devices, format, channels, sampleRate, acoustics);
- if (status) {
- *status = lStatus;
- }
- if (lStatus == NO_ERROR) {
- mInput = in;
- } else {
- delete in;
- }
- return mInput;
-}
-
-void AudioHardwareGeneric::closeInputStream(AudioStreamIn* in) {
- if (mInput && in == mInput) {
- delete mInput;
- mInput = 0;
- }
-}
-
-status_t AudioHardwareGeneric::setVoiceVolume(float v)
-{
- // Implement: set voice volume
- return NO_ERROR;
-}
-
-status_t AudioHardwareGeneric::setMasterVolume(float v)
-{
- // Implement: set master volume
- // return error - software mixer will handle it
- return INVALID_OPERATION;
-}
-
-status_t AudioHardwareGeneric::setMicMute(bool state)
-{
- mMicMute = state;
- return NO_ERROR;
-}
-
-status_t AudioHardwareGeneric::getMicMute(bool* state)
-{
- *state = mMicMute;
- return NO_ERROR;
-}
-
-status_t AudioHardwareGeneric::dumpInternals(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- result.append("AudioHardwareGeneric::dumpInternals\n");
- snprintf(buffer, SIZE, "\tmFd: %d mMicMute: %s\n", mFd, mMicMute? "true": "false");
- result.append(buffer);
- ::write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-status_t AudioHardwareGeneric::dump(int fd, const Vector<String16>& args)
-{
- dumpInternals(fd, args);
- if (mInput) {
- mInput->dump(fd, args);
- }
- if (mOutput) {
- mOutput->dump(fd, args);
- }
- return NO_ERROR;
-}
-
-// ----------------------------------------------------------------------------
-
-status_t AudioStreamOutGeneric::set(
- AudioHardwareGeneric *hw,
- int fd,
- uint32_t devices,
- int *pFormat,
- uint32_t *pChannels,
- uint32_t *pRate)
-{
- int lFormat = pFormat ? *pFormat : 0;
- uint32_t lChannels = pChannels ? *pChannels : 0;
- uint32_t lRate = pRate ? *pRate : 0;
-
- // fix up defaults
- if (lFormat == 0) lFormat = format();
- if (lChannels == 0) lChannels = channels();
- if (lRate == 0) lRate = sampleRate();
-
- // check values
- if ((lFormat != format()) ||
- (lChannels != channels()) ||
- (lRate != sampleRate())) {
- if (pFormat) *pFormat = format();
- if (pChannels) *pChannels = channels();
- if (pRate) *pRate = sampleRate();
- return BAD_VALUE;
- }
-
- if (pFormat) *pFormat = lFormat;
- if (pChannels) *pChannels = lChannels;
- if (pRate) *pRate = lRate;
-
- mAudioHardware = hw;
- mFd = fd;
- mDevice = devices;
- return NO_ERROR;
-}
-
-AudioStreamOutGeneric::~AudioStreamOutGeneric()
-{
-}
-
-ssize_t AudioStreamOutGeneric::write(const void* buffer, size_t bytes)
-{
- Mutex::Autolock _l(mLock);
- return ssize_t(::write(mFd, buffer, bytes));
-}
-
-status_t AudioStreamOutGeneric::standby()
-{
- // Implement: audio hardware to standby mode
- return NO_ERROR;
-}
-
-status_t AudioStreamOutGeneric::dump(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- snprintf(buffer, SIZE, "AudioStreamOutGeneric::dump\n");
- result.append(buffer);
- snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tformat: %d\n", format());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tdevice: %d\n", mDevice);
- result.append(buffer);
- snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
- result.append(buffer);
- snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
- result.append(buffer);
- ::write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-status_t AudioStreamOutGeneric::setParameters(const String8& keyValuePairs)
-{
- AudioParameter param = AudioParameter(keyValuePairs);
- String8 key = String8(AudioParameter::keyRouting);
- status_t status = NO_ERROR;
- int device;
- LOGV("setParameters() %s", keyValuePairs.string());
-
- if (param.getInt(key, device) == NO_ERROR) {
- mDevice = device;
- param.remove(key);
- }
-
- if (param.size()) {
- status = BAD_VALUE;
- }
- return status;
-}
-
-String8 AudioStreamOutGeneric::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- String8 value;
- String8 key = String8(AudioParameter::keyRouting);
-
- if (param.get(key, value) == NO_ERROR) {
- param.addInt(key, (int)mDevice);
- }
-
- LOGV("getParameters() %s", param.toString().string());
- return param.toString();
-}
-
-status_t AudioStreamOutGeneric::getRenderPosition(uint32_t *dspFrames)
-{
- return INVALID_OPERATION;
-}
-
-// ----------------------------------------------------------------------------
-
-// record functions
-status_t AudioStreamInGeneric::set(
- AudioHardwareGeneric *hw,
- int fd,
- uint32_t devices,
- int *pFormat,
- uint32_t *pChannels,
- uint32_t *pRate,
- AudioSystem::audio_in_acoustics acoustics)
-{
- if (pFormat == 0 || pChannels == 0 || pRate == 0) return BAD_VALUE;
- LOGV("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, *pFormat, *pChannels, *pRate);
- // check values
- if ((*pFormat != format()) ||
- (*pChannels != channels()) ||
- (*pRate != sampleRate())) {
- LOGE("Error opening input channel");
- *pFormat = format();
- *pChannels = channels();
- *pRate = sampleRate();
- return BAD_VALUE;
- }
-
- mAudioHardware = hw;
- mFd = fd;
- mDevice = devices;
- return NO_ERROR;
-}
-
-AudioStreamInGeneric::~AudioStreamInGeneric()
-{
-}
-
-ssize_t AudioStreamInGeneric::read(void* buffer, ssize_t bytes)
-{
- AutoMutex lock(mLock);
- if (mFd < 0) {
- LOGE("Attempt to read from unopened device");
- return NO_INIT;
- }
- return ::read(mFd, buffer, bytes);
-}
-
-status_t AudioStreamInGeneric::dump(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- snprintf(buffer, SIZE, "AudioStreamInGeneric::dump\n");
- result.append(buffer);
- snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tformat: %d\n", format());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tdevice: %d\n", mDevice);
- result.append(buffer);
- snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
- result.append(buffer);
- snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
- result.append(buffer);
- ::write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-status_t AudioStreamInGeneric::setParameters(const String8& keyValuePairs)
-{
- AudioParameter param = AudioParameter(keyValuePairs);
- String8 key = String8(AudioParameter::keyRouting);
- status_t status = NO_ERROR;
- int device;
- LOGV("setParameters() %s", keyValuePairs.string());
-
- if (param.getInt(key, device) == NO_ERROR) {
- mDevice = device;
- param.remove(key);
- }
-
- if (param.size()) {
- status = BAD_VALUE;
- }
- return status;
-}
-
-String8 AudioStreamInGeneric::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- String8 value;
- String8 key = String8(AudioParameter::keyRouting);
-
- if (param.get(key, value) == NO_ERROR) {
- param.addInt(key, (int)mDevice);
- }
-
- LOGV("getParameters() %s", param.toString().string());
- return param.toString();
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/libs/audioflinger/AudioHardwareGeneric.h b/libs/audioflinger/AudioHardwareGeneric.h
deleted file mode 100644
index aa4e78d..0000000
--- a/libs/audioflinger/AudioHardwareGeneric.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_AUDIO_HARDWARE_GENERIC_H
-#define ANDROID_AUDIO_HARDWARE_GENERIC_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/threads.h>
-
-#include <hardware_legacy/AudioHardwareBase.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class AudioHardwareGeneric;
-
-class AudioStreamOutGeneric : public AudioStreamOut {
-public:
- AudioStreamOutGeneric() : mAudioHardware(0), mFd(-1) {}
- virtual ~AudioStreamOutGeneric();
-
- virtual status_t set(
- AudioHardwareGeneric *hw,
- int mFd,
- uint32_t devices,
- int *pFormat,
- uint32_t *pChannels,
- uint32_t *pRate);
-
- virtual uint32_t sampleRate() const { return 44100; }
- virtual size_t bufferSize() const { return 4096; }
- virtual uint32_t channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
- virtual int format() const { return AudioSystem::PCM_16_BIT; }
- virtual uint32_t latency() const { return 20; }
- virtual status_t setVolume(float left, float right) { return INVALID_OPERATION; }
- virtual ssize_t write(const void* buffer, size_t bytes);
- virtual status_t standby();
- virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys);
- virtual status_t getRenderPosition(uint32_t *dspFrames);
-
-private:
- AudioHardwareGeneric *mAudioHardware;
- Mutex mLock;
- int mFd;
- uint32_t mDevice;
-};
-
-class AudioStreamInGeneric : public AudioStreamIn {
-public:
- AudioStreamInGeneric() : mAudioHardware(0), mFd(-1) {}
- virtual ~AudioStreamInGeneric();
-
- virtual status_t set(
- AudioHardwareGeneric *hw,
- int mFd,
- uint32_t devices,
- int *pFormat,
- uint32_t *pChannels,
- uint32_t *pRate,
- AudioSystem::audio_in_acoustics acoustics);
-
- virtual uint32_t sampleRate() const { return 8000; }
- virtual size_t bufferSize() const { return 320; }
- virtual uint32_t channels() const { return AudioSystem::CHANNEL_IN_MONO; }
- virtual int format() const { return AudioSystem::PCM_16_BIT; }
- virtual status_t setGain(float gain) { return INVALID_OPERATION; }
- virtual ssize_t read(void* buffer, ssize_t bytes);
- virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t standby() { return NO_ERROR; }
- virtual status_t setParameters(const String8& keyValuePairs);
- virtual String8 getParameters(const String8& keys);
- virtual unsigned int getInputFramesLost() const { return 0; }
-
-private:
- AudioHardwareGeneric *mAudioHardware;
- Mutex mLock;
- int mFd;
- uint32_t mDevice;
-};
-
-
-class AudioHardwareGeneric : public AudioHardwareBase
-{
-public:
- AudioHardwareGeneric();
- virtual ~AudioHardwareGeneric();
- virtual status_t initCheck();
- virtual status_t setVoiceVolume(float volume);
- virtual status_t setMasterVolume(float volume);
-
- // mic mute
- virtual status_t setMicMute(bool state);
- virtual status_t getMicMute(bool* state);
-
- // create I/O streams
- virtual AudioStreamOut* openOutputStream(
- uint32_t devices,
- int *format=0,
- uint32_t *channels=0,
- uint32_t *sampleRate=0,
- status_t *status=0);
- virtual void closeOutputStream(AudioStreamOut* out);
-
- virtual AudioStreamIn* openInputStream(
- uint32_t devices,
- int *format,
- uint32_t *channels,
- uint32_t *sampleRate,
- status_t *status,
- AudioSystem::audio_in_acoustics acoustics);
- virtual void closeInputStream(AudioStreamIn* in);
-
- void closeOutputStream(AudioStreamOutGeneric* out);
- void closeInputStream(AudioStreamInGeneric* in);
-protected:
- virtual status_t dump(int fd, const Vector<String16>& args);
-
-private:
- status_t dumpInternals(int fd, const Vector<String16>& args);
-
- Mutex mLock;
- AudioStreamOutGeneric *mOutput;
- AudioStreamInGeneric *mInput;
- int mFd;
- bool mMicMute;
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_AUDIO_HARDWARE_GENERIC_H
diff --git a/libs/audioflinger/AudioHardwareInterface.cpp b/libs/audioflinger/AudioHardwareInterface.cpp
deleted file mode 100644
index 9a4a7f9..0000000
--- a/libs/audioflinger/AudioHardwareInterface.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <cutils/properties.h>
-#include <string.h>
-#include <unistd.h>
-//#define LOG_NDEBUG 0
-
-#define LOG_TAG "AudioHardwareInterface"
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include "AudioHardwareStub.h"
-#include "AudioHardwareGeneric.h"
-#ifdef WITH_A2DP
-#include "A2dpAudioInterface.h"
-#endif
-
-#ifdef ENABLE_AUDIO_DUMP
-#include "AudioDumpInterface.h"
-#endif
-
-
-// change to 1 to log routing calls
-#define LOG_ROUTING_CALLS 1
-
-namespace android {
-
-#if LOG_ROUTING_CALLS
-static const char* routingModeStrings[] =
-{
- "OUT OF RANGE",
- "INVALID",
- "CURRENT",
- "NORMAL",
- "RINGTONE",
- "IN_CALL"
-};
-
-static const char* routeNone = "NONE";
-
-static const char* displayMode(int mode)
-{
- if ((mode < -2) || (mode > 2))
- return routingModeStrings[0];
- return routingModeStrings[mode+3];
-}
-#endif
-
-// ----------------------------------------------------------------------------
-
-AudioHardwareInterface* AudioHardwareInterface::create()
-{
- /*
- * FIXME: This code needs to instantiate the correct audio device
- * interface. For now - we use compile-time switches.
- */
- AudioHardwareInterface* hw = 0;
- char value[PROPERTY_VALUE_MAX];
-
-#ifdef GENERIC_AUDIO
- hw = new AudioHardwareGeneric();
-#else
- // if running in emulation - use the emulator driver
- if (property_get("ro.kernel.qemu", value, 0)) {
- LOGD("Running in emulation - using generic audio driver");
- hw = new AudioHardwareGeneric();
- }
- else {
- LOGV("Creating Vendor Specific AudioHardware");
- hw = createAudioHardware();
- }
-#endif
- if (hw->initCheck() != NO_ERROR) {
- LOGW("Using stubbed audio hardware. No sound will be produced.");
- delete hw;
- hw = new AudioHardwareStub();
- }
-
-#ifdef WITH_A2DP
- hw = new A2dpAudioInterface(hw);
-#endif
-
-#ifdef ENABLE_AUDIO_DUMP
- // This code adds a record of buffers in a file to write calls made by AudioFlinger.
- // It replaces the current AudioHardwareInterface object by an intermediate one which
- // will record buffers in a file (after sending them to hardware) for testing purpose.
- // This feature is enabled by defining symbol ENABLE_AUDIO_DUMP.
- // The output file is set with setParameters("test_cmd_file_name=<name>"). Pause are not recorded in the file.
- LOGV("opening PCM dump interface");
- hw = new AudioDumpInterface(hw); // replace interface
-#endif
- return hw;
-}
-
-AudioStreamOut::~AudioStreamOut()
-{
-}
-
-AudioStreamIn::~AudioStreamIn() {}
-
-AudioHardwareBase::AudioHardwareBase()
-{
- mMode = 0;
-}
-
-status_t AudioHardwareBase::setMode(int mode)
-{
-#if LOG_ROUTING_CALLS
- LOGD("setMode(%s)", displayMode(mode));
-#endif
- if ((mode < 0) || (mode >= AudioSystem::NUM_MODES))
- return BAD_VALUE;
- if (mMode == mode)
- return ALREADY_EXISTS;
- mMode = mode;
- return NO_ERROR;
-}
-
-// default implementation
-status_t AudioHardwareBase::setParameters(const String8& keyValuePairs)
-{
- return NO_ERROR;
-}
-
-// default implementation
-String8 AudioHardwareBase::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- return param.toString();
-}
-
-// default implementation
-size_t AudioHardwareBase::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
-{
- if (sampleRate != 8000) {
- LOGW("getInputBufferSize bad sampling rate: %d", sampleRate);
- return 0;
- }
- if (format != AudioSystem::PCM_16_BIT) {
- LOGW("getInputBufferSize bad format: %d", format);
- return 0;
- }
- if (channelCount != 1) {
- LOGW("getInputBufferSize bad channel count: %d", channelCount);
- return 0;
- }
-
- return 320;
-}
-
-status_t AudioHardwareBase::dumpState(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- snprintf(buffer, SIZE, "AudioHardwareBase::dumpState\n");
- result.append(buffer);
- snprintf(buffer, SIZE, "\tmMode: %d\n", mMode);
- result.append(buffer);
- ::write(fd, result.string(), result.size());
- dump(fd, args); // Dump the state of the concrete child.
- return NO_ERROR;
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/libs/audioflinger/AudioHardwareStub.cpp
deleted file mode 100644
index d481150..0000000
--- a/libs/audioflinger/AudioHardwareStub.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-/* //device/servers/AudioFlinger/AudioHardwareStub.cpp
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <utils/String8.h>
-
-#include "AudioHardwareStub.h"
-#include <media/AudioRecord.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-AudioHardwareStub::AudioHardwareStub() : mMicMute(false)
-{
-}
-
-AudioHardwareStub::~AudioHardwareStub()
-{
-}
-
-status_t AudioHardwareStub::initCheck()
-{
- return NO_ERROR;
-}
-
-AudioStreamOut* AudioHardwareStub::openOutputStream(
- uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
-{
- AudioStreamOutStub* out = new AudioStreamOutStub();
- status_t lStatus = out->set(format, channels, sampleRate);
- if (status) {
- *status = lStatus;
- }
- if (lStatus == NO_ERROR)
- return out;
- delete out;
- return 0;
-}
-
-void AudioHardwareStub::closeOutputStream(AudioStreamOut* out)
-{
- delete out;
-}
-
-AudioStreamIn* AudioHardwareStub::openInputStream(
- uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate,
- status_t *status, AudioSystem::audio_in_acoustics acoustics)
-{
- // check for valid input source
- if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
- return 0;
- }
-
- AudioStreamInStub* in = new AudioStreamInStub();
- status_t lStatus = in->set(format, channels, sampleRate, acoustics);
- if (status) {
- *status = lStatus;
- }
- if (lStatus == NO_ERROR)
- return in;
- delete in;
- return 0;
-}
-
-void AudioHardwareStub::closeInputStream(AudioStreamIn* in)
-{
- delete in;
-}
-
-status_t AudioHardwareStub::setVoiceVolume(float volume)
-{
- return NO_ERROR;
-}
-
-status_t AudioHardwareStub::setMasterVolume(float volume)
-{
- return NO_ERROR;
-}
-
-status_t AudioHardwareStub::dumpInternals(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- result.append("AudioHardwareStub::dumpInternals\n");
- snprintf(buffer, SIZE, "\tmMicMute: %s\n", mMicMute? "true": "false");
- result.append(buffer);
- ::write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-status_t AudioHardwareStub::dump(int fd, const Vector<String16>& args)
-{
- dumpInternals(fd, args);
- return NO_ERROR;
-}
-
-// ----------------------------------------------------------------------------
-
-status_t AudioStreamOutStub::set(int *pFormat, uint32_t *pChannels, uint32_t *pRate)
-{
- if (pFormat) *pFormat = format();
- if (pChannels) *pChannels = channels();
- if (pRate) *pRate = sampleRate();
-
- return NO_ERROR;
-}
-
-ssize_t AudioStreamOutStub::write(const void* buffer, size_t bytes)
-{
- // fake timing for audio output
- usleep(bytes * 1000000 / sizeof(int16_t) / AudioSystem::popCount(channels()) / sampleRate());
- return bytes;
-}
-
-status_t AudioStreamOutStub::standby()
-{
- return NO_ERROR;
-}
-
-status_t AudioStreamOutStub::dump(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- snprintf(buffer, SIZE, "AudioStreamOutStub::dump\n");
- snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
- snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
- snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
- snprintf(buffer, SIZE, "\tformat: %d\n", format());
- result.append(buffer);
- ::write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-String8 AudioStreamOutStub::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- return param.toString();
-}
-
-status_t AudioStreamOutStub::getRenderPosition(uint32_t *dspFrames)
-{
- return INVALID_OPERATION;
-}
-
-// ----------------------------------------------------------------------------
-
-status_t AudioStreamInStub::set(int *pFormat, uint32_t *pChannels, uint32_t *pRate,
- AudioSystem::audio_in_acoustics acoustics)
-{
- return NO_ERROR;
-}
-
-ssize_t AudioStreamInStub::read(void* buffer, ssize_t bytes)
-{
- // fake timing for audio input
- usleep(bytes * 1000000 / sizeof(int16_t) / AudioSystem::popCount(channels()) / sampleRate());
- memset(buffer, 0, bytes);
- return bytes;
-}
-
-status_t AudioStreamInStub::dump(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- snprintf(buffer, SIZE, "AudioStreamInStub::dump\n");
- result.append(buffer);
- snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
- result.append(buffer);
- snprintf(buffer, SIZE, "\tformat: %d\n", format());
- result.append(buffer);
- ::write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-String8 AudioStreamInStub::getParameters(const String8& keys)
-{
- AudioParameter param = AudioParameter(keys);
- return param.toString();
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/libs/audioflinger/AudioHardwareStub.h b/libs/audioflinger/AudioHardwareStub.h
deleted file mode 100644
index 06a29de..0000000
--- a/libs/audioflinger/AudioHardwareStub.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* //device/servers/AudioFlinger/AudioHardwareStub.h
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_AUDIO_HARDWARE_STUB_H
-#define ANDROID_AUDIO_HARDWARE_STUB_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <hardware_legacy/AudioHardwareBase.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class AudioStreamOutStub : public AudioStreamOut {
-public:
- virtual status_t set(int *pFormat, uint32_t *pChannels, uint32_t *pRate);
- virtual uint32_t sampleRate() const { return 44100; }
- virtual size_t bufferSize() const { return 4096; }
- virtual uint32_t channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
- virtual int format() const { return AudioSystem::PCM_16_BIT; }
- virtual uint32_t latency() const { return 0; }
- virtual status_t setVolume(float left, float right) { return NO_ERROR; }
- virtual ssize_t write(const void* buffer, size_t bytes);
- virtual status_t standby();
- virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t setParameters(const String8& keyValuePairs) { return NO_ERROR;}
- virtual String8 getParameters(const String8& keys);
- virtual status_t getRenderPosition(uint32_t *dspFrames);
-};
-
-class AudioStreamInStub : public AudioStreamIn {
-public:
- virtual status_t set(int *pFormat, uint32_t *pChannels, uint32_t *pRate, AudioSystem::audio_in_acoustics acoustics);
- virtual uint32_t sampleRate() const { return 8000; }
- virtual size_t bufferSize() const { return 320; }
- virtual uint32_t channels() const { return AudioSystem::CHANNEL_IN_MONO; }
- virtual int format() const { return AudioSystem::PCM_16_BIT; }
- virtual status_t setGain(float gain) { return NO_ERROR; }
- virtual ssize_t read(void* buffer, ssize_t bytes);
- virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t standby() { return NO_ERROR; }
- virtual status_t setParameters(const String8& keyValuePairs) { return NO_ERROR;}
- virtual String8 getParameters(const String8& keys);
- virtual unsigned int getInputFramesLost() const { return 0; }
-};
-
-class AudioHardwareStub : public AudioHardwareBase
-{
-public:
- AudioHardwareStub();
- virtual ~AudioHardwareStub();
- virtual status_t initCheck();
- virtual status_t setVoiceVolume(float volume);
- virtual status_t setMasterVolume(float volume);
-
- // mic mute
- virtual status_t setMicMute(bool state) { mMicMute = state; return NO_ERROR; }
- virtual status_t getMicMute(bool* state) { *state = mMicMute ; return NO_ERROR; }
-
- // create I/O streams
- virtual AudioStreamOut* openOutputStream(
- uint32_t devices,
- int *format=0,
- uint32_t *channels=0,
- uint32_t *sampleRate=0,
- status_t *status=0);
- virtual void closeOutputStream(AudioStreamOut* out);
-
- virtual AudioStreamIn* openInputStream(
- uint32_t devices,
- int *format,
- uint32_t *channels,
- uint32_t *sampleRate,
- status_t *status,
- AudioSystem::audio_in_acoustics acoustics);
- virtual void closeInputStream(AudioStreamIn* in);
-
-protected:
- virtual status_t dump(int fd, const Vector<String16>& args);
-
- bool mMicMute;
-private:
- status_t dumpInternals(int fd, const Vector<String16>& args);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_AUDIO_HARDWARE_STUB_H
diff --git a/libs/audioflinger/AudioMixer.cpp b/libs/audioflinger/AudioMixer.cpp
deleted file mode 100644
index 8aaa325..0000000
--- a/libs/audioflinger/AudioMixer.cpp
+++ /dev/null
@@ -1,1195 +0,0 @@
-/* //device/include/server/AudioFlinger/AudioMixer.cpp
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "AudioMixer"
-//#define LOG_NDEBUG 0
-
-#include <stdint.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/Log.h>
-
-#include "AudioMixer.h"
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-static inline int16_t clamp16(int32_t sample)
-{
- if ((sample>>15) ^ (sample>>31))
- sample = 0x7FFF ^ (sample>>31);
- return sample;
-}
-
-// ----------------------------------------------------------------------------
-
-AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate)
- : mActiveTrack(0), mTrackNames(0), mSampleRate(sampleRate)
-{
- mState.enabledTracks= 0;
- mState.needsChanged = 0;
- mState.frameCount = frameCount;
- mState.outputTemp = 0;
- mState.resampleTemp = 0;
- mState.hook = process__nop;
- track_t* t = mState.tracks;
- for (int i=0 ; i<32 ; i++) {
- t->needs = 0;
- t->volume[0] = UNITY_GAIN;
- t->volume[1] = UNITY_GAIN;
- t->volumeInc[0] = 0;
- t->volumeInc[1] = 0;
- t->auxLevel = 0;
- t->auxInc = 0;
- t->channelCount = 2;
- t->enabled = 0;
- t->format = 16;
- t->buffer.raw = 0;
- t->bufferProvider = 0;
- t->hook = 0;
- t->resampler = 0;
- t->sampleRate = mSampleRate;
- t->in = 0;
- t->mainBuffer = NULL;
- t->auxBuffer = NULL;
- t++;
- }
-}
-
- AudioMixer::~AudioMixer()
- {
- track_t* t = mState.tracks;
- for (int i=0 ; i<32 ; i++) {
- delete t->resampler;
- t++;
- }
- delete [] mState.outputTemp;
- delete [] mState.resampleTemp;
- }
-
- int AudioMixer::getTrackName()
- {
- uint32_t names = mTrackNames;
- uint32_t mask = 1;
- int n = 0;
- while (names & mask) {
- mask <<= 1;
- n++;
- }
- if (mask) {
- LOGV("add track (%d)", n);
- mTrackNames |= mask;
- return TRACK0 + n;
- }
- return -1;
- }
-
- void AudioMixer::invalidateState(uint32_t mask)
- {
- if (mask) {
- mState.needsChanged |= mask;
- mState.hook = process__validate;
- }
- }
-
- void AudioMixer::deleteTrackName(int name)
- {
- name -= TRACK0;
- if (uint32_t(name) < MAX_NUM_TRACKS) {
- LOGV("deleteTrackName(%d)", name);
- track_t& track(mState.tracks[ name ]);
- if (track.enabled != 0) {
- track.enabled = 0;
- invalidateState(1<<name);
- }
- if (track.resampler) {
- // delete the resampler
- delete track.resampler;
- track.resampler = 0;
- track.sampleRate = mSampleRate;
- invalidateState(1<<name);
- }
- track.volumeInc[0] = 0;
- track.volumeInc[1] = 0;
- mTrackNames &= ~(1<<name);
- }
- }
-
-status_t AudioMixer::enable(int name)
-{
- switch (name) {
- case MIXING: {
- if (mState.tracks[ mActiveTrack ].enabled != 1) {
- mState.tracks[ mActiveTrack ].enabled = 1;
- LOGV("enable(%d)", mActiveTrack);
- invalidateState(1<<mActiveTrack);
- }
- } break;
- default:
- return NAME_NOT_FOUND;
- }
- return NO_ERROR;
-}
-
-status_t AudioMixer::disable(int name)
-{
- switch (name) {
- case MIXING: {
- if (mState.tracks[ mActiveTrack ].enabled != 0) {
- mState.tracks[ mActiveTrack ].enabled = 0;
- LOGV("disable(%d)", mActiveTrack);
- invalidateState(1<<mActiveTrack);
- }
- } break;
- default:
- return NAME_NOT_FOUND;
- }
- return NO_ERROR;
-}
-
-status_t AudioMixer::setActiveTrack(int track)
-{
- if (uint32_t(track-TRACK0) >= MAX_NUM_TRACKS) {
- return BAD_VALUE;
- }
- mActiveTrack = track - TRACK0;
- return NO_ERROR;
-}
-
-status_t AudioMixer::setParameter(int target, int name, void *value)
-{
- int valueInt = (int)value;
- int32_t *valueBuf = (int32_t *)value;
-
- switch (target) {
- case TRACK:
- if (name == CHANNEL_COUNT) {
- if ((uint32_t(valueInt) <= MAX_NUM_CHANNELS) && (valueInt)) {
- if (mState.tracks[ mActiveTrack ].channelCount != valueInt) {
- mState.tracks[ mActiveTrack ].channelCount = valueInt;
- LOGV("setParameter(TRACK, CHANNEL_COUNT, %d)", valueInt);
- invalidateState(1<<mActiveTrack);
- }
- return NO_ERROR;
- }
- }
- if (name == MAIN_BUFFER) {
- if (mState.tracks[ mActiveTrack ].mainBuffer != valueBuf) {
- mState.tracks[ mActiveTrack ].mainBuffer = valueBuf;
- LOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
- invalidateState(1<<mActiveTrack);
- }
- return NO_ERROR;
- }
- if (name == AUX_BUFFER) {
- if (mState.tracks[ mActiveTrack ].auxBuffer != valueBuf) {
- mState.tracks[ mActiveTrack ].auxBuffer = valueBuf;
- LOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
- invalidateState(1<<mActiveTrack);
- }
- return NO_ERROR;
- }
-
- break;
- case RESAMPLE:
- if (name == SAMPLE_RATE) {
- if (valueInt > 0) {
- track_t& track = mState.tracks[ mActiveTrack ];
- if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
- LOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
- uint32_t(valueInt));
- invalidateState(1<<mActiveTrack);
- }
- return NO_ERROR;
- }
- }
- break;
- case RAMP_VOLUME:
- case VOLUME:
- if ((uint32_t(name-VOLUME0) < MAX_NUM_CHANNELS)) {
- track_t& track = mState.tracks[ mActiveTrack ];
- if (track.volume[name-VOLUME0] != valueInt) {
- LOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
- track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16;
- track.volume[name-VOLUME0] = valueInt;
- if (target == VOLUME) {
- track.prevVolume[name-VOLUME0] = valueInt << 16;
- track.volumeInc[name-VOLUME0] = 0;
- } else {
- int32_t d = (valueInt<<16) - track.prevVolume[name-VOLUME0];
- int32_t volInc = d / int32_t(mState.frameCount);
- track.volumeInc[name-VOLUME0] = volInc;
- if (volInc == 0) {
- track.prevVolume[name-VOLUME0] = valueInt << 16;
- }
- }
- invalidateState(1<<mActiveTrack);
- }
- return NO_ERROR;
- } else if (name == AUXLEVEL) {
- track_t& track = mState.tracks[ mActiveTrack ];
- if (track.auxLevel != valueInt) {
- LOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
- track.prevAuxLevel = track.auxLevel << 16;
- track.auxLevel = valueInt;
- if (target == VOLUME) {
- track.prevAuxLevel = valueInt << 16;
- track.auxInc = 0;
- } else {
- int32_t d = (valueInt<<16) - track.prevAuxLevel;
- int32_t volInc = d / int32_t(mState.frameCount);
- track.auxInc = volInc;
- if (volInc == 0) {
- track.prevAuxLevel = valueInt << 16;
- }
- }
- invalidateState(1<<mActiveTrack);
- }
- return NO_ERROR;
- }
- break;
- }
- return BAD_VALUE;
-}
-
-bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
-{
- if (value!=devSampleRate || resampler) {
- if (sampleRate != value) {
- sampleRate = value;
- if (resampler == 0) {
- resampler = AudioResampler::create(
- format, channelCount, devSampleRate);
- }
- return true;
- }
- }
- return false;
-}
-
-bool AudioMixer::track_t::doesResample() const
-{
- return resampler != 0;
-}
-
-inline
-void AudioMixer::track_t::adjustVolumeRamp(bool aux)
-{
- for (int i=0 ; i<2 ; i++) {
- if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
- ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
- volumeInc[i] = 0;
- prevVolume[i] = volume[i]<<16;
- }
- }
- if (aux) {
- if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
- ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
- auxInc = 0;
- prevAuxLevel = auxLevel<<16;
- }
- }
-}
-
-
-status_t AudioMixer::setBufferProvider(AudioBufferProvider* buffer)
-{
- mState.tracks[ mActiveTrack ].bufferProvider = buffer;
- return NO_ERROR;
-}
-
-
-
-void AudioMixer::process()
-{
- mState.hook(&mState);
-}
-
-
-void AudioMixer::process__validate(state_t* state)
-{
- LOGW_IF(!state->needsChanged,
- "in process__validate() but nothing's invalid");
-
- uint32_t changed = state->needsChanged;
- state->needsChanged = 0; // clear the validation flag
-
- // recompute which tracks are enabled / disabled
- uint32_t enabled = 0;
- uint32_t disabled = 0;
- while (changed) {
- const int i = 31 - __builtin_clz(changed);
- const uint32_t mask = 1<<i;
- changed &= ~mask;
- track_t& t = state->tracks[i];
- (t.enabled ? enabled : disabled) |= mask;
- }
- state->enabledTracks &= ~disabled;
- state->enabledTracks |= enabled;
-
- // compute everything we need...
- int countActiveTracks = 0;
- int all16BitsStereoNoResample = 1;
- int resampling = 0;
- int volumeRamp = 0;
- uint32_t en = state->enabledTracks;
- while (en) {
- const int i = 31 - __builtin_clz(en);
- en &= ~(1<<i);
-
- countActiveTracks++;
- track_t& t = state->tracks[i];
- uint32_t n = 0;
- n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
- n |= NEEDS_FORMAT_16;
- n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
- if (t.auxLevel != 0 && t.auxBuffer != NULL) {
- n |= NEEDS_AUX_ENABLED;
- }
-
- if (t.volumeInc[0]|t.volumeInc[1]) {
- volumeRamp = 1;
- } else if (!t.doesResample() && t.volumeRL == 0) {
- n |= NEEDS_MUTE_ENABLED;
- }
- t.needs = n;
-
- if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
- t.hook = track__nop;
- } else {
- if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
- all16BitsStereoNoResample = 0;
- }
- if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
- all16BitsStereoNoResample = 0;
- resampling = 1;
- t.hook = track__genericResample;
- } else {
- if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
- t.hook = track__16BitsMono;
- all16BitsStereoNoResample = 0;
- }
- if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){
- t.hook = track__16BitsStereo;
- }
- }
- }
- }
-
- // select the processing hooks
- state->hook = process__nop;
- if (countActiveTracks) {
- if (resampling) {
- if (!state->outputTemp) {
- state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
- }
- if (!state->resampleTemp) {
- state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
- }
- state->hook = process__genericResampling;
- } else {
- if (state->outputTemp) {
- delete [] state->outputTemp;
- state->outputTemp = 0;
- }
- if (state->resampleTemp) {
- delete [] state->resampleTemp;
- state->resampleTemp = 0;
- }
- state->hook = process__genericNoResampling;
- if (all16BitsStereoNoResample && !volumeRamp) {
- if (countActiveTracks == 1) {
- state->hook = process__OneTrack16BitsStereoNoResampling;
- }
- }
- }
- }
-
- LOGV("mixer configuration change: %d activeTracks (%08x) "
- "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
- countActiveTracks, state->enabledTracks,
- all16BitsStereoNoResample, resampling, volumeRamp);
-
- state->hook(state);
-
- // Now that the volume ramp has been done, set optimal state and
- // track hooks for subsequent mixer process
- if (countActiveTracks) {
- int allMuted = 1;
- uint32_t en = state->enabledTracks;
- while (en) {
- const int i = 31 - __builtin_clz(en);
- en &= ~(1<<i);
- track_t& t = state->tracks[i];
- if (!t.doesResample() && t.volumeRL == 0)
- {
- t.needs |= NEEDS_MUTE_ENABLED;
- t.hook = track__nop;
- } else {
- allMuted = 0;
- }
- }
- if (allMuted) {
- state->hook = process__nop;
- } else if (all16BitsStereoNoResample) {
- if (countActiveTracks == 1) {
- state->hook = process__OneTrack16BitsStereoNoResampling;
- }
- }
- }
-}
-
-static inline
-int32_t mulAdd(int16_t in, int16_t v, int32_t a)
-{
-#if defined(__arm__) && !defined(__thumb__)
- int32_t out;
- asm( "smlabb %[out], %[in], %[v], %[a] \n"
- : [out]"=r"(out)
- : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
- : );
- return out;
-#else
- return a + in * int32_t(v);
-#endif
-}
-
-static inline
-int32_t mul(int16_t in, int16_t v)
-{
-#if defined(__arm__) && !defined(__thumb__)
- int32_t out;
- asm( "smulbb %[out], %[in], %[v] \n"
- : [out]"=r"(out)
- : [in]"%r"(in), [v]"r"(v)
- : );
- return out;
-#else
- return in * int32_t(v);
-#endif
-}
-
-static inline
-int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a)
-{
-#if defined(__arm__) && !defined(__thumb__)
- int32_t out;
- if (left) {
- asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n"
- : [out]"=r"(out)
- : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
- : );
- } else {
- asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n"
- : [out]"=r"(out)
- : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
- : );
- }
- return out;
-#else
- if (left) {
- return a + int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
- } else {
- return a + int16_t(inRL>>16) * int16_t(vRL>>16);
- }
-#endif
-}
-
-static inline
-int32_t mulRL(int left, uint32_t inRL, uint32_t vRL)
-{
-#if defined(__arm__) && !defined(__thumb__)
- int32_t out;
- if (left) {
- asm( "smulbb %[out], %[inRL], %[vRL] \n"
- : [out]"=r"(out)
- : [inRL]"%r"(inRL), [vRL]"r"(vRL)
- : );
- } else {
- asm( "smultt %[out], %[inRL], %[vRL] \n"
- : [out]"=r"(out)
- : [inRL]"%r"(inRL), [vRL]"r"(vRL)
- : );
- }
- return out;
-#else
- if (left) {
- return int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
- } else {
- return int16_t(inRL>>16) * int16_t(vRL>>16);
- }
-#endif
-}
-
-
-void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
-{
- t->resampler->setSampleRate(t->sampleRate);
-
- // ramp gain - resample to temp buffer and scale/mix in 2nd step
- if (aux != NULL) {
- // always resample with unity gain when sending to auxiliary buffer to be able
- // to apply send level after resampling
- // TODO: modify each resampler to support aux channel?
- t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
- memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
- t->resampler->resample(temp, outFrameCount, t->bufferProvider);
- if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
- volumeRampStereo(t, out, outFrameCount, temp, aux);
- } else {
- volumeStereo(t, out, outFrameCount, temp, aux);
- }
- } else {
- if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
- t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
- memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
- t->resampler->resample(temp, outFrameCount, t->bufferProvider);
- volumeRampStereo(t, out, outFrameCount, temp, aux);
- }
-
- // constant gain
- else {
- t->resampler->setVolume(t->volume[0], t->volume[1]);
- t->resampler->resample(out, outFrameCount, t->bufferProvider);
- }
- }
-}
-
-void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
-{
-}
-
-void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
-{
- int32_t vl = t->prevVolume[0];
- int32_t vr = t->prevVolume[1];
- const int32_t vlInc = t->volumeInc[0];
- const int32_t vrInc = t->volumeInc[1];
-
- //LOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
- // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
- // (vl + vlInc*frameCount)/65536.0f, frameCount);
-
- // ramp volume
- if UNLIKELY(aux != NULL) {
- int32_t va = t->prevAuxLevel;
- const int32_t vaInc = t->auxInc;
- int32_t l;
- int32_t r;
-
- do {
- l = (*temp++ >> 12);
- r = (*temp++ >> 12);
- *out++ += (vl >> 16) * l;
- *out++ += (vr >> 16) * r;
- *aux++ += (va >> 17) * (l + r);
- vl += vlInc;
- vr += vrInc;
- va += vaInc;
- } while (--frameCount);
- t->prevAuxLevel = va;
- } else {
- do {
- *out++ += (vl >> 16) * (*temp++ >> 12);
- *out++ += (vr >> 16) * (*temp++ >> 12);
- vl += vlInc;
- vr += vrInc;
- } while (--frameCount);
- }
- t->prevVolume[0] = vl;
- t->prevVolume[1] = vr;
- t->adjustVolumeRamp((aux != NULL));
-}
-
-void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
-{
- const int16_t vl = t->volume[0];
- const int16_t vr = t->volume[1];
-
- if UNLIKELY(aux != NULL) {
- const int16_t va = (int16_t)t->auxLevel;
- do {
- int16_t l = (int16_t)(*temp++ >> 12);
- int16_t r = (int16_t)(*temp++ >> 12);
- out[0] = mulAdd(l, vl, out[0]);
- int16_t a = (int16_t)(((int32_t)l + r) >> 1);
- out[1] = mulAdd(r, vr, out[1]);
- out += 2;
- aux[0] = mulAdd(a, va, aux[0]);
- aux++;
- } while (--frameCount);
- } else {
- do {
- int16_t l = (int16_t)(*temp++ >> 12);
- int16_t r = (int16_t)(*temp++ >> 12);
- out[0] = mulAdd(l, vl, out[0]);
- out[1] = mulAdd(r, vr, out[1]);
- out += 2;
- } while (--frameCount);
- }
-}
-
-void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
-{
- int16_t const *in = static_cast<int16_t const *>(t->in);
-
- if UNLIKELY(aux != NULL) {
- int32_t l;
- int32_t r;
- // ramp gain
- if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
- int32_t vl = t->prevVolume[0];
- int32_t vr = t->prevVolume[1];
- int32_t va = t->prevAuxLevel;
- const int32_t vlInc = t->volumeInc[0];
- const int32_t vrInc = t->volumeInc[1];
- const int32_t vaInc = t->auxInc;
- // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
- // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
- // (vl + vlInc*frameCount)/65536.0f, frameCount);
-
- do {
- l = (int32_t)*in++;
- r = (int32_t)*in++;
- *out++ += (vl >> 16) * l;
- *out++ += (vr >> 16) * r;
- *aux++ += (va >> 17) * (l + r);
- vl += vlInc;
- vr += vrInc;
- va += vaInc;
- } while (--frameCount);
-
- t->prevVolume[0] = vl;
- t->prevVolume[1] = vr;
- t->prevAuxLevel = va;
- t->adjustVolumeRamp(true);
- }
-
- // constant gain
- else {
- const uint32_t vrl = t->volumeRL;
- const int16_t va = (int16_t)t->auxLevel;
- do {
- uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
- int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
- in += 2;
- out[0] = mulAddRL(1, rl, vrl, out[0]);
- out[1] = mulAddRL(0, rl, vrl, out[1]);
- out += 2;
- aux[0] = mulAdd(a, va, aux[0]);
- aux++;
- } while (--frameCount);
- }
- } else {
- // ramp gain
- if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
- int32_t vl = t->prevVolume[0];
- int32_t vr = t->prevVolume[1];
- const int32_t vlInc = t->volumeInc[0];
- const int32_t vrInc = t->volumeInc[1];
-
- // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
- // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
- // (vl + vlInc*frameCount)/65536.0f, frameCount);
-
- do {
- *out++ += (vl >> 16) * (int32_t) *in++;
- *out++ += (vr >> 16) * (int32_t) *in++;
- vl += vlInc;
- vr += vrInc;
- } while (--frameCount);
-
- t->prevVolume[0] = vl;
- t->prevVolume[1] = vr;
- t->adjustVolumeRamp(false);
- }
-
- // constant gain
- else {
- const uint32_t vrl = t->volumeRL;
- do {
- uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
- in += 2;
- out[0] = mulAddRL(1, rl, vrl, out[0]);
- out[1] = mulAddRL(0, rl, vrl, out[1]);
- out += 2;
- } while (--frameCount);
- }
- }
- t->in = in;
-}
-
-void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
-{
- int16_t const *in = static_cast<int16_t const *>(t->in);
-
- if UNLIKELY(aux != NULL) {
- // ramp gain
- if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
- int32_t vl = t->prevVolume[0];
- int32_t vr = t->prevVolume[1];
- int32_t va = t->prevAuxLevel;
- const int32_t vlInc = t->volumeInc[0];
- const int32_t vrInc = t->volumeInc[1];
- const int32_t vaInc = t->auxInc;
-
- // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
- // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
- // (vl + vlInc*frameCount)/65536.0f, frameCount);
-
- do {
- int32_t l = *in++;
- *out++ += (vl >> 16) * l;
- *out++ += (vr >> 16) * l;
- *aux++ += (va >> 16) * l;
- vl += vlInc;
- vr += vrInc;
- va += vaInc;
- } while (--frameCount);
-
- t->prevVolume[0] = vl;
- t->prevVolume[1] = vr;
- t->prevAuxLevel = va;
- t->adjustVolumeRamp(true);
- }
- // constant gain
- else {
- const int16_t vl = t->volume[0];
- const int16_t vr = t->volume[1];
- const int16_t va = (int16_t)t->auxLevel;
- do {
- int16_t l = *in++;
- out[0] = mulAdd(l, vl, out[0]);
- out[1] = mulAdd(l, vr, out[1]);
- out += 2;
- aux[0] = mulAdd(l, va, aux[0]);
- aux++;
- } while (--frameCount);
- }
- } else {
- // ramp gain
- if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
- int32_t vl = t->prevVolume[0];
- int32_t vr = t->prevVolume[1];
- const int32_t vlInc = t->volumeInc[0];
- const int32_t vrInc = t->volumeInc[1];
-
- // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
- // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
- // (vl + vlInc*frameCount)/65536.0f, frameCount);
-
- do {
- int32_t l = *in++;
- *out++ += (vl >> 16) * l;
- *out++ += (vr >> 16) * l;
- vl += vlInc;
- vr += vrInc;
- } while (--frameCount);
-
- t->prevVolume[0] = vl;
- t->prevVolume[1] = vr;
- t->adjustVolumeRamp(false);
- }
- // constant gain
- else {
- const int16_t vl = t->volume[0];
- const int16_t vr = t->volume[1];
- do {
- int16_t l = *in++;
- out[0] = mulAdd(l, vl, out[0]);
- out[1] = mulAdd(l, vr, out[1]);
- out += 2;
- } while (--frameCount);
- }
- }
- t->in = in;
-}
-
-void AudioMixer::ditherAndClamp(int32_t* out, int32_t const *sums, size_t c)
-{
- for (size_t i=0 ; i<c ; i++) {
- int32_t l = *sums++;
- int32_t r = *sums++;
- int32_t nl = l >> 12;
- int32_t nr = r >> 12;
- l = clamp16(nl);
- r = clamp16(nr);
- *out++ = (r<<16) | (l & 0xFFFF);
- }
-}
-
-// no-op case
-void AudioMixer::process__nop(state_t* state)
-{
- uint32_t e0 = state->enabledTracks;
- size_t bufSize = state->frameCount * sizeof(int16_t) * MAX_NUM_CHANNELS;
- while (e0) {
- // process by group of tracks with same output buffer to
- // avoid multiple memset() on same buffer
- uint32_t e1 = e0, e2 = e0;
- int i = 31 - __builtin_clz(e1);
- track_t& t1 = state->tracks[i];
- e2 &= ~(1<<i);
- while (e2) {
- i = 31 - __builtin_clz(e2);
- e2 &= ~(1<<i);
- track_t& t2 = state->tracks[i];
- if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
- e1 &= ~(1<<i);
- }
- }
- e0 &= ~(e1);
-
- memset(t1.mainBuffer, 0, bufSize);
-
- while (e1) {
- i = 31 - __builtin_clz(e1);
- e1 &= ~(1<<i);
- t1 = state->tracks[i];
- size_t outFrames = state->frameCount;
- while (outFrames) {
- t1.buffer.frameCount = outFrames;
- t1.bufferProvider->getNextBuffer(&t1.buffer);
- if (!t1.buffer.raw) break;
- outFrames -= t1.buffer.frameCount;
- t1.bufferProvider->releaseBuffer(&t1.buffer);
- }
- }
- }
-}
-
-// generic code without resampling
-void AudioMixer::process__genericNoResampling(state_t* state)
-{
- int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
-
- // acquire each track's buffer
- uint32_t enabledTracks = state->enabledTracks;
- uint32_t e0 = enabledTracks;
- while (e0) {
- const int i = 31 - __builtin_clz(e0);
- e0 &= ~(1<<i);
- track_t& t = state->tracks[i];
- t.buffer.frameCount = state->frameCount;
- t.bufferProvider->getNextBuffer(&t.buffer);
- t.frameCount = t.buffer.frameCount;
- t.in = t.buffer.raw;
- // t.in == NULL can happen if the track was flushed just after having
- // been enabled for mixing.
- if (t.in == NULL)
- enabledTracks &= ~(1<<i);
- }
-
- e0 = enabledTracks;
- while (e0) {
- // process by group of tracks with same output buffer to
- // optimize cache use
- uint32_t e1 = e0, e2 = e0;
- int j = 31 - __builtin_clz(e1);
- track_t& t1 = state->tracks[j];
- e2 &= ~(1<<j);
- while (e2) {
- j = 31 - __builtin_clz(e2);
- e2 &= ~(1<<j);
- track_t& t2 = state->tracks[j];
- if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
- e1 &= ~(1<<j);
- }
- }
- e0 &= ~(e1);
- // this assumes output 16 bits stereo, no resampling
- int32_t *out = t1.mainBuffer;
- size_t numFrames = 0;
- do {
- memset(outTemp, 0, sizeof(outTemp));
- e2 = e1;
- while (e2) {
- const int i = 31 - __builtin_clz(e2);
- e2 &= ~(1<<i);
- track_t& t = state->tracks[i];
- size_t outFrames = BLOCKSIZE;
- int32_t *aux = NULL;
- if UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
- aux = t.auxBuffer + numFrames;
- }
- while (outFrames) {
- size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
- if (inFrames) {
- (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp, aux);
- t.frameCount -= inFrames;
- outFrames -= inFrames;
- if UNLIKELY(aux != NULL) {
- aux += inFrames;
- }
- }
- if (t.frameCount == 0 && outFrames) {
- t.bufferProvider->releaseBuffer(&t.buffer);
- t.buffer.frameCount = (state->frameCount - numFrames) - (BLOCKSIZE - outFrames);
- t.bufferProvider->getNextBuffer(&t.buffer);
- t.in = t.buffer.raw;
- if (t.in == NULL) {
- enabledTracks &= ~(1<<i);
- e1 &= ~(1<<i);
- break;
- }
- t.frameCount = t.buffer.frameCount;
- }
- }
- }
- ditherAndClamp(out, outTemp, BLOCKSIZE);
- out += BLOCKSIZE;
- numFrames += BLOCKSIZE;
- } while (numFrames < state->frameCount);
- }
-
- // release each track's buffer
- e0 = enabledTracks;
- while (e0) {
- const int i = 31 - __builtin_clz(e0);
- e0 &= ~(1<<i);
- track_t& t = state->tracks[i];
- t.bufferProvider->releaseBuffer(&t.buffer);
- }
-}
-
-
- // generic code with resampling
-void AudioMixer::process__genericResampling(state_t* state)
-{
- int32_t* const outTemp = state->outputTemp;
- const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
- memset(outTemp, 0, size);
-
- size_t numFrames = state->frameCount;
-
- uint32_t e0 = state->enabledTracks;
- while (e0) {
- // process by group of tracks with same output buffer
- // to optimize cache use
- uint32_t e1 = e0, e2 = e0;
- int j = 31 - __builtin_clz(e1);
- track_t& t1 = state->tracks[j];
- e2 &= ~(1<<j);
- while (e2) {
- j = 31 - __builtin_clz(e2);
- e2 &= ~(1<<j);
- track_t& t2 = state->tracks[j];
- if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
- e1 &= ~(1<<j);
- }
- }
- e0 &= ~(e1);
- int32_t *out = t1.mainBuffer;
- while (e1) {
- const int i = 31 - __builtin_clz(e1);
- e1 &= ~(1<<i);
- track_t& t = state->tracks[i];
- int32_t *aux = NULL;
- if UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
- aux = t.auxBuffer;
- }
-
- // this is a little goofy, on the resampling case we don't
- // acquire/release the buffers because it's done by
- // the resampler.
- if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
- (t.hook)(&t, outTemp, numFrames, state->resampleTemp, aux);
- } else {
-
- size_t outFrames = 0;
-
- while (outFrames < numFrames) {
- t.buffer.frameCount = numFrames - outFrames;
- t.bufferProvider->getNextBuffer(&t.buffer);
- t.in = t.buffer.raw;
- // t.in == NULL can happen if the track was flushed just after having
- // been enabled for mixing.
- if (t.in == NULL) break;
-
- if UNLIKELY(aux != NULL) {
- aux += outFrames;
- }
- (t.hook)(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp, aux);
- outFrames += t.buffer.frameCount;
- t.bufferProvider->releaseBuffer(&t.buffer);
- }
- }
- }
- ditherAndClamp(out, outTemp, numFrames);
- }
-}
-
-// one track, 16 bits stereo without resampling is the most common case
-void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state)
-{
- const int i = 31 - __builtin_clz(state->enabledTracks);
- const track_t& t = state->tracks[i];
-
- AudioBufferProvider::Buffer& b(t.buffer);
-
- int32_t* out = t.mainBuffer;
- size_t numFrames = state->frameCount;
-
- const int16_t vl = t.volume[0];
- const int16_t vr = t.volume[1];
- const uint32_t vrl = t.volumeRL;
- while (numFrames) {
- b.frameCount = numFrames;
- t.bufferProvider->getNextBuffer(&b);
- int16_t const *in = b.i16;
-
- // in == NULL can happen if the track was flushed just after having
- // been enabled for mixing.
- if (in == NULL || ((unsigned long)in & 3)) {
- memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
- LOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x",
- in, i, t.channelCount, t.needs);
- return;
- }
- size_t outFrames = b.frameCount;
-
- if (UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
- // volume is boosted, so we might need to clamp even though
- // we process only one track.
- do {
- uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
- in += 2;
- int32_t l = mulRL(1, rl, vrl) >> 12;
- int32_t r = mulRL(0, rl, vrl) >> 12;
- // clamping...
- l = clamp16(l);
- r = clamp16(r);
- *out++ = (r<<16) | (l & 0xFFFF);
- } while (--outFrames);
- } else {
- do {
- uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
- in += 2;
- int32_t l = mulRL(1, rl, vrl) >> 12;
- int32_t r = mulRL(0, rl, vrl) >> 12;
- *out++ = (r<<16) | (l & 0xFFFF);
- } while (--outFrames);
- }
- numFrames -= b.frameCount;
- t.bufferProvider->releaseBuffer(&b);
- }
-}
-
-// 2 tracks is also a common case
-// NEVER used in current implementation of process__validate()
-// only use if the 2 tracks have the same output buffer
-void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state)
-{
- int i;
- uint32_t en = state->enabledTracks;
-
- i = 31 - __builtin_clz(en);
- const track_t& t0 = state->tracks[i];
- AudioBufferProvider::Buffer& b0(t0.buffer);
-
- en &= ~(1<<i);
- i = 31 - __builtin_clz(en);
- const track_t& t1 = state->tracks[i];
- AudioBufferProvider::Buffer& b1(t1.buffer);
-
- int16_t const *in0;
- const int16_t vl0 = t0.volume[0];
- const int16_t vr0 = t0.volume[1];
- size_t frameCount0 = 0;
-
- int16_t const *in1;
- const int16_t vl1 = t1.volume[0];
- const int16_t vr1 = t1.volume[1];
- size_t frameCount1 = 0;
-
- //FIXME: only works if two tracks use same buffer
- int32_t* out = t0.mainBuffer;
- size_t numFrames = state->frameCount;
- int16_t const *buff = NULL;
-
-
- while (numFrames) {
-
- if (frameCount0 == 0) {
- b0.frameCount = numFrames;
- t0.bufferProvider->getNextBuffer(&b0);
- if (b0.i16 == NULL) {
- if (buff == NULL) {
- buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
- }
- in0 = buff;
- b0.frameCount = numFrames;
- } else {
- in0 = b0.i16;
- }
- frameCount0 = b0.frameCount;
- }
- if (frameCount1 == 0) {
- b1.frameCount = numFrames;
- t1.bufferProvider->getNextBuffer(&b1);
- if (b1.i16 == NULL) {
- if (buff == NULL) {
- buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
- }
- in1 = buff;
- b1.frameCount = numFrames;
- } else {
- in1 = b1.i16;
- }
- frameCount1 = b1.frameCount;
- }
-
- size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
-
- numFrames -= outFrames;
- frameCount0 -= outFrames;
- frameCount1 -= outFrames;
-
- do {
- int32_t l0 = *in0++;
- int32_t r0 = *in0++;
- l0 = mul(l0, vl0);
- r0 = mul(r0, vr0);
- int32_t l = *in1++;
- int32_t r = *in1++;
- l = mulAdd(l, vl1, l0) >> 12;
- r = mulAdd(r, vr1, r0) >> 12;
- // clamping...
- l = clamp16(l);
- r = clamp16(r);
- *out++ = (r<<16) | (l & 0xFFFF);
- } while (--outFrames);
-
- if (frameCount0 == 0) {
- t0.bufferProvider->releaseBuffer(&b0);
- }
- if (frameCount1 == 0) {
- t1.bufferProvider->releaseBuffer(&b1);
- }
- }
-
- if (buff != NULL) {
- delete [] buff;
- }
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/libs/audioflinger/AudioMixer.h b/libs/audioflinger/AudioMixer.h
deleted file mode 100644
index aee3e17..0000000
--- a/libs/audioflinger/AudioMixer.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/* //device/include/server/AudioFlinger/AudioMixer.h
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_AUDIO_MIXER_H
-#define ANDROID_AUDIO_MIXER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "AudioBufferProvider.h"
-#include "AudioResampler.h"
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
-#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
-
-// ----------------------------------------------------------------------------
-
-class AudioMixer
-{
-public:
- AudioMixer(size_t frameCount, uint32_t sampleRate);
-
- ~AudioMixer();
-
- static const uint32_t MAX_NUM_TRACKS = 32;
- static const uint32_t MAX_NUM_CHANNELS = 2;
-
- static const uint16_t UNITY_GAIN = 0x1000;
-
- enum { // names
-
- // track units (32 units)
- TRACK0 = 0x1000,
-
- // enable/disable
- MIXING = 0x2000,
-
- // setParameter targets
- TRACK = 0x3000,
- RESAMPLE = 0x3001,
- RAMP_VOLUME = 0x3002, // ramp to new volume
- VOLUME = 0x3003, // don't ramp
-
- // set Parameter names
- // for target TRACK
- CHANNEL_COUNT = 0x4000,
- FORMAT = 0x4001,
- MAIN_BUFFER = 0x4002,
- AUX_BUFFER = 0x4003,
- // for TARGET RESAMPLE
- SAMPLE_RATE = 0x4100,
- // for TARGET VOLUME (8 channels max)
- VOLUME0 = 0x4200,
- VOLUME1 = 0x4201,
- AUXLEVEL = 0x4210,
- };
-
-
- int getTrackName();
- void deleteTrackName(int name);
-
- status_t enable(int name);
- status_t disable(int name);
-
- status_t setActiveTrack(int track);
- status_t setParameter(int target, int name, void *value);
-
- status_t setBufferProvider(AudioBufferProvider* bufferProvider);
- void process();
-
- uint32_t trackNames() const { return mTrackNames; }
-
- static void ditherAndClamp(int32_t* out, int32_t const *sums, size_t c);
-
-private:
-
- enum {
- NEEDS_CHANNEL_COUNT__MASK = 0x00000003,
- NEEDS_FORMAT__MASK = 0x000000F0,
- NEEDS_MUTE__MASK = 0x00000100,
- NEEDS_RESAMPLE__MASK = 0x00001000,
- NEEDS_AUX__MASK = 0x00010000,
- };
-
- enum {
- NEEDS_CHANNEL_1 = 0x00000000,
- NEEDS_CHANNEL_2 = 0x00000001,
-
- NEEDS_FORMAT_16 = 0x00000010,
-
- NEEDS_MUTE_DISABLED = 0x00000000,
- NEEDS_MUTE_ENABLED = 0x00000100,
-
- NEEDS_RESAMPLE_DISABLED = 0x00000000,
- NEEDS_RESAMPLE_ENABLED = 0x00001000,
-
- NEEDS_AUX_DISABLED = 0x00000000,
- NEEDS_AUX_ENABLED = 0x00010000,
- };
-
- static inline int32_t applyVolume(int32_t in, int32_t v) {
- return in * v;
- }
-
-
- struct state_t;
- struct track_t;
-
- typedef void (*mix_t)(state_t* state);
- typedef void (*hook_t)(track_t* t, int32_t* output, size_t numOutFrames, int32_t* temp, int32_t* aux);
- static const int BLOCKSIZE = 16; // 4 cache lines
-
- struct track_t {
- uint32_t needs;
-
- union {
- int16_t volume[2]; // [0]3.12 fixed point
- int32_t volumeRL;
- };
-
- int32_t prevVolume[2];
-
- int32_t volumeInc[2];
- int32_t auxLevel;
- int32_t auxInc;
- int32_t prevAuxLevel;
-
- uint16_t frameCount;
-
- uint8_t channelCount : 4;
- uint8_t enabled : 1;
- uint8_t reserved0 : 3;
- uint8_t format;
-
- AudioBufferProvider* bufferProvider;
- mutable AudioBufferProvider::Buffer buffer;
-
- hook_t hook;
- void const* in; // current location in buffer
-
- AudioResampler* resampler;
- uint32_t sampleRate;
- int32_t* mainBuffer;
- int32_t* auxBuffer;
-
- bool setResampler(uint32_t sampleRate, uint32_t devSampleRate);
- bool doesResample() const;
- void adjustVolumeRamp(bool aux);
- };
-
- // pad to 32-bytes to fill cache line
- struct state_t {
- uint32_t enabledTracks;
- uint32_t needsChanged;
- size_t frameCount;
- mix_t hook;
- int32_t *outputTemp;
- int32_t *resampleTemp;
- int32_t reserved[2];
- track_t tracks[32]; __attribute__((aligned(32)));
- };
-
- int mActiveTrack;
- uint32_t mTrackNames;
- const uint32_t mSampleRate;
-
- state_t mState __attribute__((aligned(32)));
-
- void invalidateState(uint32_t mask);
-
- static void track__genericResample(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
- static void track__nop(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
- static void track__16BitsStereo(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
- static void track__16BitsMono(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
- static void volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
- static void volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
-
- static void process__validate(state_t* state);
- static void process__nop(state_t* state);
- static void process__genericNoResampling(state_t* state);
- static void process__genericResampling(state_t* state);
- static void process__OneTrack16BitsStereoNoResampling(state_t* state);
- static void process__TwoTracks16BitsStereoNoResampling(state_t* state);
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_AUDIO_MIXER_H
diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/libs/audioflinger/AudioPolicyManagerBase.cpp
deleted file mode 100644
index 381a958..0000000
--- a/libs/audioflinger/AudioPolicyManagerBase.cpp
+++ /dev/null
@@ -1,1973 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "AudioPolicyManagerBase"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-#include <hardware_legacy/AudioPolicyManagerBase.h>
-#include <media/mediarecorder.h>
-
-namespace android {
-
-
-// ----------------------------------------------------------------------------
-// AudioPolicyInterface implementation
-// ----------------------------------------------------------------------------
-
-
-status_t AudioPolicyManagerBase::setDeviceConnectionState(AudioSystem::audio_devices device,
- AudioSystem::device_connection_state state,
- const char *device_address)
-{
-
- LOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address);
-
- // connect/disconnect only 1 device at a time
- if (AudioSystem::popCount(device) != 1) return BAD_VALUE;
-
- if (strlen(device_address) >= MAX_DEVICE_ADDRESS_LEN) {
- LOGE("setDeviceConnectionState() invalid address: %s", device_address);
- return BAD_VALUE;
- }
-
- // handle output devices
- if (AudioSystem::isOutputDevice(device)) {
-
-#ifndef WITH_A2DP
- if (AudioSystem::isA2dpDevice(device)) {
- LOGE("setDeviceConnectionState() invalid device: %x", device);
- return BAD_VALUE;
- }
-#endif
-
- switch (state)
- {
- // handle output device connection
- case AudioSystem::DEVICE_STATE_AVAILABLE:
- if (mAvailableOutputDevices & device) {
- LOGW("setDeviceConnectionState() device already connected: %x", device);
- return INVALID_OPERATION;
- }
- LOGV("setDeviceConnectionState() connecting device %x", device);
-
- // register new device as available
- mAvailableOutputDevices |= device;
-
-#ifdef WITH_A2DP
- // handle A2DP device connection
- if (AudioSystem::isA2dpDevice(device)) {
- status_t status = handleA2dpConnection(device, device_address);
- if (status != NO_ERROR) {
- mAvailableOutputDevices &= ~device;
- return status;
- }
- } else
-#endif
- {
- if (AudioSystem::isBluetoothScoDevice(device)) {
- LOGV("setDeviceConnectionState() BT SCO device, address %s", device_address);
- // keep track of SCO device address
- mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
-#ifdef WITH_A2DP
- if (mA2dpOutput != 0 &&
- mPhoneState != AudioSystem::MODE_NORMAL) {
- mpClientInterface->suspendOutput(mA2dpOutput);
- }
-#endif
- }
- }
- break;
- // handle output device disconnection
- case AudioSystem::DEVICE_STATE_UNAVAILABLE: {
- if (!(mAvailableOutputDevices & device)) {
- LOGW("setDeviceConnectionState() device not connected: %x", device);
- return INVALID_OPERATION;
- }
-
-
- LOGV("setDeviceConnectionState() disconnecting device %x", device);
- // remove device from available output devices
- mAvailableOutputDevices &= ~device;
-
-#ifdef WITH_A2DP
- // handle A2DP device disconnection
- if (AudioSystem::isA2dpDevice(device)) {
- status_t status = handleA2dpDisconnection(device, device_address);
- if (status != NO_ERROR) {
- mAvailableOutputDevices |= device;
- return status;
- }
- } else
-#endif
- {
- if (AudioSystem::isBluetoothScoDevice(device)) {
- mScoDeviceAddress = "";
-#ifdef WITH_A2DP
- if (mA2dpOutput != 0 &&
- mPhoneState != AudioSystem::MODE_NORMAL) {
- mpClientInterface->restoreOutput(mA2dpOutput);
- }
-#endif
- }
- }
- } break;
-
- default:
- LOGE("setDeviceConnectionState() invalid state: %x", state);
- return BAD_VALUE;
- }
-
- // request routing change if necessary
- uint32_t newDevice = getNewDevice(mHardwareOutput, false);
-#ifdef WITH_A2DP
- checkOutputForAllStrategies(newDevice);
- // A2DP outputs must be closed after checkOutputForAllStrategies() is executed
- if (state == AudioSystem::DEVICE_STATE_UNAVAILABLE && AudioSystem::isA2dpDevice(device)) {
- closeA2dpOutputs();
- }
-#endif
- updateDeviceForStrategy();
- setOutputDevice(mHardwareOutput, newDevice);
-
- if (device == AudioSystem::DEVICE_OUT_WIRED_HEADSET) {
- device = AudioSystem::DEVICE_IN_WIRED_HEADSET;
- } else if (device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO ||
- device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET ||
- device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
- device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET;
- } else {
- return NO_ERROR;
- }
- }
- // handle input devices
- if (AudioSystem::isInputDevice(device)) {
-
- switch (state)
- {
- // handle input device connection
- case AudioSystem::DEVICE_STATE_AVAILABLE: {
- if (mAvailableInputDevices & device) {
- LOGW("setDeviceConnectionState() device already connected: %d", device);
- return INVALID_OPERATION;
- }
- mAvailableInputDevices |= device;
- }
- break;
-
- // handle input device disconnection
- case AudioSystem::DEVICE_STATE_UNAVAILABLE: {
- if (!(mAvailableInputDevices & device)) {
- LOGW("setDeviceConnectionState() device not connected: %d", device);
- return INVALID_OPERATION;
- }
- mAvailableInputDevices &= ~device;
- } break;
-
- default:
- LOGE("setDeviceConnectionState() invalid state: %x", state);
- return BAD_VALUE;
- }
-
- audio_io_handle_t activeInput = getActiveInput();
- if (activeInput != 0) {
- AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);
- uint32_t newDevice = getDeviceForInputSource(inputDesc->mInputSource);
- if (newDevice != inputDesc->mDevice) {
- LOGV("setDeviceConnectionState() changing device from %x to %x for input %d",
- inputDesc->mDevice, newDevice, activeInput);
- inputDesc->mDevice = newDevice;
- AudioParameter param = AudioParameter();
- param.addInt(String8(AudioParameter::keyRouting), (int)newDevice);
- mpClientInterface->setParameters(activeInput, param.toString());
- }
- }
-
- return NO_ERROR;
- }
-
- LOGW("setDeviceConnectionState() invalid device: %x", device);
- return BAD_VALUE;
-}
-
-AudioSystem::device_connection_state AudioPolicyManagerBase::getDeviceConnectionState(AudioSystem::audio_devices device,
- const char *device_address)
-{
- AudioSystem::device_connection_state state = AudioSystem::DEVICE_STATE_UNAVAILABLE;
- String8 address = String8(device_address);
- if (AudioSystem::isOutputDevice(device)) {
- if (device & mAvailableOutputDevices) {
-#ifdef WITH_A2DP
- if (AudioSystem::isA2dpDevice(device) &&
- address != "" && mA2dpDeviceAddress != address) {
- return state;
- }
-#endif
- if (AudioSystem::isBluetoothScoDevice(device) &&
- address != "" && mScoDeviceAddress != address) {
- return state;
- }
- state = AudioSystem::DEVICE_STATE_AVAILABLE;
- }
- } else if (AudioSystem::isInputDevice(device)) {
- if (device & mAvailableInputDevices) {
- state = AudioSystem::DEVICE_STATE_AVAILABLE;
- }
- }
-
- return state;
-}
-
-void AudioPolicyManagerBase::setPhoneState(int state)
-{
- LOGV("setPhoneState() state %d", state);
- uint32_t newDevice = 0;
- if (state < 0 || state >= AudioSystem::NUM_MODES) {
- LOGW("setPhoneState() invalid state %d", state);
- return;
- }
-
- if (state == mPhoneState ) {
- LOGW("setPhoneState() setting same state %d", state);
- return;
- }
-
- // if leaving call state, handle special case of active streams
- // pertaining to sonification strategy see handleIncallSonification()
- if (mPhoneState == AudioSystem::MODE_IN_CALL) {
- LOGV("setPhoneState() in call state management: new state is %d", state);
- for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
- handleIncallSonification(stream, false, true);
- }
- }
-
- // store previous phone state for management of sonification strategy below
- int oldState = mPhoneState;
- mPhoneState = state;
- bool force = false;
-
- // are we entering or starting a call
- if ((oldState != AudioSystem::MODE_IN_CALL) && (state == AudioSystem::MODE_IN_CALL)) {
- LOGV(" Entering call in setPhoneState()");
- // force routing command to audio hardware when starting a call
- // even if no device change is needed
- force = true;
- } else if ((oldState == AudioSystem::MODE_IN_CALL) && (state != AudioSystem::MODE_IN_CALL)) {
- LOGV(" Exiting call in setPhoneState()");
- // force routing command to audio hardware when exiting a call
- // even if no device change is needed
- force = true;
- }
-
- // check for device and output changes triggered by new phone state
- newDevice = getNewDevice(mHardwareOutput, false);
-#ifdef WITH_A2DP
- checkOutputForAllStrategies(newDevice);
- // suspend A2DP output if a SCO device is present.
- if (mA2dpOutput != 0 && mScoDeviceAddress != "") {
- if (oldState == AudioSystem::MODE_NORMAL) {
- mpClientInterface->suspendOutput(mA2dpOutput);
- } else if (state == AudioSystem::MODE_NORMAL) {
- mpClientInterface->restoreOutput(mA2dpOutput);
- }
- }
-#endif
- updateDeviceForStrategy();
-
- AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
-
- // force routing command to audio hardware when ending call
- // even if no device change is needed
- if (oldState == AudioSystem::MODE_IN_CALL && newDevice == 0) {
- newDevice = hwOutputDesc->device();
- }
-
- // when changing from ring tone to in call mode, mute the ringing tone
- // immediately and delay the route change to avoid sending the ring tone
- // tail into the earpiece or headset.
- int delayMs = 0;
- if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) {
- // delay the device change command by twice the output latency to have some margin
- // and be sure that audio buffers not yet affected by the mute are out when
- // we actually apply the route change
- delayMs = hwOutputDesc->mLatency*2;
- setStreamMute(AudioSystem::RING, true, mHardwareOutput);
- }
-
- // change routing is necessary
- setOutputDevice(mHardwareOutput, newDevice, force, delayMs);
-
- // if entering in call state, handle special case of active streams
- // pertaining to sonification strategy see handleIncallSonification()
- if (state == AudioSystem::MODE_IN_CALL) {
- LOGV("setPhoneState() in call state management: new state is %d", state);
- // unmute the ringing tone after a sufficient delay if it was muted before
- // setting output device above
- if (oldState == AudioSystem::MODE_RINGTONE) {
- setStreamMute(AudioSystem::RING, false, mHardwareOutput, MUTE_TIME_MS);
- }
- for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
- handleIncallSonification(stream, true, true);
- }
- }
-
- // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE
- if (state == AudioSystem::MODE_RINGTONE &&
- (hwOutputDesc->mRefCount[AudioSystem::MUSIC] ||
- (systemTime() - mMusicStopTime) < seconds(SONIFICATION_HEADSET_MUSIC_DELAY))) {
- mLimitRingtoneVolume = true;
- } else {
- mLimitRingtoneVolume = false;
- }
-}
-
-void AudioPolicyManagerBase::setRingerMode(uint32_t mode, uint32_t mask)
-{
- LOGV("setRingerMode() mode %x, mask %x", mode, mask);
-
- mRingerMode = mode;
-}
-
-void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
-{
- LOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState);
-
- bool forceVolumeReeval = false;
- switch(usage) {
- case AudioSystem::FOR_COMMUNICATION:
- if (config != AudioSystem::FORCE_SPEAKER && config != AudioSystem::FORCE_BT_SCO &&
- config != AudioSystem::FORCE_NONE) {
- LOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
- return;
- }
- mForceUse[usage] = config;
- break;
- case AudioSystem::FOR_MEDIA:
- if (config != AudioSystem::FORCE_HEADPHONES && config != AudioSystem::FORCE_BT_A2DP &&
- config != AudioSystem::FORCE_WIRED_ACCESSORY && config != AudioSystem::FORCE_NONE) {
- LOGW("setForceUse() invalid config %d for FOR_MEDIA", config);
- return;
- }
- mForceUse[usage] = config;
- break;
- case AudioSystem::FOR_RECORD:
- if (config != AudioSystem::FORCE_BT_SCO && config != AudioSystem::FORCE_WIRED_ACCESSORY &&
- config != AudioSystem::FORCE_NONE) {
- LOGW("setForceUse() invalid config %d for FOR_RECORD", config);
- return;
- }
- mForceUse[usage] = config;
- break;
- case AudioSystem::FOR_DOCK:
- if (config != AudioSystem::FORCE_NONE && config != AudioSystem::FORCE_BT_CAR_DOCK &&
- config != AudioSystem::FORCE_BT_DESK_DOCK && config != AudioSystem::FORCE_WIRED_ACCESSORY) {
- LOGW("setForceUse() invalid config %d for FOR_DOCK", config);
- }
- forceVolumeReeval = true;
- mForceUse[usage] = config;
- break;
- default:
- LOGW("setForceUse() invalid usage %d", usage);
- break;
- }
-
- // check for device and output changes triggered by new phone state
- uint32_t newDevice = getNewDevice(mHardwareOutput, false);
-#ifdef WITH_A2DP
- checkOutputForAllStrategies(newDevice);
-#endif
- updateDeviceForStrategy();
- setOutputDevice(mHardwareOutput, newDevice);
- if (forceVolumeReeval) {
- applyStreamVolumes(mHardwareOutput, newDevice);
- }
-}
-
-AudioSystem::forced_config AudioPolicyManagerBase::getForceUse(AudioSystem::force_use usage)
-{
- return mForceUse[usage];
-}
-
-void AudioPolicyManagerBase::setSystemProperty(const char* property, const char* value)
-{
- LOGV("setSystemProperty() property %s, value %s", property, value);
- if (strcmp(property, "ro.camera.sound.forced") == 0) {
- if (atoi(value)) {
- LOGV("ENFORCED_AUDIBLE cannot be muted");
- mStreams[AudioSystem::ENFORCED_AUDIBLE].mCanBeMuted = false;
- } else {
- LOGV("ENFORCED_AUDIBLE can be muted");
- mStreams[AudioSystem::ENFORCED_AUDIBLE].mCanBeMuted = true;
- }
- }
-}
-
-audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type stream,
- uint32_t samplingRate,
- uint32_t format,
- uint32_t channels,
- AudioSystem::output_flags flags)
-{
- audio_io_handle_t output = 0;
- uint32_t latency = 0;
- routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
- uint32_t device = getDeviceForStrategy(strategy);
- LOGV("getOutput() stream %d, samplingRate %d, format %d, channels %x, flags %x", stream, samplingRate, format, channels, flags);
-
-#ifdef AUDIO_POLICY_TEST
- if (mCurOutput != 0) {
- LOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channels %x, mDirectOutput %d",
- mCurOutput, mTestSamplingRate, mTestFormat, mTestChannels, mDirectOutput);
-
- if (mTestOutputs[mCurOutput] == 0) {
- LOGV("getOutput() opening test output");
- AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
- outputDesc->mDevice = mTestDevice;
- outputDesc->mSamplingRate = mTestSamplingRate;
- outputDesc->mFormat = mTestFormat;
- outputDesc->mChannels = mTestChannels;
- outputDesc->mLatency = mTestLatencyMs;
- outputDesc->mFlags = (AudioSystem::output_flags)(mDirectOutput ? AudioSystem::OUTPUT_FLAG_DIRECT : 0);
- outputDesc->mRefCount[stream] = 0;
- mTestOutputs[mCurOutput] = mpClientInterface->openOutput(&outputDesc->mDevice,
- &outputDesc->mSamplingRate,
- &outputDesc->mFormat,
- &outputDesc->mChannels,
- &outputDesc->mLatency,
- outputDesc->mFlags);
- if (mTestOutputs[mCurOutput]) {
- AudioParameter outputCmd = AudioParameter();
- outputCmd.addInt(String8("set_id"),mCurOutput);
- mpClientInterface->setParameters(mTestOutputs[mCurOutput],outputCmd.toString());
- addOutput(mTestOutputs[mCurOutput], outputDesc);
- }
- }
- return mTestOutputs[mCurOutput];
- }
-#endif //AUDIO_POLICY_TEST
-
- // open a direct output if required by specified parameters
- if (needsDirectOuput(stream, samplingRate, format, channels, flags, device)) {
-
- LOGV("getOutput() opening direct output device %x", device);
- AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
- outputDesc->mDevice = device;
- outputDesc->mSamplingRate = samplingRate;
- outputDesc->mFormat = format;
- outputDesc->mChannels = channels;
- outputDesc->mLatency = 0;
- outputDesc->mFlags = (AudioSystem::output_flags)(flags | AudioSystem::OUTPUT_FLAG_DIRECT);
- outputDesc->mRefCount[stream] = 0;
- output = mpClientInterface->openOutput(&outputDesc->mDevice,
- &outputDesc->mSamplingRate,
- &outputDesc->mFormat,
- &outputDesc->mChannels,
- &outputDesc->mLatency,
- outputDesc->mFlags);
-
- // only accept an output with the requeted parameters
- if (output == 0 ||
- (samplingRate != 0 && samplingRate != outputDesc->mSamplingRate) ||
- (format != 0 && format != outputDesc->mFormat) ||
- (channels != 0 && channels != outputDesc->mChannels)) {
- LOGV("getOutput() failed opening direct output: samplingRate %d, format %d, channels %d",
- samplingRate, format, channels);
- if (output != 0) {
- mpClientInterface->closeOutput(output);
- }
- delete outputDesc;
- return 0;
- }
- addOutput(output, outputDesc);
- return output;
- }
-
- if (channels != 0 && channels != AudioSystem::CHANNEL_OUT_MONO &&
- channels != AudioSystem::CHANNEL_OUT_STEREO) {
- return 0;
- }
- // open a non direct output
-
- // get which output is suitable for the specified stream. The actual routing change will happen
- // when startOutput() will be called
- uint32_t a2dpDevice = device & AudioSystem::DEVICE_OUT_ALL_A2DP;
- if (AudioSystem::popCount((AudioSystem::audio_devices)device) == 2) {
-#ifdef WITH_A2DP
- if (a2dpUsedForSonification() && a2dpDevice != 0) {
- // if playing on 2 devices among which one is A2DP, use duplicated output
- LOGV("getOutput() using duplicated output");
- LOGW_IF((mA2dpOutput == 0), "getOutput() A2DP device in multiple %x selected but A2DP output not opened", device);
- output = mDuplicatedOutput;
- } else
-#endif
- {
- // if playing on 2 devices among which none is A2DP, use hardware output
- output = mHardwareOutput;
- }
- LOGV("getOutput() using output %d for 2 devices %x", output, device);
- } else {
-#ifdef WITH_A2DP
- if (a2dpDevice != 0) {
- // if playing on A2DP device, use a2dp output
- LOGW_IF((mA2dpOutput == 0), "getOutput() A2DP device %x selected but A2DP output not opened", device);
- output = mA2dpOutput;
- } else
-#endif
- {
- // if playing on not A2DP device, use hardware output
- output = mHardwareOutput;
- }
- }
-
-
- LOGW_IF((output ==0), "getOutput() could not find output for stream %d, samplingRate %d, format %d, channels %x, flags %x",
- stream, samplingRate, format, channels, flags);
-
- return output;
-}
-
-status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
-{
- LOGV("startOutput() output %d, stream %d", output, stream);
- ssize_t index = mOutputs.indexOfKey(output);
- if (index < 0) {
- LOGW("startOutput() unknow output %d", output);
- return BAD_VALUE;
- }
-
- AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
- routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
-
-#ifdef WITH_A2DP
- if (mA2dpOutput != 0 && !a2dpUsedForSonification() && strategy == STRATEGY_SONIFICATION) {
- setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput);
- }
-#endif
-
- // incremenent usage count for this stream on the requested output:
- // NOTE that the usage count is the same for duplicated output and hardware output which is
- // necassary for a correct control of hardware output routing by startOutput() and stopOutput()
- outputDesc->changeRefCount(stream, 1);
-
- setOutputDevice(output, getNewDevice(output));
-
- // handle special case for sonification while in call
- if (mPhoneState == AudioSystem::MODE_IN_CALL) {
- handleIncallSonification(stream, true, false);
- }
-
- // apply volume rules for current stream and device if necessary
- checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, outputDesc->device());
-
- return NO_ERROR;
-}
-
-status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
-{
- LOGV("stopOutput() output %d, stream %d", output, stream);
- ssize_t index = mOutputs.indexOfKey(output);
- if (index < 0) {
- LOGW("stopOutput() unknow output %d", output);
- return BAD_VALUE;
- }
-
- AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
- routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
-
- // handle special case for sonification while in call
- if (mPhoneState == AudioSystem::MODE_IN_CALL) {
- handleIncallSonification(stream, false, false);
- }
-
- if (outputDesc->mRefCount[stream] > 0) {
- // decrement usage count of this stream on the output
- outputDesc->changeRefCount(stream, -1);
- // store time at which the last music track was stopped - see computeVolume()
- if (stream == AudioSystem::MUSIC) {
- mMusicStopTime = systemTime();
- }
-
- setOutputDevice(output, getNewDevice(output));
-
-#ifdef WITH_A2DP
- if (mA2dpOutput != 0 && !a2dpUsedForSonification() && strategy == STRATEGY_SONIFICATION) {
- setStrategyMute(STRATEGY_MEDIA, false, mA2dpOutput, mOutputs.valueFor(mHardwareOutput)->mLatency*2);
- }
-#endif
- if (output != mHardwareOutput) {
- setOutputDevice(mHardwareOutput, getNewDevice(mHardwareOutput), true);
- }
- return NO_ERROR;
- } else {
- LOGW("stopOutput() refcount is already 0 for output %d", output);
- return INVALID_OPERATION;
- }
-}
-
-void AudioPolicyManagerBase::releaseOutput(audio_io_handle_t output)
-{
- LOGV("releaseOutput() %d", output);
- ssize_t index = mOutputs.indexOfKey(output);
- if (index < 0) {
- LOGW("releaseOutput() releasing unknown output %d", output);
- return;
- }
-
-#ifdef AUDIO_POLICY_TEST
- int testIndex = testOutputIndex(output);
- if (testIndex != 0) {
- AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
- if (outputDesc->refCount() == 0) {
- mpClientInterface->closeOutput(output);
- delete mOutputs.valueAt(index);
- mOutputs.removeItem(output);
- mTestOutputs[testIndex] = 0;
- }
- return;
- }
-#endif //AUDIO_POLICY_TEST
-
- if (mOutputs.valueAt(index)->mFlags & AudioSystem::OUTPUT_FLAG_DIRECT) {
- mpClientInterface->closeOutput(output);
- delete mOutputs.valueAt(index);
- mOutputs.removeItem(output);
- }
-}
-
-audio_io_handle_t AudioPolicyManagerBase::getInput(int inputSource,
- uint32_t samplingRate,
- uint32_t format,
- uint32_t channels,
- AudioSystem::audio_in_acoustics acoustics)
-{
- audio_io_handle_t input = 0;
- uint32_t device = getDeviceForInputSource(inputSource);
-
- LOGV("getInput() inputSource %d, samplingRate %d, format %d, channels %x, acoustics %x", inputSource, samplingRate, format, channels, acoustics);
-
- if (device == 0) {
- return 0;
- }
-
- // adapt channel selection to input source
- switch(inputSource) {
- case AUDIO_SOURCE_VOICE_UPLINK:
- channels = AudioSystem::CHANNEL_IN_VOICE_UPLINK;
- break;
- case AUDIO_SOURCE_VOICE_DOWNLINK:
- channels = AudioSystem::CHANNEL_IN_VOICE_DNLINK;
- break;
- case AUDIO_SOURCE_VOICE_CALL:
- channels = (AudioSystem::CHANNEL_IN_VOICE_UPLINK | AudioSystem::CHANNEL_IN_VOICE_DNLINK);
- break;
- default:
- break;
- }
-
- AudioInputDescriptor *inputDesc = new AudioInputDescriptor();
-
- inputDesc->mInputSource = inputSource;
- inputDesc->mDevice = device;
- inputDesc->mSamplingRate = samplingRate;
- inputDesc->mFormat = format;
- inputDesc->mChannels = channels;
- inputDesc->mAcoustics = acoustics;
- inputDesc->mRefCount = 0;
- input = mpClientInterface->openInput(&inputDesc->mDevice,
- &inputDesc->mSamplingRate,
- &inputDesc->mFormat,
- &inputDesc->mChannels,
- inputDesc->mAcoustics);
-
- // only accept input with the exact requested set of parameters
- if (input == 0 ||
- (samplingRate != inputDesc->mSamplingRate) ||
- (format != inputDesc->mFormat) ||
- (channels != inputDesc->mChannels)) {
- LOGV("getInput() failed opening input: samplingRate %d, format %d, channels %d",
- samplingRate, format, channels);
- if (input != 0) {
- mpClientInterface->closeInput(input);
- }
- delete inputDesc;
- return 0;
- }
- mInputs.add(input, inputDesc);
- return input;
-}
-
-status_t AudioPolicyManagerBase::startInput(audio_io_handle_t input)
-{
- LOGV("startInput() input %d", input);
- ssize_t index = mInputs.indexOfKey(input);
- if (index < 0) {
- LOGW("startInput() unknow input %d", input);
- return BAD_VALUE;
- }
- AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
-
-#ifdef AUDIO_POLICY_TEST
- if (mTestInput == 0)
-#endif //AUDIO_POLICY_TEST
- {
- // refuse 2 active AudioRecord clients at the same time
- if (getActiveInput() != 0) {
- LOGW("startInput() input %d failed: other input already started", input);
- return INVALID_OPERATION;
- }
- }
-
- AudioParameter param = AudioParameter();
- param.addInt(String8(AudioParameter::keyRouting), (int)inputDesc->mDevice);
-
- // use Voice Recognition mode or not for this input based on input source
- int vr_enabled = inputDesc->mInputSource == AUDIO_SOURCE_VOICE_RECOGNITION ? 1 : 0;
- param.addInt(String8("vr_mode"), vr_enabled);
- LOGV("AudioPolicyManager::startInput(%d), setting vr_mode to %d", inputDesc->mInputSource, vr_enabled);
-
- mpClientInterface->setParameters(input, param.toString());
-
- inputDesc->mRefCount = 1;
- return NO_ERROR;
-}
-
-status_t AudioPolicyManagerBase::stopInput(audio_io_handle_t input)
-{
- LOGV("stopInput() input %d", input);
- ssize_t index = mInputs.indexOfKey(input);
- if (index < 0) {
- LOGW("stopInput() unknow input %d", input);
- return BAD_VALUE;
- }
- AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
-
- if (inputDesc->mRefCount == 0) {
- LOGW("stopInput() input %d already stopped", input);
- return INVALID_OPERATION;
- } else {
- AudioParameter param = AudioParameter();
- param.addInt(String8(AudioParameter::keyRouting), 0);
- mpClientInterface->setParameters(input, param.toString());
- inputDesc->mRefCount = 0;
- return NO_ERROR;
- }
-}
-
-void AudioPolicyManagerBase::releaseInput(audio_io_handle_t input)
-{
- LOGV("releaseInput() %d", input);
- ssize_t index = mInputs.indexOfKey(input);
- if (index < 0) {
- LOGW("releaseInput() releasing unknown input %d", input);
- return;
- }
- mpClientInterface->closeInput(input);
- delete mInputs.valueAt(index);
- mInputs.removeItem(input);
- LOGV("releaseInput() exit");
-}
-
-void AudioPolicyManagerBase::initStreamVolume(AudioSystem::stream_type stream,
- int indexMin,
- int indexMax)
-{
- LOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
- if (indexMin < 0 || indexMin >= indexMax) {
- LOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d", stream , indexMin, indexMax);
- return;
- }
- mStreams[stream].mIndexMin = indexMin;
- mStreams[stream].mIndexMax = indexMax;
-}
-
-status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
-{
-
- if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
- return BAD_VALUE;
- }
-
- // Force max volume if stream cannot be muted
- if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax;
-
- LOGV("setStreamVolumeIndex() stream %d, index %d", stream, index);
- mStreams[stream].mIndexCur = index;
-
- // compute and apply stream volume on all outputs according to connected device
- status_t status = NO_ERROR;
- for (size_t i = 0; i < mOutputs.size(); i++) {
- status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), mOutputs.valueAt(i)->device());
- if (volStatus != NO_ERROR) {
- status = volStatus;
- }
- }
- return status;
-}
-
-status_t AudioPolicyManagerBase::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
-{
- if (index == 0) {
- return BAD_VALUE;
- }
- LOGV("getStreamVolumeIndex() stream %d", stream);
- *index = mStreams[stream].mIndexCur;
- return NO_ERROR;
-}
-
-status_t AudioPolicyManagerBase::dump(int fd)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "\nAudioPolicyManager Dump: %p\n", this);
- result.append(buffer);
- snprintf(buffer, SIZE, " Hardware Output: %d\n", mHardwareOutput);
- result.append(buffer);
-#ifdef WITH_A2DP
- snprintf(buffer, SIZE, " A2DP Output: %d\n", mA2dpOutput);
- result.append(buffer);
- snprintf(buffer, SIZE, " Duplicated Output: %d\n", mDuplicatedOutput);
- result.append(buffer);
- snprintf(buffer, SIZE, " A2DP device address: %s\n", mA2dpDeviceAddress.string());
- result.append(buffer);
-#endif
- snprintf(buffer, SIZE, " SCO device address: %s\n", mScoDeviceAddress.string());
- result.append(buffer);
- snprintf(buffer, SIZE, " Output devices: %08x\n", mAvailableOutputDevices);
- result.append(buffer);
- snprintf(buffer, SIZE, " Input devices: %08x\n", mAvailableInputDevices);
- result.append(buffer);
- snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState);
- result.append(buffer);
- snprintf(buffer, SIZE, " Ringer mode: %d\n", mRingerMode);
- result.append(buffer);
- snprintf(buffer, SIZE, " Force use for communications %d\n", mForceUse[AudioSystem::FOR_COMMUNICATION]);
- result.append(buffer);
- snprintf(buffer, SIZE, " Force use for media %d\n", mForceUse[AudioSystem::FOR_MEDIA]);
- result.append(buffer);
- snprintf(buffer, SIZE, " Force use for record %d\n", mForceUse[AudioSystem::FOR_RECORD]);
- result.append(buffer);
- snprintf(buffer, SIZE, " Force use for dock %d\n", mForceUse[AudioSystem::FOR_DOCK]);
- result.append(buffer);
- write(fd, result.string(), result.size());
-
- snprintf(buffer, SIZE, "\nOutputs dump:\n");
- write(fd, buffer, strlen(buffer));
- for (size_t i = 0; i < mOutputs.size(); i++) {
- snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i));
- write(fd, buffer, strlen(buffer));
- mOutputs.valueAt(i)->dump(fd);
- }
-
- snprintf(buffer, SIZE, "\nInputs dump:\n");
- write(fd, buffer, strlen(buffer));
- for (size_t i = 0; i < mInputs.size(); i++) {
- snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i));
- write(fd, buffer, strlen(buffer));
- mInputs.valueAt(i)->dump(fd);
- }
-
- snprintf(buffer, SIZE, "\nStreams dump:\n");
- write(fd, buffer, strlen(buffer));
- snprintf(buffer, SIZE, " Stream Index Min Index Max Index Cur Can be muted\n");
- write(fd, buffer, strlen(buffer));
- for (size_t i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
- snprintf(buffer, SIZE, " %02d", i);
- mStreams[i].dump(buffer + 3, SIZE);
- write(fd, buffer, strlen(buffer));
- }
-
- return NO_ERROR;
-}
-
-// ----------------------------------------------------------------------------
-// AudioPolicyManagerBase
-// ----------------------------------------------------------------------------
-
-AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
- :
-#ifdef AUDIO_POLICY_TEST
- Thread(false),
-#endif //AUDIO_POLICY_TEST
- mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0), mMusicStopTime(0), mLimitRingtoneVolume(false)
-{
- mpClientInterface = clientInterface;
-
- for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {
- mForceUse[i] = AudioSystem::FORCE_NONE;
- }
-
- // devices available by default are speaker, ear piece and microphone
- mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE |
- AudioSystem::DEVICE_OUT_SPEAKER;
- mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;
-
-#ifdef WITH_A2DP
- mA2dpOutput = 0;
- mDuplicatedOutput = 0;
- mA2dpDeviceAddress = String8("");
-#endif
- mScoDeviceAddress = String8("");
-
- // open hardware output
- AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
- outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
- mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
- &outputDesc->mSamplingRate,
- &outputDesc->mFormat,
- &outputDesc->mChannels,
- &outputDesc->mLatency,
- outputDesc->mFlags);
-
- if (mHardwareOutput == 0) {
- LOGE("Failed to initialize hardware output stream, samplingRate: %d, format %d, channels %d",
- outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels);
- } else {
- addOutput(mHardwareOutput, outputDesc);
- setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER, true);
- }
-
- updateDeviceForStrategy();
-#ifdef AUDIO_POLICY_TEST
- AudioParameter outputCmd = AudioParameter();
- outputCmd.addInt(String8("set_id"), 0);
- mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString());
-
- mTestDevice = AudioSystem::DEVICE_OUT_SPEAKER;
- mTestSamplingRate = 44100;
- mTestFormat = AudioSystem::PCM_16_BIT;
- mTestChannels = AudioSystem::CHANNEL_OUT_STEREO;
- mTestLatencyMs = 0;
- mCurOutput = 0;
- mDirectOutput = false;
- for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
- mTestOutputs[i] = 0;
- }
-
- const size_t SIZE = 256;
- char buffer[SIZE];
- snprintf(buffer, SIZE, "AudioPolicyManagerTest");
- run(buffer, ANDROID_PRIORITY_AUDIO);
-#endif //AUDIO_POLICY_TEST
-}
-
-AudioPolicyManagerBase::~AudioPolicyManagerBase()
-{
-#ifdef AUDIO_POLICY_TEST
- exit();
-#endif //AUDIO_POLICY_TEST
- for (size_t i = 0; i < mOutputs.size(); i++) {
- mpClientInterface->closeOutput(mOutputs.keyAt(i));
- delete mOutputs.valueAt(i);
- }
- mOutputs.clear();
- for (size_t i = 0; i < mInputs.size(); i++) {
- mpClientInterface->closeInput(mInputs.keyAt(i));
- delete mInputs.valueAt(i);
- }
- mInputs.clear();
-}
-
-#ifdef AUDIO_POLICY_TEST
-bool AudioPolicyManagerBase::threadLoop()
-{
- LOGV("entering threadLoop()");
- while (!exitPending())
- {
- String8 command;
- int valueInt;
- String8 value;
-
- Mutex::Autolock _l(mLock);
- mWaitWorkCV.waitRelative(mLock, milliseconds(50));
-
- command = mpClientInterface->getParameters(0, String8("test_cmd_policy"));
- AudioParameter param = AudioParameter(command);
-
- if (param.getInt(String8("test_cmd_policy"), valueInt) == NO_ERROR &&
- valueInt != 0) {
- LOGV("Test command %s received", command.string());
- String8 target;
- if (param.get(String8("target"), target) != NO_ERROR) {
- target = "Manager";
- }
- if (param.getInt(String8("test_cmd_policy_output"), valueInt) == NO_ERROR) {
- param.remove(String8("test_cmd_policy_output"));
- mCurOutput = valueInt;
- }
- if (param.get(String8("test_cmd_policy_direct"), value) == NO_ERROR) {
- param.remove(String8("test_cmd_policy_direct"));
- if (value == "false") {
- mDirectOutput = false;
- } else if (value == "true") {
- mDirectOutput = true;
- }
- }
- if (param.getInt(String8("test_cmd_policy_input"), valueInt) == NO_ERROR) {
- param.remove(String8("test_cmd_policy_input"));
- mTestInput = valueInt;
- }
-
- if (param.get(String8("test_cmd_policy_format"), value) == NO_ERROR) {
- param.remove(String8("test_cmd_policy_format"));
- int format = AudioSystem::INVALID_FORMAT;
- if (value == "PCM 16 bits") {
- format = AudioSystem::PCM_16_BIT;
- } else if (value == "PCM 8 bits") {
- format = AudioSystem::PCM_8_BIT;
- } else if (value == "Compressed MP3") {
- format = AudioSystem::MP3;
- }
- if (format != AudioSystem::INVALID_FORMAT) {
- if (target == "Manager") {
- mTestFormat = format;
- } else if (mTestOutputs[mCurOutput] != 0) {
- AudioParameter outputParam = AudioParameter();
- outputParam.addInt(String8("format"), format);
- mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
- }
- }
- }
- if (param.get(String8("test_cmd_policy_channels"), value) == NO_ERROR) {
- param.remove(String8("test_cmd_policy_channels"));
- int channels = 0;
-
- if (value == "Channels Stereo") {
- channels = AudioSystem::CHANNEL_OUT_STEREO;
- } else if (value == "Channels Mono") {
- channels = AudioSystem::CHANNEL_OUT_MONO;
- }
- if (channels != 0) {
- if (target == "Manager") {
- mTestChannels = channels;
- } else if (mTestOutputs[mCurOutput] != 0) {
- AudioParameter outputParam = AudioParameter();
- outputParam.addInt(String8("channels"), channels);
- mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
- }
- }
- }
- if (param.getInt(String8("test_cmd_policy_sampleRate"), valueInt) == NO_ERROR) {
- param.remove(String8("test_cmd_policy_sampleRate"));
- if (valueInt >= 0 && valueInt <= 96000) {
- int samplingRate = valueInt;
- if (target == "Manager") {
- mTestSamplingRate = samplingRate;
- } else if (mTestOutputs[mCurOutput] != 0) {
- AudioParameter outputParam = AudioParameter();
- outputParam.addInt(String8("sampling_rate"), samplingRate);
- mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
- }
- }
- }
-
- if (param.get(String8("test_cmd_policy_reopen"), value) == NO_ERROR) {
- param.remove(String8("test_cmd_policy_reopen"));
-
- mpClientInterface->closeOutput(mHardwareOutput);
- delete mOutputs.valueFor(mHardwareOutput);
- mOutputs.removeItem(mHardwareOutput);
-
- AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
- outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
- mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
- &outputDesc->mSamplingRate,
- &outputDesc->mFormat,
- &outputDesc->mChannels,
- &outputDesc->mLatency,
- outputDesc->mFlags);
- if (mHardwareOutput == 0) {
- LOGE("Failed to reopen hardware output stream, samplingRate: %d, format %d, channels %d",
- outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels);
- } else {
- AudioParameter outputCmd = AudioParameter();
- outputCmd.addInt(String8("set_id"), 0);
- mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString());
- addOutput(mHardwareOutput, outputDesc);
- }
- }
-
-
- mpClientInterface->setParameters(0, String8("test_cmd_policy="));
- }
- }
- return false;
-}
-
-void AudioPolicyManagerBase::exit()
-{
- {
- AutoMutex _l(mLock);
- requestExit();
- mWaitWorkCV.signal();
- }
- requestExitAndWait();
-}
-
-int AudioPolicyManagerBase::testOutputIndex(audio_io_handle_t output)
-{
- for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
- if (output == mTestOutputs[i]) return i;
- }
- return 0;
-}
-#endif //AUDIO_POLICY_TEST
-
-// ---
-
-void AudioPolicyManagerBase::addOutput(audio_io_handle_t id, AudioOutputDescriptor *outputDesc)
-{
- outputDesc->mId = id;
- mOutputs.add(id, outputDesc);
-}
-
-
-#ifdef WITH_A2DP
-status_t AudioPolicyManagerBase::handleA2dpConnection(AudioSystem::audio_devices device,
- const char *device_address)
-{
- // when an A2DP device is connected, open an A2DP and a duplicated output
- LOGV("opening A2DP output for device %s", device_address);
- AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
- outputDesc->mDevice = device;
- mA2dpOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
- &outputDesc->mSamplingRate,
- &outputDesc->mFormat,
- &outputDesc->mChannels,
- &outputDesc->mLatency,
- outputDesc->mFlags);
- if (mA2dpOutput) {
- // add A2DP output descriptor
- addOutput(mA2dpOutput, outputDesc);
- // set initial stream volume for A2DP device
- applyStreamVolumes(mA2dpOutput, device);
- if (a2dpUsedForSonification()) {
- mDuplicatedOutput = mpClientInterface->openDuplicateOutput(mA2dpOutput, mHardwareOutput);
- }
- if (mDuplicatedOutput != 0 ||
- !a2dpUsedForSonification()) {
- // If both A2DP and duplicated outputs are open, send device address to A2DP hardware
- // interface
- AudioParameter param;
- param.add(String8("a2dp_sink_address"), String8(device_address));
- mpClientInterface->setParameters(mA2dpOutput, param.toString());
- mA2dpDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
-
- if (a2dpUsedForSonification()) {
- // add duplicated output descriptor
- AudioOutputDescriptor *dupOutputDesc = new AudioOutputDescriptor();
- dupOutputDesc->mOutput1 = mOutputs.valueFor(mHardwareOutput);
- dupOutputDesc->mOutput2 = mOutputs.valueFor(mA2dpOutput);
- dupOutputDesc->mSamplingRate = outputDesc->mSamplingRate;
- dupOutputDesc->mFormat = outputDesc->mFormat;
- dupOutputDesc->mChannels = outputDesc->mChannels;
- dupOutputDesc->mLatency = outputDesc->mLatency;
- addOutput(mDuplicatedOutput, dupOutputDesc);
- applyStreamVolumes(mDuplicatedOutput, device);
- }
- } else {
- LOGW("getOutput() could not open duplicated output for %d and %d",
- mHardwareOutput, mA2dpOutput);
- mpClientInterface->closeOutput(mA2dpOutput);
- mOutputs.removeItem(mA2dpOutput);
- mA2dpOutput = 0;
- delete outputDesc;
- return NO_INIT;
- }
- } else {
- LOGW("setDeviceConnectionState() could not open A2DP output for device %x", device);
- delete outputDesc;
- return NO_INIT;
- }
- AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
-
- if (mScoDeviceAddress != "") {
- // It is normal to suspend twice if we are both in call,
- // and have the hardware audio output routed to BT SCO
- if (mPhoneState != AudioSystem::MODE_NORMAL) {
- mpClientInterface->suspendOutput(mA2dpOutput);
- }
- if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)hwOutputDesc->device())) {
- mpClientInterface->suspendOutput(mA2dpOutput);
- }
- }
-
- if (!a2dpUsedForSonification()) {
- // mute music on A2DP output if a notification or ringtone is playing
- uint32_t refCount = hwOutputDesc->strategyRefCount(STRATEGY_SONIFICATION);
- for (uint32_t i = 0; i < refCount; i++) {
- setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput);
- }
- }
- return NO_ERROR;
-}
-
-status_t AudioPolicyManagerBase::handleA2dpDisconnection(AudioSystem::audio_devices device,
- const char *device_address)
-{
- if (mA2dpOutput == 0) {
- LOGW("setDeviceConnectionState() disconnecting A2DP and no A2DP output!");
- return INVALID_OPERATION;
- }
-
- if (mA2dpDeviceAddress != device_address) {
- LOGW("setDeviceConnectionState() disconnecting unknow A2DP sink address %s", device_address);
- return INVALID_OPERATION;
- }
-
- // mute media strategy to avoid outputting sound on hardware output while music stream
- // is switched from A2DP output and before music is paused by music application
- setStrategyMute(STRATEGY_MEDIA, true, mHardwareOutput);
- setStrategyMute(STRATEGY_MEDIA, false, mHardwareOutput, MUTE_TIME_MS);
-
- if (!a2dpUsedForSonification()) {
- // unmute music on A2DP output if a notification or ringtone is playing
- uint32_t refCount = mOutputs.valueFor(mHardwareOutput)->strategyRefCount(STRATEGY_SONIFICATION);
- for (uint32_t i = 0; i < refCount; i++) {
- setStrategyMute(STRATEGY_MEDIA, false, mA2dpOutput);
- }
- }
- mA2dpDeviceAddress = "";
- return NO_ERROR;
-}
-
-void AudioPolicyManagerBase::closeA2dpOutputs()
-{
- LOGV("setDeviceConnectionState() closing A2DP and duplicated output!");
-
- if (mDuplicatedOutput != 0) {
- AudioOutputDescriptor *dupOutputDesc = mOutputs.valueFor(mDuplicatedOutput);
- AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
- // As all active tracks on duplicated output will be deleted,
- // and as they were also referenced on hardware output, the reference
- // count for their stream type must be adjusted accordingly on
- // hardware output.
- for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
- int refCount = dupOutputDesc->mRefCount[i];
- hwOutputDesc->changeRefCount((AudioSystem::stream_type)i,-refCount);
- }
-
- mpClientInterface->closeOutput(mDuplicatedOutput);
- delete mOutputs.valueFor(mDuplicatedOutput);
- mOutputs.removeItem(mDuplicatedOutput);
- mDuplicatedOutput = 0;
- }
- if (mA2dpOutput != 0) {
- AudioParameter param;
- param.add(String8("closing"), String8("true"));
- mpClientInterface->setParameters(mA2dpOutput, param.toString());
- mpClientInterface->closeOutput(mA2dpOutput);
- delete mOutputs.valueFor(mA2dpOutput);
- mOutputs.removeItem(mA2dpOutput);
- mA2dpOutput = 0;
- }
-}
-
-void AudioPolicyManagerBase::checkOutputForStrategy(routing_strategy strategy, uint32_t &newDevice)
-{
- uint32_t prevDevice = getDeviceForStrategy(strategy);
- uint32_t curDevice = getDeviceForStrategy(strategy, false);
- bool a2dpWasUsed = AudioSystem::isA2dpDevice((AudioSystem::audio_devices)(prevDevice & ~AudioSystem::DEVICE_OUT_SPEAKER));
- bool a2dpIsUsed = AudioSystem::isA2dpDevice((AudioSystem::audio_devices)(curDevice & ~AudioSystem::DEVICE_OUT_SPEAKER));
- AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
- AudioOutputDescriptor *a2dpOutputDesc;
-
- if (a2dpWasUsed && !a2dpIsUsed) {
- bool dupUsed = a2dpUsedForSonification() && a2dpWasUsed && (AudioSystem::popCount(prevDevice) == 2);
-
- if (dupUsed) {
- LOGV("checkOutputForStrategy() moving strategy %d to duplicated", strategy);
- a2dpOutputDesc = mOutputs.valueFor(mDuplicatedOutput);
- } else {
- LOGV("checkOutputForStrategy() moving strategy %d to a2dp", strategy);
- a2dpOutputDesc = mOutputs.valueFor(mA2dpOutput);
- }
-
- for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
- if (getStrategy((AudioSystem::stream_type)i) == strategy) {
- mpClientInterface->setStreamOutput((AudioSystem::stream_type)i, mHardwareOutput);
- }
- }
- // do not change newDevice if it was already set before this call by a previous call to
- // getNewDevice() or checkOutputForStrategy() for a strategy with higher priority
- if (newDevice == 0 && hwOutputDesc->isUsedByStrategy(strategy)) {
- newDevice = getDeviceForStrategy(strategy, false);
- }
- }
- if (a2dpIsUsed && !a2dpWasUsed) {
- bool dupUsed = a2dpUsedForSonification() && a2dpIsUsed && (AudioSystem::popCount(curDevice) == 2);
- audio_io_handle_t a2dpOutput;
-
- if (dupUsed) {
- LOGV("checkOutputForStrategy() moving strategy %d from duplicated", strategy);
- a2dpOutputDesc = mOutputs.valueFor(mDuplicatedOutput);
- a2dpOutput = mDuplicatedOutput;
- } else {
- LOGV("checkOutputForStrategy() moving strategy %d from a2dp", strategy);
- a2dpOutputDesc = mOutputs.valueFor(mA2dpOutput);
- a2dpOutput = mA2dpOutput;
- }
-
- for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
- if (getStrategy((AudioSystem::stream_type)i) == strategy) {
- mpClientInterface->setStreamOutput((AudioSystem::stream_type)i, a2dpOutput);
- }
- }
- }
-}
-
-void AudioPolicyManagerBase::checkOutputForAllStrategies(uint32_t &newDevice)
-{
- // Check strategies in order of priority so that once newDevice is set
- // for a given strategy it is not modified by subsequent calls to
- // checkOutputForStrategy()
- checkOutputForStrategy(STRATEGY_PHONE, newDevice);
- checkOutputForStrategy(STRATEGY_SONIFICATION, newDevice);
- checkOutputForStrategy(STRATEGY_MEDIA, newDevice);
- checkOutputForStrategy(STRATEGY_DTMF, newDevice);
-}
-
-#endif
-
-uint32_t AudioPolicyManagerBase::getNewDevice(audio_io_handle_t output, bool fromCache)
-{
- uint32_t device = 0;
-
- AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
- // check the following by order of priority to request a routing change if necessary:
- // 1: we are in call or the strategy phone is active on the hardware output:
- // use device for strategy phone
- // 2: the strategy sonification is active on the hardware output:
- // use device for strategy sonification
- // 3: the strategy media is active on the hardware output:
- // use device for strategy media
- // 4: the strategy DTMF is active on the hardware output:
- // use device for strategy DTMF
- if (mPhoneState == AudioSystem::MODE_IN_CALL ||
- outputDesc->isUsedByStrategy(STRATEGY_PHONE)) {
- device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
- } else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION)) {
- device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
- } else if (outputDesc->isUsedByStrategy(STRATEGY_MEDIA)) {
- device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache);
- } else if (outputDesc->isUsedByStrategy(STRATEGY_DTMF)) {
- device = getDeviceForStrategy(STRATEGY_DTMF, fromCache);
- }
-
- LOGV("getNewDevice() selected device %x", device);
- return device;
-}
-
-AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(AudioSystem::stream_type stream)
-{
- // stream to strategy mapping
- switch (stream) {
- case AudioSystem::VOICE_CALL:
- case AudioSystem::BLUETOOTH_SCO:
- return STRATEGY_PHONE;
- case AudioSystem::RING:
- case AudioSystem::NOTIFICATION:
- case AudioSystem::ALARM:
- case AudioSystem::ENFORCED_AUDIBLE:
- return STRATEGY_SONIFICATION;
- case AudioSystem::DTMF:
- return STRATEGY_DTMF;
- default:
- LOGE("unknown stream type");
- case AudioSystem::SYSTEM:
- // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
- // while key clicks are played produces a poor result
- case AudioSystem::TTS:
- case AudioSystem::MUSIC:
- return STRATEGY_MEDIA;
- }
-}
-
-uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache)
-{
- uint32_t device = 0;
-
- if (fromCache) {
- LOGV("getDeviceForStrategy() from cache strategy %d, device %x", strategy, mDeviceForStrategy[strategy]);
- return mDeviceForStrategy[strategy];
- }
-
- switch (strategy) {
- case STRATEGY_DTMF:
- if (mPhoneState != AudioSystem::MODE_IN_CALL) {
- // when off call, DTMF strategy follows the same rules as MEDIA strategy
- device = getDeviceForStrategy(STRATEGY_MEDIA, false);
- break;
- }
- // when in call, DTMF and PHONE strategies follow the same rules
- // FALL THROUGH
-
- case STRATEGY_PHONE:
- // for phone strategy, we first consider the forced use and then the available devices by order
- // of priority
- switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) {
- case AudioSystem::FORCE_BT_SCO:
- if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
- if (device) break;
- }
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
- if (device) break;
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO;
- if (device) break;
- // if SCO device is requested but no SCO device is available, fall back to default case
- // FALL THROUGH
-
- default: // FORCE_NONE
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
- if (device) break;
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
- if (device) break;
-#ifdef WITH_A2DP
- // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
- if (mPhoneState != AudioSystem::MODE_IN_CALL) {
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
- if (device) break;
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
- if (device) break;
- }
-#endif
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE;
- if (device == 0) {
- LOGE("getDeviceForStrategy() earpiece device not found");
- }
- break;
-
- case AudioSystem::FORCE_SPEAKER:
- if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
- if (device) break;
- }
-#ifdef WITH_A2DP
- // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
- // A2DP speaker when forcing to speaker output
- if (mPhoneState != AudioSystem::MODE_IN_CALL) {
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
- if (device) break;
- }
-#endif
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
- if (device == 0) {
- LOGE("getDeviceForStrategy() speaker device not found");
- }
- break;
- }
- break;
-
- case STRATEGY_SONIFICATION:
-
- // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
- // handleIncallSonification().
- if (mPhoneState == AudioSystem::MODE_IN_CALL) {
- device = getDeviceForStrategy(STRATEGY_PHONE, false);
- break;
- }
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
- if (device == 0) {
- LOGE("getDeviceForStrategy() speaker device not found");
- }
- // The second device used for sonification is the same as the device used by media strategy
- // FALL THROUGH
-
- case STRATEGY_MEDIA: {
- uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
- }
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
- }
-#ifdef WITH_A2DP
- if (mA2dpOutput != 0) {
- if (strategy == STRATEGY_SONIFICATION && !a2dpUsedForSonification()) {
- break;
- }
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
- }
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
- }
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
- }
- }
-#endif
- if (device2 == 0) {
- device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
- }
-
- // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION, 0 otherwise
- device |= device2;
- if (device == 0) {
- LOGE("getDeviceForStrategy() speaker device not found");
- }
- } break;
-
- default:
- LOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
- break;
- }
-
- LOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
- return device;
-}
-
-void AudioPolicyManagerBase::updateDeviceForStrategy()
-{
- for (int i = 0; i < NUM_STRATEGIES; i++) {
- mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false);
- }
-}
-
-void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t device, bool force, int delayMs)
-{
- LOGV("setOutputDevice() output %d device %x delayMs %d", output, device, delayMs);
- AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
-
-
- if (outputDesc->isDuplicated()) {
- setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs);
- setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs);
- return;
- }
-#ifdef WITH_A2DP
- // filter devices according to output selected
- if (output == mA2dpOutput) {
- device &= AudioSystem::DEVICE_OUT_ALL_A2DP;
- } else {
- device &= ~AudioSystem::DEVICE_OUT_ALL_A2DP;
- }
-#endif
-
- uint32_t prevDevice = (uint32_t)outputDesc->device();
- // Do not change the routing if:
- // - the requestede device is 0
- // - the requested device is the same as current device and force is not specified.
- // Doing this check here allows the caller to call setOutputDevice() without conditions
- if ((device == 0 || device == prevDevice) && !force) {
- LOGV("setOutputDevice() setting same device %x or null device for output %d", device, output);
- return;
- }
-
- outputDesc->mDevice = device;
- // mute media streams if both speaker and headset are selected
- if (output == mHardwareOutput && AudioSystem::popCount(device) == 2) {
- setStrategyMute(STRATEGY_MEDIA, true, output);
- // wait for the PCM output buffers to empty before proceeding with the rest of the command
- usleep(outputDesc->mLatency*2*1000);
- }
-#ifdef WITH_A2DP
- // suspend A2DP output if SCO device is selected
- if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)device)) {
- if (mA2dpOutput != 0) {
- mpClientInterface->suspendOutput(mA2dpOutput);
- }
- }
-#endif
- // do the routing
- AudioParameter param = AudioParameter();
- param.addInt(String8(AudioParameter::keyRouting), (int)device);
- mpClientInterface->setParameters(mHardwareOutput, param.toString(), delayMs);
- // update stream volumes according to new device
- applyStreamVolumes(output, device, delayMs);
-
-#ifdef WITH_A2DP
- // if disconnecting SCO device, restore A2DP output
- if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)prevDevice)) {
- if (mA2dpOutput != 0) {
- LOGV("restore A2DP output");
- mpClientInterface->restoreOutput(mA2dpOutput);
- }
- }
-#endif
- // if changing from a combined headset + speaker route, unmute media streams
- if (output == mHardwareOutput && AudioSystem::popCount(prevDevice) == 2) {
- setStrategyMute(STRATEGY_MEDIA, false, output, delayMs);
- }
-}
-
-uint32_t AudioPolicyManagerBase::getDeviceForInputSource(int inputSource)
-{
- uint32_t device;
-
- switch(inputSource) {
- case AUDIO_SOURCE_DEFAULT:
- case AUDIO_SOURCE_MIC:
- case AUDIO_SOURCE_VOICE_RECOGNITION:
- if (mForceUse[AudioSystem::FOR_RECORD] == AudioSystem::FORCE_BT_SCO &&
- mAvailableInputDevices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
- device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET;
- } else if (mAvailableInputDevices & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
- device = AudioSystem::DEVICE_IN_WIRED_HEADSET;
- } else {
- device = AudioSystem::DEVICE_IN_BUILTIN_MIC;
- }
- break;
- case AUDIO_SOURCE_CAMCORDER:
- if (hasBackMicrophone()) {
- device = AudioSystem::DEVICE_IN_BACK_MIC;
- } else {
- device = AudioSystem::DEVICE_IN_BUILTIN_MIC;
- }
- break;
- case AUDIO_SOURCE_VOICE_UPLINK:
- case AUDIO_SOURCE_VOICE_DOWNLINK:
- case AUDIO_SOURCE_VOICE_CALL:
- device = AudioSystem::DEVICE_IN_VOICE_CALL;
- break;
- default:
- LOGW("getInput() invalid input source %d", inputSource);
- device = 0;
- break;
- }
- LOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
- return device;
-}
-
-audio_io_handle_t AudioPolicyManagerBase::getActiveInput()
-{
- for (size_t i = 0; i < mInputs.size(); i++) {
- if (mInputs.valueAt(i)->mRefCount > 0) {
- return mInputs.keyAt(i);
- }
- }
- return 0;
-}
-
-float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_handle_t output, uint32_t device)
-{
- float volume = 1.0;
- AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
- StreamDescriptor &streamDesc = mStreams[stream];
-
- if (device == 0) {
- device = outputDesc->device();
- }
-
- int volInt = (100 * (index - streamDesc.mIndexMin)) / (streamDesc.mIndexMax - streamDesc.mIndexMin);
- volume = AudioSystem::linearToLog(volInt);
-
- // if a headset is connected, apply the following rules to ring tones and notifications
- // to avoid sound level bursts in user's ears:
- // - always attenuate ring tones and notifications volume by 6dB
- // - if music is playing, always limit the volume to current music volume,
- // with a minimum threshold at -36dB so that notification is always perceived.
- if ((device &
- (AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP |
- AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AudioSystem::DEVICE_OUT_WIRED_HEADSET |
- AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) &&
- (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) &&
- streamDesc.mCanBeMuted) {
- volume *= SONIFICATION_HEADSET_VOLUME_FACTOR;
- // when the phone is ringing we must consider that music could have been paused just before
- // by the music application and behave as if music was active if the last music track was
- // just stopped
- if (outputDesc->mRefCount[AudioSystem::MUSIC] || mLimitRingtoneVolume) {
- float musicVol = computeVolume(AudioSystem::MUSIC, mStreams[AudioSystem::MUSIC].mIndexCur, output, device);
- float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ? musicVol : SONIFICATION_HEADSET_VOLUME_MIN;
- if (volume > minVol) {
- volume = minVol;
- LOGV("computeVolume limiting volume to %f musicVol %f", minVol, musicVol);
- }
- }
- }
-
- return volume;
-}
-
-status_t AudioPolicyManagerBase::checkAndSetVolume(int stream, int index, audio_io_handle_t output, uint32_t device, int delayMs, bool force)
-{
-
- // do not change actual stream volume if the stream is muted
- if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) {
- LOGV("checkAndSetVolume() stream %d muted count %d", stream, mOutputs.valueFor(output)->mMuteCount[stream]);
- return NO_ERROR;
- }
-
- // do not change in call volume if bluetooth is connected and vice versa
- if ((stream == AudioSystem::VOICE_CALL && mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) ||
- (stream == AudioSystem::BLUETOOTH_SCO && mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO)) {
- LOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm",
- stream, mForceUse[AudioSystem::FOR_COMMUNICATION]);
- return INVALID_OPERATION;
- }
-
- float volume = computeVolume(stream, index, output, device);
- // do not set volume if the float value did not change
- if (volume != mOutputs.valueFor(output)->mCurVolume[stream] || force) {
- mOutputs.valueFor(output)->mCurVolume[stream] = volume;
- LOGV("setStreamVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs);
- if (stream == AudioSystem::VOICE_CALL ||
- stream == AudioSystem::DTMF ||
- stream == AudioSystem::BLUETOOTH_SCO) {
- float voiceVolume = -1.0;
- // offset value to reflect actual hardware volume that never reaches 0
- // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
- volume = 0.01 + 0.99 * volume;
- if (stream == AudioSystem::VOICE_CALL) {
- voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
- } else if (stream == AudioSystem::BLUETOOTH_SCO) {
- voiceVolume = 1.0;
- }
- if (voiceVolume >= 0 && output == mHardwareOutput) {
- mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
- }
- }
- mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);
- }
-
- return NO_ERROR;
-}
-
-void AudioPolicyManagerBase::applyStreamVolumes(audio_io_handle_t output, uint32_t device, int delayMs)
-{
- LOGV("applyStreamVolumes() for output %d and device %x", output, device);
-
- for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
- checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, device, delayMs);
- }
-}
-
-void AudioPolicyManagerBase::setStrategyMute(routing_strategy strategy, bool on, audio_io_handle_t output, int delayMs)
-{
- LOGV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output);
- for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
- if (getStrategy((AudioSystem::stream_type)stream) == strategy) {
- setStreamMute(stream, on, output, delayMs);
- }
- }
-}
-
-void AudioPolicyManagerBase::setStreamMute(int stream, bool on, audio_io_handle_t output, int delayMs)
-{
- StreamDescriptor &streamDesc = mStreams[stream];
- AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
-
- LOGV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d", stream, on, output, outputDesc->mMuteCount[stream]);
-
- if (on) {
- if (outputDesc->mMuteCount[stream] == 0) {
- if (streamDesc.mCanBeMuted) {
- checkAndSetVolume(stream, 0, output, outputDesc->device(), delayMs);
- }
- }
- // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored
- outputDesc->mMuteCount[stream]++;
- } else {
- if (outputDesc->mMuteCount[stream] == 0) {
- LOGW("setStreamMute() unmuting non muted stream!");
- return;
- }
- if (--outputDesc->mMuteCount[stream] == 0) {
- checkAndSetVolume(stream, streamDesc.mIndexCur, output, outputDesc->device(), delayMs);
- }
- }
-}
-
-void AudioPolicyManagerBase::handleIncallSonification(int stream, bool starting, bool stateChange)
-{
- // if the stream pertains to sonification strategy and we are in call we must
- // mute the stream if it is low visibility. If it is high visibility, we must play a tone
- // in the device used for phone strategy and play the tone if the selected device does not
- // interfere with the device used for phone strategy
- // if stateChange is true, we are called from setPhoneState() and we must mute or unmute as
- // many times as there are active tracks on the output
-
- if (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) {
- AudioOutputDescriptor *outputDesc = mOutputs.valueFor(mHardwareOutput);
- LOGV("handleIncallSonification() stream %d starting %d device %x stateChange %d",
- stream, starting, outputDesc->mDevice, stateChange);
- if (outputDesc->mRefCount[stream]) {
- int muteCount = 1;
- if (stateChange) {
- muteCount = outputDesc->mRefCount[stream];
- }
- if (AudioSystem::isLowVisibility((AudioSystem::stream_type)stream)) {
- LOGV("handleIncallSonification() low visibility, muteCount %d", muteCount);
- for (int i = 0; i < muteCount; i++) {
- setStreamMute(stream, starting, mHardwareOutput);
- }
- } else {
- LOGV("handleIncallSonification() high visibility");
- if (outputDesc->device() & getDeviceForStrategy(STRATEGY_PHONE)) {
- LOGV("handleIncallSonification() high visibility muted, muteCount %d", muteCount);
- for (int i = 0; i < muteCount; i++) {
- setStreamMute(stream, starting, mHardwareOutput);
- }
- }
- if (starting) {
- mpClientInterface->startTone(ToneGenerator::TONE_SUP_CALL_WAITING, AudioSystem::VOICE_CALL);
- } else {
- mpClientInterface->stopTone();
- }
- }
- }
- }
-}
-
-bool AudioPolicyManagerBase::needsDirectOuput(AudioSystem::stream_type stream,
- uint32_t samplingRate,
- uint32_t format,
- uint32_t channels,
- AudioSystem::output_flags flags,
- uint32_t device)
-{
- return ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
- (format !=0 && !AudioSystem::isLinearPCM(format)));
-}
-
-// --- AudioOutputDescriptor class implementation
-
-AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor()
- : mId(0), mSamplingRate(0), mFormat(0), mChannels(0), mLatency(0),
- mFlags((AudioSystem::output_flags)0), mDevice(0), mOutput1(0), mOutput2(0)
-{
- // clear usage count for all stream types
- for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
- mRefCount[i] = 0;
- mCurVolume[i] = -1.0;
- mMuteCount[i] = 0;
- }
-}
-
-uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::device()
-{
- uint32_t device = 0;
- if (isDuplicated()) {
- device = mOutput1->mDevice | mOutput2->mDevice;
- } else {
- device = mDevice;
- }
- return device;
-}
-
-void AudioPolicyManagerBase::AudioOutputDescriptor::changeRefCount(AudioSystem::stream_type stream, int delta)
-{
- // forward usage count change to attached outputs
- if (isDuplicated()) {
- mOutput1->changeRefCount(stream, delta);
- mOutput2->changeRefCount(stream, delta);
- }
- if ((delta + (int)mRefCount[stream]) < 0) {
- LOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", delta, stream, mRefCount[stream]);
- mRefCount[stream] = 0;
- return;
- }
- mRefCount[stream] += delta;
- LOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]);
-}
-
-uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::refCount()
-{
- uint32_t refcount = 0;
- for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
- refcount += mRefCount[i];
- }
- return refcount;
-}
-
-uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::strategyRefCount(routing_strategy strategy)
-{
- uint32_t refCount = 0;
- for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
- if (getStrategy((AudioSystem::stream_type)i) == strategy) {
- refCount += mRefCount[i];
- }
- }
- return refCount;
-}
-
-
-status_t AudioPolicyManagerBase::AudioOutputDescriptor::dump(int fd)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
- result.append(buffer);
- snprintf(buffer, SIZE, " Format: %d\n", mFormat);
- result.append(buffer);
- snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
- result.append(buffer);
- snprintf(buffer, SIZE, " Latency: %d\n", mLatency);
- result.append(buffer);
- snprintf(buffer, SIZE, " Flags %08x\n", mFlags);
- result.append(buffer);
- snprintf(buffer, SIZE, " Devices %08x\n", device());
- result.append(buffer);
- snprintf(buffer, SIZE, " Stream volume refCount muteCount\n");
- result.append(buffer);
- for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
- snprintf(buffer, SIZE, " %02d %.03f %02d %02d\n", i, mCurVolume[i], mRefCount[i], mMuteCount[i]);
- result.append(buffer);
- }
- write(fd, result.string(), result.size());
-
- return NO_ERROR;
-}
-
-// --- AudioInputDescriptor class implementation
-
-AudioPolicyManagerBase::AudioInputDescriptor::AudioInputDescriptor()
- : mSamplingRate(0), mFormat(0), mChannels(0),
- mAcoustics((AudioSystem::audio_in_acoustics)0), mDevice(0), mRefCount(0)
-{
-}
-
-status_t AudioPolicyManagerBase::AudioInputDescriptor::dump(int fd)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
- result.append(buffer);
- snprintf(buffer, SIZE, " Format: %d\n", mFormat);
- result.append(buffer);
- snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
- result.append(buffer);
- snprintf(buffer, SIZE, " Acoustics %08x\n", mAcoustics);
- result.append(buffer);
- snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
- result.append(buffer);
- snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount);
- result.append(buffer);
- write(fd, result.string(), result.size());
-
- return NO_ERROR;
-}
-
-// --- StreamDescriptor class implementation
-
-void AudioPolicyManagerBase::StreamDescriptor::dump(char* buffer, size_t size)
-{
- snprintf(buffer, size, " %02d %02d %02d %d\n",
- mIndexMin,
- mIndexMax,
- mIndexCur,
- mCanBeMuted);
-}
-
-
-}; // namespace android
diff --git a/libs/audioflinger/AudioPolicyService.cpp b/libs/audioflinger/AudioPolicyService.cpp
deleted file mode 100644
index bb3905c..0000000
--- a/libs/audioflinger/AudioPolicyService.cpp
+++ /dev/null
@@ -1,924 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "AudioPolicyService"
-//#define LOG_NDEBUG 0
-
-#undef __STRICT_ANSI__
-#define __STDINT_LIMITS
-#define __STDC_LIMIT_MACROS
-#include <stdint.h>
-
-#include <sys/time.h>
-#include <binder/IServiceManager.h>
-#include <utils/Log.h>
-#include <cutils/properties.h>
-#include <binder/IPCThreadState.h>
-#include <utils/String16.h>
-#include <utils/threads.h>
-#include "AudioPolicyService.h"
-#include <hardware_legacy/AudioPolicyManagerBase.h>
-#include <cutils/properties.h>
-#include <dlfcn.h>
-#include <hardware_legacy/power.h>
-
-// ----------------------------------------------------------------------------
-// the sim build doesn't have gettid
-
-#ifndef HAVE_GETTID
-# define gettid getpid
-#endif
-
-namespace android {
-
-
-static const char *kDeadlockedString = "AudioPolicyService may be deadlocked\n";
-static const char *kCmdDeadlockedString = "AudioPolicyService command thread may be deadlocked\n";
-
-static const int kDumpLockRetries = 50;
-static const int kDumpLockSleep = 20000;
-
-static bool checkPermission() {
-#ifndef HAVE_ANDROID_OS
- return true;
-#endif
- if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
- bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
- if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
- return ok;
-}
-
-// ----------------------------------------------------------------------------
-
-AudioPolicyService::AudioPolicyService()
- : BnAudioPolicyService() , mpPolicyManager(NULL)
-{
- char value[PROPERTY_VALUE_MAX];
-
- // start tone playback thread
- mTonePlaybackThread = new AudioCommandThread(String8(""));
- // start audio commands thread
- mAudioCommandThread = new AudioCommandThread(String8("ApmCommandThread"));
-
-#if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)
- mpPolicyManager = new AudioPolicyManagerBase(this);
- LOGV("build for GENERIC_AUDIO - using generic audio policy");
-#else
- // if running in emulation - use the emulator driver
- if (property_get("ro.kernel.qemu", value, 0)) {
- LOGV("Running in emulation - using generic audio policy");
- mpPolicyManager = new AudioPolicyManagerBase(this);
- }
- else {
- LOGV("Using hardware specific audio policy");
- mpPolicyManager = createAudioPolicyManager(this);
- }
-#endif
-
- // load properties
- property_get("ro.camera.sound.forced", value, "0");
- mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
-}
-
-AudioPolicyService::~AudioPolicyService()
-{
- mTonePlaybackThread->exit();
- mTonePlaybackThread.clear();
- mAudioCommandThread->exit();
- mAudioCommandThread.clear();
-
- if (mpPolicyManager) {
- delete mpPolicyManager;
- }
-}
-
-
-status_t AudioPolicyService::setDeviceConnectionState(AudioSystem::audio_devices device,
- AudioSystem::device_connection_state state,
- const char *device_address)
-{
- if (mpPolicyManager == NULL) {
- return NO_INIT;
- }
- if (!checkPermission()) {
- return PERMISSION_DENIED;
- }
- if (!AudioSystem::isOutputDevice(device) && !AudioSystem::isInputDevice(device)) {
- return BAD_VALUE;
- }
- if (state != AudioSystem::DEVICE_STATE_AVAILABLE && state != AudioSystem::DEVICE_STATE_UNAVAILABLE) {
- return BAD_VALUE;
- }
-
- LOGV("setDeviceConnectionState() tid %d", gettid());
- Mutex::Autolock _l(mLock);
- return mpPolicyManager->setDeviceConnectionState(device, state, device_address);
-}
-
-AudioSystem::device_connection_state AudioPolicyService::getDeviceConnectionState(AudioSystem::audio_devices device,
- const char *device_address)
-{
- if (mpPolicyManager == NULL) {
- return AudioSystem::DEVICE_STATE_UNAVAILABLE;
- }
- if (!checkPermission()) {
- return AudioSystem::DEVICE_STATE_UNAVAILABLE;
- }
- return mpPolicyManager->getDeviceConnectionState(device, device_address);
-}
-
-status_t AudioPolicyService::setPhoneState(int state)
-{
- if (mpPolicyManager == NULL) {
- return NO_INIT;
- }
- if (!checkPermission()) {
- return PERMISSION_DENIED;
- }
- if (state < 0 || state >= AudioSystem::NUM_MODES) {
- return BAD_VALUE;
- }
-
- LOGV("setPhoneState() tid %d", gettid());
-
- // TODO: check if it is more appropriate to do it in platform specific policy manager
- AudioSystem::setMode(state);
-
- Mutex::Autolock _l(mLock);
- mpPolicyManager->setPhoneState(state);
- return NO_ERROR;
-}
-
-status_t AudioPolicyService::setRingerMode(uint32_t mode, uint32_t mask)
-{
- if (mpPolicyManager == NULL) {
- return NO_INIT;
- }
- if (!checkPermission()) {
- return PERMISSION_DENIED;
- }
-
- mpPolicyManager->setRingerMode(mode, mask);
- return NO_ERROR;
-}
-
-status_t AudioPolicyService::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
-{
- if (mpPolicyManager == NULL) {
- return NO_INIT;
- }
- if (!checkPermission()) {
- return PERMISSION_DENIED;
- }
- if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
- return BAD_VALUE;
- }
- if (config < 0 || config >= AudioSystem::NUM_FORCE_CONFIG) {
- return BAD_VALUE;
- }
- LOGV("setForceUse() tid %d", gettid());
- Mutex::Autolock _l(mLock);
- mpPolicyManager->setForceUse(usage, config);
- return NO_ERROR;
-}
-
-AudioSystem::forced_config AudioPolicyService::getForceUse(AudioSystem::force_use usage)
-{
- if (mpPolicyManager == NULL) {
- return AudioSystem::FORCE_NONE;
- }
- if (!checkPermission()) {
- return AudioSystem::FORCE_NONE;
- }
- if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
- return AudioSystem::FORCE_NONE;
- }
- return mpPolicyManager->getForceUse(usage);
-}
-
-audio_io_handle_t AudioPolicyService::getOutput(AudioSystem::stream_type stream,
- uint32_t samplingRate,
- uint32_t format,
- uint32_t channels,
- AudioSystem::output_flags flags)
-{
- if (mpPolicyManager == NULL) {
- return 0;
- }
- LOGV("getOutput() tid %d", gettid());
- Mutex::Autolock _l(mLock);
- return mpPolicyManager->getOutput(stream, samplingRate, format, channels, flags);
-}
-
-status_t AudioPolicyService::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
-{
- if (mpPolicyManager == NULL) {
- return NO_INIT;
- }
- LOGV("startOutput() tid %d", gettid());
- Mutex::Autolock _l(mLock);
- return mpPolicyManager->startOutput(output, stream);
-}
-
-status_t AudioPolicyService::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
-{
- if (mpPolicyManager == NULL) {
- return NO_INIT;
- }
- LOGV("stopOutput() tid %d", gettid());
- Mutex::Autolock _l(mLock);
- return mpPolicyManager->stopOutput(output, stream);
-}
-
-void AudioPolicyService::releaseOutput(audio_io_handle_t output)
-{
- if (mpPolicyManager == NULL) {
- return;
- }
- LOGV("releaseOutput() tid %d", gettid());
- Mutex::Autolock _l(mLock);
- mpPolicyManager->releaseOutput(output);
-}
-
-audio_io_handle_t AudioPolicyService::getInput(int inputSource,
- uint32_t samplingRate,
- uint32_t format,
- uint32_t channels,
- AudioSystem::audio_in_acoustics acoustics)
-{
- if (mpPolicyManager == NULL) {
- return 0;
- }
- Mutex::Autolock _l(mLock);
- return mpPolicyManager->getInput(inputSource, samplingRate, format, channels, acoustics);
-}
-
-status_t AudioPolicyService::startInput(audio_io_handle_t input)
-{
- if (mpPolicyManager == NULL) {
- return NO_INIT;
- }
- Mutex::Autolock _l(mLock);
- return mpPolicyManager->startInput(input);
-}
-
-status_t AudioPolicyService::stopInput(audio_io_handle_t input)
-{
- if (mpPolicyManager == NULL) {
- return NO_INIT;
- }
- Mutex::Autolock _l(mLock);
- return mpPolicyManager->stopInput(input);
-}
-
-void AudioPolicyService::releaseInput(audio_io_handle_t input)
-{
- if (mpPolicyManager == NULL) {
- return;
- }
- Mutex::Autolock _l(mLock);
- mpPolicyManager->releaseInput(input);
-}
-
-status_t AudioPolicyService::initStreamVolume(AudioSystem::stream_type stream,
- int indexMin,
- int indexMax)
-{
- if (mpPolicyManager == NULL) {
- return NO_INIT;
- }
- if (!checkPermission()) {
- return PERMISSION_DENIED;
- }
- if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
- return BAD_VALUE;
- }
- mpPolicyManager->initStreamVolume(stream, indexMin, indexMax);
- return NO_ERROR;
-}
-
-status_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
-{
- if (mpPolicyManager == NULL) {
- return NO_INIT;
- }
- if (!checkPermission()) {
- return PERMISSION_DENIED;
- }
- if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
- return BAD_VALUE;
- }
-
- return mpPolicyManager->setStreamVolumeIndex(stream, index);
-}
-
-status_t AudioPolicyService::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
-{
- if (mpPolicyManager == NULL) {
- return NO_INIT;
- }
- if (!checkPermission()) {
- return PERMISSION_DENIED;
- }
- if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
- return BAD_VALUE;
- }
- return mpPolicyManager->getStreamVolumeIndex(stream, index);
-}
-
-void AudioPolicyService::binderDied(const wp<IBinder>& who) {
- LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
-}
-
-static bool tryLock(Mutex& mutex)
-{
- bool locked = false;
- for (int i = 0; i < kDumpLockRetries; ++i) {
- if (mutex.tryLock() == NO_ERROR) {
- locked = true;
- break;
- }
- usleep(kDumpLockSleep);
- }
- return locked;
-}
-
-status_t AudioPolicyService::dumpInternals(int fd)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpPolicyManager);
- result.append(buffer);
- snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
- result.append(buffer);
- snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
- result.append(buffer);
-
- write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
-{
- if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
- dumpPermissionDenial(fd);
- } else {
- bool locked = tryLock(mLock);
- if (!locked) {
- String8 result(kDeadlockedString);
- write(fd, result.string(), result.size());
- }
-
- dumpInternals(fd);
- if (mAudioCommandThread != NULL) {
- mAudioCommandThread->dump(fd);
- }
- if (mTonePlaybackThread != NULL) {
- mTonePlaybackThread->dump(fd);
- }
-
- if (mpPolicyManager) {
- mpPolicyManager->dump(fd);
- }
-
- if (locked) mLock.unlock();
- }
- return NO_ERROR;
-}
-
-status_t AudioPolicyService::dumpPermissionDenial(int fd)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
- snprintf(buffer, SIZE, "Permission Denial: "
- "can't dump AudioPolicyService from pid=%d, uid=%d\n",
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid());
- result.append(buffer);
- write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-status_t AudioPolicyService::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- return BnAudioPolicyService::onTransact(code, data, reply, flags);
-}
-
-
-// ----------------------------------------------------------------------------
-void AudioPolicyService::instantiate() {
- defaultServiceManager()->addService(
- String16("media.audio_policy"), new AudioPolicyService());
-}
-
-
-// ----------------------------------------------------------------------------
-// AudioPolicyClientInterface implementation
-// ----------------------------------------------------------------------------
-
-
-audio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t *pLatencyMs,
- AudioSystem::output_flags flags)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) {
- LOGW("openOutput() could not get AudioFlinger");
- return 0;
- }
-
- return af->openOutput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, pLatencyMs, flags);
-}
-
-audio_io_handle_t AudioPolicyService::openDuplicateOutput(audio_io_handle_t output1, audio_io_handle_t output2)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) {
- LOGW("openDuplicateOutput() could not get AudioFlinger");
- return 0;
- }
- return af->openDuplicateOutput(output1, output2);
-}
-
-status_t AudioPolicyService::closeOutput(audio_io_handle_t output)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) return PERMISSION_DENIED;
-
- return af->closeOutput(output);
-}
-
-
-status_t AudioPolicyService::suspendOutput(audio_io_handle_t output)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) {
- LOGW("suspendOutput() could not get AudioFlinger");
- return PERMISSION_DENIED;
- }
-
- return af->suspendOutput(output);
-}
-
-status_t AudioPolicyService::restoreOutput(audio_io_handle_t output)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) {
- LOGW("restoreOutput() could not get AudioFlinger");
- return PERMISSION_DENIED;
- }
-
- return af->restoreOutput(output);
-}
-
-audio_io_handle_t AudioPolicyService::openInput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t acoustics)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) {
- LOGW("openInput() could not get AudioFlinger");
- return 0;
- }
-
- return af->openInput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, acoustics);
-}
-
-status_t AudioPolicyService::closeInput(audio_io_handle_t input)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) return PERMISSION_DENIED;
-
- return af->closeInput(input);
-}
-
-status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs)
-{
- return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);
-}
-
-status_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output)
-{
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
- if (af == 0) return PERMISSION_DENIED;
-
- return af->setStreamOutput(stream, output);
-}
-
-
-void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs)
-{
- mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs);
-}
-
-String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys)
-{
- String8 result = AudioSystem::getParameters(ioHandle, keys);
- return result;
-}
-
-status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream)
-{
- mTonePlaybackThread->startToneCommand(tone, stream);
- return NO_ERROR;
-}
-
-status_t AudioPolicyService::stopTone()
-{
- mTonePlaybackThread->stopToneCommand();
- return NO_ERROR;
-}
-
-status_t AudioPolicyService::setVoiceVolume(float volume, int delayMs)
-{
- return mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
-}
-
-// ----------- AudioPolicyService::AudioCommandThread implementation ----------
-
-AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name)
- : Thread(false), mName(name)
-{
- mpToneGenerator = NULL;
-}
-
-
-AudioPolicyService::AudioCommandThread::~AudioCommandThread()
-{
- if (mName != "" && !mAudioCommands.isEmpty()) {
- release_wake_lock(mName.string());
- }
- mAudioCommands.clear();
- if (mpToneGenerator != NULL) delete mpToneGenerator;
-}
-
-void AudioPolicyService::AudioCommandThread::onFirstRef()
-{
- if (mName != "") {
- run(mName.string(), ANDROID_PRIORITY_AUDIO);
- } else {
- run("AudioCommandThread", ANDROID_PRIORITY_AUDIO);
- }
-}
-
-bool AudioPolicyService::AudioCommandThread::threadLoop()
-{
- nsecs_t waitTime = INT64_MAX;
-
- mLock.lock();
- while (!exitPending())
- {
- while(!mAudioCommands.isEmpty()) {
- nsecs_t curTime = systemTime();
- // commands are sorted by increasing time stamp: execute them from index 0 and up
- if (mAudioCommands[0]->mTime <= curTime) {
- AudioCommand *command = mAudioCommands[0];
- mAudioCommands.removeAt(0);
- mLastCommand = *command;
-
- switch (command->mCommand) {
- case START_TONE: {
- mLock.unlock();
- ToneData *data = (ToneData *)command->mParam;
- LOGV("AudioCommandThread() processing start tone %d on stream %d",
- data->mType, data->mStream);
- if (mpToneGenerator != NULL)
- delete mpToneGenerator;
- mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
- mpToneGenerator->startTone(data->mType);
- delete data;
- mLock.lock();
- }break;
- case STOP_TONE: {
- mLock.unlock();
- LOGV("AudioCommandThread() processing stop tone");
- if (mpToneGenerator != NULL) {
- mpToneGenerator->stopTone();
- delete mpToneGenerator;
- mpToneGenerator = NULL;
- }
- mLock.lock();
- }break;
- case SET_VOLUME: {
- VolumeData *data = (VolumeData *)command->mParam;
- LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %d", data->mStream, data->mVolume, data->mIO);
- command->mStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
- if (command->mWaitStatus) {
- command->mCond.signal();
- mWaitWorkCV.wait(mLock);
- }
- delete data;
- }break;
- case SET_PARAMETERS: {
- ParametersData *data = (ParametersData *)command->mParam;
- LOGV("AudioCommandThread() processing set parameters string %s, io %d", data->mKeyValuePairs.string(), data->mIO);
- command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
- if (command->mWaitStatus) {
- command->mCond.signal();
- mWaitWorkCV.wait(mLock);
- }
- delete data;
- }break;
- case SET_VOICE_VOLUME: {
- VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
- LOGV("AudioCommandThread() processing set voice volume volume %f", data->mVolume);
- command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
- if (command->mWaitStatus) {
- command->mCond.signal();
- mWaitWorkCV.wait(mLock);
- }
- delete data;
- }break;
- default:
- LOGW("AudioCommandThread() unknown command %d", command->mCommand);
- }
- delete command;
- waitTime = INT64_MAX;
- } else {
- waitTime = mAudioCommands[0]->mTime - curTime;
- break;
- }
- }
- // release delayed commands wake lock
- if (mName != "" && mAudioCommands.isEmpty()) {
- release_wake_lock(mName.string());
- }
- LOGV("AudioCommandThread() going to sleep");
- mWaitWorkCV.waitRelative(mLock, waitTime);
- LOGV("AudioCommandThread() waking up");
- }
- mLock.unlock();
- return false;
-}
-
-status_t AudioPolicyService::AudioCommandThread::dump(int fd)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
- result.append(buffer);
- write(fd, result.string(), result.size());
-
- bool locked = tryLock(mLock);
- if (!locked) {
- String8 result2(kCmdDeadlockedString);
- write(fd, result2.string(), result2.size());
- }
-
- snprintf(buffer, SIZE, "- Commands:\n");
- result = String8(buffer);
- result.append(" Command Time Wait pParam\n");
- for (int i = 0; i < (int)mAudioCommands.size(); i++) {
- mAudioCommands[i]->dump(buffer, SIZE);
- result.append(buffer);
- }
- result.append(" Last Command\n");
- mLastCommand.dump(buffer, SIZE);
- result.append(buffer);
-
- write(fd, result.string(), result.size());
-
- if (locked) mLock.unlock();
-
- return NO_ERROR;
-}
-
-void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
-{
- AudioCommand *command = new AudioCommand();
- command->mCommand = START_TONE;
- ToneData *data = new ToneData();
- data->mType = type;
- data->mStream = stream;
- command->mParam = (void *)data;
- command->mWaitStatus = false;
- Mutex::Autolock _l(mLock);
- insertCommand_l(command);
- LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
- mWaitWorkCV.signal();
-}
-
-void AudioPolicyService::AudioCommandThread::stopToneCommand()
-{
- AudioCommand *command = new AudioCommand();
- command->mCommand = STOP_TONE;
- command->mParam = NULL;
- command->mWaitStatus = false;
- Mutex::Autolock _l(mLock);
- insertCommand_l(command);
- LOGV("AudioCommandThread() adding tone stop");
- mWaitWorkCV.signal();
-}
-
-status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output, int delayMs)
-{
- status_t status = NO_ERROR;
-
- AudioCommand *command = new AudioCommand();
- command->mCommand = SET_VOLUME;
- VolumeData *data = new VolumeData();
- data->mStream = stream;
- data->mVolume = volume;
- data->mIO = output;
- command->mParam = data;
- if (delayMs == 0) {
- command->mWaitStatus = true;
- } else {
- command->mWaitStatus = false;
- }
- Mutex::Autolock _l(mLock);
- insertCommand_l(command, delayMs);
- LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", stream, volume, output);
- mWaitWorkCV.signal();
- if (command->mWaitStatus) {
- command->mCond.wait(mLock);
- status = command->mStatus;
- mWaitWorkCV.signal();
- }
- return status;
-}
-
-status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs)
-{
- status_t status = NO_ERROR;
-
- AudioCommand *command = new AudioCommand();
- command->mCommand = SET_PARAMETERS;
- ParametersData *data = new ParametersData();
- data->mIO = ioHandle;
- data->mKeyValuePairs = keyValuePairs;
- command->mParam = data;
- if (delayMs == 0) {
- command->mWaitStatus = true;
- } else {
- command->mWaitStatus = false;
- }
- Mutex::Autolock _l(mLock);
- insertCommand_l(command, delayMs);
- LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", keyValuePairs.string(), ioHandle, delayMs);
- mWaitWorkCV.signal();
- if (command->mWaitStatus) {
- command->mCond.wait(mLock);
- status = command->mStatus;
- mWaitWorkCV.signal();
- }
- return status;
-}
-
-status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
-{
- status_t status = NO_ERROR;
-
- AudioCommand *command = new AudioCommand();
- command->mCommand = SET_VOICE_VOLUME;
- VoiceVolumeData *data = new VoiceVolumeData();
- data->mVolume = volume;
- command->mParam = data;
- if (delayMs == 0) {
- command->mWaitStatus = true;
- } else {
- command->mWaitStatus = false;
- }
- Mutex::Autolock _l(mLock);
- insertCommand_l(command, delayMs);
- LOGV("AudioCommandThread() adding set voice volume volume %f", volume);
- mWaitWorkCV.signal();
- if (command->mWaitStatus) {
- command->mCond.wait(mLock);
- status = command->mStatus;
- mWaitWorkCV.signal();
- }
- return status;
-}
-
-// insertCommand_l() must be called with mLock held
-void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
-{
- ssize_t i;
- Vector <AudioCommand *> removedCommands;
-
- command->mTime = systemTime() + milliseconds(delayMs);
-
- // acquire wake lock to make sure delayed commands are processed
- if (mName != "" && mAudioCommands.isEmpty()) {
- acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string());
- }
-
- // check same pending commands with later time stamps and eliminate them
- for (i = mAudioCommands.size()-1; i >= 0; i--) {
- AudioCommand *command2 = mAudioCommands[i];
- // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
- if (command2->mTime <= command->mTime) break;
- if (command2->mCommand != command->mCommand) continue;
-
- switch (command->mCommand) {
- case SET_PARAMETERS: {
- ParametersData *data = (ParametersData *)command->mParam;
- ParametersData *data2 = (ParametersData *)command2->mParam;
- if (data->mIO != data2->mIO) break;
- LOGV("Comparing parameter command %s to new command %s", data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
- AudioParameter param = AudioParameter(data->mKeyValuePairs);
- AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
- for (size_t j = 0; j < param.size(); j++) {
- String8 key;
- String8 value;
- param.getAt(j, key, value);
- for (size_t k = 0; k < param2.size(); k++) {
- String8 key2;
- String8 value2;
- param2.getAt(k, key2, value2);
- if (key2 == key) {
- param2.remove(key2);
- LOGV("Filtering out parameter %s", key2.string());
- break;
- }
- }
- }
- // if all keys have been filtered out, remove the command.
- // otherwise, update the key value pairs
- if (param2.size() == 0) {
- removedCommands.add(command2);
- } else {
- data2->mKeyValuePairs = param2.toString();
- }
- } break;
-
- case SET_VOLUME: {
- VolumeData *data = (VolumeData *)command->mParam;
- VolumeData *data2 = (VolumeData *)command2->mParam;
- if (data->mIO != data2->mIO) break;
- if (data->mStream != data2->mStream) break;
- LOGV("Filtering out volume command on output %d for stream %d", data->mIO, data->mStream);
- removedCommands.add(command2);
- } break;
- case START_TONE:
- case STOP_TONE:
- default:
- break;
- }
- }
-
- // remove filtered commands
- for (size_t j = 0; j < removedCommands.size(); j++) {
- // removed commands always have time stamps greater than current command
- for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
- if (mAudioCommands[k] == removedCommands[j]) {
- LOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
- mAudioCommands.removeAt(k);
- break;
- }
- }
- }
- removedCommands.clear();
-
- // insert command at the right place according to its time stamp
- LOGV("inserting command: %d at index %d, num commands %d", command->mCommand, (int)i+1, mAudioCommands.size());
- mAudioCommands.insertAt(command, i + 1);
-}
-
-void AudioPolicyService::AudioCommandThread::exit()
-{
- LOGV("AudioCommandThread::exit");
- {
- AutoMutex _l(mLock);
- requestExit();
- mWaitWorkCV.signal();
- }
- requestExitAndWait();
-}
-
-void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size)
-{
- snprintf(buffer, size, " %02d %06d.%03d %01u %p\n",
- mCommand,
- (int)ns2s(mTime),
- (int)ns2ms(mTime)%1000,
- mWaitStatus,
- mParam);
-}
-
-}; // namespace android
diff --git a/libs/audioflinger/AudioPolicyService.h b/libs/audioflinger/AudioPolicyService.h
deleted file mode 100644
index a13d0bd..0000000
--- a/libs/audioflinger/AudioPolicyService.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_AUDIOPOLICYSERVICE_H
-#define ANDROID_AUDIOPOLICYSERVICE_H
-
-#include <media/IAudioPolicyService.h>
-#include <hardware_legacy/AudioPolicyInterface.h>
-#include <media/ToneGenerator.h>
-#include <utils/Vector.h>
-
-namespace android {
-
-class String8;
-
-// ----------------------------------------------------------------------------
-
-class AudioPolicyService: public BnAudioPolicyService, public AudioPolicyClientInterface, public IBinder::DeathRecipient
-{
-
-public:
- static void instantiate();
-
- virtual status_t dump(int fd, const Vector<String16>& args);
-
- //
- // BnAudioPolicyService (see AudioPolicyInterface for method descriptions)
- //
-
- virtual status_t setDeviceConnectionState(AudioSystem::audio_devices device,
- AudioSystem::device_connection_state state,
- const char *device_address);
- virtual AudioSystem::device_connection_state getDeviceConnectionState(AudioSystem::audio_devices device,
- const char *device_address);
- virtual status_t setPhoneState(int state);
- virtual status_t setRingerMode(uint32_t mode, uint32_t mask);
- virtual status_t setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config);
- virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage);
- virtual audio_io_handle_t getOutput(AudioSystem::stream_type stream,
- uint32_t samplingRate = 0,
- uint32_t format = AudioSystem::FORMAT_DEFAULT,
- uint32_t channels = 0,
- AudioSystem::output_flags flags = AudioSystem::OUTPUT_FLAG_INDIRECT);
- virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
- virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
- virtual void releaseOutput(audio_io_handle_t output);
- virtual audio_io_handle_t getInput(int inputSource,
- uint32_t samplingRate = 0,
- uint32_t format = AudioSystem::FORMAT_DEFAULT,
- uint32_t channels = 0,
- AudioSystem::audio_in_acoustics acoustics = (AudioSystem::audio_in_acoustics)0);
- virtual status_t startInput(audio_io_handle_t input);
- virtual status_t stopInput(audio_io_handle_t input);
- virtual void releaseInput(audio_io_handle_t input);
- virtual status_t initStreamVolume(AudioSystem::stream_type stream,
- int indexMin,
- int indexMax);
- virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index);
- virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index);
-
- virtual status_t onTransact(
- uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags);
-
- // IBinder::DeathRecipient
- virtual void binderDied(const wp<IBinder>& who);
-
- //
- // AudioPolicyClientInterface
- //
- virtual audio_io_handle_t openOutput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t *pLatencyMs,
- AudioSystem::output_flags flags);
- virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1, audio_io_handle_t output2);
- virtual status_t closeOutput(audio_io_handle_t output);
- virtual status_t suspendOutput(audio_io_handle_t output);
- virtual status_t restoreOutput(audio_io_handle_t output);
- virtual audio_io_handle_t openInput(uint32_t *pDevices,
- uint32_t *pSamplingRate,
- uint32_t *pFormat,
- uint32_t *pChannels,
- uint32_t acoustics);
- virtual status_t closeInput(audio_io_handle_t input);
- virtual status_t setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs = 0);
- virtual status_t setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output);
- virtual void setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs = 0);
- virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys);
- virtual status_t startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream);
- virtual status_t stopTone();
- virtual status_t setVoiceVolume(float volume, int delayMs = 0);
-
-private:
- AudioPolicyService();
- virtual ~AudioPolicyService();
-
- status_t dumpInternals(int fd);
-
- // Thread used for tone playback and to send audio config commands to audio flinger
- // For tone playback, using a separate thread is necessary to avoid deadlock with mLock because startTone()
- // and stopTone() are normally called with mLock locked and requesting a tone start or stop will cause
- // calls to AudioPolicyService and an attempt to lock mLock.
- // For audio config commands, it is necessary because audio flinger requires that the calling process (user)
- // has permission to modify audio settings.
- class AudioCommandThread : public Thread {
- class AudioCommand;
- public:
-
- // commands for tone AudioCommand
- enum {
- START_TONE,
- STOP_TONE,
- SET_VOLUME,
- SET_PARAMETERS,
- SET_VOICE_VOLUME
- };
-
- AudioCommandThread (String8 name);
- virtual ~AudioCommandThread();
-
- status_t dump(int fd);
-
- // Thread virtuals
- virtual void onFirstRef();
- virtual bool threadLoop();
-
- void exit();
- void startToneCommand(int type = 0, int stream = 0);
- void stopToneCommand();
- status_t volumeCommand(int stream, float volume, int output, int delayMs = 0);
- status_t parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs = 0);
- status_t voiceVolumeCommand(float volume, int delayMs = 0);
- void insertCommand_l(AudioCommand *command, int delayMs = 0);
-
- private:
- // descriptor for requested tone playback event
- class AudioCommand {
-
- public:
- AudioCommand()
- : mCommand(-1) {}
-
- void dump(char* buffer, size_t size);
-
- int mCommand; // START_TONE, STOP_TONE ...
- nsecs_t mTime; // time stamp
- Condition mCond; // condition for status return
- status_t mStatus; // command status
- bool mWaitStatus; // true if caller is waiting for status
- void *mParam; // command parameter (ToneData, VolumeData, ParametersData)
- };
-
- class ToneData {
- public:
- int mType; // tone type (START_TONE only)
- int mStream; // stream type (START_TONE only)
- };
-
- class VolumeData {
- public:
- int mStream;
- float mVolume;
- int mIO;
- };
-
- class ParametersData {
- public:
- int mIO;
- String8 mKeyValuePairs;
- };
-
- class VoiceVolumeData {
- public:
- float mVolume;
- };
-
- Mutex mLock;
- Condition mWaitWorkCV;
- Vector <AudioCommand *> mAudioCommands; // list of pending commands
- ToneGenerator *mpToneGenerator; // the tone generator
- AudioCommand mLastCommand; // last processed command (used by dump)
- String8 mName; // string used by wake lock fo delayed commands
- };
-
- // Internal dump utilities.
- status_t dumpPermissionDenial(int fd);
-
-
- Mutex mLock; // prevents concurrent access to AudioPolicy manager functions changing device
- // connection stated our routing
- AudioPolicyInterface* mpPolicyManager; // the platform specific policy manager
- sp <AudioCommandThread> mAudioCommandThread; // audio commands thread
- sp <AudioCommandThread> mTonePlaybackThread; // tone playback thread
-};
-
-}; // namespace android
-
-#endif // ANDROID_AUDIOPOLICYSERVICE_H
-
-
-
-
-
-
-
-
diff --git a/libs/audioflinger/AudioResampler.cpp b/libs/audioflinger/AudioResampler.cpp
deleted file mode 100644
index 5dabacb..0000000
--- a/libs/audioflinger/AudioResampler.cpp
+++ /dev/null
@@ -1,595 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "AudioResampler"
-//#define LOG_NDEBUG 0
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <cutils/log.h>
-#include <cutils/properties.h>
-#include "AudioResampler.h"
-#include "AudioResamplerSinc.h"
-#include "AudioResamplerCubic.h"
-
-namespace android {
-
-#ifdef __ARM_ARCH_5E__ // optimized asm option
- #define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1
-#endif // __ARM_ARCH_5E__
-// ----------------------------------------------------------------------------
-
-class AudioResamplerOrder1 : public AudioResampler {
-public:
- AudioResamplerOrder1(int bitDepth, int inChannelCount, int32_t sampleRate) :
- AudioResampler(bitDepth, inChannelCount, sampleRate), mX0L(0), mX0R(0) {
- }
- virtual void resample(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider);
-private:
- // number of bits used in interpolation multiply - 15 bits avoids overflow
- static const int kNumInterpBits = 15;
-
- // bits to shift the phase fraction down to avoid overflow
- static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits;
-
- void init() {}
- void resampleMono16(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider);
- void resampleStereo16(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider);
-#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
- void AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
- size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
- uint32_t &phaseFraction, uint32_t phaseIncrement);
- void AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
- size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
- uint32_t &phaseFraction, uint32_t phaseIncrement);
-#endif // ASM_ARM_RESAMP1
-
- static inline int32_t Interp(int32_t x0, int32_t x1, uint32_t f) {
- return x0 + (((x1 - x0) * (int32_t)(f >> kPreInterpShift)) >> kNumInterpBits);
- }
- static inline void Advance(size_t* index, uint32_t* frac, uint32_t inc) {
- *frac += inc;
- *index += (size_t)(*frac >> kNumPhaseBits);
- *frac &= kPhaseMask;
- }
- int mX0L;
- int mX0R;
-};
-
-// ----------------------------------------------------------------------------
-AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount,
- int32_t sampleRate, int quality) {
-
- // can only create low quality resample now
- AudioResampler* resampler;
-
- char value[PROPERTY_VALUE_MAX];
- if (property_get("af.resampler.quality", value, 0)) {
- quality = atoi(value);
- LOGD("forcing AudioResampler quality to %d", quality);
- }
-
- if (quality == DEFAULT)
- quality = LOW_QUALITY;
-
- switch (quality) {
- default:
- case LOW_QUALITY:
- LOGV("Create linear Resampler");
- resampler = new AudioResamplerOrder1(bitDepth, inChannelCount, sampleRate);
- break;
- case MED_QUALITY:
- LOGV("Create cubic Resampler");
- resampler = new AudioResamplerCubic(bitDepth, inChannelCount, sampleRate);
- break;
- case HIGH_QUALITY:
- LOGV("Create sinc Resampler");
- resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate);
- break;
- }
-
- // initialize resampler
- resampler->init();
- return resampler;
-}
-
-AudioResampler::AudioResampler(int bitDepth, int inChannelCount,
- int32_t sampleRate) :
- mBitDepth(bitDepth), mChannelCount(inChannelCount),
- mSampleRate(sampleRate), mInSampleRate(sampleRate), mInputIndex(0),
- mPhaseFraction(0) {
- // sanity check on format
- if ((bitDepth != 16) ||(inChannelCount < 1) || (inChannelCount > 2)) {
- LOGE("Unsupported sample format, %d bits, %d channels", bitDepth,
- inChannelCount);
- // LOG_ASSERT(0);
- }
-
- // initialize common members
- mVolume[0] = mVolume[1] = 0;
- mBuffer.frameCount = 0;
-
- // save format for quick lookup
- if (inChannelCount == 1) {
- mFormat = MONO_16_BIT;
- } else {
- mFormat = STEREO_16_BIT;
- }
-}
-
-AudioResampler::~AudioResampler() {
-}
-
-void AudioResampler::setSampleRate(int32_t inSampleRate) {
- mInSampleRate = inSampleRate;
- mPhaseIncrement = (uint32_t)((kPhaseMultiplier * inSampleRate) / mSampleRate);
-}
-
-void AudioResampler::setVolume(int16_t left, int16_t right) {
- // TODO: Implement anti-zipper filter
- mVolume[0] = left;
- mVolume[1] = right;
-}
-
-// ----------------------------------------------------------------------------
-
-void AudioResamplerOrder1::resample(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider) {
-
- // should never happen, but we overflow if it does
- // LOG_ASSERT(outFrameCount < 32767);
-
- // select the appropriate resampler
- switch (mChannelCount) {
- case 1:
- resampleMono16(out, outFrameCount, provider);
- break;
- case 2:
- resampleStereo16(out, outFrameCount, provider);
- break;
- }
-}
-
-void AudioResamplerOrder1::resampleStereo16(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider) {
-
- int32_t vl = mVolume[0];
- int32_t vr = mVolume[1];
-
- size_t inputIndex = mInputIndex;
- uint32_t phaseFraction = mPhaseFraction;
- uint32_t phaseIncrement = mPhaseIncrement;
- size_t outputIndex = 0;
- size_t outputSampleCount = outFrameCount * 2;
- size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
-
- // LOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d\n",
- // outFrameCount, inputIndex, phaseFraction, phaseIncrement);
-
- while (outputIndex < outputSampleCount) {
-
- // buffer is empty, fetch a new one
- while (mBuffer.frameCount == 0) {
- mBuffer.frameCount = inFrameCount;
- provider->getNextBuffer(&mBuffer);
- if (mBuffer.raw == NULL) {
- goto resampleStereo16_exit;
- }
-
- // LOGE("New buffer fetched: %d frames\n", mBuffer.frameCount);
- if (mBuffer.frameCount > inputIndex) break;
-
- inputIndex -= mBuffer.frameCount;
- mX0L = mBuffer.i16[mBuffer.frameCount*2-2];
- mX0R = mBuffer.i16[mBuffer.frameCount*2-1];
- provider->releaseBuffer(&mBuffer);
- // mBuffer.frameCount == 0 now so we reload a new buffer
- }
-
- int16_t *in = mBuffer.i16;
-
- // handle boundary case
- while (inputIndex == 0) {
- // LOGE("boundary case\n");
- out[outputIndex++] += vl * Interp(mX0L, in[0], phaseFraction);
- out[outputIndex++] += vr * Interp(mX0R, in[1], phaseFraction);
- Advance(&inputIndex, &phaseFraction, phaseIncrement);
- if (outputIndex == outputSampleCount)
- break;
- }
-
- // process input samples
- // LOGE("general case\n");
-
-#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
- if (inputIndex + 2 < mBuffer.frameCount) {
- int32_t* maxOutPt;
- int32_t maxInIdx;
-
- maxOutPt = out + (outputSampleCount - 2); // 2 because 2 frames per loop
- maxInIdx = mBuffer.frameCount - 2;
- AsmStereo16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr,
- phaseFraction, phaseIncrement);
- }
-#endif // ASM_ARM_RESAMP1
-
- while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) {
- out[outputIndex++] += vl * Interp(in[inputIndex*2-2],
- in[inputIndex*2], phaseFraction);
- out[outputIndex++] += vr * Interp(in[inputIndex*2-1],
- in[inputIndex*2+1], phaseFraction);
- Advance(&inputIndex, &phaseFraction, phaseIncrement);
- }
-
- // LOGE("loop done - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex);
-
- // if done with buffer, save samples
- if (inputIndex >= mBuffer.frameCount) {
- inputIndex -= mBuffer.frameCount;
-
- // LOGE("buffer done, new input index %d", inputIndex);
-
- mX0L = mBuffer.i16[mBuffer.frameCount*2-2];
- mX0R = mBuffer.i16[mBuffer.frameCount*2-1];
- provider->releaseBuffer(&mBuffer);
-
- // verify that the releaseBuffer resets the buffer frameCount
- // LOG_ASSERT(mBuffer.frameCount == 0);
- }
- }
-
- // LOGE("output buffer full - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex);
-
-resampleStereo16_exit:
- // save state
- mInputIndex = inputIndex;
- mPhaseFraction = phaseFraction;
-}
-
-void AudioResamplerOrder1::resampleMono16(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider) {
-
- int32_t vl = mVolume[0];
- int32_t vr = mVolume[1];
-
- size_t inputIndex = mInputIndex;
- uint32_t phaseFraction = mPhaseFraction;
- uint32_t phaseIncrement = mPhaseIncrement;
- size_t outputIndex = 0;
- size_t outputSampleCount = outFrameCount * 2;
- size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
-
- // LOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d\n",
- // outFrameCount, inputIndex, phaseFraction, phaseIncrement);
- while (outputIndex < outputSampleCount) {
- // buffer is empty, fetch a new one
- while (mBuffer.frameCount == 0) {
- mBuffer.frameCount = inFrameCount;
- provider->getNextBuffer(&mBuffer);
- if (mBuffer.raw == NULL) {
- mInputIndex = inputIndex;
- mPhaseFraction = phaseFraction;
- goto resampleMono16_exit;
- }
- // LOGE("New buffer fetched: %d frames\n", mBuffer.frameCount);
- if (mBuffer.frameCount > inputIndex) break;
-
- inputIndex -= mBuffer.frameCount;
- mX0L = mBuffer.i16[mBuffer.frameCount-1];
- provider->releaseBuffer(&mBuffer);
- // mBuffer.frameCount == 0 now so we reload a new buffer
- }
- int16_t *in = mBuffer.i16;
-
- // handle boundary case
- while (inputIndex == 0) {
- // LOGE("boundary case\n");
- int32_t sample = Interp(mX0L, in[0], phaseFraction);
- out[outputIndex++] += vl * sample;
- out[outputIndex++] += vr * sample;
- Advance(&inputIndex, &phaseFraction, phaseIncrement);
- if (outputIndex == outputSampleCount)
- break;
- }
-
- // process input samples
- // LOGE("general case\n");
-
-#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
- if (inputIndex + 2 < mBuffer.frameCount) {
- int32_t* maxOutPt;
- int32_t maxInIdx;
-
- maxOutPt = out + (outputSampleCount - 2);
- maxInIdx = (int32_t)mBuffer.frameCount - 2;
- AsmMono16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr,
- phaseFraction, phaseIncrement);
- }
-#endif // ASM_ARM_RESAMP1
-
- while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) {
- int32_t sample = Interp(in[inputIndex-1], in[inputIndex],
- phaseFraction);
- out[outputIndex++] += vl * sample;
- out[outputIndex++] += vr * sample;
- Advance(&inputIndex, &phaseFraction, phaseIncrement);
- }
-
-
- // LOGE("loop done - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex);
-
- // if done with buffer, save samples
- if (inputIndex >= mBuffer.frameCount) {
- inputIndex -= mBuffer.frameCount;
-
- // LOGE("buffer done, new input index %d", inputIndex);
-
- mX0L = mBuffer.i16[mBuffer.frameCount-1];
- provider->releaseBuffer(&mBuffer);
-
- // verify that the releaseBuffer resets the buffer frameCount
- // LOG_ASSERT(mBuffer.frameCount == 0);
- }
- }
-
- // LOGE("output buffer full - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex);
-
-resampleMono16_exit:
- // save state
- mInputIndex = inputIndex;
- mPhaseFraction = phaseFraction;
-}
-
-#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
-
-/*******************************************************************
-*
-* AsmMono16Loop
-* asm optimized monotonic loop version; one loop is 2 frames
-* Input:
-* in : pointer on input samples
-* maxOutPt : pointer on first not filled
-* maxInIdx : index on first not used
-* outputIndex : pointer on current output index
-* out : pointer on output buffer
-* inputIndex : pointer on current input index
-* vl, vr : left and right gain
-* phaseFraction : pointer on current phase fraction
-* phaseIncrement
-* Ouput:
-* outputIndex :
-* out : updated buffer
-* inputIndex : index of next to use
-* phaseFraction : phase fraction for next interpolation
-*
-*******************************************************************/
-void AudioResamplerOrder1::AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
- size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
- uint32_t &phaseFraction, uint32_t phaseIncrement)
-{
-#define MO_PARAM5 "36" // offset of parameter 5 (outputIndex)
-
- asm(
- "stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n"
- // get parameters
- " ldr r6, [sp, #" MO_PARAM5 " + 20]\n" // &phaseFraction
- " ldr r6, [r6]\n" // phaseFraction
- " ldr r7, [sp, #" MO_PARAM5 " + 8]\n" // &inputIndex
- " ldr r7, [r7]\n" // inputIndex
- " ldr r8, [sp, #" MO_PARAM5 " + 4]\n" // out
- " ldr r0, [sp, #" MO_PARAM5 " + 0]\n" // &outputIndex
- " ldr r0, [r0]\n" // outputIndex
- " add r8, r0, asl #2\n" // curOut
- " ldr r9, [sp, #" MO_PARAM5 " + 24]\n" // phaseIncrement
- " ldr r10, [sp, #" MO_PARAM5 " + 12]\n" // vl
- " ldr r11, [sp, #" MO_PARAM5 " + 16]\n" // vr
-
- // r0 pin, x0, Samp
-
- // r1 in
- // r2 maxOutPt
- // r3 maxInIdx
-
- // r4 x1, i1, i3, Out1
- // r5 out0
-
- // r6 frac
- // r7 inputIndex
- // r8 curOut
-
- // r9 inc
- // r10 vl
- // r11 vr
-
- // r12
- // r13 sp
- // r14
-
- // the following loop works on 2 frames
-
- ".Y4L01:\n"
- " cmp r8, r2\n" // curOut - maxCurOut
- " bcs .Y4L02\n"
-
-#define MO_ONE_FRAME \
- " add r0, r1, r7, asl #1\n" /* in + inputIndex */\
- " ldrsh r4, [r0]\n" /* in[inputIndex] */\
- " ldr r5, [r8]\n" /* out[outputIndex] */\
- " ldrsh r0, [r0, #-2]\n" /* in[inputIndex-1] */\
- " bic r6, r6, #0xC0000000\n" /* phaseFraction & ... */\
- " sub r4, r4, r0\n" /* in[inputIndex] - in[inputIndex-1] */\
- " mov r4, r4, lsl #2\n" /* <<2 */\
- " smulwt r4, r4, r6\n" /* (x1-x0)*.. */\
- " add r6, r6, r9\n" /* phaseFraction + phaseIncrement */\
- " add r0, r0, r4\n" /* x0 - (..) */\
- " mla r5, r0, r10, r5\n" /* vl*interp + out[] */\
- " ldr r4, [r8, #4]\n" /* out[outputIndex+1] */\
- " str r5, [r8], #4\n" /* out[outputIndex++] = ... */\
- " mla r4, r0, r11, r4\n" /* vr*interp + out[] */\
- " add r7, r7, r6, lsr #30\n" /* inputIndex + phaseFraction>>30 */\
- " str r4, [r8], #4\n" /* out[outputIndex++] = ... */
-
- MO_ONE_FRAME // frame 1
- MO_ONE_FRAME // frame 2
-
- " cmp r7, r3\n" // inputIndex - maxInIdx
- " bcc .Y4L01\n"
- ".Y4L02:\n"
-
- " bic r6, r6, #0xC0000000\n" // phaseFraction & ...
- // save modified values
- " ldr r0, [sp, #" MO_PARAM5 " + 20]\n" // &phaseFraction
- " str r6, [r0]\n" // phaseFraction
- " ldr r0, [sp, #" MO_PARAM5 " + 8]\n" // &inputIndex
- " str r7, [r0]\n" // inputIndex
- " ldr r0, [sp, #" MO_PARAM5 " + 4]\n" // out
- " sub r8, r0\n" // curOut - out
- " asr r8, #2\n" // new outputIndex
- " ldr r0, [sp, #" MO_PARAM5 " + 0]\n" // &outputIndex
- " str r8, [r0]\n" // save outputIndex
-
- " ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}\n"
- );
-}
-
-/*******************************************************************
-*
-* AsmStereo16Loop
-* asm optimized stereo loop version; one loop is 2 frames
-* Input:
-* in : pointer on input samples
-* maxOutPt : pointer on first not filled
-* maxInIdx : index on first not used
-* outputIndex : pointer on current output index
-* out : pointer on output buffer
-* inputIndex : pointer on current input index
-* vl, vr : left and right gain
-* phaseFraction : pointer on current phase fraction
-* phaseIncrement
-* Ouput:
-* outputIndex :
-* out : updated buffer
-* inputIndex : index of next to use
-* phaseFraction : phase fraction for next interpolation
-*
-*******************************************************************/
-void AudioResamplerOrder1::AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
- size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
- uint32_t &phaseFraction, uint32_t phaseIncrement)
-{
-#define ST_PARAM5 "40" // offset of parameter 5 (outputIndex)
- asm(
- "stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n"
- // get parameters
- " ldr r6, [sp, #" ST_PARAM5 " + 20]\n" // &phaseFraction
- " ldr r6, [r6]\n" // phaseFraction
- " ldr r7, [sp, #" ST_PARAM5 " + 8]\n" // &inputIndex
- " ldr r7, [r7]\n" // inputIndex
- " ldr r8, [sp, #" ST_PARAM5 " + 4]\n" // out
- " ldr r0, [sp, #" ST_PARAM5 " + 0]\n" // &outputIndex
- " ldr r0, [r0]\n" // outputIndex
- " add r8, r0, asl #2\n" // curOut
- " ldr r9, [sp, #" ST_PARAM5 " + 24]\n" // phaseIncrement
- " ldr r10, [sp, #" ST_PARAM5 " + 12]\n" // vl
- " ldr r11, [sp, #" ST_PARAM5 " + 16]\n" // vr
-
- // r0 pin, x0, Samp
-
- // r1 in
- // r2 maxOutPt
- // r3 maxInIdx
-
- // r4 x1, i1, i3, out1
- // r5 out0
-
- // r6 frac
- // r7 inputIndex
- // r8 curOut
-
- // r9 inc
- // r10 vl
- // r11 vr
-
- // r12 temporary
- // r13 sp
- // r14
-
- ".Y5L01:\n"
- " cmp r8, r2\n" // curOut - maxCurOut
- " bcs .Y5L02\n"
-
-#define ST_ONE_FRAME \
- " bic r6, r6, #0xC0000000\n" /* phaseFraction & ... */\
-\
- " add r0, r1, r7, asl #2\n" /* in + 2*inputIndex */\
-\
- " ldrsh r4, [r0]\n" /* in[2*inputIndex] */\
- " ldr r5, [r8]\n" /* out[outputIndex] */\
- " ldrsh r12, [r0, #-4]\n" /* in[2*inputIndex-2] */\
- " sub r4, r4, r12\n" /* in[2*InputIndex] - in[2*InputIndex-2] */\
- " mov r4, r4, lsl #2\n" /* <<2 */\
- " smulwt r4, r4, r6\n" /* (x1-x0)*.. */\
- " add r12, r12, r4\n" /* x0 - (..) */\
- " mla r5, r12, r10, r5\n" /* vl*interp + out[] */\
- " ldr r4, [r8, #4]\n" /* out[outputIndex+1] */\
- " str r5, [r8], #4\n" /* out[outputIndex++] = ... */\
-\
- " ldrsh r12, [r0, #+2]\n" /* in[2*inputIndex+1] */\
- " ldrsh r0, [r0, #-2]\n" /* in[2*inputIndex-1] */\
- " sub r12, r12, r0\n" /* in[2*InputIndex] - in[2*InputIndex-2] */\
- " mov r12, r12, lsl #2\n" /* <<2 */\
- " smulwt r12, r12, r6\n" /* (x1-x0)*.. */\
- " add r12, r0, r12\n" /* x0 - (..) */\
- " mla r4, r12, r11, r4\n" /* vr*interp + out[] */\
- " str r4, [r8], #4\n" /* out[outputIndex++] = ... */\
-\
- " add r6, r6, r9\n" /* phaseFraction + phaseIncrement */\
- " add r7, r7, r6, lsr #30\n" /* inputIndex + phaseFraction>>30 */
-
- ST_ONE_FRAME // frame 1
- ST_ONE_FRAME // frame 1
-
- " cmp r7, r3\n" // inputIndex - maxInIdx
- " bcc .Y5L01\n"
- ".Y5L02:\n"
-
- " bic r6, r6, #0xC0000000\n" // phaseFraction & ...
- // save modified values
- " ldr r0, [sp, #" ST_PARAM5 " + 20]\n" // &phaseFraction
- " str r6, [r0]\n" // phaseFraction
- " ldr r0, [sp, #" ST_PARAM5 " + 8]\n" // &inputIndex
- " str r7, [r0]\n" // inputIndex
- " ldr r0, [sp, #" ST_PARAM5 " + 4]\n" // out
- " sub r8, r0\n" // curOut - out
- " asr r8, #2\n" // new outputIndex
- " ldr r0, [sp, #" ST_PARAM5 " + 0]\n" // &outputIndex
- " str r8, [r0]\n" // save outputIndex
-
- " ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, pc}\n"
- );
-}
-
-#endif // ASM_ARM_RESAMP1
-
-
-// ----------------------------------------------------------------------------
-}
-; // namespace android
-
diff --git a/libs/audioflinger/AudioResampler.h b/libs/audioflinger/AudioResampler.h
deleted file mode 100644
index 2dfac76..0000000
--- a/libs/audioflinger/AudioResampler.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_AUDIO_RESAMPLER_H
-#define ANDROID_AUDIO_RESAMPLER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "AudioBufferProvider.h"
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class AudioResampler {
-public:
- // Determines quality of SRC.
- // LOW_QUALITY: linear interpolator (1st order)
- // MED_QUALITY: cubic interpolator (3rd order)
- // HIGH_QUALITY: fixed multi-tap FIR (e.g. 48KHz->44.1KHz)
- // NOTE: high quality SRC will only be supported for
- // certain fixed rate conversions. Sample rate cannot be
- // changed dynamically.
- enum src_quality {
- DEFAULT=0,
- LOW_QUALITY=1,
- MED_QUALITY=2,
- HIGH_QUALITY=3
- };
-
- static AudioResampler* create(int bitDepth, int inChannelCount,
- int32_t sampleRate, int quality=DEFAULT);
-
- virtual ~AudioResampler();
-
- virtual void init() = 0;
- virtual void setSampleRate(int32_t inSampleRate);
- virtual void setVolume(int16_t left, int16_t right);
-
- virtual void resample(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider) = 0;
-
-protected:
- // number of bits for phase fraction - 30 bits allows nearly 2x downsampling
- static const int kNumPhaseBits = 30;
-
- // phase mask for fraction
- static const uint32_t kPhaseMask = (1LU<<kNumPhaseBits)-1;
-
- // multiplier to calculate fixed point phase increment
- static const double kPhaseMultiplier = 1L << kNumPhaseBits;
-
- enum format {MONO_16_BIT, STEREO_16_BIT};
- AudioResampler(int bitDepth, int inChannelCount, int32_t sampleRate);
-
- // prevent copying
- AudioResampler(const AudioResampler&);
- AudioResampler& operator=(const AudioResampler&);
-
- int32_t mBitDepth;
- int32_t mChannelCount;
- int32_t mSampleRate;
- int32_t mInSampleRate;
- AudioBufferProvider::Buffer mBuffer;
- union {
- int16_t mVolume[2];
- uint32_t mVolumeRL;
- };
- int16_t mTargetVolume[2];
- format mFormat;
- size_t mInputIndex;
- int32_t mPhaseIncrement;
- uint32_t mPhaseFraction;
-};
-
-// ----------------------------------------------------------------------------
-}
-; // namespace android
-
-#endif // ANDROID_AUDIO_RESAMPLER_H
diff --git a/libs/audioflinger/AudioResamplerCubic.cpp b/libs/audioflinger/AudioResamplerCubic.cpp
deleted file mode 100644
index 1d247bd..0000000
--- a/libs/audioflinger/AudioResamplerCubic.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdint.h>
-#include <string.h>
-#include <sys/types.h>
-#include <cutils/log.h>
-
-#include "AudioResampler.h"
-#include "AudioResamplerCubic.h"
-
-#define LOG_TAG "AudioSRC"
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-void AudioResamplerCubic::init() {
- memset(&left, 0, sizeof(state));
- memset(&right, 0, sizeof(state));
-}
-
-void AudioResamplerCubic::resample(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider) {
-
- // should never happen, but we overflow if it does
- // LOG_ASSERT(outFrameCount < 32767);
-
- // select the appropriate resampler
- switch (mChannelCount) {
- case 1:
- resampleMono16(out, outFrameCount, provider);
- break;
- case 2:
- resampleStereo16(out, outFrameCount, provider);
- break;
- }
-}
-
-void AudioResamplerCubic::resampleStereo16(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider) {
-
- int32_t vl = mVolume[0];
- int32_t vr = mVolume[1];
-
- size_t inputIndex = mInputIndex;
- uint32_t phaseFraction = mPhaseFraction;
- uint32_t phaseIncrement = mPhaseIncrement;
- size_t outputIndex = 0;
- size_t outputSampleCount = outFrameCount * 2;
- size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
-
- // fetch first buffer
- if (mBuffer.frameCount == 0) {
- mBuffer.frameCount = inFrameCount;
- provider->getNextBuffer(&mBuffer);
- if (mBuffer.raw == NULL)
- return;
- // LOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount);
- }
- int16_t *in = mBuffer.i16;
-
- while (outputIndex < outputSampleCount) {
- int32_t sample;
- int32_t x;
-
- // calculate output sample
- x = phaseFraction >> kPreInterpShift;
- out[outputIndex++] += vl * interp(&left, x);
- out[outputIndex++] += vr * interp(&right, x);
- // out[outputIndex++] += vr * in[inputIndex*2];
-
- // increment phase
- phaseFraction += phaseIncrement;
- uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits);
- phaseFraction &= kPhaseMask;
-
- // time to fetch another sample
- while (indexIncrement--) {
-
- inputIndex++;
- if (inputIndex == mBuffer.frameCount) {
- inputIndex = 0;
- provider->releaseBuffer(&mBuffer);
- mBuffer.frameCount = inFrameCount;
- provider->getNextBuffer(&mBuffer);
- if (mBuffer.raw == NULL)
- goto save_state; // ugly, but efficient
- in = mBuffer.i16;
- // LOGW("New buffer: offset=%p, frames=%d\n", mBuffer.raw, mBuffer.frameCount);
- }
-
- // advance sample state
- advance(&left, in[inputIndex*2]);
- advance(&right, in[inputIndex*2+1]);
- }
- }
-
-save_state:
- // LOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction);
- mInputIndex = inputIndex;
- mPhaseFraction = phaseFraction;
-}
-
-void AudioResamplerCubic::resampleMono16(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider) {
-
- int32_t vl = mVolume[0];
- int32_t vr = mVolume[1];
-
- size_t inputIndex = mInputIndex;
- uint32_t phaseFraction = mPhaseFraction;
- uint32_t phaseIncrement = mPhaseIncrement;
- size_t outputIndex = 0;
- size_t outputSampleCount = outFrameCount * 2;
- size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
-
- // fetch first buffer
- if (mBuffer.frameCount == 0) {
- mBuffer.frameCount = inFrameCount;
- provider->getNextBuffer(&mBuffer);
- if (mBuffer.raw == NULL)
- return;
- // LOGW("New buffer: offset=%p, frames=%d\n", mBuffer.raw, mBuffer.frameCount);
- }
- int16_t *in = mBuffer.i16;
-
- while (outputIndex < outputSampleCount) {
- int32_t sample;
- int32_t x;
-
- // calculate output sample
- x = phaseFraction >> kPreInterpShift;
- sample = interp(&left, x);
- out[outputIndex++] += vl * sample;
- out[outputIndex++] += vr * sample;
-
- // increment phase
- phaseFraction += phaseIncrement;
- uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits);
- phaseFraction &= kPhaseMask;
-
- // time to fetch another sample
- while (indexIncrement--) {
-
- inputIndex++;
- if (inputIndex == mBuffer.frameCount) {
- inputIndex = 0;
- provider->releaseBuffer(&mBuffer);
- mBuffer.frameCount = inFrameCount;
- provider->getNextBuffer(&mBuffer);
- if (mBuffer.raw == NULL)
- goto save_state; // ugly, but efficient
- // LOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount);
- in = mBuffer.i16;
- }
-
- // advance sample state
- advance(&left, in[inputIndex]);
- }
- }
-
-save_state:
- // LOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction);
- mInputIndex = inputIndex;
- mPhaseFraction = phaseFraction;
-}
-
-// ----------------------------------------------------------------------------
-}
-; // namespace android
-
diff --git a/libs/audioflinger/AudioResamplerCubic.h b/libs/audioflinger/AudioResamplerCubic.h
deleted file mode 100644
index b72b62a..0000000
--- a/libs/audioflinger/AudioResamplerCubic.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_AUDIO_RESAMPLER_CUBIC_H
-#define ANDROID_AUDIO_RESAMPLER_CUBIC_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <cutils/log.h>
-
-#include "AudioResampler.h"
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class AudioResamplerCubic : public AudioResampler {
-public:
- AudioResamplerCubic(int bitDepth, int inChannelCount, int32_t sampleRate) :
- AudioResampler(bitDepth, inChannelCount, sampleRate) {
- }
- virtual void resample(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider);
-private:
- // number of bits used in interpolation multiply - 14 bits avoids overflow
- static const int kNumInterpBits = 14;
-
- // bits to shift the phase fraction down to avoid overflow
- static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits;
- typedef struct {
- int32_t a, b, c, y0, y1, y2, y3;
- } state;
- void init();
- void resampleMono16(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider);
- void resampleStereo16(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider);
- static inline int32_t interp(state* p, int32_t x) {
- return (((((p->a * x >> 14) + p->b) * x >> 14) + p->c) * x >> 14) + p->y1;
- }
- static inline void advance(state* p, int16_t in) {
- p->y0 = p->y1;
- p->y1 = p->y2;
- p->y2 = p->y3;
- p->y3 = in;
- p->a = (3 * (p->y1 - p->y2) - p->y0 + p->y3) >> 1;
- p->b = (p->y2 << 1) + p->y0 - (((5 * p->y1 + p->y3)) >> 1);
- p->c = (p->y2 - p->y0) >> 1;
- }
- state left, right;
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif /*ANDROID_AUDIO_RESAMPLER_CUBIC_H*/
diff --git a/libs/audioflinger/AudioResamplerSinc.cpp b/libs/audioflinger/AudioResamplerSinc.cpp
deleted file mode 100644
index 9e5e254..0000000
--- a/libs/audioflinger/AudioResamplerSinc.cpp
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <string.h>
-#include "AudioResamplerSinc.h"
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-
-/*
- * These coeficients are computed with the "fir" utility found in
- * tools/resampler_tools
- * TODO: A good optimization would be to transpose this matrix, to take
- * better advantage of the data-cache.
- */
-const int32_t AudioResamplerSinc::mFirCoefsUp[] = {
- 0x7fffffff, 0x7f15d078, 0x7c5e0da6, 0x77ecd867, 0x71e2e251, 0x6a6c304a, 0x61be7269, 0x58170412, 0x4db8ab05, 0x42e92ea6, 0x37eee214, 0x2d0e3bb1, 0x22879366, 0x18951e95, 0x0f693d0d, 0x072d2621,
- 0x00000000, 0xf9f66655, 0xf51a5fd7, 0xf16bbd84, 0xeee0d9ac, 0xed67a922, 0xece70de6, 0xed405897, 0xee50e505, 0xeff3be30, 0xf203370f, 0xf45a6741, 0xf6d67d53, 0xf957db66, 0xfbc2f647, 0xfe00f2b9,
- 0x00000000, 0x01b37218, 0x0313a0c6, 0x041d930d, 0x04d28057, 0x053731b0, 0x05534dff, 0x05309bfd, 0x04da440d, 0x045c1aee, 0x03c1fcdd, 0x03173ef5, 0x02663ae8, 0x01b7f736, 0x0113ec79, 0x007fe6a9,
- 0x00000000, 0xff96b229, 0xff44f99f, 0xff0a86be, 0xfee5f803, 0xfed518fd, 0xfed521fd, 0xfee2f4fd, 0xfefb54f8, 0xff1b159b, 0xff3f4203, 0xff6539e0, 0xff8ac502, 0xffae1ddd, 0xffcdf3f9, 0xffe96798,
- 0x00000000, 0x00119de6, 0x001e6b7e, 0x0026cb7a, 0x002b4830, 0x002c83d6, 0x002b2a82, 0x0027e67a, 0x002356f9, 0x001e098e, 0x001875e4, 0x0012fbbe, 0x000de2d1, 0x00095c10, 0x00058414, 0x00026636,
- 0x00000000, 0xfffe44a9, 0xfffd206d, 0xfffc7b7f, 0xfffc3c8f, 0xfffc4ac2, 0xfffc8f2b, 0xfffcf5c4, 0xfffd6df3, 0xfffdeab2, 0xfffe6275, 0xfffececf, 0xffff2c07, 0xffff788c, 0xffffb471, 0xffffe0f2,
- 0x00000000, 0x000013e6, 0x00001f03, 0x00002396, 0x00002399, 0x000020b6, 0x00001c3c, 0x00001722, 0x00001216, 0x00000d81, 0x0000099c, 0x0000067c, 0x00000419, 0x0000025f, 0x00000131, 0x00000070,
- 0x00000000, 0xffffffc7, 0xffffffb3, 0xffffffb3, 0xffffffbe, 0xffffffcd, 0xffffffdb, 0xffffffe7, 0xfffffff0, 0xfffffff7, 0xfffffffb, 0xfffffffe, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000 // this one is needed for lerping the last coefficient
-};
-
-/*
- * These coefficients are optimized for 48KHz -> 44.1KHz (stop-band at 22.050KHz)
- * It's possible to use the above coefficient for any down-sampling
- * at the expense of a slower processing loop (we can interpolate
- * these coefficient from the above by "Stretching" them in time).
- */
-const int32_t AudioResamplerSinc::mFirCoefsDown[] = {
- 0x7fffffff, 0x7f55e46d, 0x7d5b4c60, 0x7a1b4b98, 0x75a7fb14, 0x7019f0bd, 0x698f875a, 0x622bfd59, 0x5a167256, 0x5178cc54, 0x487e8e6c, 0x3f53aae8, 0x36235ad4, 0x2d17047b, 0x245539ab, 0x1c00d540,
- 0x14383e57, 0x0d14d5ca, 0x06aa910b, 0x0107c38b, 0xfc351654, 0xf835abae, 0xf5076b45, 0xf2a37202, 0xf0fe9faa, 0xf00a3bbd, 0xefb4aa81, 0xefea2b05, 0xf0959716, 0xf1a11e83, 0xf2f6f7a0, 0xf481fff4,
- 0xf62e48ce, 0xf7e98ca5, 0xf9a38b4c, 0xfb4e4bfa, 0xfcde456f, 0xfe4a6d30, 0xff8c2fdf, 0x009f5555, 0x0181d393, 0x0233940f, 0x02b62f06, 0x030ca07d, 0x033afa62, 0x03461725, 0x03334f83, 0x030835fa,
- 0x02ca59cc, 0x027f12d1, 0x022b570d, 0x01d39a49, 0x017bb78f, 0x0126e414, 0x00d7aaaf, 0x008feec7, 0x0050f584, 0x001b73e3, 0xffefa063, 0xffcd46ed, 0xffb3ddcd, 0xffa29aaa, 0xff988691, 0xff949066,
- 0xff959d24, 0xff9a959e, 0xffa27195, 0xffac4011, 0xffb72d2b, 0xffc28569, 0xffcdb706, 0xffd85171, 0xffe20364, 0xffea97e9, 0xfff1f2b2, 0xfff80c06, 0xfffcec92, 0x0000a955, 0x00035fd8, 0x000532cf,
- 0x00064735, 0x0006c1f9, 0x0006c62d, 0x000673ba, 0x0005e68f, 0x00053630, 0x000475a3, 0x0003b397, 0x0002fac1, 0x00025257, 0x0001be9e, 0x0001417a, 0x0000dafd, 0x000089eb, 0x00004c28, 0x00001f1d,
- 0x00000000, 0xffffec10, 0xffffe0be, 0xffffdbc5, 0xffffdb39, 0xffffdd8b, 0xffffe182, 0xffffe638, 0xffffeb0a, 0xffffef8f, 0xfffff38b, 0xfffff6e3, 0xfffff993, 0xfffffba6, 0xfffffd30, 0xfffffe4a,
- 0xffffff09, 0xffffff85, 0xffffffd1, 0xfffffffb, 0x0000000f, 0x00000016, 0x00000015, 0x00000012, 0x0000000d, 0x00000009, 0x00000006, 0x00000003, 0x00000002, 0x00000001, 0x00000000, 0x00000000,
- 0x00000000 // this one is needed for lerping the last coefficient
-};
-
-// ----------------------------------------------------------------------------
-
-static inline
-int32_t mulRL(int left, int32_t in, uint32_t vRL)
-{
-#if defined(__arm__) && !defined(__thumb__)
- int32_t out;
- if (left) {
- asm( "smultb %[out], %[in], %[vRL] \n"
- : [out]"=r"(out)
- : [in]"%r"(in), [vRL]"r"(vRL)
- : );
- } else {
- asm( "smultt %[out], %[in], %[vRL] \n"
- : [out]"=r"(out)
- : [in]"%r"(in), [vRL]"r"(vRL)
- : );
- }
- return out;
-#else
- if (left) {
- return int16_t(in>>16) * int16_t(vRL&0xFFFF);
- } else {
- return int16_t(in>>16) * int16_t(vRL>>16);
- }
-#endif
-}
-
-static inline
-int32_t mulAdd(int16_t in, int32_t v, int32_t a)
-{
-#if defined(__arm__) && !defined(__thumb__)
- int32_t out;
- asm( "smlawb %[out], %[v], %[in], %[a] \n"
- : [out]"=r"(out)
- : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
- : );
- return out;
-#else
- return a + in * (v>>16);
- // improved precision
- // return a + in * (v>>16) + ((in * (v & 0xffff)) >> 16);
-#endif
-}
-
-static inline
-int32_t mulAddRL(int left, uint32_t inRL, int32_t v, int32_t a)
-{
-#if defined(__arm__) && !defined(__thumb__)
- int32_t out;
- if (left) {
- asm( "smlawb %[out], %[v], %[inRL], %[a] \n"
- : [out]"=r"(out)
- : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
- : );
- } else {
- asm( "smlawt %[out], %[v], %[inRL], %[a] \n"
- : [out]"=r"(out)
- : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
- : );
- }
- return out;
-#else
- if (left) {
- return a + (int16_t(inRL&0xFFFF) * (v>>16));
- //improved precision
- // return a + (int16_t(inRL&0xFFFF) * (v>>16)) + ((int16_t(inRL&0xFFFF) * (v & 0xffff)) >> 16);
- } else {
- return a + (int16_t(inRL>>16) * (v>>16));
- }
-#endif
-}
-
-// ----------------------------------------------------------------------------
-
-AudioResamplerSinc::AudioResamplerSinc(int bitDepth,
- int inChannelCount, int32_t sampleRate)
- : AudioResampler(bitDepth, inChannelCount, sampleRate),
- mState(0)
-{
- /*
- * Layout of the state buffer for 32 tap:
- *
- * "present" sample beginning of 2nd buffer
- * v v
- * 0 01 2 23 3
- * 0 F0 0 F0 F
- * [pppppppppppppppInnnnnnnnnnnnnnnnpppppppppppppppInnnnnnnnnnnnnnnn]
- * ^ ^ head
- *
- * p = past samples, convoluted with the (p)ositive side of sinc()
- * n = future samples, convoluted with the (n)egative side of sinc()
- * r = extra space for implementing the ring buffer
- *
- */
-
- const size_t numCoefs = 2*halfNumCoefs;
- const size_t stateSize = numCoefs * inChannelCount * 2;
- mState = new int16_t[stateSize];
- memset(mState, 0, sizeof(int16_t)*stateSize);
- mImpulse = mState + (halfNumCoefs-1)*inChannelCount;
- mRingFull = mImpulse + (numCoefs+1)*inChannelCount;
-}
-
-AudioResamplerSinc::~AudioResamplerSinc()
-{
- delete [] mState;
-}
-
-void AudioResamplerSinc::init() {
-}
-
-void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider)
-{
- mFirCoefs = (mInSampleRate <= mSampleRate) ? mFirCoefsUp : mFirCoefsDown;
-
- // select the appropriate resampler
- switch (mChannelCount) {
- case 1:
- resample<1>(out, outFrameCount, provider);
- break;
- case 2:
- resample<2>(out, outFrameCount, provider);
- break;
- }
-}
-
-
-template<int CHANNELS>
-void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider)
-{
- int16_t* impulse = mImpulse;
- uint32_t vRL = mVolumeRL;
- size_t inputIndex = mInputIndex;
- uint32_t phaseFraction = mPhaseFraction;
- uint32_t phaseIncrement = mPhaseIncrement;
- size_t outputIndex = 0;
- size_t outputSampleCount = outFrameCount * 2;
- size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
-
- AudioBufferProvider::Buffer& buffer(mBuffer);
- while (outputIndex < outputSampleCount) {
- // buffer is empty, fetch a new one
- while (buffer.frameCount == 0) {
- buffer.frameCount = inFrameCount;
- provider->getNextBuffer(&buffer);
- if (buffer.raw == NULL) {
- goto resample_exit;
- }
- const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits;
- if (phaseIndex == 1) {
- // read one frame
- read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex);
- } else if (phaseIndex == 2) {
- // read 2 frames
- read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex);
- inputIndex++;
- if (inputIndex >= mBuffer.frameCount) {
- inputIndex -= mBuffer.frameCount;
- provider->releaseBuffer(&buffer);
- } else {
- read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex);
- }
- }
- }
- int16_t *in = buffer.i16;
- const size_t frameCount = buffer.frameCount;
-
- // Always read-in the first samples from the input buffer
- int16_t* head = impulse + halfNumCoefs*CHANNELS;
- head[0] = in[inputIndex*CHANNELS + 0];
- if (CHANNELS == 2)
- head[1] = in[inputIndex*CHANNELS + 1];
-
- // handle boundary case
- int32_t l, r;
- while (outputIndex < outputSampleCount) {
- filterCoefficient<CHANNELS>(l, r, phaseFraction, impulse);
- out[outputIndex++] += 2 * mulRL(1, l, vRL);
- out[outputIndex++] += 2 * mulRL(0, r, vRL);
-
- phaseFraction += phaseIncrement;
- const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits;
- if (phaseIndex == 1) {
- inputIndex++;
- if (inputIndex >= frameCount)
- break; // need a new buffer
- read<CHANNELS>(impulse, phaseFraction, in, inputIndex);
- } else if(phaseIndex == 2) { // maximum value
- inputIndex++;
- if (inputIndex >= frameCount)
- break; // 0 frame available, 2 frames needed
- // read first frame
- read<CHANNELS>(impulse, phaseFraction, in, inputIndex);
- inputIndex++;
- if (inputIndex >= frameCount)
- break; // 0 frame available, 1 frame needed
- // read second frame
- read<CHANNELS>(impulse, phaseFraction, in, inputIndex);
- }
- }
-
- // if done with buffer, save samples
- if (inputIndex >= frameCount) {
- inputIndex -= frameCount;
- provider->releaseBuffer(&buffer);
- }
- }
-
-resample_exit:
- mImpulse = impulse;
- mInputIndex = inputIndex;
- mPhaseFraction = phaseFraction;
-}
-
-template<int CHANNELS>
-/***
-* read()
-*
-* This function reads only one frame from input buffer and writes it in
-* state buffer
-*
-**/
-void AudioResamplerSinc::read(
- int16_t*& impulse, uint32_t& phaseFraction,
- int16_t const* in, size_t inputIndex)
-{
- const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits;
- impulse += CHANNELS;
- phaseFraction -= 1LU<<kNumPhaseBits;
- if (impulse >= mRingFull) {
- const size_t stateSize = (halfNumCoefs*2)*CHANNELS;
- memcpy(mState, mState+stateSize, sizeof(int16_t)*stateSize);
- impulse -= stateSize;
- }
- int16_t* head = impulse + halfNumCoefs*CHANNELS;
- head[0] = in[inputIndex*CHANNELS + 0];
- if (CHANNELS == 2)
- head[1] = in[inputIndex*CHANNELS + 1];
-}
-
-template<int CHANNELS>
-void AudioResamplerSinc::filterCoefficient(
- int32_t& l, int32_t& r, uint32_t phase, int16_t const *samples)
-{
- // compute the index of the coefficient on the positive side and
- // negative side
- uint32_t indexP = (phase & cMask) >> cShift;
- uint16_t lerpP = (phase & pMask) >> pShift;
- uint32_t indexN = (-phase & cMask) >> cShift;
- uint16_t lerpN = (-phase & pMask) >> pShift;
- if ((indexP == 0) && (lerpP == 0)) {
- indexN = cMask >> cShift;
- lerpN = pMask >> pShift;
- }
-
- l = 0;
- r = 0;
- int32_t const* coefs = mFirCoefs;
- int16_t const *sP = samples;
- int16_t const *sN = samples+CHANNELS;
- for (unsigned int i=0 ; i<halfNumCoefs/4 ; i++) {
- interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
- interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
- sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
- interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
- interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
- sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
- interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
- interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
- sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
- interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
- interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
- sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
- }
-}
-
-template<int CHANNELS>
-void AudioResamplerSinc::interpolate(
- int32_t& l, int32_t& r,
- int32_t const* coefs, int16_t lerp, int16_t const* samples)
-{
- int32_t c0 = coefs[0];
- int32_t c1 = coefs[1];
- int32_t sinc = mulAdd(lerp, (c1-c0)<<1, c0);
- if (CHANNELS == 2) {
- uint32_t rl = *reinterpret_cast<uint32_t const*>(samples);
- l = mulAddRL(1, rl, sinc, l);
- r = mulAddRL(0, rl, sinc, r);
- } else {
- r = l = mulAdd(samples[0], sinc, l);
- }
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
diff --git a/libs/audioflinger/AudioResamplerSinc.h b/libs/audioflinger/AudioResamplerSinc.h
deleted file mode 100644
index e6cb90b..0000000
--- a/libs/audioflinger/AudioResamplerSinc.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_AUDIO_RESAMPLER_SINC_H
-#define ANDROID_AUDIO_RESAMPLER_SINC_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <cutils/log.h>
-
-#include "AudioResampler.h"
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class AudioResamplerSinc : public AudioResampler {
-public:
- AudioResamplerSinc(int bitDepth, int inChannelCount, int32_t sampleRate);
-
- ~AudioResamplerSinc();
-
- virtual void resample(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider);
-private:
- void init();
-
- template<int CHANNELS>
- void resample(int32_t* out, size_t outFrameCount,
- AudioBufferProvider* provider);
-
- template<int CHANNELS>
- inline void filterCoefficient(
- int32_t& l, int32_t& r, uint32_t phase, int16_t const *samples);
-
- template<int CHANNELS>
- inline void interpolate(
- int32_t& l, int32_t& r,
- int32_t const* coefs, int16_t lerp, int16_t const* samples);
-
- template<int CHANNELS>
- inline void read(int16_t*& impulse, uint32_t& phaseFraction,
- int16_t const* in, size_t inputIndex);
-
- int16_t *mState;
- int16_t *mImpulse;
- int16_t *mRingFull;
-
- int32_t const * mFirCoefs;
- static const int32_t mFirCoefsDown[];
- static const int32_t mFirCoefsUp[];
-
- // ----------------------------------------------------------------------------
- static const int32_t RESAMPLE_FIR_NUM_COEF = 8;
- static const int32_t RESAMPLE_FIR_LERP_INT_BITS = 4;
-
- // we have 16 coefs samples per zero-crossing
- static const int coefsBits = RESAMPLE_FIR_LERP_INT_BITS; // 4
- static const int cShift = kNumPhaseBits - coefsBits; // 26
- static const uint32_t cMask = ((1<<coefsBits)-1) << cShift; // 0xf<<26 = 3c00 0000
-
- // and we use 15 bits to interpolate between these samples
- // this cannot change because the mul below rely on it.
- static const int pLerpBits = 15;
- static const int pShift = kNumPhaseBits - coefsBits - pLerpBits; // 11
- static const uint32_t pMask = ((1<<pLerpBits)-1) << pShift; // 0x7fff << 11
-
- // number of zero-crossing on each side
- static const unsigned int halfNumCoefs = RESAMPLE_FIR_NUM_COEF;
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif /*ANDROID_AUDIO_RESAMPLER_SINC_H*/
diff --git a/libs/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index a14bfb5..a14bfb5 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
diff --git a/libs/surfaceflinger/Barrier.h b/services/surfaceflinger/Barrier.h
index 6f8507e..6f8507e 100644
--- a/libs/surfaceflinger/Barrier.h
+++ b/services/surfaceflinger/Barrier.h
diff --git a/libs/surfaceflinger/BlurFilter.cpp b/services/surfaceflinger/BlurFilter.cpp
index 1ffbd5b..1ffbd5b 100644
--- a/libs/surfaceflinger/BlurFilter.cpp
+++ b/services/surfaceflinger/BlurFilter.cpp
diff --git a/libs/surfaceflinger/BlurFilter.h b/services/surfaceflinger/BlurFilter.h
index 294db43..294db43 100644
--- a/libs/surfaceflinger/BlurFilter.h
+++ b/services/surfaceflinger/BlurFilter.h
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 2eac0a8..2eac0a8 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
index 66bf521..66bf521 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
index 1d09f84..1d09f84 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
index 8369bb8..8369bb8 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
diff --git a/libs/surfaceflinger/GLExtensions.cpp b/services/surfaceflinger/GLExtensions.cpp
index 7f4f9fc..7f4f9fc 100644
--- a/libs/surfaceflinger/GLExtensions.cpp
+++ b/services/surfaceflinger/GLExtensions.cpp
diff --git a/libs/surfaceflinger/GLExtensions.h b/services/surfaceflinger/GLExtensions.h
index bbb284e..bbb284e 100644
--- a/libs/surfaceflinger/GLExtensions.h
+++ b/services/surfaceflinger/GLExtensions.h
diff --git a/libs/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 758da4e..758da4e 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
diff --git a/libs/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index e1d283b..e1d283b 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
diff --git a/libs/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index d5aa53f..d5aa53f 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
diff --git a/libs/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 4288cf7..4288cf7 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/services/surfaceflinger/LayerBlur.cpp
index 64a43c7..64a43c7 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/services/surfaceflinger/LayerBlur.cpp
diff --git a/libs/surfaceflinger/LayerBlur.h b/services/surfaceflinger/LayerBlur.h
index 4c9ec64..4c9ec64 100644
--- a/libs/surfaceflinger/LayerBlur.h
+++ b/services/surfaceflinger/LayerBlur.h
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/services/surfaceflinger/LayerBuffer.cpp
index 5f83636..5f83636 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/services/surfaceflinger/LayerBuffer.cpp
diff --git a/libs/surfaceflinger/LayerBuffer.h b/services/surfaceflinger/LayerBuffer.h
index 1c0bf83..1c0bf83 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/services/surfaceflinger/LayerBuffer.h
diff --git a/libs/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index a1f339e..a1f339e 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
diff --git a/libs/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h
index f032314..f032314 100644
--- a/libs/surfaceflinger/LayerDim.h
+++ b/services/surfaceflinger/LayerDim.h
diff --git a/libs/surfaceflinger/MODULE_LICENSE_APACHE2 b/services/surfaceflinger/MODULE_LICENSE_APACHE2
index e69de29..e69de29 100644
--- a/libs/surfaceflinger/MODULE_LICENSE_APACHE2
+++ b/services/surfaceflinger/MODULE_LICENSE_APACHE2
diff --git a/libs/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index d668e88..d668e88 100644
--- a/libs/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
diff --git a/libs/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index 890f809..890f809 100644
--- a/libs/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 68e8f19..68e8f19 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 0bfc170..0bfc170 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
diff --git a/libs/surfaceflinger/TextureManager.cpp b/services/surfaceflinger/TextureManager.cpp
index 3b326df..3b326df 100644
--- a/libs/surfaceflinger/TextureManager.cpp
+++ b/services/surfaceflinger/TextureManager.cpp
diff --git a/libs/surfaceflinger/TextureManager.h b/services/surfaceflinger/TextureManager.h
index c7c14e7..c7c14e7 100644
--- a/libs/surfaceflinger/TextureManager.h
+++ b/services/surfaceflinger/TextureManager.h
diff --git a/libs/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp
index 5e27cc9..5e27cc9 100644
--- a/libs/surfaceflinger/Transform.cpp
+++ b/services/surfaceflinger/Transform.cpp
diff --git a/libs/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h
index 20fa11a..20fa11a 100644
--- a/libs/surfaceflinger/Transform.h
+++ b/services/surfaceflinger/Transform.h
diff --git a/libs/surfaceflinger/clz.cpp b/services/surfaceflinger/clz.cpp
index 2456b86..2456b86 100644
--- a/libs/surfaceflinger/clz.cpp
+++ b/services/surfaceflinger/clz.cpp
diff --git a/libs/surfaceflinger/clz.h b/services/surfaceflinger/clz.h
index 0ddf986..0ddf986 100644
--- a/libs/surfaceflinger/clz.h
+++ b/services/surfaceflinger/clz.h
diff --git a/libs/surfaceflinger/tests/Android.mk b/services/surfaceflinger/tests/Android.mk
index 5053e7d..5053e7d 100644
--- a/libs/surfaceflinger/tests/Android.mk
+++ b/services/surfaceflinger/tests/Android.mk
diff --git a/libs/surfaceflinger/tests/overlays/Android.mk b/services/surfaceflinger/tests/overlays/Android.mk
index 592b601..592b601 100644
--- a/libs/surfaceflinger/tests/overlays/Android.mk
+++ b/services/surfaceflinger/tests/overlays/Android.mk
diff --git a/libs/surfaceflinger/tests/overlays/overlays.cpp b/services/surfaceflinger/tests/overlays/overlays.cpp
index c248a615..c248a615 100644
--- a/libs/surfaceflinger/tests/overlays/overlays.cpp
+++ b/services/surfaceflinger/tests/overlays/overlays.cpp
diff --git a/libs/surfaceflinger/tests/resize/Android.mk b/services/surfaceflinger/tests/resize/Android.mk
index 24c2d01..24c2d01 100644
--- a/libs/surfaceflinger/tests/resize/Android.mk
+++ b/services/surfaceflinger/tests/resize/Android.mk
diff --git a/libs/surfaceflinger/tests/resize/resize.cpp b/services/surfaceflinger/tests/resize/resize.cpp
index 127cca3..127cca3 100644
--- a/libs/surfaceflinger/tests/resize/resize.cpp
+++ b/services/surfaceflinger/tests/resize/resize.cpp