Export support types from extractors

Make each extractor  plugin export a list of file types it supports,
so we no longer need to hardcode such a list in the framework.

Test: manual
Change-Id: I1e41a5d477ea56960ad3e4bc35f5183c03c3fe3a
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..590358c 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -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/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/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,