Merge changes I8c3a4dbd,I608ed8d7,I4a70abba,I61fcf6fe,I9ae8dd64, ...
* changes:
audiopolicy: engineconfigurable: Get rid of criteria text file
AudioFlinger: update cache in/out configuration on device port id change
audiopolicy: engineconfigurable: Forward device connection state to Policy PFW wrapper
audiopolicy: engineconfigurable: switch to unix socket for PFW debug
audiopolicy: engineconfigurable: Simplify policy PFW plugin: remove Id from structure
audiopolicy: engineconfigurable: Migrate to XML criteria and criterion type defintion
audiopolicy: engineconfigurable: apply coding style
diff --git a/include/media/MediaExtractorPluginApi.h b/include/media/MediaExtractorPluginApi.h
index 854bf83..916472c 100644
--- a/include/media/MediaExtractorPluginApi.h
+++ b/include/media/MediaExtractorPluginApi.h
@@ -135,8 +135,16 @@
const char *extractor_name;
union {
- SnifferFunc v2;
- } sniff;
+ struct {
+ SnifferFunc sniff;
+ } v2;
+ struct {
+ SnifferFunc sniff;
+ // a NULL terminated list of container mime types and/or file extensions
+ // that this extractor supports
+ const char **supported_types;
+ } v3;
+ } u;
};
// the C++ based API which first shipped in P and is no longer supported
@@ -145,7 +153,10 @@
// the first C/NDK based API
const uint32_t EXTRACTORDEF_VERSION_NDK_V1 = 2;
-const uint32_t EXTRACTORDEF_VERSION = EXTRACTORDEF_VERSION_NDK_V1;
+// the second C/NDK based API
+const uint32_t EXTRACTORDEF_VERSION_NDK_V2 = 3;
+
+const uint32_t EXTRACTORDEF_VERSION = EXTRACTORDEF_VERSION_NDK_V2;
// each plugin library exports one function of this type
typedef ExtractorDef (*GetExtractorDef)();
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/extractors/aac/AACExtractor.cpp
index 4e9ac6e..beddad0 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/extractors/aac/AACExtractor.cpp
@@ -377,6 +377,10 @@
return NULL;
}
+static const char *extensions[] = {
+ "aac",
+ NULL
+};
extern "C" {
// This is the only symbol that needs to be exported
@@ -387,7 +391,7 @@
UUID("4fd80eae-03d2-4d72-9eb9-48fa6bb54613"),
1, // version
"AAC Extractor",
- { .v2 = Sniff }
+ { .v3 = {Sniff, extensions} },
};
}
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/extractors/amr/AMRExtractor.cpp
index 00d2a92..df8de9b 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/extractors/amr/AMRExtractor.cpp
@@ -199,7 +199,7 @@
if (mInitCheck == OK) {
AMediaFormat_setString(meta,
- AMEDIAFORMAT_KEY_MIME, mIsWide ? "audio/amr-wb" : "audio/amr");
+ AMEDIAFORMAT_KEY_MIME, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB : "audio/amr");
}
return AMEDIA_OK;
@@ -358,6 +358,12 @@
////////////////////////////////////////////////////////////////////////////////
+static const char *extensions[] = {
+ "amr",
+ "awb",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -368,21 +374,24 @@
1,
"AMR Extractor",
{
- .v2 = [](
- CDataSource *source,
- float *confidence,
- void **,
- FreeMetaFunc *) -> CreatorFunc {
- DataSourceHelper helper(source);
- if (SniffAMR(&helper, nullptr, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new AMRExtractor(new DataSourceHelper(source)));};
- }
- return NULL;
- }
- }
+ .v3 = {
+ [](
+ CDataSource *source,
+ float *confidence,
+ void **,
+ FreeMetaFunc *) -> CreatorFunc {
+ DataSourceHelper helper(source);
+ if (SniffAMR(&helper, nullptr, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new AMRExtractor(new DataSourceHelper(source)));};
+ }
+ return NULL;
+ },
+ extensions
+ },
+ },
};
}
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index b5eaf9b..e4bbc07 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -822,6 +822,11 @@
return true;
}
+static const char *extensions[] = {
+ "flac",
+ "fl",
+ NULL
+};
extern "C" {
// This is the only symbol that needs to be exported
@@ -833,21 +838,24 @@
1,
"FLAC Extractor",
{
- .v2 = [](
+ .v3 = {
+ [](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
- DataSourceHelper helper(source);
- if (SniffFLAC(&helper, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new FLACExtractor(new DataSourceHelper(source)));};
- }
- return NULL;
+ DataSourceHelper helper(source);
+ if (SniffFLAC(&helper, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new FLACExtractor(new DataSourceHelper(source)));};
+ }
+ return NULL;
+ },
+ extensions
}
- }
+ },
};
}
diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/extractors/midi/MidiExtractor.cpp
index 0c74376..9f4f9e6 100644
--- a/media/extractors/midi/MidiExtractor.cpp
+++ b/media/extractors/midi/MidiExtractor.cpp
@@ -326,6 +326,18 @@
}
+static const char *extensions[] = {
+ "imy",
+ "mid",
+ "midi",
+ "mxmf",
+ "ota",
+ "rtttl",
+ "rtx",
+ "smf",
+ "xmf",
+ NULL
+};
extern "C" {
// This is the only symbol that needs to be exported
@@ -337,20 +349,23 @@
1,
"MIDI Extractor",
{
- .v2 = [](
+ .v3 = {
+ [](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
- if (SniffMidi(source, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new MidiExtractor(source));};
- }
- return NULL;
+ if (SniffMidi(source, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new MidiExtractor(source));};
+ }
+ return NULL;
+ },
+ extensions
}
- }
+ },
};
}
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 9f197b0..4200a46 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -1669,6 +1669,12 @@
return true;
}
+static const char *extensions[] = {
+ "mka",
+ "mkv",
+ "webm",
+ NULL
+};
extern "C" {
// This is the only symbol that needs to be exported
@@ -1680,19 +1686,22 @@
1,
"Matroska Extractor",
{
- .v2 = [](
+ .v3 = {
+ [](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
- DataSourceHelper helper(source);
- if (SniffMatroska(&helper, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new MatroskaExtractor(new DataSourceHelper(source)));};
- }
- return NULL;
+ DataSourceHelper helper(source);
+ if (SniffMatroska(&helper, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new MatroskaExtractor(new DataSourceHelper(source)));};
+ }
+ return NULL;
+ },
+ extensions
}
}
};
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index 20bcda8..61838f6 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -609,7 +609,7 @@
if (mInitCheck != OK) {
return AMEDIA_ERROR_UNKNOWN;
}
- AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, "audio/mpeg");
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG);
DataSourceHelper helper(mDataSource);
ID3 id3(&helper);
@@ -707,6 +707,14 @@
return CreateExtractor;
}
+static const char *extensions[] = {
+ "mp3",
+ "mpeg",
+ "mpg",
+ "mpga",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -716,7 +724,7 @@
UUID("812a3f6c-c8cf-46de-b529-3774b14103d4"),
1, // version
"MP3 Extractor",
- { .v2 = Sniff }
+ { .v3 = {Sniff, extensions} }
};
}
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 524db4e..0441359 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -6183,6 +6183,19 @@
return NULL;
}
+static const char *extensions[] = {
+ "3g2",
+ "3gp",
+ "3gpp",
+ "3gpp2",
+ "m4a",
+ "m4r",
+ "m4v",
+ "mov",
+ "mp4",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -6192,7 +6205,7 @@
UUID("27575c67-4417-4c54-8d3d-8e626985a164"),
2, // version
"MP4 Extractor",
- { .v2 = Sniff }
+ { .v3 = {Sniff, extensions} },
};
}
diff --git a/media/extractors/mpeg2/ExtractorBundle.cpp b/media/extractors/mpeg2/ExtractorBundle.cpp
index 2f4196c..946a2a9 100644
--- a/media/extractors/mpeg2/ExtractorBundle.cpp
+++ b/media/extractors/mpeg2/ExtractorBundle.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <media/MediaExtractorPluginHelper.h>
+#include <media/stagefright/MediaDefs.h>
#include "MPEG2PSExtractor.h"
#include "MPEG2TSExtractor.h"
@@ -26,6 +27,12 @@
struct CDataSource;
+static const char *extensions[] = {
+ "m2p",
+ "ts",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -36,26 +43,29 @@
1,
"MPEG2-PS/TS Extractor",
{
- .v2 = [](
+ .v3 = {
+ [](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
- DataSourceHelper helper(source);
- if (SniffMPEG2TS(&helper, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new MPEG2TSExtractor(new DataSourceHelper(source)));};
- } else if (SniffMPEG2PS(&helper, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new MPEG2PSExtractor(new DataSourceHelper(source)));};
- }
- return NULL;
+ DataSourceHelper helper(source);
+ if (SniffMPEG2TS(&helper, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new MPEG2TSExtractor(new DataSourceHelper(source)));};
+ } else if (SniffMPEG2PS(&helper, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new MPEG2PSExtractor(new DataSourceHelper(source)));};
+ }
+ return NULL;
+ },
+ extensions
}
- }
+ },
};
}
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index c3914f1..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
@@ -1379,6 +1379,12 @@
return CreateExtractor;
}
+static const char *extensions[] = {
+ "oga",
+ "ogg",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -1388,7 +1394,7 @@
UUID("8cc5cd06-f772-495e-8a62-cba9649374e9"),
1, // version
"Ogg Extractor",
- { .v2 = Sniff }
+ { .v3 = {Sniff, extensions} },
};
}
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index 6f9f689..e58bd1f 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -616,6 +616,11 @@
return CreateExtractor;
}
+static const char *extensions[] = {
+ "wav",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -625,7 +630,7 @@
UUID("7d613858-5837-4a38-84c5-332d1cddee27"),
1, // version
"WAV Extractor",
- { .v2 = Sniff }
+ { .v3 = {Sniff, extensions} },
};
}
diff --git a/media/libmedia/IMediaExtractorService.cpp b/media/libmedia/IMediaExtractorService.cpp
index 0295abc..243b09d 100644
--- a/media/libmedia/IMediaExtractorService.cpp
+++ b/media/libmedia/IMediaExtractorService.cpp
@@ -29,6 +29,7 @@
enum {
MAKE_EXTRACTOR = IBinder::FIRST_CALL_TRANSACTION,
MAKE_IDATA_SOURCE_FD,
+ GET_SUPPORTED_TYPES,
};
class BpMediaExtractorService : public BpInterface<IMediaExtractorService>
@@ -68,6 +69,24 @@
}
return nullptr;
}
+
+ virtual std::unordered_set<std::string> getSupportedTypes() {
+ std::unordered_set<std::string> supportedTypes;
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaExtractorService::getInterfaceDescriptor());
+ status_t ret = remote()->transact(GET_SUPPORTED_TYPES, data, &reply);
+ if (ret == NO_ERROR) {
+ // process reply
+ while(true) {
+ const char *ext = reply.readCString();
+ if (!ext) {
+ break;
+ }
+ supportedTypes.insert(std::string(ext));
+ }
+ }
+ return supportedTypes;
+ }
};
IMPLEMENT_META_INTERFACE(MediaExtractorService, "android.media.IMediaExtractorService");
@@ -113,6 +132,15 @@
return NO_ERROR;
}
+ case GET_SUPPORTED_TYPES:
+ {
+ CHECK_INTERFACE(IMediaExtractorService, data, reply);
+ std::unordered_set<std::string> supportedTypes = getSupportedTypes();
+ for (auto it = supportedTypes.begin(); it != supportedTypes.end(); ++it) {
+ reply->writeCString((*it).c_str());
+ }
+ return NO_ERROR;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/include/media/IMediaExtractorService.h b/media/libmedia/include/media/IMediaExtractorService.h
index 45e9620..5ce2cdb 100644
--- a/media/libmedia/include/media/IMediaExtractorService.h
+++ b/media/libmedia/include/media/IMediaExtractorService.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_IMEDIAEXTRACTORSERVICE_H
#define ANDROID_IMEDIAEXTRACTORSERVICE_H
+#include <unordered_set>
+
#include <binder/IInterface.h>
#include <binder/IMemory.h>
#include <binder/Parcel.h>
@@ -33,6 +35,8 @@
virtual sp<IMediaExtractor> makeExtractor(const sp<IDataSource> &source, const char *mime) = 0;
virtual sp<IDataSource> makeIDataSource(int fd, int64_t offset, int64_t length) = 0;
+
+ virtual std::unordered_set<std::string> getSupportedTypes() = 0;
};
class BnMediaExtractorService: public BnInterface<IMediaExtractorService>
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 2c7a4e5..86402ce 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -30,6 +30,7 @@
#include <media/stagefright/MediaExtractorFactory.h>
#include <media/IMediaExtractor.h>
#include <media/IMediaExtractorService.h>
+#include <private/android_filesystem_config.h>
#include <cutils/properties.h>
#include <utils/String8.h>
#include <ziparchive/zip_archive.h>
@@ -106,7 +107,8 @@
}
MediaExtractor *ex = nullptr;
- if (creatorVersion == EXTRACTORDEF_VERSION_NDK_V1) {
+ if (creatorVersion == EXTRACTORDEF_VERSION_NDK_V1 ||
+ creatorVersion == EXTRACTORDEF_VERSION_NDK_V2) {
CMediaExtractor *ret = ((CreatorFunc)creator)(source->wrap(), meta);
if (meta != nullptr && freeMeta != nullptr) {
freeMeta(meta);
@@ -184,7 +186,10 @@
void *curCreator = NULL;
if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V1) {
- curCreator = (void*) (*it)->def.sniff.v2(
+ curCreator = (void*) (*it)->def.u.v2.sniff(
+ source->wrap(), &newConfidence, &newMeta, &newFreeMeta);
+ } else if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V2) {
+ curCreator = (void*) (*it)->def.u.v3.sniff(
source->wrap(), &newConfidence, &newMeta, &newFreeMeta);
}
@@ -214,7 +219,8 @@
void MediaExtractorFactory::RegisterExtractor(const sp<ExtractorPlugin> &plugin,
std::list<sp<ExtractorPlugin>> &pluginList) {
// sanity check check struct version, uuid, name
- if (plugin->def.def_version != EXTRACTORDEF_VERSION_NDK_V1) {
+ if (plugin->def.def_version != EXTRACTORDEF_VERSION_NDK_V1 &&
+ plugin->def.def_version != EXTRACTORDEF_VERSION_NDK_V2) {
ALOGE("don't understand extractor format %u, ignoring.", plugin->def.def_version);
return;
}
@@ -394,6 +400,8 @@
return strcmp(first->def.extractor_name, second->def.extractor_name) < 0;
}
+static std::unordered_set<std::string> gSupportedExtensions;
+
// static
void MediaExtractorFactory::UpdateExtractors(const char *newUpdateApkPath) {
Mutex::Autolock autoLock(gPluginMutex);
@@ -426,9 +434,37 @@
newList->sort(compareFunc);
gPlugins = newList;
+
+ for (auto it = gPlugins->begin(); it != gPlugins->end(); ++it) {
+ if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V2) {
+ for (size_t i = 0;; i++) {
+ const char* ext = (*it)->def.u.v3.supported_types[i];
+ if (ext == nullptr) {
+ break;
+ }
+ gSupportedExtensions.insert(std::string(ext));
+ }
+ }
+ }
+
gPluginsRegistered = true;
}
+// static
+std::unordered_set<std::string> MediaExtractorFactory::getSupportedTypes() {
+ if (getuid() == AID_MEDIA_EX) {
+ return gSupportedExtensions;
+ }
+ ALOGV("get service manager");
+ sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor"));
+
+ if (binder != 0) {
+ sp<IMediaExtractorService> mediaExService(interface_cast<IMediaExtractorService>(binder));
+ return mediaExService->getSupportedTypes();
+ }
+ return std::unordered_set<std::string>();
+}
+
status_t MediaExtractorFactory::dump(int fd, const Vector<String16>&) {
Mutex::Autolock autoLock(gPluginMutex);
String8 out;
@@ -445,13 +481,25 @@
out.append("Available extractors:\n");
if (gPluginsRegistered) {
for (auto it = gPlugins->begin(); it != gPlugins->end(); ++it) {
- out.appendFormat(" %25s: plugin_version(%d), uuid(%s), version(%u), path(%s)\n",
+ out.appendFormat(" %25s: plugin_version(%d), uuid(%s), version(%u), path(%s)",
(*it)->def.extractor_name,
(*it)->def.def_version,
(*it)->uuidString.c_str(),
(*it)->def.extractor_version,
(*it)->libPath.c_str());
+ if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V2) {
+ out.append(", supports: ");
+ for (size_t i = 0;; i++) {
+ const char* mime = (*it)->def.u.v3.supported_types[i];
+ if (mime == nullptr) {
+ break;
+ }
+ out.appendFormat("%s ", mime);
+ }
+ }
+ out.append("\n");
}
+ out.append("\n");
} else {
out.append(" (no plugins registered)\n");
}
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 17187a8..74b7340 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -22,6 +22,7 @@
#include <sys/stat.h>
#include <fcntl.h>
+#include <media/stagefright/MediaExtractorFactory.h>
#include <media/stagefright/StagefrightMediaScanner.h>
#include <media/IMediaHTTPService.h>
@@ -34,25 +35,16 @@
StagefrightMediaScanner::~StagefrightMediaScanner() {}
-static bool FileHasAcceptableExtension(const char *extension) {
- static const char *kValidExtensions[] = {
- ".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2",
- ".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",
- ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",
- ".mkv", ".mka", ".webm", ".ts", ".fl", ".flac", ".mxmf",
- ".avi", ".mpeg", ".mpg", ".awb", ".mpga", ".mov",
- ".m4v", ".oga", ".m4r"
- };
- static const size_t kNumValidExtensions =
- sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
+static std::unordered_set<std::string> gSupportedExtensions;
- for (size_t i = 0; i < kNumValidExtensions; ++i) {
- if (!strcasecmp(extension, kValidExtensions[i])) {
- return true;
- }
+static bool FileHasAcceptableExtension(const char *extension) {
+
+ if (gSupportedExtensions.empty()) {
+ // get the list from the service
+ gSupportedExtensions = MediaExtractorFactory::getSupportedTypes();
}
- return false;
+ return gSupportedExtensions.count(std::string(extension + 1)) != 0;
}
MediaScanResult StagefrightMediaScanner::processFile(
diff --git a/media/libstagefright/VideoFrameScheduler2.cpp b/media/libstagefright/VideoFrameScheduler2.cpp
index e02ae7d..fc76904 100644
--- a/media/libstagefright/VideoFrameScheduler2.cpp
+++ b/media/libstagefright/VideoFrameScheduler2.cpp
@@ -36,7 +36,7 @@
namespace android {
-static void getVsyncOffset(long* appVsyncOffsetPtr, long* sfVsyncOffsetPtr);
+static void getVsyncOffset(nsecs_t* appVsyncOffsetPtr, nsecs_t* sfVsyncOffsetPtr);
/* ======================================================================= */
/* VsyncTracker */
@@ -46,19 +46,19 @@
public:
VsyncTracker();
~VsyncTracker() {}
- long getVsyncPeriod();
- long getVsyncTime(long periodOffset);
- void addSample(long timestamp);
+ nsecs_t getVsyncPeriod();
+ nsecs_t getVsyncTime(nsecs_t periodOffset);
+ void addSample(nsecs_t timestamp);
private:
static const int kMaxSamples = 32;
static const int kMinSamplesForUpdate = 6;
int mNumSamples;
int mFirstSample;
- long mReferenceTime;
- long mPhase;
- long mPeriod;
- long mTimestampSamples[kMaxSamples];
+ nsecs_t mReferenceTime;
+ nsecs_t mPhase;
+ nsecs_t mPeriod;
+ nsecs_t mTimestampSamples[kMaxSamples];
Mutex mLock;
void updateModelLocked();
@@ -75,19 +75,39 @@
}
}
-long VsyncTracker::getVsyncPeriod() {
+nsecs_t VsyncTracker::getVsyncPeriod() {
Mutex::Autolock dataLock(mLock);
return mPeriod;
}
-long VsyncTracker::getVsyncTime(long periodOffset) {
+nsecs_t VsyncTracker::getVsyncTime(nsecs_t periodOffset) {
Mutex::Autolock dataLock(mLock);
- const long now = systemTime();
- long phase = mReferenceTime + mPhase;
- return (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase;
+ const nsecs_t now = systemTime();
+ nsecs_t phase = mReferenceTime + mPhase;
+
+ // result = (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase
+ // prevent overflow
+ nsecs_t result = (now - phase) / mPeriod;
+ if (result > LONG_LONG_MAX - periodOffset - 1) {
+ return LONG_LONG_MAX;
+ } else {
+ result += periodOffset + 1;
+ }
+ if (result > LONG_LONG_MAX / mPeriod) {
+ return LONG_LONG_MAX;
+ } else {
+ result *= mPeriod;
+ }
+ if (result > LONG_LONG_MAX - phase) {
+ return LONG_LONG_MAX;
+ } else {
+ result += phase;
+ }
+
+ return result;
}
-void VsyncTracker::addSample(long timestamp) {
+void VsyncTracker::addSample(nsecs_t timestamp) {
Mutex::Autolock dataLock(mLock);
if (mNumSamples == 0) {
mPhase = 0;
@@ -107,17 +127,17 @@
if (mNumSamples < kMinSamplesForUpdate) {
return;
}
- long durationSum = 0;
- long minDuration = LONG_MAX;
- long maxDuration = 0;
+ nsecs_t durationSum = 0;
+ nsecs_t minDuration = LONG_MAX;
+ nsecs_t maxDuration = 0;
for (int i = 1; i < mNumSamples; i++) {
int idx = (mFirstSample + i) % kMaxSamples;
int prev = (idx + kMaxSamples - 1) % kMaxSamples;
long duration = mTimestampSamples[idx] - mTimestampSamples[prev];
durationSum += duration;
- minDuration = min(minDuration, duration);
- maxDuration = max(maxDuration, duration);
+ if (minDuration > duration) { minDuration = duration; }
+ if (maxDuration < duration) { maxDuration = duration; }
}
durationSum -= (minDuration + maxDuration);
@@ -154,9 +174,9 @@
/* JNI */
/* ======================================================================= */
-static void getVsyncOffset(long* appVsyncOffsetPtr, long* sfVsyncOffsetPtr) {
- static const long kOneMillisecInNanosec = 1000000;
- static const long kOneSecInNanosec = kOneMillisecInNanosec * 1000;
+static void getVsyncOffset(nsecs_t* appVsyncOffsetPtr, nsecs_t* sfVsyncOffsetPtr) {
+ static const nsecs_t kOneMillisecInNanosec = 1000000;
+ static const nsecs_t kOneSecInNanosec = kOneMillisecInNanosec * 1000;
JNIEnv *env = JavaVMHelper::getJNIEnv();
jclass jDisplayManagerGlobalCls = env->FindClass(
@@ -178,19 +198,19 @@
jmethodID jGetRefreshRate = env->GetMethodID(jDisplayCls, "getRefreshRate", "()F");
jfloat javaRefreshRate = env->CallFloatMethod(javaDisplayObj, jGetRefreshRate);
- long vsyncPeriod = (long) (kOneSecInNanosec / (float) javaRefreshRate);
+ nsecs_t vsyncPeriod = (nsecs_t) (kOneSecInNanosec / (float) javaRefreshRate);
jmethodID jGetAppVsyncOffsetNanos = env->GetMethodID(
jDisplayCls, "getAppVsyncOffsetNanos", "()J");
jlong javaAppVsyncOffset = env->CallLongMethod(javaDisplayObj, jGetAppVsyncOffsetNanos);
- *appVsyncOffsetPtr = (long) javaAppVsyncOffset;
+ *appVsyncOffsetPtr = (nsecs_t) javaAppVsyncOffset;
jmethodID jGetPresentationDeadlineNanos = env->GetMethodID(
jDisplayCls, "getPresentationDeadlineNanos", "()J");
jlong javaPresentationDeadline = env->CallLongMethod(
javaDisplayObj, jGetPresentationDeadlineNanos);
- *sfVsyncOffsetPtr = vsyncPeriod - ((long) javaPresentationDeadline - kOneMillisecInNanosec);
+ *sfVsyncOffsetPtr = vsyncPeriod - ((nsecs_t) javaPresentationDeadline - kOneMillisecInNanosec);
}
/* ======================================================================= */
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 84e01f3..ba6631c 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -19,6 +19,7 @@
#define MEDIA_EXTRACTOR_FACTORY_H_
#include <stdio.h>
+#include <unordered_set>
#include <media/IMediaExtractor.h>
@@ -35,6 +36,7 @@
const sp<DataSource> &source, const char *mime = NULL);
static void LoadPlugins(const ::std::string& apkPath);
static status_t dump(int fd, const Vector<String16>& args);
+ static std::unordered_set<std::string> getSupportedTypes();
static void SetLinkedLibraries(const std::string& linkedLibraries);
private:
diff --git a/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h b/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h
index be911cc..891b9a0 100644
--- a/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h
+++ b/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h
@@ -34,8 +34,8 @@
private:
void updateVsync() override;
- long mAppVsyncOffset;
- long mSfVsyncOffset;
+ nsecs_t mAppVsyncOffset;
+ nsecs_t mSfVsyncOffset;
sp<VsyncTracker> mVsyncTracker;
sp<ChoreographerThread> mChoreographerThread;
Mutex mLock;
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/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
index 8b26178..0665930 100644
--- a/services/mediaextractor/MediaExtractorService.cpp
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -59,6 +59,10 @@
return CreateIDataSourceFromDataSource(source);
}
+std::unordered_set<std::string> MediaExtractorService::getSupportedTypes() {
+ return MediaExtractorFactory::getSupportedTypes();
+}
+
status_t MediaExtractorService::dump(int fd, const Vector<String16>& args) {
return MediaExtractorFactory::dump(fd, args) || dumpExtractors(fd, args);
}
diff --git a/services/mediaextractor/MediaExtractorService.h b/services/mediaextractor/MediaExtractorService.h
index 6007004..c9cebcf 100644
--- a/services/mediaextractor/MediaExtractorService.h
+++ b/services/mediaextractor/MediaExtractorService.h
@@ -37,6 +37,8 @@
virtual sp<IDataSource> makeIDataSource(int fd, int64_t offset, int64_t length);
+ virtual std::unordered_set<std::string> getSupportedTypes();
+
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,