Merge "Move more types from android.media -> a.m.audio.common SAIDL"
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index 03439fd..24c9108 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -68,6 +68,9 @@
unavailablePhysicalIds16.push_back(String16(id8));
}
res = parcel->writeString16Vector(unavailablePhysicalIds16);
+ if (res != OK) return res;
+
+ res = parcel->writeString16(String16(clientPackage));
return res;
}
@@ -86,6 +89,12 @@
for (auto& id16 : unavailablePhysicalIds16) {
unavailablePhysicalIds.push_back(String8(id16));
}
+
+ String16 tempClientPackage;
+ res = parcel->readString16(&tempClientPackage);
+ if (res != OK) return res;
+ clientPackage = String8(tempClientPackage);
+
return res;
}
diff --git a/camera/include/camera/CameraBase.h b/camera/include/camera/CameraBase.h
index e156994..8e53968 100644
--- a/camera/include/camera/CameraBase.h
+++ b/camera/include/camera/CameraBase.h
@@ -85,11 +85,17 @@
*/
std::vector<String8> unavailablePhysicalIds;
+ /**
+ * Client package name if camera is open, otherwise not applicable
+ */
+ String8 clientPackage;
+
virtual status_t writeToParcel(android::Parcel* parcel) const;
virtual status_t readFromParcel(const android::Parcel* parcel);
- CameraStatus(String8 id, int32_t s, const std::vector<String8>& unavailSubIds) :
- cameraId(id), status(s), unavailablePhysicalIds(unavailSubIds) {}
+ CameraStatus(String8 id, int32_t s, const std::vector<String8>& unavailSubIds,
+ const String8& clientPkg) : cameraId(id), status(s),
+ unavailablePhysicalIds(unavailSubIds), clientPackage(clientPkg) {}
CameraStatus() : status(ICameraServiceListener::STATUS_PRESENT) {}
};
diff --git a/media/codec2/fuzzer/C2Fuzzer.cpp b/media/codec2/fuzzer/C2Fuzzer.cpp
index e35ee48..e469d8b 100644
--- a/media/codec2/fuzzer/C2Fuzzer.cpp
+++ b/media/codec2/fuzzer/C2Fuzzer.cpp
@@ -239,17 +239,17 @@
}
void Codec2Fuzzer::decodeFrames(const uint8_t* data, size_t size) {
- mBufferSource = new BufferSource(data, size);
- if (!mBufferSource) {
+ std::unique_ptr<BufferSource> bufferSource = std::make_unique<BufferSource>(data, size);
+ if (!bufferSource) {
return;
}
- mBufferSource->parse();
+ bufferSource->parse();
c2_status_t status = C2_OK;
size_t numFrames = 0;
- while (!mBufferSource->isEos()) {
+ while (!bufferSource->isEos()) {
uint8_t* frame = nullptr;
size_t frameSize = 0;
- FrameData frameData = mBufferSource->getFrame();
+ FrameData frameData = bufferSource->getFrame();
frame = std::get<0>(frameData);
frameSize = std::get<1>(frameData);
@@ -298,7 +298,6 @@
mConditionalVariable.wait_for(waitForDecodeComplete, kC2FuzzerTimeOut, [this] { return mEos; });
std::list<std::unique_ptr<C2Work>> c2flushedWorks;
mComponent->flush_sm(C2Component::FLUSH_COMPONENT, &c2flushedWorks);
- delete mBufferSource;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
diff --git a/media/codec2/fuzzer/C2Fuzzer.h b/media/codec2/fuzzer/C2Fuzzer.h
index d5ac81a..da76885 100644
--- a/media/codec2/fuzzer/C2Fuzzer.h
+++ b/media/codec2/fuzzer/C2Fuzzer.h
@@ -104,7 +104,6 @@
static constexpr size_t kMarkerSuffixSize = 3;
};
- BufferSource* mBufferSource;
bool mEos = false;
C2BlockPool::local_id_t mBlockPoolId;
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 4070478..62c8fcd 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -248,7 +248,10 @@
// align width and height to support subsampling cleanly
uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
- uint32_t vStride = align(view.crop().height, 2);
+
+ int32_t fmtHeight = mHeight;
+ format->findInt32(KEY_HEIGHT, &fmtHeight);
+ uint32_t vStride = align(fmtHeight, 2);
bool tryWrapping = !copy;
diff --git a/media/libeffects/downmix/EffectDownmix.cpp b/media/libeffects/downmix/EffectDownmix.cpp
index f500bc3..90bb410 100644
--- a/media/libeffects/downmix/EffectDownmix.cpp
+++ b/media/libeffects/downmix/EffectDownmix.cpp
@@ -19,7 +19,7 @@
#include <log/log.h>
#include "EffectDownmix.h"
-#include <math.h>
+#include <audio_utils/ChannelMix.h>
// Do not submit with DOWNMIX_TEST_CHANNEL_INDEX defined, strictly for testing
//#define DOWNMIX_TEST_CHANNEL_INDEX 0
@@ -35,12 +35,13 @@
} downmix_state_t;
/* parameters for each downmixer */
-typedef struct {
+struct downmix_object_t {
downmix_state_t state;
downmix_type_t type;
bool apply_volume_correction;
uint8_t input_channel_count;
-} downmix_object_t;
+ android::audio_utils::channels::ChannelMix channelMix;
+};
typedef struct downmix_module_s {
const struct effect_interface_s *itfe;
@@ -77,11 +78,6 @@
downmix_object_t *pDownmixer, int32_t param, uint32_t size, void *pValue);
static int Downmix_getParameter(
downmix_object_t *pDownmixer, int32_t param, uint32_t *pSize, void *pValue);
-static void Downmix_foldFromQuad(float *pSrc, float *pDst, size_t numFrames, bool accumulate);
-static void Downmix_foldFrom5Point1(float *pSrc, float *pDst, size_t numFrames, bool accumulate);
-static void Downmix_foldFrom7Point1(float *pSrc, float *pDst, size_t numFrames, bool accumulate);
-static bool Downmix_foldGeneric(
- uint32_t mask, float *pSrc, float *pDst, size_t numFrames, bool accumulate);
// effect_handle_t interface implementation for downmix effect
const struct effect_interface_s gDownmixInterface = {
@@ -315,7 +311,8 @@
audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
downmix_object_t *pDownmixer;
- float *pSrc, *pDst;
+ const float *pSrc;
+ float *pDst;
downmix_module_t *pDwmModule = (downmix_module_t *)self;
if (pDwmModule == NULL) {
@@ -344,7 +341,8 @@
const bool accumulate =
(pDwmModule->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
- const uint32_t downmixInputChannelMask = pDwmModule->config.inputCfg.channels;
+ const audio_channel_mask_t downmixInputChannelMask =
+ (audio_channel_mask_t)pDwmModule->config.inputCfg.channels;
switch(pDownmixer->type) {
@@ -368,38 +366,13 @@
}
break;
- case DOWNMIX_TYPE_FOLD:
-#ifdef DOWNMIX_ALWAYS_USE_GENERIC_DOWNMIXER
- // bypass the optimized downmix routines for the common formats
- if (!Downmix_foldGeneric(
- downmixInputChannelMask, pSrc, pDst, numFrames, accumulate)) {
- ALOGE("Multichannel configuration %#x is not supported",
- downmixInputChannelMask);
- return -EINVAL;
- }
- break;
-#endif
- // optimize for the common formats
- switch (downmixInputChannelMask) {
- case AUDIO_CHANNEL_OUT_QUAD_BACK:
- case AUDIO_CHANNEL_OUT_QUAD_SIDE:
- Downmix_foldFromQuad(pSrc, pDst, numFrames, accumulate);
- break;
- case AUDIO_CHANNEL_OUT_5POINT1_BACK:
- case AUDIO_CHANNEL_OUT_5POINT1_SIDE:
- Downmix_foldFrom5Point1(pSrc, pDst, numFrames, accumulate);
- break;
- case AUDIO_CHANNEL_OUT_7POINT1:
- Downmix_foldFrom7Point1(pSrc, pDst, numFrames, accumulate);
- break;
- default:
- if (!Downmix_foldGeneric(
- downmixInputChannelMask, pSrc, pDst, numFrames, accumulate)) {
+ case DOWNMIX_TYPE_FOLD: {
+ if (!pDownmixer->channelMix.process(
+ pSrc, pDst, numFrames, accumulate, downmixInputChannelMask)) {
ALOGE("Multichannel configuration %#x is not supported",
downmixInputChannelMask);
return -EINVAL;
}
- break;
}
break;
@@ -780,7 +753,6 @@
return 0;
} /* end Downmix_setParameter */
-
/*----------------------------------------------------------------------------
* Downmix_getParameter()
*----------------------------------------------------------------------------
@@ -829,299 +801,3 @@
return 0;
} /* end Downmix_getParameter */
-
-/*----------------------------------------------------------------------------
- * Downmix_foldFromQuad()
- *----------------------------------------------------------------------------
- * Purpose:
- * downmix a quad signal to stereo
- *
- * Inputs:
- * pSrc quad audio samples to downmix
- * numFrames the number of quad frames to downmix
- * accumulate whether to mix (when true) the result of the downmix with the contents of pDst,
- * or overwrite pDst (when false)
- *
- * Outputs:
- * pDst downmixed stereo audio samples
- *
- *----------------------------------------------------------------------------
- */
-void Downmix_foldFromQuad(float *pSrc, float *pDst, size_t numFrames, bool accumulate) {
- // sample at index 0 is FL
- // sample at index 1 is FR
- // sample at index 2 is RL
- // sample at index 3 is RR
- if (accumulate) {
- while (numFrames) {
- // FL + RL
- pDst[0] = clamp_float(pDst[0] + ((pSrc[0] + pSrc[2]) / 2.0f));
- // FR + RR
- pDst[1] = clamp_float(pDst[1] + ((pSrc[1] + pSrc[3]) / 2.0f));
- pSrc += 4;
- pDst += 2;
- numFrames--;
- }
- } else { // same code as above but without adding and clamping pDst[i] to itself
- while (numFrames) {
- // FL + RL
- pDst[0] = clamp_float((pSrc[0] + pSrc[2]) / 2.0f);
- // FR + RR
- pDst[1] = clamp_float((pSrc[1] + pSrc[3]) / 2.0f);
- pSrc += 4;
- pDst += 2;
- numFrames--;
- }
- }
-}
-
-/*----------------------------------------------------------------------------
- * Downmix_foldFrom5Point1()
- *----------------------------------------------------------------------------
- * Purpose:
- * downmix a 5.1 signal to stereo
- *
- * Inputs:
- * pSrc 5.1 audio samples to downmix
- * numFrames the number of 5.1 frames to downmix
- * accumulate whether to mix (when true) the result of the downmix with the contents of pDst,
- * or overwrite pDst (when false)
- *
- * Outputs:
- * pDst downmixed stereo audio samples
- *
- *----------------------------------------------------------------------------
- */
-void Downmix_foldFrom5Point1(float *pSrc, float *pDst, size_t numFrames, bool accumulate) {
- float lt, rt, centerPlusLfeContrib; // samples in Q19.12 format
- // sample at index 0 is FL
- // sample at index 1 is FR
- // sample at index 2 is FC
- // sample at index 3 is LFE
- // sample at index 4 is RL
- // sample at index 5 is RR
- // code is mostly duplicated between the two values of accumulate to avoid repeating the test
- // for every sample
- if (accumulate) {
- while (numFrames) {
- // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
- centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_FLOAT)
- + (pSrc[3] * MINUS_3_DB_IN_FLOAT);
- // FL + centerPlusLfeContrib + RL
- lt = pSrc[0] + centerPlusLfeContrib + pSrc[4];
- // FR + centerPlusLfeContrib + RR
- rt = pSrc[1] + centerPlusLfeContrib + pSrc[5];
- // accumulate in destination
- pDst[0] = clamp_float(pDst[0] + (lt / 2.0f));
- pDst[1] = clamp_float(pDst[1] + (rt / 2.0f));
- pSrc += 6;
- pDst += 2;
- numFrames--;
- }
- } else { // same code as above but without adding and clamping pDst[i] to itself
- while (numFrames) {
- // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
- centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_FLOAT)
- + (pSrc[3] * MINUS_3_DB_IN_FLOAT);
- // FL + centerPlusLfeContrib + RL
- lt = pSrc[0] + centerPlusLfeContrib + pSrc[4];
- // FR + centerPlusLfeContrib + RR
- rt = pSrc[1] + centerPlusLfeContrib + pSrc[5];
- // store in destination
- pDst[0] = clamp_float(lt / 2.0f); // differs from when accumulate is true above
- pDst[1] = clamp_float(rt / 2.0f); // differs from when accumulate is true above
- pSrc += 6;
- pDst += 2;
- numFrames--;
- }
- }
-}
-
-/*----------------------------------------------------------------------------
- * Downmix_foldFrom7Point1()
- *----------------------------------------------------------------------------
- * Purpose:
- * downmix a 7.1 signal to stereo
- *
- * Inputs:
- * pSrc 7.1 audio samples to downmix
- * numFrames the number of 7.1 frames to downmix
- * accumulate whether to mix (when true) the result of the downmix with the contents of pDst,
- * or overwrite pDst (when false)
- *
- * Outputs:
- * pDst downmixed stereo audio samples
- *
- *----------------------------------------------------------------------------
- */
-void Downmix_foldFrom7Point1(float *pSrc, float *pDst, size_t numFrames, bool accumulate) {
- float lt, rt, centerPlusLfeContrib; // samples in Q19.12 format
- // sample at index 0 is FL
- // sample at index 1 is FR
- // sample at index 2 is FC
- // sample at index 3 is LFE
- // sample at index 4 is RL
- // sample at index 5 is RR
- // sample at index 6 is SL
- // sample at index 7 is SR
- // code is mostly duplicated between the two values of accumulate to avoid repeating the test
- // for every sample
- if (accumulate) {
- while (numFrames) {
- // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
- centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_FLOAT)
- + (pSrc[3] * MINUS_3_DB_IN_FLOAT);
- // FL + centerPlusLfeContrib + SL + RL
- lt = pSrc[0] + centerPlusLfeContrib + pSrc[6] + pSrc[4];
- // FR + centerPlusLfeContrib + SR + RR
- rt = pSrc[1] + centerPlusLfeContrib + pSrc[7] + pSrc[5];
- //accumulate in destination
- pDst[0] = clamp_float(pDst[0] + (lt / 2.0f));
- pDst[1] = clamp_float(pDst[1] + (rt / 2.0f));
- pSrc += 8;
- pDst += 2;
- numFrames--;
- }
- } else { // same code as above but without adding and clamping pDst[i] to itself
- while (numFrames) {
- // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
- centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_FLOAT)
- + (pSrc[3] * MINUS_3_DB_IN_FLOAT);
- // FL + centerPlusLfeContrib + SL + RL
- lt = pSrc[0] + centerPlusLfeContrib + pSrc[6] + pSrc[4];
- // FR + centerPlusLfeContrib + SR + RR
- rt = pSrc[1] + centerPlusLfeContrib + pSrc[7] + pSrc[5];
- // store in destination
- pDst[0] = clamp_float(lt / 2.0f); // differs from when accumulate is true above
- pDst[1] = clamp_float(rt / 2.0f); // differs from when accumulate is true above
- pSrc += 8;
- pDst += 2;
- numFrames--;
- }
- }
-}
-
-/*----------------------------------------------------------------------------
- * Downmix_foldGeneric()
- *----------------------------------------------------------------------------
- * Purpose:
- * downmix to stereo a multichannel signal of arbitrary channel position mask.
- *
- * Inputs:
- * mask the channel mask of pSrc
- * pSrc multichannel audio buffer to downmix
- * numFrames the number of multichannel frames to downmix
- * accumulate whether to mix (when true) the result of the downmix with the contents of pDst,
- * or overwrite pDst (when false)
- *
- * Outputs:
- * pDst downmixed stereo audio samples
- *
- * Returns: false if multichannel format is not supported
- *
- *----------------------------------------------------------------------------
- */
-bool Downmix_foldGeneric(
- uint32_t mask, float *pSrc, float *pDst, size_t numFrames, bool accumulate) {
-
- if (!Downmix_validChannelMask(mask)) {
- return false;
- }
- const int numChan = audio_channel_count_from_out_mask(mask);
-
- // compute at what index each channel is: samples will be in the following order:
- // FL FR FC LFE BL BR BC SL SR
- //
- // (transfer matrix)
- // FL FR FC LFE BL BR BC SL SR
- // 0.5 0.353 0.353 0.5 0.353 0.5
- // 0.5 0.353 0.353 0.5 0.353 0.5
-
- // derive the indices for the transfer matrix columns that have non-zero values.
- int indexFL = -1;
- int indexFR = -1;
- int indexFC = -1;
- int indexLFE = -1;
- int indexBL = -1;
- int indexBR = -1;
- int indexBC = -1;
- int indexSL = -1;
- int indexSR = -1;
- int index = 0;
- for (unsigned tmp = mask;
- (tmp & (AUDIO_CHANNEL_OUT_7POINT1 | AUDIO_CHANNEL_OUT_BACK_CENTER)) != 0;
- ++index) {
- const unsigned lowestBit = tmp & -(signed)tmp;
- switch (lowestBit) {
- case AUDIO_CHANNEL_OUT_FRONT_LEFT:
- indexFL = index;
- break;
- case AUDIO_CHANNEL_OUT_FRONT_RIGHT:
- indexFR = index;
- break;
- case AUDIO_CHANNEL_OUT_FRONT_CENTER:
- indexFC = index;
- break;
- case AUDIO_CHANNEL_OUT_LOW_FREQUENCY:
- indexLFE = index;
- break;
- case AUDIO_CHANNEL_OUT_BACK_LEFT:
- indexBL = index;
- break;
- case AUDIO_CHANNEL_OUT_BACK_RIGHT:
- indexBR = index;
- break;
- case AUDIO_CHANNEL_OUT_BACK_CENTER:
- indexBC = index;
- break;
- case AUDIO_CHANNEL_OUT_SIDE_LEFT:
- indexSL = index;
- break;
- case AUDIO_CHANNEL_OUT_SIDE_RIGHT:
- indexSR = index;
- break;
- }
- tmp ^= lowestBit;
- }
-
- // With good branch prediction, this should run reasonably fast.
- // Also consider using a transfer matrix form.
- while (numFrames) {
- // compute contribution of FC, BC and LFE
- float centersLfeContrib = 0;
- if (indexFC >= 0) centersLfeContrib = pSrc[indexFC];
- if (indexLFE >= 0) centersLfeContrib += pSrc[indexLFE];
- if (indexBC >= 0) centersLfeContrib += pSrc[indexBC];
- centersLfeContrib *= MINUS_3_DB_IN_FLOAT;
-
- float ch[2];
- ch[0] = centersLfeContrib;
- ch[1] = centersLfeContrib;
-
- // mix in left / right channels
- if (indexFL >= 0) ch[0] += pSrc[indexFL];
- if (indexFR >= 0) ch[1] += pSrc[indexFR];
-
- if (indexSL >= 0) ch[0] += pSrc[indexSL];
- if (indexSR >= 0) ch[1] += pSrc[indexSR]; // note pair checks enforce this if indexSL != 0
-
- if (indexBL >= 0) ch[0] += pSrc[indexBL];
- if (indexBR >= 0) ch[1] += pSrc[indexBR]; // note pair checks enforce this if indexBL != 0
-
- // scale to prevent overflow.
- ch[0] *= 0.5f;
- ch[1] *= 0.5f;
-
- if (accumulate) {
- ch[0] += pDst[0];
- ch[1] += pDst[1];
- }
-
- pDst[0] = clamp_float(ch[0]);
- pDst[1] = clamp_float(ch[1]);
- pSrc += numChan;
- pDst += 2;
- numFrames--;
- }
- return true;
-}
diff --git a/media/libeffects/downmix/benchmark/downmix_benchmark.cpp b/media/libeffects/downmix/benchmark/downmix_benchmark.cpp
index ee169c2..d4adf5e 100644
--- a/media/libeffects/downmix/benchmark/downmix_benchmark.cpp
+++ b/media/libeffects/downmix/benchmark/downmix_benchmark.cpp
@@ -35,16 +35,14 @@
AUDIO_CHANNEL_OUT_STEREO,
AUDIO_CHANNEL_OUT_2POINT1,
AUDIO_CHANNEL_OUT_2POINT0POINT2,
- AUDIO_CHANNEL_OUT_QUAD,
- AUDIO_CHANNEL_OUT_QUAD_BACK,
+ AUDIO_CHANNEL_OUT_QUAD, // AUDIO_CHANNEL_OUT_QUAD_BACK
AUDIO_CHANNEL_OUT_QUAD_SIDE,
AUDIO_CHANNEL_OUT_SURROUND,
AUDIO_CHANNEL_OUT_2POINT1POINT2,
AUDIO_CHANNEL_OUT_3POINT0POINT2,
AUDIO_CHANNEL_OUT_PENTA,
AUDIO_CHANNEL_OUT_3POINT1POINT2,
- AUDIO_CHANNEL_OUT_5POINT1,
- AUDIO_CHANNEL_OUT_5POINT1_BACK,
+ AUDIO_CHANNEL_OUT_5POINT1, // AUDIO_CHANNEL_OUT_5POINT1_BACK
AUDIO_CHANNEL_OUT_5POINT1_SIDE,
AUDIO_CHANNEL_OUT_6POINT1,
AUDIO_CHANNEL_OUT_5POINT1POINT2,
@@ -62,58 +60,32 @@
static constexpr size_t kFrameCount = 1000;
/*
-Pixel 3XL
-downmix_benchmark:
- #BM_Downmix/0 4723 ns 4708 ns 148694
- #BM_Downmix/1 4717 ns 4702 ns 148873
- #BM_Downmix/2 4803 ns 4788 ns 145893
- #BM_Downmix/3 5056 ns 5041 ns 139110
- #BM_Downmix/4 4710 ns 4696 ns 149625
- #BM_Downmix/5 1514 ns 1509 ns 463694
- #BM_Downmix/6 1513 ns 1509 ns 463451
- #BM_Downmix/7 1516 ns 1511 ns 463899
- #BM_Downmix/8 4445 ns 4431 ns 157831
- #BM_Downmix/9 5081 ns 5065 ns 138412
- #BM_Downmix/10 4354 ns 4341 ns 161247
- #BM_Downmix/11 4411 ns 4397 ns 158893
- #BM_Downmix/12 4434 ns 4420 ns 157992
- #BM_Downmix/13 4845 ns 4830 ns 144873
- #BM_Downmix/14 4851 ns 4835 ns 144954
- #BM_Downmix/15 4884 ns 4870 ns 144233
- #BM_Downmix/16 5832 ns 5813 ns 120565
- #BM_Downmix/17 5241 ns 5224 ns 133927
- #BM_Downmix/18 5044 ns 5028 ns 139131
- #BM_Downmix/19 5244 ns 5227 ns 132315
- #BM_Downmix/20 5943 ns 5923 ns 117759
- #BM_Downmix/21 5990 ns 5971 ns 117263
- #BM_Downmix/22 4468 ns 4454 ns 156689
- #BM_Downmix/23 7306 ns 7286 ns 95911
---
-downmix_benchmark: (generic fold)
- #BM_Downmix/0 4722 ns 4707 ns 149847
- #BM_Downmix/1 4714 ns 4698 ns 148748
- #BM_Downmix/2 4794 ns 4779 ns 145661
- #BM_Downmix/3 5053 ns 5035 ns 139172
- #BM_Downmix/4 4695 ns 4678 ns 149762
- #BM_Downmix/5 4381 ns 4368 ns 159675
- #BM_Downmix/6 4387 ns 4373 ns 160267
- #BM_Downmix/7 4732 ns 4717 ns 148514
- #BM_Downmix/8 4430 ns 4415 ns 158133
- #BM_Downmix/9 5101 ns 5084 ns 138353
- #BM_Downmix/10 4356 ns 4343 ns 160821
- #BM_Downmix/11 4397 ns 4383 ns 159995
- #BM_Downmix/12 4438 ns 4424 ns 158117
- #BM_Downmix/13 5243 ns 5226 ns 133863
- #BM_Downmix/14 5259 ns 5242 ns 131855
- #BM_Downmix/15 5245 ns 5228 ns 133686
- #BM_Downmix/16 5829 ns 5809 ns 120543
- #BM_Downmix/17 5245 ns 5228 ns 133533
- #BM_Downmix/18 5935 ns 5916 ns 118282
- #BM_Downmix/19 5263 ns 5245 ns 133657
- #BM_Downmix/20 5998 ns 5978 ns 114693
- #BM_Downmix/21 5989 ns 5969 ns 117450
- #BM_Downmix/22 4442 ns 4431 ns 157913
- #BM_Downmix/23 7309 ns 7290 ns 95797
+Pixel 4XL
+--------------------------------------------------------
+Benchmark Time CPU Iterations
+--------------------------------------------------------
+BM_Downmix/0 3553 ns 3545 ns 197503 AUDIO_CHANNEL_OUT_MONO
+BM_Downmix/1 2846 ns 2840 ns 202849
+BM_Downmix/2 4436 ns 4426 ns 158176 AUDIO_CHANNEL_OUT_STEREO
+BM_Downmix/3 5320 ns 5307 ns 131870 AUDIO_CHANNEL_OUT_2POINT1
+BM_Downmix/4 4437 ns 4426 ns 159523 AUDIO_CHANNEL_OUT_2POINT0POINT2
+BM_Downmix/5 2493 ns 2487 ns 281496 AUDIO_CHANNEL_OUT_QUAD
+BM_Downmix/6 2493 ns 2487 ns 281456 AUDIO_CHANNEL_OUT_QUAD_SIDE
+BM_Downmix/7 6204 ns 6188 ns 115044 AUDIO_CHANNEL_OUT_SURROUND
+BM_Downmix/8 5320 ns 5307 ns 100000 AUDIO_CHANNEL_OUT_2POINT1POINT2
+BM_Downmix/9 5320 ns 5307 ns 100000 AUDIO_CHANNEL_OUT_3POINT0POINT2
+BM_Downmix/10 7088 ns 7071 ns 108264 AUDIO_CHANNEL_OUT_PENTA
+BM_Downmix/11 6203 ns 6188 ns 117021 AUDIO_CHANNEL_OUT_3POINT1POINT2
+BM_Downmix/12 3105 ns 3097 ns 226182 AUDIO_CHANNEL_OUT_5POINT1
+BM_Downmix/13 3112 ns 3105 ns 225488 AUDIO_CHANNEL_OUT_5POINT1_SIDE
+BM_Downmix/14 8855 ns 8831 ns 79265 AUDIO_CHANNEL_OUT_6POINT1
+BM_Downmix/15 7971 ns 7951 ns 90918 AUDIO_CHANNEL_OUT_5POINT1POINT2
+BM_Downmix/16 3547 ns 3539 ns 197780 AUDIO_CHANNEL_OUT_7POINT1
+BM_Downmix/17 7972 ns 7953 ns 90101 AUDIO_CHANNEL_OUT_5POINT1POINT4
+BM_Downmix/18 9737 ns 9714 ns 72773 AUDIO_CHANNEL_OUT_7POINT1POINT2
+BM_Downmix/19 9745 ns 9721 ns 72015 AUDIO_CHANNEL_OUT_7POINT1POINT4
+BM_Downmix/20 7070 ns 7053 ns 109476 AUDIO_CHANNEL_OUT_13POINT_360RA
+BM_Downmix/21 12413 ns 12381 ns 57455 AUDIO_CHANNEL_OUT_22POINT2
*/
static void BM_Downmix(benchmark::State& state) {
@@ -125,7 +97,7 @@
std::minstd_rand gen(channelMask);
std::uniform_real_distribution<> dis(-1.0f, 1.0f);
std::vector<float> input(kFrameCount * channelCount);
- std::vector<float> output(kFrameCount * 2);
+ std::vector<float> output(kFrameCount * FCC_2);
for (auto& in : input) {
in = dis(gen);
}
@@ -187,7 +159,8 @@
benchmark::ClobberMemory();
}
- state.SetComplexityN(state.range(0));
+ state.SetComplexityN(channelCount);
+ state.SetLabel(audio_channel_out_mask_to_string(channelMask));
if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(effectHandle); status != 0) {
ALOGE("release_effect returned an error = %d\n", status);
diff --git a/media/libeffects/downmix/tests/downmix_tests.cpp b/media/libeffects/downmix/tests/downmix_tests.cpp
index d4b7a3a..d378044 100644
--- a/media/libeffects/downmix/tests/downmix_tests.cpp
+++ b/media/libeffects/downmix/tests/downmix_tests.cpp
@@ -33,16 +33,14 @@
AUDIO_CHANNEL_OUT_STEREO,
AUDIO_CHANNEL_OUT_2POINT1,
AUDIO_CHANNEL_OUT_2POINT0POINT2,
- AUDIO_CHANNEL_OUT_QUAD,
- AUDIO_CHANNEL_OUT_QUAD_BACK,
+ AUDIO_CHANNEL_OUT_QUAD, // AUDIO_CHANNEL_OUT_QUAD_BACK
AUDIO_CHANNEL_OUT_QUAD_SIDE,
AUDIO_CHANNEL_OUT_SURROUND,
AUDIO_CHANNEL_OUT_2POINT1POINT2,
AUDIO_CHANNEL_OUT_3POINT0POINT2,
AUDIO_CHANNEL_OUT_PENTA,
AUDIO_CHANNEL_OUT_3POINT1POINT2,
- AUDIO_CHANNEL_OUT_5POINT1,
- AUDIO_CHANNEL_OUT_5POINT1_BACK,
+ AUDIO_CHANNEL_OUT_5POINT1, // AUDIO_CHANNEL_OUT_5POINT1_BACK
AUDIO_CHANNEL_OUT_5POINT1_SIDE,
AUDIO_CHANNEL_OUT_6POINT1,
AUDIO_CHANNEL_OUT_5POINT1POINT2,
@@ -57,6 +55,33 @@
static constexpr audio_channel_mask_t kConsideredChannels =
(audio_channel_mask_t)(AUDIO_CHANNEL_OUT_7POINT1 | AUDIO_CHANNEL_OUT_BACK_CENTER);
+constexpr inline float kScaleFromChannelIdx[] = {
+ 0.5f, // AUDIO_CHANNEL_OUT_FRONT_LEFT = 0x1u,
+ 0.5f, // AUDIO_CHANNEL_OUT_FRONT_RIGHT = 0x2u,
+ 0.5f * M_SQRT1_2, // AUDIO_CHANNEL_OUT_FRONT_CENTER = 0x4u,
+ 0.5f * M_SQRT1_2, // AUDIO_CHANNEL_OUT_LOW_FREQUENCY = 0x8u,
+ 0.5f, // AUDIO_CHANNEL_OUT_BACK_LEFT = 0x10u,
+ 0.5f, // AUDIO_CHANNEL_OUT_BACK_RIGHT = 0x20u,
+ 0, // AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x40u,
+ 0, // AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80u,
+ 0.5f * M_SQRT1_2, // AUDIO_CHANNEL_OUT_BACK_CENTER = 0x100u,
+ 0.5f, // AUDIO_CHANNEL_OUT_SIDE_LEFT = 0x200u,
+ 0.5f, // AUDIO_CHANNEL_OUT_SIDE_RIGHT = 0x400u,
+ 0, // AUDIO_CHANNEL_OUT_TOP_CENTER = 0x800u,
+ 0, // AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT = 0x1000u,
+ 0, // AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER = 0x2000u,
+ 0, // AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT = 0x4000u,
+ 0, // AUDIO_CHANNEL_OUT_TOP_BACK_LEFT = 0x8000u,
+ 0, // AUDIO_CHANNEL_OUT_TOP_BACK_CENTER = 0x10000u,
+ 0, // AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT = 0x20000u,
+ 0, // AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT = 0x40000u,
+ 0, // AUDIO_CHANNEL_OUT_TOP_SIDE_RIGHT = 0x80000u,
+ 0, // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_LEFT = 0x100000u,
+ 0, // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_CENTER = 0x200000u,
+ 0, // AUDIO_CHANNEL_OUT_BOTTOM_FRONT_RIGHT = 0x400000u,
+ 0, // AUDIO_CHANNEL_OUT_LOW_FREQUENCY_2 = 0x800000u,
+};
+
// Downmix doesn't change with sample rate
static constexpr size_t kSampleRates[] = {
48000,
@@ -93,8 +118,8 @@
void testBalance(int sampleRate, audio_channel_mask_t channelMask) {
using namespace ::android::audio_utils::channels;
- size_t frames = 100;
- unsigned outChannels = 2;
+ size_t frames = 100; // set to an even number (2, 4, 6 ... ) stream alternates +1, -1.
+ constexpr unsigned outChannels = 2;
unsigned inChannels = audio_channel_count_from_out_mask(channelMask);
std::vector<float> input(frames * inChannels);
std::vector<float> output(frames * outChannels);
@@ -119,7 +144,7 @@
auto stats = channelStatistics(output, 2 /* channels */);
// printf("power: %s %s\n", stats[0].toString().c_str(), stats[1].toString().c_str());
- double power[2] = { stats[0].getVariance(), stats[1].getVariance() };
+ double power[2] = { stats[0].getPopVariance(), stats[1].getPopVariance() };
// Check symmetric power for pair channels on exchange of left/right position.
// to do this, we save previous power measurements.
@@ -139,20 +164,21 @@
EXPECT_EQ(0.f, power[1]);
continue;
}
- constexpr float POWER_TOLERANCE = 0.01; // for variance sum error.
+
+ constexpr float POWER_TOLERANCE = 0.001;
+ const float expectedPower = kScaleFromChannelIdx[index] * kScaleFromChannelIdx[index];
switch (side) {
case AUDIO_GEOMETRY_SIDE_LEFT:
- EXPECT_NEAR(0.25f, power[0], POWER_TOLERANCE);
- EXPECT_EQ(0.f, power[1]);
+ EXPECT_EQ(0.f, power[1]); // always true
+ EXPECT_NEAR(expectedPower, power[0], POWER_TOLERANCE);
break;
case AUDIO_GEOMETRY_SIDE_RIGHT:
- EXPECT_EQ(0.f, power[0]);
- EXPECT_NEAR(0.25f, power[1], POWER_TOLERANCE);
+ EXPECT_EQ(0.f, power[0]); // always true
+ EXPECT_NEAR(expectedPower, power[1], POWER_TOLERANCE);
break;
case AUDIO_GEOMETRY_SIDE_CENTER:
- EXPECT_NEAR(0.125f, power[0], POWER_TOLERANCE);
- EXPECT_NEAR(0.125f, power[1], POWER_TOLERANCE);
- EXPECT_NEAR_EPSILON(power[0], power[1]);
+ EXPECT_NEAR_EPSILON(power[0], power[1]); // always true
+ EXPECT_NEAR(expectedPower, power[0], POWER_TOLERANCE);
break;
}
}
@@ -244,10 +270,11 @@
::testing::Combine(
::testing::Range(0, (int)std::size(kSampleRates)),
::testing::Range(0, (int)std::size(kChannelPositionMasks))
- ));
-
-int main(int argc, /* const */ char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- int status = RUN_ALL_TESTS();
- return status;
-}
+ ),
+ [](const testing::TestParamInfo<DownmixTest::ParamType>& info) {
+ const int index = std::get<1>(info.param);
+ const audio_channel_mask_t channelMask = kChannelPositionMasks[index];
+ const std::string name = std::string(audio_channel_out_mask_to_string(channelMask))
+ + "_" + std::to_string(std::get<0>(info.param)) + "_" + std::to_string(index);
+ return name;
+ });
diff --git a/media/libstagefright/MediaAppender.cpp b/media/libstagefright/MediaAppender.cpp
index 5d80b30..21dcfa1 100644
--- a/media/libstagefright/MediaAppender.cpp
+++ b/media/libstagefright/MediaAppender.cpp
@@ -75,10 +75,21 @@
return status;
}
- if (strcmp("MPEG4Extractor", mExtractor->getName()) == 0) {
+ sp<AMessage> fileFormat;
+ status = mExtractor->getFileFormat(&fileFormat);
+ if (status != OK) {
+ ALOGE("extractor_getFileFormat failed, status :%d", status);
+ return status;
+ }
+
+ AString fileMime;
+ fileFormat->findString("mime", &fileMime);
+ // only compare the end of the file MIME type to allow for vendor customized mime type
+ if (fileMime.endsWith("mp4")){
mFormat = MediaMuxer::OUTPUT_FORMAT_MPEG_4;
} else {
- ALOGE("Unsupported format, extractor name:%s", mExtractor->getName());
+ ALOGE("Unsupported file format, extractor name:%s, fileformat %s",
+ mExtractor->getName(), fileMime.c_str());
return ERROR_UNSUPPORTED;
}
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index e9e98ca..b069462 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -195,6 +195,10 @@
audio_output_flags_t getOutputFlags() const { return mFlags; }
float getSpeed() const { return mSpeed; }
+
+ bool canBeSpatialized() const { return (mAttr.flags
+ & (AUDIO_FLAG_CONTENT_SPATIALIZED | AUDIO_FLAG_NEVER_SPATIALIZE)) == 0; }
+
protected:
// for numerous
friend class PlaybackThread;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 9242f89..c158620 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2052,6 +2052,7 @@
free(mSinkBuffer);
free(mMixerBuffer);
free(mEffectBuffer);
+ free(mEffectToSinkBuffer);
}
// Thread virtuals
@@ -3004,11 +3005,18 @@
// Originally this was int16_t[] array, need to remove legacy implications.
free(mSinkBuffer);
mSinkBuffer = NULL;
+ free(mEffectToSinkBuffer);
+ mEffectToSinkBuffer = nullptr;
+
// For sink buffer size, we use the frame size from the downstream sink to avoid problems
// with non PCM formats for compressed music, e.g. AAC, and Offload threads.
const size_t sinkBufferSize = mNormalFrameCount * mFrameSize;
(void)posix_memalign(&mSinkBuffer, 32, sinkBufferSize);
+ if (mType == SPATIALIZER) {
+ (void)posix_memalign(&mEffectToSinkBuffer, 32, sinkBufferSize);
+ }
+
// We resize the mMixerBuffer according to the requirements of the sink buffer which
// drives the output.
free(mMixerBuffer);
@@ -3839,11 +3847,11 @@
//
// mMixerBufferValid is only set true by MixerThread::prepareTracks_l().
// TODO use mSleepTimeUs == 0 as an additional condition.
+ uint32_t mixerChannelCount = mEffectBufferValid ?
+ audio_channel_count_from_out_mask(mMixerChannelMask) : mChannelCount;
if (mMixerBufferValid) {
void *buffer = mEffectBufferValid ? mEffectBuffer : mSinkBuffer;
audio_format_t format = mEffectBufferValid ? mEffectBufferFormat : mFormat;
- uint32_t channelCount = mEffectBufferValid ?
- audio_channel_count_from_out_mask(mMixerChannelMask) : mChannelCount;
// mono blend occurs for mixer threads only (not direct or offloaded)
// and is handled here if we're going directly to the sink.
@@ -3861,7 +3869,7 @@
}
memcpy_by_audio_format(buffer, format, mMixerBuffer, mMixerBufferFormat,
- mNormalFrameCount * (channelCount + mHapticChannelCount));
+ mNormalFrameCount * (mixerChannelCount + mHapticChannelCount));
// If we're going directly to the sink and there are haptic channels,
// we should adjust channels as the sample data is partially interleaved
@@ -3894,8 +3902,11 @@
&& activeHapticSessionId == effectChains[i]->sessionId()) {
// Haptic data is active in this case, copy it directly from
// in buffer to out buffer.
+ uint32_t channelCount =
+ effectChains[i]->sessionId() == AUDIO_SESSION_OUTPUT_STAGE ?
+ mixerChannelCount : mChannelCount;
const size_t audioBufferSize = mNormalFrameCount
- * audio_bytes_per_frame(mChannelCount, EFFECT_BUFFER_FORMAT);
+ * audio_bytes_per_frame(channelCount, EFFECT_BUFFER_FORMAT);
memcpy_by_audio_format(
(uint8_t*)effectChains[i]->outBuffer() + audioBufferSize,
EFFECT_BUFFER_FORMAT,
@@ -3935,8 +3946,23 @@
mBalance.process((float *)mEffectBuffer, mNormalFrameCount);
}
- memcpy_by_audio_format(mSinkBuffer, mFormat, mEffectBuffer, mEffectBufferFormat,
- mNormalFrameCount * (mChannelCount + mHapticChannelCount));
+ if (mType == SPATIALIZER) {
+ memcpy_by_audio_format(mEffectToSinkBuffer, mFormat, mEffectBuffer,
+ mEffectBufferFormat,
+ mNormalFrameCount * (mChannelCount + mHapticChannelCount));
+ accumulate_by_audio_format(mSinkBuffer, mEffectToSinkBuffer, mFormat,
+ mNormalFrameCount * mChannelCount);
+ const size_t audioBufferSize = mNormalFrameCount
+ * audio_bytes_per_frame(mChannelCount, mFormat);
+ memcpy_by_audio_format(
+ (uint8_t*)mSinkBuffer + audioBufferSize,
+ mFormat,
+ (uint8_t*)mEffectToSinkBuffer + audioBufferSize,
+ mFormat, mNormalFrameCount * mHapticChannelCount);
+ } else {
+ memcpy_by_audio_format(mSinkBuffer, mFormat, mEffectBuffer, mEffectBufferFormat,
+ mNormalFrameCount * (mChannelCount + mHapticChannelCount));
+ }
// The sample data is partially interleaved when haptic channels exist,
// we need to adjust channels here.
if (mHapticChannelCount > 0) {
@@ -4598,6 +4624,7 @@
initFastMixer = mFrameCount < mNormalFrameCount;
break;
}
+ ALOG_ASSERT(initFastMixer && mType == SPATIALIZER);
ALOGW_IF(initFastMixer == false && mFrameCount < mNormalFrameCount,
"FastMixer is preferred for this sink as frameCount %zu is less than threshold %zu",
mFrameCount, mNormalFrameCount);
@@ -4956,6 +4983,9 @@
// before effects processing or output.
if (mMixerBufferValid) {
memset(mMixerBuffer, 0, mMixerBufferSize);
+ if (mType == SPATIALIZER) {
+ memset(mSinkBuffer, 0, mSinkBufferSize);
+ }
} else {
memset(mSinkBuffer, 0, mSinkBufferSize);
}
@@ -5448,11 +5478,21 @@
trackId,
AudioMixer::TRACK,
AudioMixer::CHANNEL_MASK, (void *)(uintptr_t)track->channelMask());
- mAudioMixer->setParameter(
- trackId,
- AudioMixer::TRACK,
- AudioMixer::MIXER_CHANNEL_MASK,
- (void *)(uintptr_t)(mMixerChannelMask | mHapticChannelMask));
+
+ if (mType == SPATIALIZER && !track->canBeSpatialized()) {
+ mAudioMixer->setParameter(
+ trackId,
+ AudioMixer::TRACK,
+ AudioMixer::MIXER_CHANNEL_MASK,
+ (void *)(uintptr_t)(mChannelMask | mHapticChannelMask));
+ } else {
+ mAudioMixer->setParameter(
+ trackId,
+ AudioMixer::TRACK,
+ AudioMixer::MIXER_CHANNEL_MASK,
+ (void *)(uintptr_t)(mMixerChannelMask | mHapticChannelMask));
+ }
+
// limit track sample rate to 2 x output sample rate, which changes at re-configuration
uint32_t maxSampleRate = mSampleRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX;
uint32_t reqSampleRate = proxy->getSampleRate();
@@ -5489,16 +5529,27 @@
if (mMixerBufferEnabled
&& (track->mainBuffer() == mSinkBuffer
|| track->mainBuffer() == mMixerBuffer)) {
- mAudioMixer->setParameter(
- trackId,
- AudioMixer::TRACK,
- AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat);
- mAudioMixer->setParameter(
- trackId,
- AudioMixer::TRACK,
- AudioMixer::MAIN_BUFFER, (void *)mMixerBuffer);
- // TODO: override track->mainBuffer()?
- mMixerBufferValid = true;
+ if (mType == SPATIALIZER && !track->canBeSpatialized()) {
+ mAudioMixer->setParameter(
+ trackId,
+ AudioMixer::TRACK,
+ AudioMixer::MIXER_FORMAT, (void *)mFormat);
+ mAudioMixer->setParameter(
+ trackId,
+ AudioMixer::TRACK,
+ AudioMixer::MAIN_BUFFER, (void *)mSinkBuffer);
+ } else {
+ mAudioMixer->setParameter(
+ trackId,
+ AudioMixer::TRACK,
+ AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat);
+ mAudioMixer->setParameter(
+ trackId,
+ AudioMixer::TRACK,
+ AudioMixer::MAIN_BUFFER, (void *)mMixerBuffer);
+ // TODO: override track->mainBuffer()?
+ mMixerBufferValid = true;
+ }
} else {
mAudioMixer->setParameter(
trackId,
@@ -5688,8 +5739,10 @@
// sink or mix buffer must be cleared if all tracks are connected to an
// effect chain as in this case the mixer will not write to the sink or mix buffer
// and track effects will accumulate into it
- if ((mBytesRemaining == 0) && ((mixedTracks != 0 && mixedTracks == tracksWithEffect) ||
- (mixedTracks == 0 && fastTracks > 0))) {
+ // always clear sink buffer for spatializer output as the output of the spatializer
+ // effect will be accumulated into it
+ if ((mBytesRemaining == 0) && (((mixedTracks != 0 && mixedTracks == tracksWithEffect) ||
+ (mixedTracks == 0 && fastTracks > 0)) || (mType == SPATIALIZER))) {
// FIXME as a performance optimization, should remember previous zero status
if (mMixerBufferValid) {
memset(mMixerBuffer, 0, mMixerBufferSize);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 300171e..5755c42 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1123,6 +1123,11 @@
// for any processing (including output processing).
bool mEffectBufferValid;
+ // Frame size aligned buffer used to convert mEffectBuffer samples to mSinkBuffer format prior
+ // to accumulate into mSinkBuffer on SPATIALIZER threads
+ void* mEffectToSinkBuffer = nullptr;
+
+
// suspend count, > 0 means suspended. While suspended, the thread continues to pull from
// tracks and mix, but doesn't write to HAL. A2DP and SCO HAL implementations can't handle
// concurrent use of both of them, so Audio Policy Service suspends one of the threads to
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 87f4694..a46da41 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -248,9 +248,7 @@
// been opened by checkOutputsForDevice() to query dynamic parameters
if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)
|| (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
- (desc->mDirectOpenCount == 0))
- || (((desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) &&
- (desc != mSpatializerOutput))) {
+ (desc->mDirectOpenCount == 0))) {
clearAudioSourcesForOutput(output);
closeOutput(output);
}
@@ -928,8 +926,7 @@
}
sp<IOProfile> AudioPolicyManager::getSpatializerOutputProfile(
- const audio_config_t *config __unused, const AudioDeviceTypeAddrVector &devices,
- bool forOpening) const
+ const audio_config_t *config __unused, const AudioDeviceTypeAddrVector &devices) const
{
for (const auto& hwModule : mHwModules) {
for (const auto& curProfile : hwModule->getOutputProfiles()) {
@@ -947,9 +944,6 @@
continue;
}
}
- if (forOpening && !curProfile->canOpenNewIo()) {
- continue;
- }
ALOGV("%s found profile %s", __func__, curProfile->getName().c_str());
return curProfile;
}
@@ -4844,6 +4838,21 @@
return source;
}
+/* static */
+bool AudioPolicyManager::isChannelMaskSpatialized(audio_channel_mask_t channels) {
+ switch (channels) {
+ case AUDIO_CHANNEL_OUT_5POINT1:
+ case AUDIO_CHANNEL_OUT_5POINT1POINT2:
+ case AUDIO_CHANNEL_OUT_5POINT1POINT4:
+ case AUDIO_CHANNEL_OUT_7POINT1:
+ case AUDIO_CHANNEL_OUT_7POINT1POINT2:
+ case AUDIO_CHANNEL_OUT_7POINT1POINT4:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool AudioPolicyManager::canBeSpatialized(const audio_attributes_t *attr,
const audio_config_t *config,
const AudioDeviceTypeAddrVector &devices) const
@@ -4852,9 +4861,13 @@
// the AUDIO_ATTRIBUTES_INITIALIZER value.
// If attributes are specified, current policy is to only allow spatialization for media
// and game usages.
- if (attr != nullptr && *attr != AUDIO_ATTRIBUTES_INITIALIZER &&
- attr->usage != AUDIO_USAGE_MEDIA && attr->usage != AUDIO_USAGE_GAME) {
- return false;
+ if (attr != nullptr && *attr != AUDIO_ATTRIBUTES_INITIALIZER) {
+ if (attr->usage != AUDIO_USAGE_MEDIA && attr->usage != AUDIO_USAGE_GAME) {
+ return false;
+ }
+ if ((attr->flags & (AUDIO_FLAG_CONTENT_SPATIALIZED | AUDIO_FLAG_NEVER_SPATIALIZE)) != 0) {
+ return false;
+ }
}
// The caller can have the devices criteria ignored by passing and empty vector, and
@@ -4862,7 +4875,7 @@
// Otherwise an output profile supporting a spatializer effect that can be routed
// to the specified devices must exist.
sp<IOProfile> profile =
- getSpatializerOutputProfile(config, devices, false /*forOpening*/);
+ getSpatializerOutputProfile(config, devices);
if (profile == nullptr) {
return false;
}
@@ -4870,37 +4883,36 @@
// The caller can have the audio config criteria ignored by either passing a null ptr or
// the AUDIO_CONFIG_INITIALIZER value.
// If an audio config is specified, current policy is to only allow spatialization for
- // 5.1, 7.1and 7.1.4 audio.
+ // some positional channel masks.
// If the spatializer output is already opened, only channel masks included in the
// spatializer output mixer channel mask are allowed.
+
if (config != nullptr && *config != AUDIO_CONFIG_INITIALIZER) {
- if (config->channel_mask != AUDIO_CHANNEL_OUT_5POINT1
- && config->channel_mask != AUDIO_CHANNEL_OUT_7POINT1
- && config->channel_mask != AUDIO_CHANNEL_OUT_7POINT1POINT4) {
+ if (!isChannelMaskSpatialized(config->channel_mask)) {
return false;
}
- if (mSpatializerOutput != nullptr) {
+ if (mSpatializerOutput != nullptr && mSpatializerOutput->mProfile == profile) {
if ((config->channel_mask & mSpatializerOutput->mMixerChannelMask)
!= config->channel_mask) {
return false;
}
}
}
-
return true;
}
void AudioPolicyManager::checkVirtualizerClientRoutes() {
std::set<audio_stream_type_t> streamsToInvalidate;
for (size_t i = 0; i < mOutputs.size(); i++) {
- const sp<SwAudioOutputDescriptor>& outputDescriptor = mOutputs[i];
- for (const sp<TrackClientDescriptor>& client : outputDescriptor->getClientIterable()) {
+ const sp<SwAudioOutputDescriptor>& desc = mOutputs[i];
+ for (const sp<TrackClientDescriptor>& client : desc->getClientIterable()) {
audio_attributes_t attr = client->attributes();
DeviceVector devices = mEngine->getOutputDevicesForAttributes(attr, nullptr, false);
AudioDeviceTypeAddrVector devicesTypeAddress = devices.toTypeAddrVector();
audio_config_base_t clientConfig = client->config();
audio_config_t config = audio_config_initializer(&clientConfig);
- if (canBeSpatialized(&attr, &config, devicesTypeAddress)) {
+ if (desc != mSpatializerOutput
+ && canBeSpatialized(&attr, &config, devicesTypeAddress)) {
streamsToInvalidate.insert(client->stream());
}
}
@@ -4916,10 +4928,6 @@
audio_io_handle_t *output) {
*output = AUDIO_IO_HANDLE_NONE;
- if (mSpatializerOutput != nullptr) {
- return INVALID_OPERATION;
- }
-
DeviceVector devices = mEngine->getOutputDevicesForAttributes(*attr, nullptr, false);
AudioDeviceTypeAddrVector devicesTypeAddress = devices.toTypeAddrVector();
audio_config_t *configPtr = nullptr;
@@ -4929,35 +4937,87 @@
configPtr = &config;
}
if (!canBeSpatialized(attr, configPtr, devicesTypeAddress)) {
+ ALOGW("%s provided attributes or mixer config cannot be spatialized", __func__);
return BAD_VALUE;
}
sp<IOProfile> profile =
- getSpatializerOutputProfile(configPtr, devicesTypeAddress, true /*forOpening*/);
+ getSpatializerOutputProfile(configPtr, devicesTypeAddress);
if (profile == nullptr) {
+ ALOGW("%s no suitable output profile for provided attributes or mixer config", __func__);
return BAD_VALUE;
}
- mSpatializerOutput = new SwAudioOutputDescriptor(profile, mpClientInterface);
- status_t status = mSpatializerOutput->open(nullptr, mixerConfig, devices,
+ if (mSpatializerOutput != nullptr && mSpatializerOutput->mProfile == profile
+ && configPtr != nullptr
+ && configPtr->channel_mask == mSpatializerOutput->mMixerChannelMask) {
+ *output = mSpatializerOutput->mIoHandle;
+ ALOGV("%s returns current spatializer output %d", __func__, *output);
+ return NO_ERROR;
+ }
+ mSpatializerOutput.clear();
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ if (!desc->isDuplicated() && desc->mProfile == profile) {
+ mSpatializerOutput = desc;
+ break;
+ }
+ }
+ if (mSpatializerOutput == nullptr) {
+ ALOGW("%s no opened spatializer output for profile %s",
+ __func__, profile->getName().c_str());
+ return BAD_VALUE;
+ }
+
+ if (configPtr != nullptr
+ && configPtr->channel_mask != mSpatializerOutput->mMixerChannelMask) {
+ audio_config_base_t savedMixerConfig = {
+ .sample_rate = mSpatializerOutput->getSamplingRate(),
+ .format = mSpatializerOutput->getFormat(),
+ .channel_mask = mSpatializerOutput->mMixerChannelMask,
+ };
+ DeviceVector savedDevices = mSpatializerOutput->devices();
+
+ closeOutput(mSpatializerOutput->mIoHandle);
+ mSpatializerOutput.clear();
+
+ const sp<SwAudioOutputDescriptor> desc =
+ new SwAudioOutputDescriptor(profile, mpClientInterface);
+ status_t status = desc->open(nullptr, mixerConfig, devices,
mEngine->getStreamTypeForAttributes(*attr),
AUDIO_OUTPUT_FLAG_SPATIALIZER, output);
- if (status != NO_ERROR) {
- ALOGV("%s failed opening output: status %d, output %d", __func__, status, *output);
- if (*output != AUDIO_IO_HANDLE_NONE) {
- mSpatializerOutput->close();
+ if (status != NO_ERROR) {
+ ALOGW("%s failed opening output: status %d, output %d", __func__, status, *output);
+ if (*output != AUDIO_IO_HANDLE_NONE) {
+ desc->close();
+ }
+ // re open the spatializer output with previous channel mask
+ status_t newStatus = desc->open(nullptr, &savedMixerConfig, savedDevices,
+ mEngine->getStreamTypeForAttributes(*attr),
+ AUDIO_OUTPUT_FLAG_SPATIALIZER, output);
+ if (newStatus != NO_ERROR) {
+ if (*output != AUDIO_IO_HANDLE_NONE) {
+ desc->close();
+ }
+ ALOGE("%s failed to re-open mSpatializerOutput, status %d", __func__, newStatus);
+ } else {
+ mSpatializerOutput = desc;
+ addOutput(*output, desc);
+ }
+ mPreviousOutputs = mOutputs;
+ mpClientInterface->onAudioPortListUpdate();
+ *output = AUDIO_IO_HANDLE_NONE;
+ return status;
}
- mSpatializerOutput.clear();
- *output = AUDIO_IO_HANDLE_NONE;
- return status;
+ mSpatializerOutput = desc;
+ addOutput(*output, desc);
+ mPreviousOutputs = mOutputs;
+ mpClientInterface->onAudioPortListUpdate();
}
checkVirtualizerClientRoutes();
- addOutput(*output, mSpatializerOutput);
- mPreviousOutputs = mOutputs;
- mpClientInterface->onAudioPortListUpdate();
-
+ *output = mSpatializerOutput->mIoHandle;
ALOGV("%s returns new spatializer output %d", __func__, *output);
return NO_ERROR;
}
@@ -4969,8 +5029,11 @@
if (mSpatializerOutput->mIoHandle != output) {
return BAD_VALUE;
}
- closeOutput(output);
+
mSpatializerOutput.clear();
+
+ checkVirtualizerClientRoutes();
+
return NO_ERROR;
}
@@ -5187,8 +5250,7 @@
outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
mPrimaryOutput = outputDesc;
}
- if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0
- || (outProfile->getFlags() & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0 ) {
+ if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
outputDesc->close();
} else {
addOutput(output, outputDesc);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 2b3f3b4..0eda10e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -962,8 +962,9 @@
audio_io_handle_t *output);
sp<IOProfile> getSpatializerOutputProfile(const audio_config_t *config,
- const AudioDeviceTypeAddrVector &devices,
- bool forOpening) const;
+ const AudioDeviceTypeAddrVector &devices) const;
+
+ static bool isChannelMaskSpatialized(audio_channel_mask_t channels);
void checkVirtualizerClientRoutes();
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index dd68ae4..0f65877 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -130,11 +130,14 @@
ALOGV("setDeviceConnectionState()");
Mutex::Autolock _l(mLock);
AutoCallerClear acc;
- return binderStatusFromStatusT(
- mAudioPolicyManager->setDeviceConnectionState(device, state,
+ status_t status = mAudioPolicyManager->setDeviceConnectionState(device, state,
deviceAidl.address.c_str(),
deviceNameAidl.c_str(),
- encodedFormat));
+ encodedFormat);
+ if (status == NO_ERROR) {
+ onCheckSpatializer_l();
+ }
+ return binderStatusFromStatusT(status);
}
Status AudioPolicyService::getDeviceConnectionState(const media::AudioDevice& deviceAidl,
@@ -174,9 +177,13 @@
ALOGV("handleDeviceConfigChange()");
Mutex::Autolock _l(mLock);
AutoCallerClear acc;
- return binderStatusFromStatusT(
- mAudioPolicyManager->handleDeviceConfigChange(device, deviceAidl.address.c_str(),
- deviceNameAidl.c_str(), encodedFormat));
+ status_t status = mAudioPolicyManager->handleDeviceConfigChange(
+ device, deviceAidl.address.c_str(), deviceNameAidl.c_str(), encodedFormat);
+
+ if (status == NO_ERROR) {
+ onCheckSpatializer_l();
+ }
+ return binderStatusFromStatusT(status);
}
Status AudioPolicyService::setPhoneState(AudioMode stateAidl, int32_t uidAidl)
@@ -243,6 +250,7 @@
Mutex::Autolock _l(mLock);
AutoCallerClear acc;
mAudioPolicyManager->setForceUse(usage, config);
+ onCheckSpatializer_l();
return Status::ok();
}
@@ -2080,8 +2088,11 @@
return binderStatusFromStatusT(NO_INIT);
}
Mutex::Autolock _l(mLock);
- return binderStatusFromStatusT(
- mAudioPolicyManager->setDevicesRoleForStrategy(strategy, role, devices));
+ status_t status = mAudioPolicyManager->setDevicesRoleForStrategy(strategy, role, devices);
+ if (status == NO_ERROR) {
+ onCheckSpatializer_l();
+ }
+ return binderStatusFromStatusT(status);
}
Status AudioPolicyService::removeDevicesRoleForStrategy(int32_t strategyAidl,
@@ -2094,8 +2105,11 @@
return binderStatusFromStatusT(NO_INIT);
}
Mutex::Autolock _l(mLock);
- return binderStatusFromStatusT(
- mAudioPolicyManager->removeDevicesRoleForStrategy(strategy, role));
+ status_t status = mAudioPolicyManager->removeDevicesRoleForStrategy(strategy, role);
+ if (status == NO_ERROR) {
+ onCheckSpatializer_l();
+ }
+ return binderStatusFromStatusT(status);
}
Status AudioPolicyService::getDevicesForRoleAndStrategy(
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 86ebe98..c21be1e 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -366,41 +366,51 @@
void AudioPolicyService::onCheckSpatializer()
{
Mutex::Autolock _l(mLock);
- mOutputCommandThread->checkSpatializerCommand();
+ onCheckSpatializer_l();
+}
+
+void AudioPolicyService::onCheckSpatializer_l()
+{
+ if (mSpatializer != nullptr) {
+ mOutputCommandThread->checkSpatializerCommand();
+ }
}
void AudioPolicyService::doOnCheckSpatializer()
{
- sp<Spatializer> spatializer;
- {
- Mutex::Autolock _l(mLock);
- spatializer = mSpatializer;
+ Mutex::Autolock _l(mLock);
- if (spatializer != nullptr) {
- audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- if (spatializer->getLevel() != media::SpatializationLevel::NONE
- && spatializer->getOutput() == AUDIO_IO_HANDLE_NONE) {
- const audio_attributes_t attr = attributes_initializer(AUDIO_USAGE_MEDIA);
- audio_config_base_t config = spatializer->getAudioInConfig();
- status_t status =
- mAudioPolicyManager->getSpatializerOutput(&config, &attr, &output);
- if (status != NO_ERROR || output == AUDIO_IO_HANDLE_NONE) {
- return;
- }
- mLock.unlock();
- status = spatializer->attachOutput(output);
+ if (mSpatializer != nullptr) {
+ if (mSpatializer->getLevel() != media::SpatializationLevel::NONE) {
+ audio_io_handle_t currentOutput = mSpatializer->getOutput();
+ audio_io_handle_t newOutput;
+ const audio_attributes_t attr = attributes_initializer(AUDIO_USAGE_MEDIA);
+ audio_config_base_t config = mSpatializer->getAudioInConfig();
+ status_t status =
+ mAudioPolicyManager->getSpatializerOutput(&config, &attr, &newOutput);
+
+ if (status == NO_ERROR && currentOutput == newOutput) {
+ return;
+ }
+ mLock.unlock();
+ // It is OK to call detachOutput() is none is already attached.
+ mSpatializer->detachOutput();
+ if (status != NO_ERROR || newOutput == AUDIO_IO_HANDLE_NONE) {
mLock.lock();
- if (status != NO_ERROR) {
- mAudioPolicyManager->releaseSpatializerOutput(output);
- }
- } else if (spatializer->getLevel() == media::SpatializationLevel::NONE
- && spatializer->getOutput() != AUDIO_IO_HANDLE_NONE) {
- mLock.unlock();
- output = spatializer->detachOutput();
- mLock.lock();
- if (output != AUDIO_IO_HANDLE_NONE) {
- mAudioPolicyManager->releaseSpatializerOutput(output);
- }
+ return;
+ }
+ status = mSpatializer->attachOutput(newOutput);
+ mLock.lock();
+ if (status != NO_ERROR) {
+ mAudioPolicyManager->releaseSpatializerOutput(newOutput);
+ }
+ } else if (mSpatializer->getLevel() == media::SpatializationLevel::NONE
+ && mSpatializer->getOutput() != AUDIO_IO_HANDLE_NONE) {
+ mLock.unlock();
+ audio_io_handle_t output = mSpatializer->detachOutput();
+ mLock.lock();
+ if (output != AUDIO_IO_HANDLE_NONE) {
+ mAudioPolicyManager->releaseSpatializerOutput(output);
}
}
}
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index b98dacb..ed766b0 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -341,6 +341,7 @@
* by audio policy manager and attach/detach the spatializer effect accordingly.
*/
void onCheckSpatializer() override;
+ void onCheckSpatializer_l();
void doOnCheckSpatializer();
void setEffectSuspended(int effectId,
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 8967fc7..82e4ef3 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2396,7 +2396,8 @@
Mutex::Autolock lock(mCameraStatesLock);
for (auto& i : mCameraStates) {
cameraStatuses->emplace_back(i.first,
- mapToInterface(i.second->getStatus()), i.second->getUnavailablePhysicalIds());
+ mapToInterface(i.second->getStatus()), i.second->getUnavailablePhysicalIds(),
+ openCloseCallbackAllowed ? i.second->getClientPackage() : String8::empty());
}
}
// Remove the camera statuses that should be hidden from the client, we do
@@ -3766,6 +3767,16 @@
return count > 0;
}
+void CameraService::CameraState::setClientPackage(const String8& clientPackage) {
+ Mutex::Autolock lock(mStatusLock);
+ mClientPackage = clientPackage;
+}
+
+String8 CameraService::CameraState::getClientPackage() const {
+ Mutex::Autolock lock(mStatusLock);
+ return mClientPackage;
+}
+
// ----------------------------------------------------------------------------
// ClientEventListener
// ----------------------------------------------------------------------------
@@ -4329,6 +4340,18 @@
void CameraService::updateOpenCloseStatus(const String8& cameraId, bool open,
const String16& clientPackageName) {
+ auto state = getCameraState(cameraId);
+ if (state == nullptr) {
+ ALOGW("%s: Could not update the status for %s, no such device exists", __FUNCTION__,
+ cameraId.string());
+ return;
+ }
+ if (open) {
+ state->setClientPackage(String8(clientPackageName));
+ } else {
+ state->setClientPackage(String8::empty());
+ }
+
Mutex::Autolock lock(mStatusListenerLock);
for (const auto& it : mListenerList) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 224287e..7a69123 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -635,6 +635,12 @@
bool removeUnavailablePhysicalId(const String8& physicalId);
/**
+ * Set and get client package name.
+ */
+ void setClientPackage(const String8& clientPackage);
+ String8 getClientPackage() const;
+
+ /**
* Return the unavailable physical ids for this device.
*
* This method acquires mStatusLock.
@@ -646,6 +652,7 @@
const int mCost;
std::set<String8> mConflicting;
std::set<String8> mUnavailablePhysicalIds;
+ String8 mClientPackage;
mutable Mutex mStatusLock;
CameraParameters mShimParams;
const SystemCameraKind mSystemCameraKind;
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 80508e4..a406e62 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -864,7 +864,6 @@
if (fabs(maxDigitalZoom.data.f[0] - 1.f) > 0.00001f) {
params.set(CameraParameters::KEY_ZOOM, zoom);
- params.set(CameraParameters::KEY_MAX_ZOOM, NUM_ZOOM_STEPS - 1);
{
String8 zoomRatios;
@@ -872,18 +871,34 @@
float zoomIncrement = (maxDigitalZoom.data.f[0] - zoom) /
(NUM_ZOOM_STEPS-1);
bool addComma = false;
- for (size_t i=0; i < NUM_ZOOM_STEPS; i++) {
+ int previousZoom = -1;
+ size_t zoomSteps = 0;
+ for (size_t i = 0; i < NUM_ZOOM_STEPS; i++) {
+ int currentZoom = static_cast<int>(zoom * 100);
+ if (previousZoom == currentZoom) {
+ zoom += zoomIncrement;
+ continue;
+ }
if (addComma) zoomRatios += ",";
addComma = true;
- zoomRatios += String8::format("%d", static_cast<int>(zoom * 100));
+ zoomRatios += String8::format("%d", currentZoom);
zoom += zoomIncrement;
+ previousZoom = currentZoom;
+ zoomSteps++;
}
- params.set(CameraParameters::KEY_ZOOM_RATIOS, zoomRatios);
+
+ if (zoomSteps > 0) {
+ params.set(CameraParameters::KEY_ZOOM_RATIOS, zoomRatios);
+ params.set(CameraParameters::KEY_ZOOM_SUPPORTED,
+ CameraParameters::TRUE);
+ params.set(CameraParameters::KEY_MAX_ZOOM, zoomSteps - 1);
+ zoomAvailable = true;
+ } else {
+ params.set(CameraParameters::KEY_ZOOM_SUPPORTED,
+ CameraParameters::FALSE);
+ }
}
- params.set(CameraParameters::KEY_ZOOM_SUPPORTED,
- CameraParameters::TRUE);
- zoomAvailable = true;
} else {
params.set(CameraParameters::KEY_ZOOM_SUPPORTED,
CameraParameters::FALSE);