Snap for 6545159 from 8ef081fcc9b8818cf3c24402ca1e6811a559e303 to mainline-release

Change-Id: I9196a43f9506a06abb7fba49c758d830ca40fd91
diff --git a/MainlineFiles.cfg b/MainlineFiles.cfg
new file mode 100644
index 0000000..37d714c
--- /dev/null
+++ b/MainlineFiles.cfg
@@ -0,0 +1,34 @@
+# 
+# mainline files for frameworks/av
+#
+# ignore comment (#) lines and blank lines
+# rest are path prefixes starting at root of the project
+# (so OWNERS, not frameworks/av/OWNERS)
+# 
+# path
+# INCLUDE path
+# EXCLUDE path
+#
+# 'path' and 'INCLUDE path' are identical -- they both indicate that this path
+# is part of mainline
+# EXCLUDE indicates that this is not part of mainline,
+# so 'foo/' and 'EXCLUDE foo/nope'
+# means everything under foo/ is part of mainline EXCEPT foo/nope.
+# INCLUDE/EXCLUDE/INCLUDE nested structuring is not supported
+#
+# matching is purely prefix
+# so 'foo' will match 'foo', 'foo.c', 'foo/bar/baz'
+# if you want to exclude a directory, best to use a pattern like "foo/"
+#
+
+media/codec2/components/
+media/codecs/
+media/extractors/
+media/libstagefright/codecs/amrnb/
+media/libstagefright/codecs/amrwb/
+media/libstagefright/codecs/amrwbenc/
+media/libstagefright/codecs/common/
+media/libstagefright/codecs/flac/
+media/libstagefright/codecs/m4v_h263/
+media/libstagefright/codecs/mp3dec/
+media/libstagefright/mpeg2ts
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 9fc0e17..29bccd5 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -278,16 +278,19 @@
         C2ApiLevelSetting;
 constexpr char C2_PARAMKEY_API_LEVEL[] = "api.level";
 
-enum C2Config::api_feature_t : uint64_t {
+C2ENUM(C2Config::api_feature_t, uint64_t,
     API_REFLECTION       = (1U << 0),  ///< ability to list supported parameters
     API_VALUES           = (1U << 1),  ///< ability to list supported values for each parameter
     API_CURRENT_VALUES   = (1U << 2),  ///< ability to list currently supported values for each parameter
     API_DEPENDENCY       = (1U << 3),  ///< have a defined parameter dependency
 
+    API_SAME_INPUT_BUFFER = (1U << 16),   ///< supporting multiple input buffers
+                                          ///< backed by the same allocation
+
     API_STREAMS          = (1ULL << 32),  ///< supporting variable number of streams
 
-    API_TUNNELING        = (1ULL << 48),  ///< tunneling API
-};
+    API_TUNNELING        = (1ULL << 48)   ///< tunneling API
+)
 
 // read-only
 typedef C2GlobalParam<C2Setting, C2SimpleValueStruct<C2Config::api_feature_t>, kParamIndexApiFeatures>
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index b90e6bd..7f5e762 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -57,6 +57,7 @@
 #include <media/stagefright/BufferProducerWrapper.h>
 #include <media/stagefright/CCodec.h>
 #include <media/stagefright/MediaCodec.h>
+#include <media/stagefright/MediaCodecConstants.h>
 #include <media/stagefright/MediaCodecList.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
@@ -95,9 +96,12 @@
 static const char *kCodecCrypto = "android.media.mediacodec.crypto";   /* 0,1 */
 static const char *kCodecProfile = "android.media.mediacodec.profile";  /* 0..n */
 static const char *kCodecLevel = "android.media.mediacodec.level";  /* 0..n */
+static const char *kCodecBitrateMode = "android.media.mediacodec.bitrate_mode";  /* CQ/VBR/CBR */
+static const char *kCodecBitrate = "android.media.mediacodec.bitrate";  /* 0..n */
 static const char *kCodecMaxWidth = "android.media.mediacodec.maxwidth";  /* 0..n */
 static const char *kCodecMaxHeight = "android.media.mediacodec.maxheight";  /* 0..n */
 static const char *kCodecError = "android.media.mediacodec.errcode";
