Merge "Export support types from extractors"
diff --git a/apex/Android.bp b/apex/Android.bp
index 05cc2c5..604b268 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -31,8 +31,25 @@
key: "com.android.media.key",
}
+apex {
+ name: "com.android.media.swcodec",
+ compile_multilib: "32",
+ manifest: "manifest_codec.json",
+ native_shared_libs: [
+ "libmedia_codecserviceregistrant",
+ ],
+ use_vendor: true,
+ key: "com.android.media.swcodec.key",
+}
+
apex_key {
name: "com.android.media.key",
public_key: "com.android.media.avbpubkey",
private_key: "com.android.media.pem",
}
+
+apex_key {
+ name: "com.android.media.swcodec.key",
+ public_key: "com.android.media.swcodec.avbpubkey",
+ private_key: "com.android.media.swcodec.pem",
+}
diff --git a/apex/com.android.media.swcodec.avbpubkey b/apex/com.android.media.swcodec.avbpubkey
new file mode 100644
index 0000000..0459723
--- /dev/null
+++ b/apex/com.android.media.swcodec.avbpubkey
Binary files differ
diff --git a/apex/com.android.media.swcodec.pem b/apex/com.android.media.swcodec.pem
new file mode 100644
index 0000000..e379cd3
--- /dev/null
+++ b/apex/com.android.media.swcodec.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKgIBAAKCAgEAvB6lOEEOR58KMcFlayEZjsXuPgcfHi/OPxcvfpiGLCpOcK3l
+OPChWUvDRcIHMB7BO+Csfxs0HgsHvvZfNyoNIm99WcjFbboiO7WrBBArIszPr14X
+cfY2NxzT9LBj+EqAnbdL+4OQW1/npLHNE0qtDcxL71ipbjSuKNb58E9qGL0KwvkS
+fwwueWj++bg/iz7dq0mz7iKpnxYscNm4RhJjqcG2Usmg4Ejhr8h5UmOUmTJbObC/
+vzClXQqeeuzS8NTtGVgQ/CI9gC2WN9upq2p/2T7P4U3o3CWvBytUoLKR0UyC83ey
+S8XJgOa42uWR3T/eJOI1ZS4H6Srg1o2XC8Yb8EprFI/NM6/+/5DX/FgDimsslAP6
+Qq4+pSte9v/FjWGqy7QBQaefFRGRuS63xHcSZhXC9J2CFdnxo8+65QT8r4yfQEei
+Ax/0Q94yB7VIL1pIJxHEonKjtd3iKdFEKQzADJ3edsmtHybERdJKCxcm9QIrDCsC
+4YVT9nX0OoC9RD5d5EVD7W5I6eEnRu6igrKIKgUVppeYFQNZD+o+eiNJa4yoggRl
+h8sT0/xLKjMRxAQ7fafi1j+LB2O7UgJmIDDAnidq8Aoz7h3pNi139rNWrjNfwhus
+nMcZvL9dTVv26JWeESHP/zAfAX7j1rfkDwR02ocRLquwEUs1+UHA27Wi1bMCAwEA
+AQKCAgAO3PT83tb7/arWh4s1zaWxTB4otHNW9Tv8bB6KiA6Bys3rxTGJMCnvXjcN
+eekLekKWMoguer3BaemwwtJ/D0l+YQSsZVqD8uLliNL8PTLLSxdVqb98d5GNBTAR
+8yXS5kAHNgZA1wI+1fL9ZjbnwUyu/Gc7f+vTE0J3Y5TX0c52KemBwiAd/Z5mZU9P
+96i9nbfx4p7ev8pbEWttdyZCEw3gybdYDyowzlFWjCZZxhhlij7+7eIYfwVxtncT
+C0cXVBtvly+wXBwz1mY5/5cGPiHfzkCqcndlfWy4ykmjcLhoqvzls51Ys0Xac2BD
+m0PNEVDB5UWGuv5RA9xD12gJvBtU3D7ggMw6C5RcXJT+jSYmSFtD2klWi+It8A/N
+Hv42soKskt6JqYAWE1cvJ3PEqH9ASEJNq2R0Z/PmuM000UJyzU9KId3SNwjXA1Xc
+Kn9hRga4uf9elHTjkTDt79/8+Xv7hjer9sF/S/np7g04rUjIWkuFkC/7NK2tQSh1
+mljV1sD9SF4DPfVK75LwJJaQUlI7TtGd5KJ7FzZwvb+w8ODrpW3hkt6FcI6KwE/a
+QT1T2Z9DknXJSYNdWGrj6vMHsYMiyz8IdAHSCrOB6eXCQxpitbn6W71Raw7f9UaZ
+VDK5AhTU493hkGj1no4cJwecXInMigg/c4ywk2Ibh6IV8O0nkQKCAQEA2+dQQ0IF
+vvVgmQ2WxHBD7M2mbOyf43YBY6Ka6oPBNGPVpZE8X8LoTavQLV+SgCkH8T6gY7XS
+5L4Ze0JFxfua0o1rm6+L2XrOx5F/A2Y40YcPclEik5h1woSwH/J1iHGiEhY8Nqeu
+9GCvjQojkgXx/Rn3Nz+lpvZ329O3H85RWWGF0l60RwLOkig0ZwUb619t8affmGIl
+sxdDv2nfy7OtJX8iGDua7Kf64dvVWQKKtACWkARrlkcWX3uoESxkpSDxue+z7ndH
+o7uHLfM8Tx+Rn+QvYWuRW5TPLbEDMbIYrX65ISt2r/T7v/04XdAC8YpCQRytlqPI
+fpDm15htyHBizQKCAQEA2v+5otRoY56JduISaVGlsJ/IbvKzDAIyWmM14EpRCR5E
+lu+MpTcRAiFQAbHGXr1tMlTFdVFD090WAzIKaKtADFVLXobIHeGspnRCq5OpVp9W
+RvLtVwLxflHAc2yN9/LNtnBqHUgt+S01LBPElybdGHQRTtqAKXhkp31sM21O34Go
+Pri/IxgupWxykMaW44Kig1Cr5DKvc8cwUsGuyDdJm8oBQeNPTMWqSnXtqoTWSaYg
+2kxiMTFokrkSXgufb8wng6OXt/QelywrhG3hAsldPO3GdKidDSxhWZSgpUXXFdAX
+y4GO0IcRJBF/WJtYTYtR+l84nQA2/1Ye4ujFlT0afwKCAQEAmXrXpSm2cvI2CnzW
+hqJIdkWOa6W3bn1VOOIrt5Rfy54GZnl4pumVU2igcpqq2HJKzdDFBvLHj8kyZbn6
+ktUp2NzFhzK9q/uvyNA+0vOMoojeeg4w0MzvG+WaO6Hw8FtHH9KPEiJ01LGKtSin
+bOpjXCC8T75HcsHBJBefTz6jvnt3eD2LG6jU3mPbNy/0rZG8XZaqU2PlJhsNuNI/
+VaBBL9OMy1cGqTgQvYS+YlKI1ls2uqurH4bcEaZvxhSy5iGZNQodDkoIITnofmSu
+6haBgBQ2EYuPN1kkRKKwNQY1fRneQk1gmCynbPdiWO+urkCuP12xtlr3u4aM51rG
+/Meb3QKCAQEA12SxZm9XhLOHLIBJ74A4YLGm50iZxXPbpn7xnHo7naZBe9p8EHtK
+pTeygxggrUnOPrSVyT92YMiQP/BVwIC+a+LwUDZsWMd/ke/DKxH+eY4Zw4pm2S+x
+6bXqfRwFvhr3LTr/g3FcljlalNGUh73Xs5dk9pN9fkxFY16+rw4Rh0709Uur4o6E
+QnuZar+H5Ji10kXj6nvXiR4ebybEC3QlV66k8fLqKe44AShf61jfkmxs34hFA3E/
+EyAn6ouv8rtvGdArBuh5teHho0yXBLCcnbKXgGHepfhCf2LpZeR9GZ0j6iqxFnPh
+7gGvqKyReyNOK9y/x9tQPG6tzit3OcNxbQKCAQEAuDheDOSkXPopXMvLAKOHBIdZ
+rbQ7oFTDHt59gbucM7U8/l2YtaxuKOQFBLnzQa/amIkkrtklYwOsz8E24d7Nm39w
+ykLHwX0XrmjAm6M4XKmDv66a+kSnSV6LEbKZdjvXP02DV+tGeZ5VsnNvJDquxMsD
+fvRTspB8j8CpU96szekxl/tCRhqbdw/4kVTSj5BF++OaRRcJrAyj1B2qf1ynAZE1
+gUvVPkEYa914zcrxg9XIXT4M7yqB7i8KJegOtOtcWjJ7uTiP+638AvygJLMJnSrV
++HjFZWG6P9btZmLHSEBRvwGOAilp0qejXo866l0fmnlGy7ehKz8u3PzvnlPYjQ==
+-----END RSA PRIVATE KEY-----
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
new file mode 100644
index 0000000..e2bceec
--- /dev/null
+++ b/apex/manifest_codec.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.media.swcodec",
+ "version": 1
+}
diff --git a/media/codec2/components/flac/Android.bp b/media/codec2/components/flac/Android.bp
index d485964..e5eb51d 100644
--- a/media/codec2/components/flac/Android.bp
+++ b/media/codec2/components/flac/Android.bp
@@ -23,5 +23,8 @@
srcs: ["C2SoftFlacEnc.cpp"],
- static_libs: ["libFLAC"],
+ static_libs: [
+ "libaudioutils",
+ "libFLAC",
+ ],
}
diff --git a/media/codec2/components/flac/C2SoftFlacDec.cpp b/media/codec2/components/flac/C2SoftFlacDec.cpp
index f1e2f51..86b16e8 100644
--- a/media/codec2/components/flac/C2SoftFlacDec.cpp
+++ b/media/codec2/components/flac/C2SoftFlacDec.cpp
@@ -83,8 +83,21 @@
DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
.withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 32768))
.build());
+
+ addParameter(
+ DefineParam(mPcmEncodingInfo, C2_PARAMKEY_PCM_ENCODING)
+ .withDefault(new C2StreamPcmEncodingInfo::output(0u, C2Config::PCM_16))
+ .withFields({C2F(mPcmEncodingInfo, value).oneOf({
+ C2Config::PCM_16,
+ // C2Config::PCM_8,
+ C2Config::PCM_FLOAT})
+ })
+ .withSetter((Setter<decltype(*mPcmEncodingInfo)>::StrictValueWithNoDeps))
+ .build());
}
+ int32_t getPcmEncodingInfo() const { return mPcmEncodingInfo->value; }
+
private:
std::shared_ptr<C2StreamFormatConfig::input> mInputFormat;
std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat;
@@ -94,6 +107,7 @@
std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount;
std::shared_ptr<C2BitrateTuning::input> mBitrate;
std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
+ std::shared_ptr<C2StreamPcmEncodingInfo::output> mPcmEncodingInfo;
};
C2SoftFlacDec::C2SoftFlacDec(
@@ -263,11 +277,11 @@
return;
}
- size_t outSize;
- if (mHasStreamInfo)
- outSize = mStreamInfo.max_blocksize * mStreamInfo.channels * sizeof(short);
- else
- outSize = kMaxBlockSize * FLACDecoder::kMaxChannels * sizeof(short);
+ const bool outputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
+ const size_t sampleSize = outputFloat ? sizeof(float) : sizeof(short);
+ size_t outSize = mHasStreamInfo ?
+ mStreamInfo.max_blocksize * mStreamInfo.channels * sampleSize
+ : kMaxBlockSize * FLACDecoder::kMaxChannels * sampleSize;
std::shared_ptr<C2LinearBlock> block;
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
@@ -284,9 +298,8 @@
return;
}
- short *output = reinterpret_cast<short *>(wView.data());
status_t decoderErr = mFLACDecoder->decodeOneFrame(
- input, inSize, output, &outSize);
+ input, inSize, wView.data(), &outSize, outputFloat);
if (decoderErr != OK) {
ALOGE("process: FLACDecoder decodeOneFrame returns error %d", decoderErr);
mSignalledError = true;
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.cpp b/media/codec2/components/flac/C2SoftFlacEnc.cpp
index e4192c7..4ea35c2 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.cpp
+++ b/media/codec2/components/flac/C2SoftFlacEnc.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "C2SoftFlacEnc"
#include <log/log.h>
+#include <audio_utils/primitives.h>
#include <media/stagefright/foundation/MediaDefs.h>
#include <C2PlatformSupport.h>
@@ -72,11 +73,23 @@
DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
.withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 4608))
.build());
+
+ addParameter(
+ DefineParam(mPcmEncodingInfo, C2_PARAMKEY_PCM_ENCODING)
+ .withDefault(new C2StreamPcmEncodingInfo::input(0u, C2Config::PCM_16))
+ .withFields({C2F(mPcmEncodingInfo, value).oneOf({
+ C2Config::PCM_16,
+ // C2Config::PCM_8,
+ C2Config::PCM_FLOAT})
+ })
+ .withSetter((Setter<decltype(*mPcmEncodingInfo)>::StrictValueWithNoDeps))
+ .build());
}
uint32_t getSampleRate() const { return mSampleRate->value; }
uint32_t getChannelCount() const { return mChannelCount->value; }
uint32_t getBitrate() const { return mBitrate->value; }
+ int32_t getPcmEncodingInfo() const { return mPcmEncodingInfo->value; }
private:
std::shared_ptr<C2StreamFormatConfig::input> mInputFormat;
@@ -87,6 +100,7 @@
std::shared_ptr<C2StreamChannelCountInfo::input> mChannelCount;
std::shared_ptr<C2BitrateTuning::output> mBitrate;
std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
+ std::shared_ptr<C2StreamPcmEncodingInfo::input> mPcmEncodingInfo;
};
constexpr char COMPONENT_NAME[] = "c2.android.flac.encoder";
@@ -224,12 +238,15 @@
mWroteHeader = true;
}
- uint32_t sampleRate = mIntf->getSampleRate();
- uint32_t channelCount = mIntf->getChannelCount();
- uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;
+ const uint32_t sampleRate = mIntf->getSampleRate();
+ const uint32_t channelCount = mIntf->getChannelCount();
+ const bool inputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
+ const unsigned sampleSize = inputFloat ? sizeof(float) : sizeof(int16_t);
+ const unsigned frameSize = channelCount * sampleSize;
+ const uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;
size_t outCapacity = inSize;
- outCapacity += mBlockSize * channelCount * sizeof(int16_t);
+ outCapacity += mBlockSize * frameSize;
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
c2_status_t err = pool->fetchLinearBlock(outCapacity, usage, &mOutputBlock);
@@ -250,14 +267,19 @@
size_t inPos = 0;
while (inPos < inSize) {
const uint8_t *inPtr = rView.data() + inOffset;
- size_t processSize = MIN(kInBlockSize * channelCount * sizeof(int16_t), (inSize - inPos));
- const unsigned nbInputFrames = processSize / (channelCount * sizeof(int16_t));
- const unsigned nbInputSamples = processSize / sizeof(int16_t);
- const int16_t *pcm16 = reinterpret_cast<const int16_t *>(inPtr + inPos);
- ALOGV("about to encode %zu bytes", processSize);
+ const size_t processSize = MIN(kInBlockSize * frameSize, (inSize - inPos));
+ const unsigned nbInputFrames = processSize / frameSize;
+ const unsigned nbInputSamples = processSize / sampleSize;
- for (unsigned i = 0; i < nbInputSamples; i++) {
- mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+ ALOGV("about to encode %zu bytes", processSize);
+ if (inputFloat) {
+ const float * const pcmFloat = reinterpret_cast<const float *>(inPtr + inPos);
+ memcpy_to_q8_23_from_float_with_clamp(mInputBufferPcm32, pcmFloat, nbInputSamples);
+ } else {
+ const int16_t * const pcm16 = reinterpret_cast<const int16_t *>(inPtr + inPos);
+ for (unsigned i = 0; i < nbInputSamples; i++) {
+ mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+ }
}
FLAC__bool ok = FLAC__stream_encoder_process_interleaved(
@@ -342,10 +364,12 @@
return UNKNOWN_ERROR;
}
+ const bool inputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
+ const int bitsPerSample = inputFloat ? 24 : 16;
FLAC__bool ok = true;
ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mIntf->getChannelCount());
ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mIntf->getSampleRate());
- ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, 16);
+ ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, bitsPerSample);
ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder, mCompressionLevel);
ok = ok && FLAC__stream_encoder_set_verify(mFlacStreamEncoder, false);
if (!ok) {
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index 590358c..6efbfee 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -872,7 +872,7 @@
ALOGV("readPage returned %zd", n);
- return n < 0 ? (media_status_t) n : AMEDIA_ERROR_END_OF_STREAM;
+ return n == ERROR_END_OF_STREAM ? AMEDIA_ERROR_END_OF_STREAM : AMEDIA_ERROR_UNKNOWN;
}
// Prevent a harmless unsigned integer overflow by clamping to 0
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index b5860de..0c6f8de 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -1544,7 +1544,7 @@
int VirtualizerIsConfigurationSupported(audio_channel_mask_t channelMask,
audio_devices_t deviceType) {
uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
- if (channelCount < 1 || channelCount > LVM_MAX_CHANNELS) {
+ if (channelCount < 1 || channelCount > FCC_2) { // TODO: update to 8 channels when supported.
return -EINVAL;
}
return VirtualizerIsDeviceSupported(deviceType);
diff --git a/media/libmedia/NdkWrapper.cpp b/media/libmedia/NdkWrapper.cpp
index 156991e..6dbc9b8 100644
--- a/media/libmedia/NdkWrapper.cpp
+++ b/media/libmedia/NdkWrapper.cpp
@@ -1249,7 +1249,11 @@
if (mAMediaExtractor == NULL) {
return NULL;
}
- return new AMediaCodecCryptoInfoWrapper(AMediaExtractor_getSampleCryptoInfo(mAMediaExtractor));
+ AMediaCodecCryptoInfo *cryptoInfo = AMediaExtractor_getSampleCryptoInfo(mAMediaExtractor);
+ if (cryptoInfo == NULL) {
+ return NULL;
+ }
+ return new AMediaCodecCryptoInfoWrapper(cryptoInfo);
}
AMediaDataSourceWrapper::AMediaDataSourceWrapper(const sp<DataSource> &dataSource)
diff --git a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
index b8d034b..78865c4 100644
--- a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
+++ b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
@@ -54,7 +54,7 @@
public:
~MediaPlayer2();
- static sp<MediaPlayer2> Create(int32_t sessionId);
+ static sp<MediaPlayer2> Create(int32_t sessionId, jobject context);
static status_t DumpAll(int fd, const Vector<String16>& args);
void disconnect();
@@ -117,7 +117,7 @@
status_t dump(int fd, const Vector<String16>& args);
private:
- MediaPlayer2(int32_t sessionId);
+ MediaPlayer2(int32_t sessionId, jobject context);
bool init();
// Disconnect from the currently connected ANativeWindow.
@@ -153,6 +153,7 @@
int mVideoHeight;
int32_t mAudioSessionId;
sp<JObjectHolder> mAudioAttributes;
+ sp<JObjectHolder> mContext;
float mSendLevel;
sp<ANativeWindowWrapper> mConnectedWindow;
};
diff --git a/media/libmediaplayer2/mediaplayer2.cpp b/media/libmediaplayer2/mediaplayer2.cpp
index e088a01..f75380c 100644
--- a/media/libmediaplayer2/mediaplayer2.cpp
+++ b/media/libmediaplayer2/mediaplayer2.cpp
@@ -211,8 +211,8 @@
} // anonymous namespace
//static
-sp<MediaPlayer2> MediaPlayer2::Create(int32_t sessionId) {
- sp<MediaPlayer2> player = new MediaPlayer2(sessionId);
+sp<MediaPlayer2> MediaPlayer2::Create(int32_t sessionId, jobject context) {
+ sp<MediaPlayer2> player = new MediaPlayer2(sessionId, context);
if (!player->init()) {
return NULL;
@@ -229,13 +229,14 @@
return dumpPlayers(fd, args);
}
-MediaPlayer2::MediaPlayer2(int32_t sessionId) {
+MediaPlayer2::MediaPlayer2(int32_t sessionId, jobject context) {
ALOGV("constructor");
mSrcId = 0;
mLockThreadId = 0;
mListener = NULL;
mStreamType = AUDIO_STREAM_MUSIC;
mAudioAttributes = NULL;
+ mContext = new JObjectHolder(context);
mCurrentPosition = -1;
mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
mSeekPosition = -1;
@@ -326,15 +327,15 @@
sp<MediaPlayer2Interface> oldPlayer;
- Mutex::Autolock _l(mLock);
{
+ Mutex::Autolock _l(mLock);
if (!((mCurrentState & MEDIA_PLAYER2_IDLE)
|| mCurrentState == MEDIA_PLAYER2_STATE_ERROR)) {
ALOGE("setDataSource called in wrong state %d", mCurrentState);
return INVALID_OPERATION;
}
- sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid);
+ sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid, mContext);
status_t err = player->initCheck();
if (err != NO_ERROR) {
ALOGE("Failed to create player object, initCheck failed(%d)", err);
diff --git a/media/libmediaplayer2/nuplayer2/JWakeLock.cpp b/media/libmediaplayer2/nuplayer2/JWakeLock.cpp
index c9a1071..983d77e 100644
--- a/media/libmediaplayer2/nuplayer2/JWakeLock.cpp
+++ b/media/libmediaplayer2/nuplayer2/JWakeLock.cpp
@@ -20,55 +20,50 @@
#include "JWakeLock.h"
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
#include <media/stagefright/foundation/ADebug.h>
-#include <powermanager/PowerManager.h>
-
namespace android {
-//TODO: use JAVA PowerManager, instead of binder
-JWakeLock::JWakeLock() :
- mPowerManager(NULL),
- mWakeLockToken(NULL),
+JWakeLock::JWakeLock(const sp<JObjectHolder> &context) :
mWakeLockCount(0),
- mDeathRecipient(new PMDeathRecipient(this)) {}
+ mWakeLock(NULL),
+ mContext(context) {}
JWakeLock::~JWakeLock() {
- if (mPowerManager != NULL) {
- sp<IBinder> binder = IInterface::asBinder(mPowerManager);
- binder->unlinkToDeath(mDeathRecipient);
- }
- clearPowerManager();
+ clearJavaWakeLock();
}
bool JWakeLock::acquire() {
if (mWakeLockCount == 0) {
- CHECK(mWakeLockToken == NULL);
- if (mPowerManager == NULL) {
- // use checkService() to avoid blocking if power service is not up yet
- sp<IBinder> binder =
- defaultServiceManager()->checkService(String16("power"));
- if (binder == NULL) {
- ALOGW("could not get the power manager service");
- } else {
- mPowerManager = interface_cast<IPowerManager>(binder);
- binder->linkToDeath(mDeathRecipient);
- }
+ if (mWakeLock == NULL) {
+ JNIEnv *env = JavaVMHelper::getJNIEnv();
+ jclass jContextCls = env->FindClass("android/content/Context");
+ jclass jPowerManagerCls = env->FindClass("android/os/PowerManager");
+
+ jmethodID jGetSystemService = env->GetMethodID(jContextCls,
+ "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
+ jobject javaPowerManagerObj = env->CallObjectMethod(mContext->getJObject(),
+ jGetSystemService, env->NewStringUTF("power"));
+
+ jfieldID jPARTIAL_WAKE_LOCK = env->GetStaticFieldID(jPowerManagerCls,
+ "PARTIAL_WAKE_LOCK", "I");
+ jint PARTIAL_WAKE_LOCK = env->GetStaticIntField(jPowerManagerCls, jPARTIAL_WAKE_LOCK);
+
+ jmethodID jNewWakeLock = env->GetMethodID(jPowerManagerCls,
+ "newWakeLock", "(ILjava/lang/String;)Landroid/os/PowerManager$WakeLock;");
+ jobject javaWakeLock = env->CallObjectMethod(javaPowerManagerObj,
+ jNewWakeLock, PARTIAL_WAKE_LOCK, env->NewStringUTF("JWakeLock"));
+ mWakeLock = new JObjectHolder(javaWakeLock);
+ env->DeleteLocalRef(javaPowerManagerObj);
+ env->DeleteLocalRef(javaWakeLock);
}
- if (mPowerManager != NULL) {
- sp<IBinder> binder = new BBinder();
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- status_t status = mPowerManager->acquireWakeLock(
- POWERMANAGER_PARTIAL_WAKE_LOCK,
- binder, String16("JWakeLock"), String16("media"));
- IPCThreadState::self()->restoreCallingIdentity(token);
- if (status == NO_ERROR) {
- mWakeLockToken = binder;
- mWakeLockCount++;
- return true;
- }
+ if (mWakeLock != NULL) {
+ JNIEnv *env = JavaVMHelper::getJNIEnv();
+ jclass wakeLockCls = env->FindClass("android/os/PowerManager$WakeLock");
+ jmethodID jAcquire = env->GetMethodID(wakeLockCls, "acquire", "()V");
+ env->CallVoidMethod(mWakeLock->getJObject(), jAcquire);
+ mWakeLockCount++;
+ return true;
}
} else {
mWakeLockCount++;
@@ -86,25 +81,17 @@
mWakeLockCount = 1;
}
if (--mWakeLockCount == 0) {
- CHECK(mWakeLockToken != NULL);
- if (mPowerManager != NULL) {
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- mPowerManager->releaseWakeLock(mWakeLockToken, 0 /* flags */);
- IPCThreadState::self()->restoreCallingIdentity(token);
+ if (mWakeLock != NULL) {
+ JNIEnv *env = JavaVMHelper::getJNIEnv();
+ jclass wakeLockCls = env->FindClass("android/os/PowerManager$WakeLock");
+ jmethodID jRelease = env->GetMethodID(wakeLockCls, "release", "()V");
+ env->CallVoidMethod(mWakeLock->getJObject(), jRelease);
}
- mWakeLockToken.clear();
}
}
-void JWakeLock::clearPowerManager() {
+void JWakeLock::clearJavaWakeLock() {
release(true);
- mPowerManager.clear();
-}
-
-void JWakeLock::PMDeathRecipient::binderDied(const wp<IBinder>& who __unused) {
- if (mWakeLock != NULL) {
- mWakeLock->clearPowerManager();
- }
}
} // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/JWakeLock.h b/media/libmediaplayer2/nuplayer2/JWakeLock.h
index eace87e..36c542e 100644
--- a/media/libmediaplayer2/nuplayer2/JWakeLock.h
+++ b/media/libmediaplayer2/nuplayer2/JWakeLock.h
@@ -18,7 +18,7 @@
#define J_WAKELOCK_H_
#include <media/stagefright/foundation/ABase.h>
-#include <powermanager/IPowerManager.h>
+#include <mediaplayer2/JObjectHolder.h>
#include <utils/RefBase.h>
namespace android {
@@ -26,7 +26,7 @@
class JWakeLock : public RefBase {
public:
- JWakeLock();
+ JWakeLock(const sp<JObjectHolder> &context);
// NOTE: acquire and release are not thread safe
@@ -37,28 +37,11 @@
virtual ~JWakeLock();
private:
- sp<IPowerManager> mPowerManager;
- sp<IBinder> mWakeLockToken;
- uint32_t mWakeLockCount;
+ uint32_t mWakeLockCount;
+ sp<JObjectHolder> mWakeLock;
+ const sp<JObjectHolder> mContext;
- class PMDeathRecipient : public IBinder::DeathRecipient {
- public:
- explicit PMDeathRecipient(JWakeLock *wakeLock) : mWakeLock(wakeLock) {}
- virtual ~PMDeathRecipient() {}
-
- // IBinder::DeathRecipient
- virtual void binderDied(const wp<IBinder> &who);
-
- private:
- PMDeathRecipient(const PMDeathRecipient&);
- PMDeathRecipient& operator= (const PMDeathRecipient&);
-
- JWakeLock *mWakeLock;
- };
-
- const sp<PMDeathRecipient> mDeathRecipient;
-
- void clearPowerManager();
+ void clearJavaWakeLock();
DISALLOW_EVIL_CONSTRUCTORS(JWakeLock);
};
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
index 080d923..5da6e24 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
@@ -209,7 +209,8 @@
////////////////////////////////////////////////////////////////////////////////
-NuPlayer2::NuPlayer2(pid_t pid, uid_t uid, const sp<MediaClock> &mediaClock)
+NuPlayer2::NuPlayer2(
+ pid_t pid, uid_t uid, const sp<MediaClock> &mediaClock, const sp<JObjectHolder> &context)
: mPID(pid),
mUID(uid),
mMediaClock(mediaClock),
@@ -240,7 +241,8 @@
mVideoDecoderError(false),
mPaused(false),
mPausedByClient(true),
- mPausedForBuffering(false) {
+ mPausedForBuffering(false),
+ mContext(context) {
CHECK(mediaClock != NULL);
clearFlushComplete();
}
@@ -1738,7 +1740,7 @@
sp<AMessage> notify = new AMessage(kWhatRendererNotify, this);
++mRendererGeneration;
notify->setInt32("generation", mRendererGeneration);
- mRenderer = new Renderer(mAudioSink, mMediaClock, notify, flags);
+ mRenderer = new Renderer(mAudioSink, mMediaClock, notify, mContext, flags);
mRendererLooper = new ALooper;
mRendererLooper->setName("NuPlayer2Renderer");
mRendererLooper->start(false, true, ANDROID_PRIORITY_AUDIO);
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.h b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
index fdc128f..798c725 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
@@ -22,6 +22,7 @@
#include <media/stagefright/foundation/AHandler.h>
#include <mediaplayer2/MediaPlayer2Interface.h>
+#include <mediaplayer2/JObjectHolder.h>
#include "mediaplayer2.pb.h"
@@ -42,7 +43,8 @@
struct NuPlayer2Driver;
struct NuPlayer2 : public AHandler {
- explicit NuPlayer2(pid_t pid, uid_t uid, const sp<MediaClock> &mediaClock);
+ explicit NuPlayer2(pid_t pid, uid_t uid,
+ const sp<MediaClock> &mediaClock, const sp<JObjectHolder> &context);
void setDriver(const wp<NuPlayer2Driver> &driver);
@@ -272,6 +274,9 @@
// Pause state as requested by source (internally) due to buffering
bool mPausedForBuffering;
+ // Passed from JAVA
+ const sp<JObjectHolder> mContext;
+
inline const sp<DecoderBase> &getDecoder(bool audio) {
return audio ? mAudioDecoder : mVideoDecoder;
}
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
index 3c11b17..56e9471 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
@@ -108,7 +108,7 @@
static const char *kPlayerRebufferingAtExit = "android.media.mediaplayer.rebufferExit";
-NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid)
+NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid, const sp<JObjectHolder> &context)
: mState(STATE_IDLE),
mAsyncResult(UNKNOWN_ERROR),
mSrcId(0),
@@ -123,7 +123,7 @@
mLooper(new ALooper),
mNuPlayer2Looper(new ALooper),
mMediaClock(new MediaClock),
- mPlayer(new NuPlayer2(pid, uid, mMediaClock)),
+ mPlayer(new NuPlayer2(pid, uid, mMediaClock, context)),
mPlayerFlags(0),
mAnalyticsItem(NULL),
mClientUid(uid),
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
index fe17d03..0ec3a4b 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
@@ -18,6 +18,7 @@
#include <media/MediaAnalyticsItem.h>
#include <media/stagefright/foundation/ABase.h>
+#include <mediaplayer2/JObjectHolder.h>
namespace android {
@@ -26,7 +27,7 @@
struct NuPlayer2;
struct NuPlayer2Driver : public MediaPlayer2Interface {
- explicit NuPlayer2Driver(pid_t pid, uid_t uid);
+ explicit NuPlayer2Driver(pid_t pid, uid_t uid, const sp<JObjectHolder> &context);
virtual status_t initCheck() override;
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
index 2881fd4..3be7e36 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
@@ -106,6 +106,7 @@
const sp<MediaPlayer2Interface::AudioSink> &sink,
const sp<MediaClock> &mediaClock,
const sp<AMessage> ¬ify,
+ const sp<JObjectHolder> &context,
uint32_t flags)
: mAudioSink(sink),
mUseVirtualAudioSink(false),
@@ -147,7 +148,7 @@
mTotalBuffersQueued(0),
mLastAudioBufferDrained(0),
mUseAudioCallback(false),
- mWakeLock(new JWakeLock()) {
+ mWakeLock(new JWakeLock(context)) {
CHECK(mediaClock != NULL);
mMediaClock->setPlaybackRate(mPlaybackSettings.mSpeed);
}
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
index 484d9b7..d065dee 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
@@ -20,6 +20,7 @@
#include <media/AudioResamplerPublic.h>
#include <media/AVSyncSettings.h>
+#include <mediaplayer2/JObjectHolder.h>
#include "NuPlayer2.h"
@@ -38,6 +39,7 @@
Renderer(const sp<MediaPlayer2Interface::AudioSink> &sink,
const sp<MediaClock> &mediaClock,
const sp<AMessage> ¬ify,
+ const sp<JObjectHolder> &context,
uint32_t flags = 0);
static size_t AudioSinkCallback(
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index e2aa8f8..1e85804 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -171,6 +171,7 @@
if (extractor == NULL) {
ALOGE("initFromDataSource, cannot create extractor!");
+ mLock.lock();
return UNKNOWN_ERROR;
}
@@ -179,6 +180,7 @@
size_t numtracks = extractor->countTracks();
if (numtracks == 0) {
ALOGE("initFromDataSource, source has no track!");
+ mLock.lock();
return UNKNOWN_ERROR;
}
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index ceb8a13..2ea5286 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -2183,7 +2183,8 @@
err = setupG711Codec(encoder, sampleRate, numChannels);
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
- int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1;
+ // numChannels needs to be set to properly communicate PCM values.
+ int32_t numChannels = 2, sampleRate = 44100, compressionLevel = -1;
if (encoder &&
(!msg->findInt32("channel-count", &numChannels)
|| !msg->findInt32("sample-rate", &sampleRate))) {
@@ -2209,7 +2210,7 @@
}
}
err = setupFlacCodec(
- encoder, numChannels, sampleRate, compressionLevel);
+ encoder, numChannels, sampleRate, compressionLevel, pcmEncoding);
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
int32_t numChannels, sampleRate;
@@ -3033,8 +3034,8 @@
}
status_t ACodec::setupFlacCodec(
- bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
-
+ bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel,
+ AudioEncoding encoding) {
if (encoder) {
OMX_AUDIO_PARAM_FLACTYPE def;
InitOMXParams(&def);
@@ -3057,7 +3058,8 @@
return setupRawAudioFormat(
encoder ? kPortIndexInput : kPortIndexOutput,
sampleRate,
- numChannels);
+ numChannels,
+ encoding);
}
status_t ACodec::setupRawAudioFormat(
@@ -3115,6 +3117,7 @@
pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
+ ALOGE("%s: incorrect numChannels: %d", __func__, numChannels);
return OMX_ErrorNone;
}
diff --git a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
index 4db0060..842a7ce 100644
--- a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
+++ b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
@@ -89,12 +89,12 @@
def.eDir = OMX_DirOutput;
def.nBufferCountMin = kNumOutputBuffers;
def.nBufferCountActual = def.nBufferCountMin;
- def.nBufferSize = 4096 * FLACDecoder::kMaxChannels;
+ def.nBufferSize = kNumSamplesPerFrame * FLACDecoder::kMaxChannels * sizeof(float);
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
def.bBuffersContiguous = OMX_FALSE;
- def.nBufferAlignment = 2;
+ def.nBufferAlignment = sizeof(float);
def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
def.format.audio.pNativeRender = NULL;
@@ -173,7 +173,7 @@
flacParams->nChannels = mStreamInfo.channels;
flacParams->nSampleRate = mStreamInfo.sample_rate;
} else {
- flacParams->nChannels = 1;
+ flacParams->nChannels = 2;
flacParams->nSampleRate = 44100;
}
@@ -195,10 +195,10 @@
return OMX_ErrorBadPortIndex;
}
- pcmParams->eNumData = OMX_NumericalDataSigned;
+ pcmParams->eNumData = mNumericalData;
pcmParams->eEndian = OMX_EndianBig;
pcmParams->bInterleaved = OMX_TRUE;
- pcmParams->nBitPerSample = 16;
+ pcmParams->nBitPerSample = mBitsPerSample;
pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
@@ -211,7 +211,7 @@
pcmParams->nChannels = mStreamInfo.channels;
pcmParams->nSamplingRate = mStreamInfo.sample_rate;
} else {
- pcmParams->nChannels = 1;
+ pcmParams->nChannels = 2;
pcmParams->nSamplingRate = 44100;
}
@@ -281,6 +281,19 @@
return OMX_ErrorBadPortIndex;
}
+ if (pcmParams->eNumData == OMX_NumericalDataFloat && pcmParams->nBitPerSample == 32) {
+ mNumericalData = OMX_NumericalDataFloat;
+ mBitsPerSample = 32;
+ } else if (pcmParams->eNumData == OMX_NumericalDataSigned
+ && pcmParams->nBitPerSample == 16) {
+ mNumericalData = OMX_NumericalDataSigned;
+ mBitsPerSample = 16;
+ } else {
+ ALOGE("Invalid eNumData %d, nBitsPerSample %d",
+ pcmParams->eNumData, pcmParams->nBitPerSample);
+ return OMX_ErrorUndefined;
+ }
+
return OMX_ErrorNone;
}
@@ -301,11 +314,13 @@
List<BufferInfo *> &inQueue = getPortQueue(0);
List<BufferInfo *> &outQueue = getPortQueue(1);
+ const bool outputFloat = mNumericalData == OMX_NumericalDataFloat;
+
ALOGV("onQueueFilled %d/%d:", inQueue.empty(), outQueue.empty());
while ((!inQueue.empty() || mSawInputEOS) && !outQueue.empty() && !mFinishedDecoder) {
BufferInfo *outInfo = *outQueue.begin();
OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
- int16_t *outBuffer = reinterpret_cast<int16_t *>(outHeader->pBuffer + outHeader->nOffset);
+ void *outBuffer = reinterpret_cast<void *>(outHeader->pBuffer + outHeader->nOffset);
size_t outBufferSize = outHeader->nAllocLen - outHeader->nOffset;
int64_t timeStamp = 0;
@@ -374,7 +389,7 @@
}
status_t decoderErr = mFLACDecoder->decodeOneFrame(
- inBuffer, inBufferLength, outBuffer, &outBufferSize);
+ inBuffer, inBufferLength, outBuffer, &outBufferSize, outputFloat);
if (decoderErr != OK) {
ALOGE("onQueueFilled: FLACDecoder decodeOneFrame returns error %d", decoderErr);
mSignalledError = true;
@@ -393,7 +408,9 @@
continue;
}
} else if (mSawInputEOS) {
- status_t decoderErr = mFLACDecoder->decodeOneFrame(NULL, 0, outBuffer, &outBufferSize);
+ status_t decoderErr = mFLACDecoder->decodeOneFrame(
+ nullptr /* inBuffer */, 0 /* inBufferLen */,
+ outBuffer, &outBufferSize, outputFloat);
mFinishedDecoder = true;
if (decoderErr != OK) {
ALOGE("onQueueFilled: FLACDecoder finish returns error %d", decoderErr);
@@ -456,7 +473,8 @@
mOutputPortSettingsChange = AWAITING_ENABLED;
PortInfo *info = editPortInfo(1 /* portIndex */);
if (!info->mDef.bEnabled) {
- info->mDef.nBufferSize = mStreamInfo.max_blocksize * mStreamInfo.channels * 2;
+ info->mDef.nBufferSize =
+ mStreamInfo.max_blocksize * mStreamInfo.channels * sizeof(float);
}
break;
}
diff --git a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h
index b63f7ad..ba02074 100644
--- a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h
+++ b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h
@@ -45,10 +45,14 @@
virtual void onReset() override;
private:
+ static constexpr unsigned int kNumSamplesPerFrame = 2048; // adjusted based on stream.
+
enum {
kNumInputBuffers = 4,
kNumOutputBuffers = 4,
};
+ OMX_NUMERICALDATATYPE mNumericalData = OMX_NumericalDataSigned;
+ OMX_U32 mBitsPerSample = 16;
FLACDecoder *mFLACDecoder;
FLAC__StreamMetadata_StreamInfo mStreamInfo;
diff --git a/media/libstagefright/codecs/flac/enc/Android.bp b/media/libstagefright/codecs/flac/enc/Android.bp
index 9b696da..b32ab08 100644
--- a/media/libstagefright/codecs/flac/enc/Android.bp
+++ b/media/libstagefright/codecs/flac/enc/Android.bp
@@ -28,7 +28,10 @@
],
header_libs: ["libbase_headers"],
- static_libs: ["libFLAC"],
+ static_libs: [
+ "libaudioutils",
+ "libFLAC",
+ ],
name: "libstagefright_soft_flacenc",
vendor_available: true,
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
index 955f211..3add006 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
@@ -20,7 +20,7 @@
#include <utils/Log.h>
#include "SoftFlacEncoder.h"
-
+#include <audio_utils/primitives.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaDefs.h>
@@ -75,7 +75,9 @@
}
if (!mSignalledError) { // no use allocating input buffer if we had an error above
- mInputBufferPcm32 = (FLAC__int32*) malloc(sizeof(FLAC__int32) * 2 * kMaxNumSamplesPerFrame);
+ // 2x the pcm16 samples can exist with the same size as pcmFloat samples.
+ mInputBufferPcm32 = (FLAC__int32*) malloc(
+ sizeof(FLAC__int32) * kNumSamplesPerFrame * kMaxChannels * 2);
if (mInputBufferPcm32 == NULL) {
ALOGE("SoftFlacEncoder::SoftFlacEncoder(name=%s) error allocating internal input buffer", name);
mSignalledError = true;
@@ -115,14 +117,14 @@
// configure input port of the encoder
def.nPortIndex = 0;
def.eDir = OMX_DirInput;
- def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
+ def.nBufferCountMin = kNumBuffers;
def.nBufferCountActual = def.nBufferCountMin;
def.nBufferSize = kMaxInputBufferSize;
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
def.bBuffersContiguous = OMX_FALSE;
- def.nBufferAlignment = 2;
+ def.nBufferAlignment = sizeof(float);
def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
def.format.audio.pNativeRender = NULL;
@@ -134,7 +136,7 @@
// configure output port of the encoder
def.nPortIndex = 1;
def.eDir = OMX_DirOutput;
- def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
+ def.nBufferCountMin = kNumBuffers;
def.nBufferCountActual = def.nBufferCountMin;
def.nBufferSize = kMaxOutputBufferSize;
def.bEnabled = OMX_TRUE;
@@ -193,10 +195,10 @@
return OMX_ErrorUndefined;
}
- pcmParams->eNumData = OMX_NumericalDataSigned;
+ pcmParams->eNumData = mNumericalData;
pcmParams->eEndian = OMX_EndianBig;
pcmParams->bInterleaved = OMX_TRUE;
- pcmParams->nBitPerSample = 16;
+ pcmParams->nBitPerSample = mBitsPerSample;
pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
@@ -270,12 +272,26 @@
return OMX_ErrorUndefined;
}
- if (pcmParams->nChannels < 1 || pcmParams->nChannels > 2) {
+ if (pcmParams->nChannels < 1 || pcmParams->nChannels > kMaxChannels) {
return OMX_ErrorUndefined;
}
mNumChannels = pcmParams->nChannels;
mSampleRate = pcmParams->nSamplingRate;
+
+ if (pcmParams->eNumData == OMX_NumericalDataFloat && pcmParams->nBitPerSample == 32) {
+ mNumericalData = OMX_NumericalDataFloat;
+ mBitsPerSample = 32;
+ } else if (pcmParams->eNumData == OMX_NumericalDataSigned
+ && pcmParams->nBitPerSample == 16) {
+ mNumericalData = OMX_NumericalDataSigned;
+ mBitsPerSample = 16;
+ } else {
+ ALOGE("%s: invalid eNumData %d, nBitsPerSample %d",
+ __func__, pcmParams->eNumData, pcmParams->nBitPerSample);
+ return OMX_ErrorUndefined;
+ }
+
ALOGV("will encode %d channels at %dHz", mNumChannels, mSampleRate);
return configureEncoder();
@@ -356,6 +372,10 @@
List<BufferInfo *> &inQueue = getPortQueue(0);
List<BufferInfo *> &outQueue = getPortQueue(1);
+ const bool inputFloat = mNumericalData == OMX_NumericalDataFloat;
+ const size_t sampleSize = inputFloat ? sizeof(float) : sizeof(int16_t);
+ const size_t frameSize = sampleSize * mNumChannels;
+
FLAC__bool ok = true;
while ((!inQueue.empty() || mSawInputEOS) && !outQueue.empty() && !mSentOutputEOS) {
@@ -381,13 +401,21 @@
mEncoderReturnedNbBytes = 0;
mCurrentInputTimeStamp = inHeader->nTimeStamp;
- const unsigned nbInputFrames = inHeader->nFilledLen / (2 * mNumChannels);
- const unsigned nbInputSamples = inHeader->nFilledLen / 2;
- const OMX_S16 * const pcm16 = reinterpret_cast<OMX_S16 *>(inHeader->pBuffer);
+ const unsigned nbInputFrames = inHeader->nFilledLen / frameSize;
+ const unsigned nbInputSamples = inHeader->nFilledLen / sampleSize;
- CHECK_LE(nbInputSamples, 2 * kMaxNumSamplesPerFrame);
- for (unsigned i=0 ; i < nbInputSamples ; i++) {
- mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+ if (inputFloat) {
+ CHECK_LE(nbInputSamples, kNumSamplesPerFrame * kMaxChannels);
+ const float * const pcmFloat = reinterpret_cast<float *>(inHeader->pBuffer);
+ memcpy_to_q8_23_from_float_with_clamp(
+ mInputBufferPcm32, pcmFloat, nbInputSamples);
+ } else {
+ // note nbInputSamples may be 2x as large for pcm16 data.
+ CHECK_LE(nbInputSamples, kNumSamplesPerFrame * kMaxChannels * 2);
+ const int16_t * const pcm16 = reinterpret_cast<int16_t *>(inHeader->pBuffer);
+ for (unsigned i = 0; i < nbInputSamples; ++i) {
+ mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+ }
}
ALOGV(" about to encode %u samples per channel", nbInputFrames);
ok = FLAC__stream_encoder_process_interleaved(
@@ -526,10 +554,12 @@
return OMX_ErrorInvalidState;
}
+ const bool inputFloat = mNumericalData == OMX_NumericalDataFloat;
+ const int codecBitsPerSample = inputFloat ? 24 : 16;
FLAC__bool ok = true;
ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mNumChannels);
ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mSampleRate);
- ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, 16);
+ ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, codecBitsPerSample);
ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder,
(unsigned)mCompressionLevel);
ok = ok && FLAC__stream_encoder_set_verify(mFlacStreamEncoder, false);
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
index 64a6b1e..722fc13 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
@@ -45,8 +45,10 @@
private:
const unsigned int kNumBuffers = 2;
- const unsigned int kMaxNumSamplesPerFrame = 1152;
- const unsigned int kMaxInputBufferSize = kMaxNumSamplesPerFrame * sizeof(int16_t) * 2;
+ static constexpr unsigned int kMaxChannels = 2;
+ static constexpr unsigned int kNumSamplesPerFrame = 1152;
+ static constexpr unsigned int kMaxInputBufferSize =
+ kNumSamplesPerFrame * kMaxChannels * sizeof(float);
const unsigned int kMaxOutputBufferSize = 65536; //TODO check if this can be reduced
bool mSignalledError;
@@ -54,6 +56,8 @@
OMX_U32 mNumChannels;
OMX_U32 mSampleRate;
OMX_U32 mCompressionLevel;
+ OMX_NUMERICALDATATYPE mNumericalData = OMX_NumericalDataSigned;
+ OMX_U32 mBitsPerSample = 16;
// should the data received by the callback be written to the output port
bool mEncoderWriteData;
diff --git a/media/libstagefright/flac/dec/Android.bp b/media/libstagefright/flac/dec/Android.bp
index 751b053..307c9b0 100644
--- a/media/libstagefright/flac/dec/Android.bp
+++ b/media/libstagefright/flac/dec/Android.bp
@@ -27,11 +27,17 @@
},
static: {
- whole_static_libs: ["libFLAC"],
+ whole_static_libs: [
+ "libFLAC",
+ "libaudioutils",
+ ],
},
shared: {
- static_libs: ["libFLAC"],
+ static_libs: [
+ "libFLAC",
+ "libaudioutils",
+ ],
},
shared_libs: [
diff --git a/media/libstagefright/flac/dec/FLACDecoder.cpp b/media/libstagefright/flac/dec/FLACDecoder.cpp
index dfdc41c..cef0bc6 100644
--- a/media/libstagefright/flac/dec/FLACDecoder.cpp
+++ b/media/libstagefright/flac/dec/FLACDecoder.cpp
@@ -20,6 +20,7 @@
#include "FLACDecoder.h"
+#include <audio_utils/primitives.h> // float_from_i32
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MediaDefs.h>
@@ -117,104 +118,43 @@
mErrorStatus = status;
}
-// Copy samples from FLAC native 32-bit non-interleaved to 16-bit interleaved.
+// Copy samples from FLAC native 32-bit non-interleaved to 16-bit signed
+// or 32-bit float interleaved.
+// TODO: Consider moving to audio_utils. See similar code at FLACExtractor.cpp
// These are candidates for optimization if needed.
-static void copyMono8(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
+static void copyTo16Signed(
+ short *dst,
+ const int *const *src,
unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i] << 8;
- }
-}
-
-static void copyStereo8(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i] << 8;
- *dst++ = src[1][i] << 8;
- }
-}
-
-static void copyMultiCh8(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned nChannels) {
- for (unsigned i = 0; i < nSamples; ++i) {
- for (unsigned c = 0; c < nChannels; ++c) {
- *dst++ = src[c][i] << 8;
+ unsigned nChannels,
+ unsigned bitsPerSample) {
+ const int leftShift = 16 - (int)bitsPerSample; // cast to int to prevent unsigned overflow.
+ if (leftShift >= 0) {
+ for (unsigned i = 0; i < nSamples; ++i) {
+ for (unsigned c = 0; c < nChannels; ++c) {
+ *dst++ = src[c][i] << leftShift;
+ }
+ }
+ } else {
+ const int rightShift = -leftShift;
+ for (unsigned i = 0; i < nSamples; ++i) {
+ for (unsigned c = 0; c < nChannels; ++c) {
+ *dst++ = src[c][i] >> rightShift;
+ }
}
}
}
-static void copyMono16(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
+static void copyToFloat(
+ float *dst,
+ const int *const *src,
unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i];
- }
-}
-
-static void copyStereo16(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i];
- *dst++ = src[1][i];
- }
-}
-
-static void copyMultiCh16(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned nChannels) {
+ unsigned nChannels,
+ unsigned bitsPerSample) {
+ const unsigned leftShift = 32 - bitsPerSample;
for (unsigned i = 0; i < nSamples; ++i) {
for (unsigned c = 0; c < nChannels; ++c) {
- *dst++ = src[c][i];
- }
- }
-}
-
-// TODO: 24-bit versions should do dithering or noise-shaping, here or in AudioFlinger
-static void copyMono24(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i] >> 8;
- }
-}
-
-static void copyStereo24(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i] >> 8;
- *dst++ = src[1][i] >> 8;
- }
-}
-
-static void copyMultiCh24(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned nChannels) {
- for (unsigned i = 0; i < nSamples; ++i) {
- for (unsigned c = 0; c < nChannels; ++c) {
- *dst++ = src[c][i] >> 8;
+ *dst++ = float_from_i32(src[c][i] << leftShift);
}
}
}
@@ -238,8 +178,7 @@
mStreamInfoValid(false),
mWriteRequested(false),
mWriteCompleted(false),
- mErrorStatus((FLAC__StreamDecoderErrorStatus) -1),
- mCopy(nullptr) {
+ mErrorStatus((FLAC__StreamDecoderErrorStatus) -1) {
ALOGV("ctor:");
memset(&mStreamInfo, 0, sizeof(mStreamInfo));
memset(&mWriteHeader, 0, sizeof(mWriteHeader));
@@ -379,6 +318,7 @@
case 8:
case 16:
case 24:
+ case 32: // generally rare, but is supported in the framework
break;
default:
@@ -387,31 +327,6 @@
return ERROR_MALFORMED;
}
- // configure the appropriate copy function, defaulting to trespass
- static const struct {
- unsigned mChannels;
- unsigned mBitsPerSample;
- void (*mCopy)(int16_t *dst, const int * src[kMaxChannels],
- unsigned nSamples, unsigned nChannels);
- } table[] = {
- { 1, 8, copyMono8 },
- { 2, 8, copyStereo8 },
- { 8, 8, copyMultiCh8 },
- { 1, 16, copyMono16 },
- { 2, 16, copyStereo16 },
- { 8, 16, copyMultiCh16 },
- { 1, 24, copyMono24 },
- { 2, 24, copyStereo24 },
- { 8, 24, copyMultiCh24 },
- };
- for (const auto &entry : table) {
- if (entry.mChannels >= getChannels() &&
- entry.mBitsPerSample == getBitsPerSample()) {
- mCopy = entry.mCopy;
- break;
- }
- }
-
// Now we have all metadata blocks.
mBufferPos = 0;
mBufferDataSize = 0;
@@ -420,7 +335,7 @@
}
status_t FLACDecoder::decodeOneFrame(const uint8_t *inBuffer, size_t inBufferLen,
- int16_t *outBuffer, size_t *outBufferLen) {
+ void *outBuffer, size_t *outBufferLen, bool outputFloat) {
ALOGV("decodeOneFrame: input size(%zu)", inBufferLen);
if (!mStreamInfoValid) {
@@ -469,21 +384,33 @@
return ERROR_MALFORMED;
}
- size_t bufferSize = blocksize * getChannels() * sizeof(int16_t);
+ const unsigned channels = getChannels();
+ const size_t sampleSize = outputFloat ? sizeof(float) : sizeof(int16_t);
+ const size_t frameSize = channels * sampleSize;
+ size_t bufferSize = blocksize * frameSize;
if (bufferSize > *outBufferLen) {
ALOGW("decodeOneFrame: output buffer holds only partial frame %zu:%zu",
*outBufferLen, bufferSize);
- blocksize = *outBufferLen / (getChannels() * sizeof(int16_t));
- bufferSize = blocksize * getChannels() * sizeof(int16_t);
+ blocksize = *outBufferLen / frameSize;
+ bufferSize = blocksize * frameSize;
}
- if (mCopy == nullptr) {
- ALOGE("decodeOneFrame: format is not supported: channels(%d), BitsPerSample(%d)",
- getChannels(), getBitsPerSample());
- return ERROR_UNSUPPORTED;
- }
// copy PCM from FLAC write buffer to output buffer, with interleaving
- (*mCopy)(outBuffer, mWriteBuffer, blocksize, getChannels());
+
+ const unsigned bitsPerSample = getBitsPerSample();
+ if (outputFloat) {
+ copyToFloat(reinterpret_cast<float*>(outBuffer),
+ mWriteBuffer,
+ blocksize,
+ channels,
+ bitsPerSample);
+ } else {
+ copyTo16Signed(reinterpret_cast<short*>(outBuffer),
+ mWriteBuffer,
+ blocksize,
+ channels,
+ bitsPerSample);
+ }
*outBufferLen = bufferSize;
return OK;
}
diff --git a/media/libstagefright/flac/dec/FLACDecoder.h b/media/libstagefright/flac/dec/FLACDecoder.h
index af419a2..694fccb 100644
--- a/media/libstagefright/flac/dec/FLACDecoder.h
+++ b/media/libstagefright/flac/dec/FLACDecoder.h
@@ -41,7 +41,7 @@
status_t parseMetadata(const uint8_t *inBuffer, size_t inBufferLen);
status_t decodeOneFrame(const uint8_t *inBuffer, size_t inBufferLen,
- int16_t *outBuffer, size_t *outBufferLen);
+ void *outBuffer, size_t *outBufferLen, bool outputFloat = false);
void flush();
virtual ~FLACDecoder();
@@ -89,8 +89,6 @@
// most recent error reported by libFLAC decoder
FLAC__StreamDecoderErrorStatus mErrorStatus;
- void (*mCopy)(int16_t *dst, const int *src[kMaxChannels], unsigned nSamples, unsigned nChannels);
-
status_t init();
// FLAC stream decoder callbacks as C++ instance methods
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 9b2853e..9d46d2d 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -488,7 +488,8 @@
status_t setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels);
status_t setupFlacCodec(
- bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel);
+ bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel,
+ AudioEncoding encoding);
status_t setupRawAudioFormat(
OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels,
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index d0b4973..e5ebab7 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -24,7 +24,6 @@
shared_libs: [
"libcutils",
"libhidlbase",
- "libicuuc",
"liblog",
"libmedia",
"libutils",
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 025f0b2..851dd69 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -83,6 +83,7 @@
"libhidltransport",
"libjpeg",
"libmemunreachable",
+ "libsensorprivacy",
"libstagefright_foundation",
"android.frameworks.cameraservice.common@2.0",
"android.frameworks.cameraservice.service@2.0",
@@ -100,6 +101,7 @@
"libbinder",
"libcamera_client",
"libfmq",
+ "libsensorprivacy",
],
include_dirs: [
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 6003607..c3113bf 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -54,6 +54,7 @@
#include <media/IMediaHTTPService.h>
#include <media/mediaplayer.h>
#include <mediautils/BatteryNotifier.h>
+#include <sensorprivacy/SensorPrivacyManager.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/String16.h>
@@ -145,6 +146,8 @@
mUidPolicy = new UidPolicy(this);
mUidPolicy->registerSelf();
+ mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
+ mSensorPrivacyPolicy->registerSelf();
sp<HidlCameraService> hcs = HidlCameraService::getInstance(this);
if (hcs->registerAsService() != android::OK) {
ALOGE("%s: Failed to register default android.frameworks.cameraservice.service@1.0",
@@ -230,6 +233,7 @@
CameraService::~CameraService() {
VendorTagDescriptor::clearGlobalVendorTagDescriptor();
mUidPolicy->unregisterSelf();
+ mSensorPrivacyPolicy->unregisterSelf();
}
void CameraService::onNewProviderRegistered() {
@@ -951,6 +955,14 @@
clientName8.string(), clientUid, clientPid, cameraId.string());
}
+ // If sensor privacy is enabled then prevent access to the camera
+ if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
+ ALOGE("Access Denial: cannot use the camera when sensor privacy is enabled");
+ return STATUS_ERROR_FMT(ERROR_DISABLED,
+ "Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" when sensor privacy "
+ "is enabled", clientName8.string(), clientUid, clientPid, cameraId.string());
+ }
+
// Only use passed in clientPid to check permission. Use calling PID as the client PID that's
// connected to camera service directly.
originalClientPid = clientPid;
@@ -1603,9 +1615,10 @@
switch(eventId) {
case ICameraService::EVENT_USER_SWITCHED: {
- // Try to register for UID policy updates, in case we're recovering
+ // Try to register for UID and sensor privacy policy updates, in case we're recovering
// from a system server crash
mUidPolicy->registerSelf();
+ mSensorPrivacyPolicy->registerSelf();
doUserSwitch(/*newUserIds*/ args);
break;
}
@@ -2577,6 +2590,59 @@
}
// ----------------------------------------------------------------------------
+// SensorPrivacyPolicy
+// ----------------------------------------------------------------------------
+void CameraService::SensorPrivacyPolicy::registerSelf() {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+ if (mRegistered) {
+ return;
+ }
+ SensorPrivacyManager spm;
+ spm.addSensorPrivacyListener(this);
+ mSensorPrivacyEnabled = spm.isSensorPrivacyEnabled();
+ status_t res = spm.linkToDeath(this);
+ if (res == OK) {
+ mRegistered = true;
+ ALOGV("SensorPrivacyPolicy: Registered with SensorPrivacyManager");
+ }
+}
+
+void CameraService::SensorPrivacyPolicy::unregisterSelf() {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+ SensorPrivacyManager spm;
+ spm.removeSensorPrivacyListener(this);
+ spm.unlinkToDeath(this);
+ mRegistered = false;
+ ALOGV("SensorPrivacyPolicy: Unregistered with SensorPrivacyManager");
+}
+
+bool CameraService::SensorPrivacyPolicy::isSensorPrivacyEnabled() {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+ return mSensorPrivacyEnabled;
+}
+
+binder::Status CameraService::SensorPrivacyPolicy::onSensorPrivacyChanged(bool enabled) {
+ {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+ mSensorPrivacyEnabled = enabled;
+ }
+ // if sensor privacy is enabled then block all clients from accessing the camera
+ if (enabled) {
+ sp<CameraService> service = mService.promote();
+ if (service != nullptr) {
+ service->blockAllClients();
+ }
+ }
+ return binder::Status::ok();
+}
+
+void CameraService::SensorPrivacyPolicy::binderDied(const wp<IBinder>& /*who*/) {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+ ALOGV("SensorPrivacyPolicy: SensorPrivacyManager has died");
+ mRegistered = false;
+}
+
+// ----------------------------------------------------------------------------
// CameraState
// ----------------------------------------------------------------------------
@@ -3062,6 +3128,18 @@
}
}
+void CameraService::blockAllClients() {
+ const auto clients = mActiveClientManager.getAll();
+ for (auto& current : clients) {
+ if (current != nullptr) {
+ const auto basicClient = current->getValue();
+ if (basicClient.get() != nullptr) {
+ basicClient->block();
+ }
+ }
+ }
+}
+
// NOTE: This is a remote API - make sure all args are validated
status_t CameraService::shellCommand(int in, int out, int err, const Vector<String16>& args) {
if (!checkCallingPermission(sManageCameraPermission, nullptr, nullptr)) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d332f6e..a296198 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -18,6 +18,7 @@
#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
#include <android/hardware/BnCameraService.h>
+#include <android/hardware/BnSensorPrivacyListener.h>
#include <android/hardware/ICameraServiceListener.h>
#include <android/hardware/ICameraServiceProxy.h>
@@ -554,8 +555,35 @@
std::unordered_map<uid_t, bool> mOverrideUids;
}; // class UidPolicy
+ // If sensor privacy is enabled then all apps, including those that are active, should be
+ // prevented from accessing the camera.
+ class SensorPrivacyPolicy : public hardware::BnSensorPrivacyListener,
+ public virtual IBinder::DeathRecipient {
+ public:
+ explicit SensorPrivacyPolicy(wp<CameraService> service)
+ : mService(service), mSensorPrivacyEnabled(false), mRegistered(false) {}
+
+ void registerSelf();
+ void unregisterSelf();
+
+ bool isSensorPrivacyEnabled();
+
+ binder::Status onSensorPrivacyChanged(bool enabled);
+
+ // IBinder::DeathRecipient implementation
+ virtual void binderDied(const wp<IBinder> &who);
+
+ private:
+ wp<CameraService> mService;
+ Mutex mSensorPrivacyLock;
+ bool mSensorPrivacyEnabled;
+ bool mRegistered;
+ };
+
sp<UidPolicy> mUidPolicy;
+ sp<SensorPrivacyPolicy> mSensorPrivacyPolicy;
+
// Delay-load the Camera HAL module
virtual void onFirstRef();
@@ -825,6 +853,9 @@
// Blocks all clients from the UID
void blockClientsForUid(uid_t uid);
+ // Blocks all active clients.
+ void blockAllClients();
+
// Overrides the UID state as if it is idle
status_t handleSetUidState(const Vector<String16>& args, int err);
diff --git a/services/mediacodec/registrant/Android.bp b/services/mediacodec/registrant/Android.bp
index f119472..8c40ad1 100644
--- a/services/mediacodec/registrant/Android.bp
+++ b/services/mediacodec/registrant/Android.bp
@@ -1,5 +1,6 @@
cc_library_shared {
name: "libmedia_codecserviceregistrant",
+ vendor_available: true,
srcs: [
"CodecServiceRegistrant.cpp",
],
diff --git a/services/mediadrm/tests/Android.mk b/services/mediadrm/tests/Android.mk
deleted file mode 100644
index e2f7399..0000000
--- a/services/mediadrm/tests/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Build the unit tests.
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := DrmSessionManager_test
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
- DrmSessionManager_test.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
- liblog \
- libmediaplayerservice \
- libutils \
-
-LOCAL_C_INCLUDES := \
- frameworks/av/include \
- frameworks/av/media/libmediaplayerservice \
-
-LOCAL_CFLAGS += -Werror -Wall
-
-LOCAL_32_BIT_ONLY := true
-
-include $(BUILD_NATIVE_TEST)
-
diff --git a/services/mediadrm/tests/DrmSessionManager_test.cpp b/services/mediadrm/tests/DrmSessionManager_test.cpp
deleted file mode 100644
index de350a1..0000000
--- a/services/mediadrm/tests/DrmSessionManager_test.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2015 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_NDEBUG 0
-#define LOG_TAG "DrmSessionManager_test"
-#include <utils/Log.h>
-
-#include <gtest/gtest.h>
-
-#include "Drm.h"
-#include "DrmSessionClientInterface.h"
-#include "DrmSessionManager.h"
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/ProcessInfoInterface.h>
-
-namespace android {
-
-struct FakeProcessInfo : public ProcessInfoInterface {
- FakeProcessInfo() {}
- virtual ~FakeProcessInfo() {}
-
- virtual bool getPriority(int pid, int* priority) {
- // For testing, use pid as priority.
- // Lower the value higher the priority.
- *priority = pid;
- return true;
- }
-
-private:
- DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
-};
-
-struct FakeDrm : public DrmSessionClientInterface {
- FakeDrm() {}
- virtual ~FakeDrm() {}
-
- virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
- mReclaimedSessions.push_back(sessionId);
- return true;
- }
-
- const Vector<Vector<uint8_t> >& reclaimedSessions() const {
- return mReclaimedSessions;
- }
-
-private:
- Vector<Vector<uint8_t> > mReclaimedSessions;
-
- DISALLOW_EVIL_CONSTRUCTORS(FakeDrm);
-};
-
-static const int kTestPid1 = 30;
-static const int kTestPid2 = 20;
-static const uint8_t kTestSessionId1[] = {1, 2, 3};
-static const uint8_t kTestSessionId2[] = {4, 5, 6, 7, 8};
-static const uint8_t kTestSessionId3[] = {9, 0};
-
-class DrmSessionManagerTest : public ::testing::Test {
-public:
- DrmSessionManagerTest()
- : mDrmSessionManager(new DrmSessionManager(new FakeProcessInfo())),
- mTestDrm1(new FakeDrm()),
- mTestDrm2(new FakeDrm()) {
- GetSessionId(kTestSessionId1, ARRAY_SIZE(kTestSessionId1), &mSessionId1);
- GetSessionId(kTestSessionId2, ARRAY_SIZE(kTestSessionId2), &mSessionId2);
- GetSessionId(kTestSessionId3, ARRAY_SIZE(kTestSessionId3), &mSessionId3);
- }
-
-protected:
- static void GetSessionId(const uint8_t* ids, size_t num, Vector<uint8_t>* sessionId) {
- for (size_t i = 0; i < num; ++i) {
- sessionId->push_back(ids[i]);
- }
- }
-
- static void ExpectEqSessionInfo(const SessionInfo& info, sp<DrmSessionClientInterface> drm,
- const Vector<uint8_t>& sessionId, int64_t timeStamp) {
- EXPECT_EQ(drm, info.drm);
- EXPECT_TRUE(isEqualSessionId(sessionId, info.sessionId));
- EXPECT_EQ(timeStamp, info.timeStamp);
- }
-
- void addSession() {
- mDrmSessionManager->addSession(kTestPid1, mTestDrm1, mSessionId1);
- mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId2);
- mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId3);
- const PidSessionInfosMap& map = sessionMap();
- EXPECT_EQ(2u, map.size());
- ssize_t index1 = map.indexOfKey(kTestPid1);
- ASSERT_GE(index1, 0);
- const SessionInfos& infos1 = map[index1];
- EXPECT_EQ(1u, infos1.size());
- ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 0);
-
- ssize_t index2 = map.indexOfKey(kTestPid2);
- ASSERT_GE(index2, 0);
- const SessionInfos& infos2 = map[index2];
- EXPECT_EQ(2u, infos2.size());
- ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId2, 1);
- ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 2);
- }
-
- const PidSessionInfosMap& sessionMap() {
- return mDrmSessionManager->mSessionMap;
- }
-
- void testGetLowestPriority() {
- int pid;
- int priority;
- EXPECT_FALSE(mDrmSessionManager->getLowestPriority_l(&pid, &priority));
-
- addSession();
- EXPECT_TRUE(mDrmSessionManager->getLowestPriority_l(&pid, &priority));
-
- EXPECT_EQ(kTestPid1, pid);
- FakeProcessInfo processInfo;
- int priority1;
- processInfo.getPriority(kTestPid1, &priority1);
- EXPECT_EQ(priority1, priority);
- }
-
- void testGetLeastUsedSession() {
- sp<DrmSessionClientInterface> drm;
- Vector<uint8_t> sessionId;
- EXPECT_FALSE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId));
-
- addSession();
-
- EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId));
- EXPECT_EQ(mTestDrm1, drm);
- EXPECT_TRUE(isEqualSessionId(mSessionId1, sessionId));
-
- EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId));
- EXPECT_EQ(mTestDrm2, drm);
- EXPECT_TRUE(isEqualSessionId(mSessionId2, sessionId));
-
- // mSessionId2 is no longer the least used session.
- mDrmSessionManager->useSession(mSessionId2);
- EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId));
- EXPECT_EQ(mTestDrm2, drm);
- EXPECT_TRUE(isEqualSessionId(mSessionId3, sessionId));
- }
-
- sp<DrmSessionManager> mDrmSessionManager;
- sp<FakeDrm> mTestDrm1;
- sp<FakeDrm> mTestDrm2;
- Vector<uint8_t> mSessionId1;
- Vector<uint8_t> mSessionId2;
- Vector<uint8_t> mSessionId3;
-};
-
-TEST_F(DrmSessionManagerTest, addSession) {
- addSession();
-}
-
-TEST_F(DrmSessionManagerTest, useSession) {
- addSession();
-
- mDrmSessionManager->useSession(mSessionId1);
- mDrmSessionManager->useSession(mSessionId3);
-
- const PidSessionInfosMap& map = sessionMap();
- const SessionInfos& infos1 = map.valueFor(kTestPid1);
- const SessionInfos& infos2 = map.valueFor(kTestPid2);
- ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 3);
- ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 4);
-}
-
-TEST_F(DrmSessionManagerTest, removeSession) {
- addSession();
-
- mDrmSessionManager->removeSession(mSessionId2);
-
- const PidSessionInfosMap& map = sessionMap();
- EXPECT_EQ(2u, map.size());
- const SessionInfos& infos1 = map.valueFor(kTestPid1);
- const SessionInfos& infos2 = map.valueFor(kTestPid2);
- EXPECT_EQ(1u, infos1.size());
- EXPECT_EQ(1u, infos2.size());
- // mSessionId2 has been removed.
- ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId3, 2);
-}
-
-TEST_F(DrmSessionManagerTest, removeDrm) {
- addSession();
-
- sp<FakeDrm> drm = new FakeDrm;
- const uint8_t ids[] = {123};
- Vector<uint8_t> sessionId;
- GetSessionId(ids, ARRAY_SIZE(ids), &sessionId);
- mDrmSessionManager->addSession(kTestPid2, drm, sessionId);
-
- mDrmSessionManager->removeDrm(mTestDrm2);
-
- const PidSessionInfosMap& map = sessionMap();
- const SessionInfos& infos2 = map.valueFor(kTestPid2);
- EXPECT_EQ(1u, infos2.size());
- // mTestDrm2 has been removed.
- ExpectEqSessionInfo(infos2[0], drm, sessionId, 3);
-}
-
-TEST_F(DrmSessionManagerTest, reclaimSession) {
- EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid1));
- addSession();
-
- // calling pid priority is too low
- EXPECT_FALSE(mDrmSessionManager->reclaimSession(50));
-
- EXPECT_TRUE(mDrmSessionManager->reclaimSession(10));
- EXPECT_EQ(1u, mTestDrm1->reclaimedSessions().size());
- EXPECT_TRUE(isEqualSessionId(mSessionId1, mTestDrm1->reclaimedSessions()[0]));
-
- mDrmSessionManager->removeSession(mSessionId1);
-
- // add a session from a higher priority process.
- sp<FakeDrm> drm = new FakeDrm;
- const uint8_t ids[] = {1, 3, 5};
- Vector<uint8_t> sessionId;
- GetSessionId(ids, ARRAY_SIZE(ids), &sessionId);
- mDrmSessionManager->addSession(15, drm, sessionId);
-
- EXPECT_TRUE(mDrmSessionManager->reclaimSession(18));
- EXPECT_EQ(1u, mTestDrm2->reclaimedSessions().size());
- // mSessionId2 is reclaimed.
- EXPECT_TRUE(isEqualSessionId(mSessionId2, mTestDrm2->reclaimedSessions()[0]));
-}
-
-TEST_F(DrmSessionManagerTest, getLowestPriority) {
- testGetLowestPriority();
-}
-
-TEST_F(DrmSessionManagerTest, getLeastUsedSession_l) {
- testGetLeastUsedSession();
-}
-
-} // namespace android
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index 944abcc..fe2ccf2 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -765,10 +765,7 @@
}
recognitionEvent->capture_session = model->mCaptureSession;
- // Don't reset the model state if this recognition event is a get-state response
- if (recognitionEvent->status != RECOGNITION_STATUS_GET_STATE_RESPONSE) {
- model->mState = Model::STATE_IDLE;
- }
+ model->mState = Model::STATE_IDLE;
clients.add(model->mModuleClient);
}
} break;