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,