+static const char *kCodecLifetimeMs = "android.media.mediacodec.lifetimeMs";   /* 0..n ms*/
 static const char *kCodecErrorState = "android.media.mediacodec.errstate";
 static const char *kCodecLatencyMax = "android.media.mediacodec.latency.max";   /* in us */
 static const char *kCodecLatencyMin = "android.media.mediacodec.latency.min";   /* in us */
@@ -619,7 +623,6 @@
       mFlags(0),
       mStickyError(OK),
       mSoftRenderer(NULL),
-      mMetricsHandle(0),
       mIsVideo(false),
       mVideoWidth(0),
       mVideoHeight(0),
@@ -679,6 +682,8 @@
         mIndexOfFirstFrameWhenLowLatencyOn = -1;
         mInputBufferCounter = 0;
     }
+
+    mLifetimeStartNs = systemTime(SYSTEM_TIME_MONOTONIC);
 }
 
 void MediaCodec::updateMediametrics() {
@@ -687,7 +692,6 @@
         return;
     }
 
-
     if (mLatencyHist.getCount() != 0 ) {
         mediametrics_setInt64(mMetricsHandle, kCodecLatencyMax, mLatencyHist.getMax());
         mediametrics_setInt64(mMetricsHandle, kCodecLatencyMin, mLatencyHist.getMin());
@@ -703,6 +707,11 @@
     if (mLatencyUnknown > 0) {
         mediametrics_setInt64(mMetricsHandle, kCodecLatencyUnknown, mLatencyUnknown);
     }
+    if (mLifetimeStartNs > 0) {
+        nsecs_t lifetime = systemTime(SYSTEM_TIME_MONOTONIC) - mLifetimeStartNs;
+        lifetime = lifetime / (1000 * 1000);    // emitted in ms, truncated not rounded
+        mediametrics_setInt64(mMetricsHandle, kCodecLifetimeMs, lifetime);
+    }
 
     {
         Mutex::Autolock al(mLatencyLock);
@@ -740,7 +749,6 @@
         }
     }
 
-
     // spit the data (if any) into the supplied analytics record
     if (recentHist.getCount()!= 0 ) {
         mediametrics_setInt64(item, kCodecRecentLatencyMax, recentHist.getMax());
@@ -2309,6 +2317,8 @@
                         // meaningful and confusing for an encoder in a transcoder scenario
                         mInputFormat->setInt32("allow-frame-drop", mAllowFrameDroppingBySurface);
                     }
+                    sp<AMessage> interestingFormat =
+                            (mFlags & kFlagIsEncoder) ? mOutputFormat : mInputFormat;
                     ALOGV("[%s] configured as input format: %s, output format: %s",
                             mComponentName.c_str(),
                             mInputFormat->debugString(4).c_str(),
@@ -2322,6 +2332,7 @@
                     (new AMessage)->postReply(mReplyID);
 
                     // augment our media metrics info, now that we know more things
+                    // such as what the codec extracted from any CSD passed in.
                     if (mMetricsHandle != 0) {
                         sp<AMessage> format;
                         if (mConfigureMsg != NULL &&
@@ -2333,6 +2344,30 @@
                                                             mime.c_str());
                                 }
                             }
+                        // perhaps video only?
+                        int32_t profile = 0;
+                        if (interestingFormat->findInt32("profile", &profile)) {
+                            mediametrics_setInt32(mMetricsHandle, kCodecProfile, profile);
+                        }
+                        int32_t level = 0;
+                        if (interestingFormat->findInt32("level", &level)) {
+                            mediametrics_setInt32(mMetricsHandle, kCodecLevel, level);
+                        }
+                        // bitrate and bitrate mode, encoder only
+                        if (mFlags & kFlagIsEncoder) {
+                            // encoder specific values
+                            int32_t bitrate_mode = -1;
+                            if (mOutputFormat->findInt32(KEY_BITRATE_MODE, &bitrate_mode)) {
+                                    mediametrics_setCString(mMetricsHandle, kCodecBitrateMode,
+                                          asString_BitrateMode(bitrate_mode));
+                            }
+                            int32_t bitrate = -1;
+                            if (mOutputFormat->findInt32(KEY_BIT_RATE, &bitrate)) {
+                                    mediametrics_setInt32(mMetricsHandle, kCodecBitrate, bitrate);
+                            }
+                        } else {
+                            // decoder specific values
+                        }
                     }
                     break;
                 }
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 63a9dad..7f308c0 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -371,7 +371,8 @@
     sp<Surface> mSurface;
     SoftwareRenderer *mSoftRenderer;
 
-    mediametrics_handle_t mMetricsHandle;
+    mediametrics_handle_t mMetricsHandle = 0;
+    nsecs_t mLifetimeStartNs = 0;
     void initMediametrics();
     void updateMediametrics();
     void flushMediametrics();
diff --git a/services/mediametrics/statsd_codec.cpp b/services/mediametrics/statsd_codec.cpp
index 7a38c7c..26eda79 100644
--- a/services/mediametrics/statsd_codec.cpp
+++ b/services/mediametrics/statsd_codec.cpp
@@ -168,6 +168,28 @@
     }
     // android.media.mediacodec.latency.hist    NOT EMITTED
 
+#if 0
+    // TODO(b/139143194)
+    // can't send them to statsd until statsd proto updates merge
+    // but in the meantime, they can appear in local 'dumpsys media.metrics' output
+    //
+    // android.media.mediacodec.bitrate_mode string
+    std::string bitrate_mode;
+    if (item->getString("android.media.mediacodec.bitrate_mode", &bitrate_mode)) {
+        metrics_proto.set_bitrate_mode(std::move(bitrate_mode));
+    }
+    // android.media.mediacodec.bitrate int32
+    int32_t bitrate = -1;
+    if (item->getInt32("android.media.mediacodec.bitrate", &bitrate)) {
+        metrics_proto.set_bitrate(bitrate);
+    }
+    // android.media.mediacodec.lifetimeMs int64
+    int64_t lifetimeMs = -1;
+    if ( item->getInt64("android.media.mediacodec.lifetimeMs", &lifetimeMs)) {
+        metrics_proto.set_lifetime_millis(lifetimeMs);
+    }
+#endif
+
     std::string serialized;
     if (!metrics_proto.SerializeToString(&serialized)) {
         ALOGE("Failed to serialize codec metrics");
diff --git a/tools/mainline_hook_partial.sh b/tools/mainline_hook_partial.sh
new file mode 100755
index 0000000..3dc6163
--- /dev/null
+++ b/tools/mainline_hook_partial.sh
@@ -0,0 +1,200 @@
+#!/bin/bash
+#set -x
+
+# used for projects where some files are mainline, some are not
+# we get a list of the files/directories out of the project's root.
+#
+# invocation   $0  ${repo_root} ${preupload_files}
+#
+# Example PREUPLOAD.cfg:
+#
+# [Hook Scripts]
+# mainline_hook = ${REPO_ROOT}/frameworks/av/tools/mainline_hook_partial.sh ${REPO_ROOT} ${PREUPLOAD_FILES}
+#
+# MainlineFiles.cfg syntax:
+#
+# ignore comment (#) lines and blank lines
+# rest are path prefixes starting at root of the project
+# (so OWNERS, not frameworks/av/OWNERS)
+# 
+# path
+# INCLUDE path
+# EXCLUDE path
+#
+# 'path' and 'INCLUDE path' are identical -- they both indicate that this path
+# is part of mainline
+# EXCLUDE indicates that this is not part of mainline,
+# so 'foo/' and 'EXCLUDE foo/nope'
+# means everything under foo/ is part of mainline EXCEPT foo/nope.
+# INCLUDE/EXCLUDE/INCLUDE nested structuring is not supported
+#
+# matching is purely prefix
+# so 'foo' will match 'foo', 'foo.c', 'foo/bar/baz'
+# if you want to exclude a directory, best to use a pattern like "foo/"
+#
+
+## tunables:
+##
+DEV_BRANCH=rvc-dev
+filelist_file=MainlineFiles.cfg
+
+###
+
+REPO_ROOT=$1; shift
+# the rest of the command line is the file list
+PREUPLOAD_FILES="$*"
+
+RED=$(tput setaf 1)
+NORMAL=$(tput sgr0)
+
+## get the active branch:
+## * <localbranch> <shainfo> [goog/master] Fix to handle missing checks on error returned
+## strip this down to "master"
+##
+current=`git branch -vv | grep -P "^\*[^\[]+\[goog/"|sed -e 's/^.*\[//' | sed -e 's/:.*$//'| sed -e 's/^goog\///'`
+if [ "${current}" = "" ] ; then
+        current=unknown
+fi
+
+## figure out whether which files are for mainline and which are not
+if [ "${PREUPLOAD_FILES}" = "" ] ; then
+    # empty files? what's up there, i suppose we'll let that go
+    exit 0
+fi
+
+## get the list of files out of the project's root
+## figure out which way I'm going .. 
+## use list of files to scan PREUPLOAD_FILES
+## use PREUPLOAD_FILES to scan the list of good/bad from the project root
+##
+## remember to do an exclude, so I can say
+## include/these/files/
+## EXCLUDE include/these/files/nested/
+##
+## and it should all be prefix based stuff...
+
+if [ ! -f ${REPO_ROOT}/${REPO_PATH}/${filelist_file} ] ; then
+    echo "Poorly Configured project, missing ${filelist_file} in root of project"
+    exit 1
+fi
+
+# is 1st arg a prefix of 2nd arg
+beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
+
+exclusions=""
+inclusions=""
+while read p1 p2
+do
+    # ignore comment lines in the file
+    # ignore empty lines in the file
+    if beginswith "#" "${p1}" ; then
+        # ignore this line
+        true
+    elif [ -z "${p1}" ] ; then
+        # ignore blanks
+        true
+    elif [ ${p1} = "EXCLUDE" ] ; then
+        # add to the exclusion list
+        if [ ! -z ${p2} ] ; then
+            exlusions="${exclusions} ${p2}"
+        fi
+    elif [ ${p1} = "INCLUDE" ] ; then
+        # add to the inclusion list
+        if [ ! -z ${p2} ] ; then
+            inclusions="${inclusions} ${p2}"
+        fi
+    elif [ ! -z ${p1} ] ; then
+        inclusions="${inclusions} ${p1}"
+    fi
+done < ${REPO_ROOT}/${REPO_PATH}/${filelist_file}
+
+# so we can play with array syntax
+#INCLUSIONS=( ${inclusions} )
+#EXCLUSIONS=( ${exclusions} )
+
+mainline_yes=""
+mainline_no=""
+
+# is it part of the list of mainline files/directories?
+for path in ${PREUPLOAD_FILES} ; do
+    #echo is ${path} a mainline file...
+    for aprefix in ${inclusions} .. ; do
+        #echo compare against ${aprefix} ...
+        if [ "${aprefix}" = ".." ] ; then
+            mainline_no="${mainline_no} ${path}"
+        elif beginswith ${aprefix} ${path} ; then
+            mainline_yes="${mainline_yes} ${path}"
+            break       # on to next uploaded file
+        fi
+    done
+done
+
+# TODO: audit the yes list to see if some should be moved to the no list
+
+# 3 situations
+# -- everything is on mainline (mainline_yes non-empty, other empty)
+# -- some is mainline, some is not (files_* both non-empty)
+# -- none is mainline   (mainline_yes empty, other non_empty
+# -- both empty only happens if PREUPLOAD_FILES is empty, covered above
+
+if [ -z "${mainline_yes}" ] ; then
+    # no mainline files, everything else is non-mainline, let it go 
+    exit 0
+fi
+
+result=0
+if [ ! -z "${mainline_no}" ] ; then
+        # mixed bag, suggest (not insist) that developer split them.
+        result=1
+        cat - <<EOF
+This CL contains files contains both mainline and non-mainline files.  Consider separating
+them into separate CLs. It may also be appropriate to update the list of mainline
+files in ${RED}${REPO_ROOT}/${filelist_file}${NORMAL}.
+
+EOF
+        echo "===== Mainline files ====="
+        echo -e ${RED}
+        echo ${mainline_yes} | sed -e 's/ /
/g'
+        echo -e ${NORMAL}
+
+        echo "===== Non-Mainline files ====="
+        echo -e ${RED}
+        echo ${mainline_no} | sed -e 's/ /
/g'
+        echo -e ${NORMAL}
+
+fi
+
+if [ "${current}" != "${DEV_BRANCH}" ] ; then
+    # Change is not in the desired mainline dev branch
+    result=1
+
+    #echo -e "${RED}"
+    cat - <<EOF
+
+You are uploading repo  ${RED}${REPO_PATH}${NORMAL} to branch ${RED}${current}${NORMAL}. 
+The source of truth for ${RED}${REPO_PATH}${NORMAL} is branch ${RED}${DEV_BRANCH}${NORMAL}. 
+
+Please upload this change to branch ${RED}${DEV_BRANCH}${NORMAL} unless one or more of
+the following apply:
+- this is a security bug prohibited from disclosure before the next dessert release.
+  (moderate security bugs fall into this category).
+- this is new functionality prohibitied from disclosure before the next dessert release.
+EOF
+    #echo -e "${NORMAL}"
+
+fi
+
+## since stdout is buffered in a way that complicates the below, we're just going
+## to tell the user what they can do to get around this check instead of asking them
+## as part of this run of the command.
+
+if [ ${result} != 0 ] ; then
+    cat - <<EOF
+
+If you are sure you want to proceed uploading to branch ${RED}${current}${NORMAL},
+re-run your repo upload command with the '--no-verify' option
+
+EOF
+fi
+exit ${result}
+
diff --git a/tools/mainline_hook_project.sh b/tools/mainline_hook_project.sh
new file mode 100755
index 0000000..8d35470
--- /dev/null
+++ b/tools/mainline_hook_project.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+#set -x
+
+# called for repo projects that are part of the media mainline modules
+# this is for projects where the entire project is part of mainline.
+# we have a separate script for projects where only part of that project gets
+# pulled into mainline.
+#
+# if the project's PREUPLOAD.cfg points to this script, it is by definition a project
+# which is entirely within mainline.
+#
+# example PREUPLOAD.cfg using this script
+# [Hook Scripts]
+# mainline_hook = ${REPO_ROOT}/frameworks/av/tools/mainline_hook_project.sh
+#
+
+
+# tunables
+DEV_BRANCH=rvc-dev
+
+###
+RED=$(tput setaf 1)
+NORMAL=$(tput sgr0)
+
+## check the active branch:
+## * b131183694 d198c6a [goog/master] Fix to handle missing checks on error returned
+##
+current=`git branch -vv | grep -P "^\*[^\[]+\[goog/"|sed -e 's/^.*\[//' | sed -e 's/:.*$//'| sed -e 's/^goog\///'`
+if [ "${current}" = "" ] ; then
+        current=unknown
+fi
+
+if [ "${current}" = "${DEV_BRANCH}" ] ; then
+    # Change appears to be in mainline dev branch
+    exit 0
+fi
+
+## warn the user that about not being on the typical/desired branch.
+
+cat - <<EOF
+
+You are uploading repo  ${RED}${REPO_PATH}${NORMAL} to branch ${RED}${current}${NORMAL}. 
+The source of truth for ${RED}${REPO_PATH}${NORMAL} is branch ${RED}${DEV_BRANCH}${NORMAL}. 
+
+Please upload this change to branch ${RED}${DEV_BRANCH}${NORMAL} unless one or more of
+the following apply:
+- this is a security bug prohibited from disclosure before the next dessert release.
+  (moderate security bugs fall into this category).
+- this is new functionality prohibitied from disclosure before the next dessert release.
+EOF
+
+
+##
+## TODO: prompt the user y/n to continue right now instead of re-invoking with no-verify
+## this has to get around how repo buffers stdout from this script such that the output
+## is not flushed before we try to read the input.
+## 
+
+cat - <<EOF
+If you are sure you want to proceed uploading to branch ${RED}${current}${NORMAL},
+re-run your repo upload command with the '--no-verify' option
+
+EOF
+exit 1
+