Merge "camera3: Don't eagerly finish configuring bidi streams more than once" into jb-mr2-dev
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index db5a7ab..64f82bb 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -599,6 +599,7 @@
     int                     mPreviousPriority;          // before start()
     SchedPolicy             mPreviousSchedulingGroup;
     AudioTrackClientProxy*  mProxy;
+    bool                    mAwaitBoost;    // thread should wait for priority boost before running
 };
 
 class TimedAudioTrack : public AudioTrack
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 1bd839f..7eeb4f8 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -893,9 +893,11 @@
         ALOGW("Requested frameCount %u but received frameCount %u", frameCount, temp);
     }
     frameCount = temp;
+    mAwaitBoost = false;
     if (flags & AUDIO_OUTPUT_FLAG_FAST) {
         if (trackFlags & IAudioFlinger::TRACK_FAST) {
             ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %u", frameCount);
+            mAwaitBoost = true;
         } else {
             ALOGV("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %u", frameCount);
             // once denied, do not request again if IAudioTrack is re-created
@@ -1219,6 +1221,25 @@
     size_t writtenSize;
 
     mLock.lock();
+    if (mAwaitBoost) {
+        mAwaitBoost = false;
+        mLock.unlock();
+        static const int32_t kMaxTries = 5;
+        int32_t tryCounter = kMaxTries;
+        uint32_t pollUs = 10000;
+        do {
+            int policy = sched_getscheduler(0);
+            if (policy == SCHED_FIFO || policy == SCHED_RR) {
+                break;
+            }
+            usleep(pollUs);
+            pollUs <<= 1;
+        } while (tryCounter-- > 0);
+        if (tryCounter < 0) {
+            ALOGE("did not receive expected priority boost on time");
+        }
+        return true;
+    }
     // acquire a strong reference on the IMemory and IAudioTrack so that they cannot be destroyed
     // while we are accessing the cblk
     sp<IAudioTrack> audioTrack = mAudioTrack;
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
index 233aed3..e64fe72 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
@@ -109,7 +109,7 @@
     def.eDir = OMX_DirInput;
     def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
     def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = kMaxNumSamplesPerFrame * sizeof(int16_t) * 2;
+    def.nBufferSize = kMaxInputBufferSize;
     def.bEnabled = OMX_TRUE;
     def.bPopulated = OMX_FALSE;
     def.eDomain = OMX_PortDomainAudio;
@@ -234,6 +234,22 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamPortDefinition:
+        {
+            OMX_PARAM_PORTDEFINITIONTYPE *defParams =
+                (OMX_PARAM_PORTDEFINITIONTYPE *)params;
+
+            if (defParams->nPortIndex == 0) {
+                if (defParams->nBufferSize > kMaxInputBufferSize) {
+                    ALOGE("Input buffer size must be at most %zu bytes",
+                        kMaxInputBufferSize);
+                    return OMX_ErrorUnsupportedSetting;
+                }
+            }
+
+            // fall through
+        }
+
         default:
             ALOGV("SoftFlacEncoder::internalSetParameter(default)");
             return SimpleSoftOMXComponent::internalSetParameter(index, params);
@@ -273,7 +289,7 @@
             return;
         }
 
-        if (inHeader->nFilledLen > kMaxNumSamplesPerFrame * sizeof(FLAC__int32) * 2) {
+        if (inHeader->nFilledLen > kMaxInputBufferSize) {
             ALOGE("input buffer too large (%ld).", inHeader->nFilledLen);
             mSignalledError = true;
             notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
@@ -290,6 +306,7 @@
         const unsigned nbInputSamples = inHeader->nFilledLen / 2;
         const OMX_S16 * const pcm16 = reinterpret_cast<OMX_S16 *>(inHeader->pBuffer);
 
+        CHECK_LE(nbInputSamples, 2 * kMaxNumSamplesPerFrame);
         for (unsigned i=0 ; i < nbInputSamples ; i++) {
             mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
         }
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
index 1e0148a..97361fa 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
@@ -52,6 +52,7 @@
     enum {
         kNumBuffers = 2,
         kMaxNumSamplesPerFrame = 1152,
+        kMaxInputBufferSize = kMaxNumSamplesPerFrame * sizeof(int16_t) * 2,
         kMaxOutputBufferSize = 65536,    //TODO check if this can be reduced
     };
 
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index c12572f..9850a46 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -1059,7 +1059,7 @@
     ssize_t sectionIndex = mPSISections.indexOfKey(PID);
 
     if (sectionIndex >= 0) {
-        const sp<PSISection> &section = mPSISections.valueAt(sectionIndex);
+        sp<PSISection> section = mPSISections.valueAt(sectionIndex);
 
         if (payload_unit_start_indicator) {
             CHECK(section->isEmpty());
@@ -1068,7 +1068,6 @@
             br->skipBits(skip * 8);
         }
 
-
         CHECK((br->numBitsLeft() % 8) == 0);
         status_t err = section->append(br->data(), br->numBitsLeft() / 8);
 
@@ -1103,10 +1102,13 @@
 
             if (!handled) {
                 mPSISections.removeItem(PID);
+                section.clear();
             }
         }
 
-        section->clear();
+        if (section != NULL) {
+            section->clear();
+        }
 
         return OK;
     }
diff --git a/media/libstagefright/wifi-display/VideoFormats.cpp b/media/libstagefright/wifi-display/VideoFormats.cpp
index d171c6f..da557f7 100644
--- a/media/libstagefright/wifi-display/VideoFormats.cpp
+++ b/media/libstagefright/wifi-display/VideoFormats.cpp
@@ -249,11 +249,20 @@
     mNativeIndex = native >> 3;
     mNativeType = (ResolutionType)(native & 7);
 
+    bool success;
     if (mNativeType >= kNumResolutionTypes) {
-        return false;
+        success = false;
+    } else {
+        success = GetConfiguration(
+                mNativeType, mNativeIndex, NULL, NULL, NULL, NULL);
     }
 
-    return GetConfiguration(mNativeType, mNativeIndex, NULL, NULL, NULL, NULL);
+    if (!success) {
+        ALOGW("sink advertised an illegal native resolution, fortunately "
+              "this value is ignored for the time being...");
+    }
+
+    return true;
 }
 
 AString VideoFormats::getFormatSpec(bool forM4Message) const {
diff --git a/media/libstagefright/wifi-display/source/Converter.cpp b/media/libstagefright/wifi-display/source/Converter.cpp
index 0a8462c..5344623 100644
--- a/media/libstagefright/wifi-display/source/Converter.cpp
+++ b/media/libstagefright/wifi-display/source/Converter.cpp
@@ -649,6 +649,13 @@
                 &bufferIndex, &offset, &size, &timeUs, &flags);
 
         if (err != OK) {
+            if (err == INFO_FORMAT_CHANGED) {
+                continue;
+            } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
+                mEncoder->getOutputBuffers(&mEncoderOutputBuffers);
+                continue;
+            }
+
             if (err == -EAGAIN) {
                 err = OK;
             }
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 24a6dfe..21df1d7 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -170,6 +170,10 @@
                 if (old <= 0) {
                     __futex_syscall4(coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL);
                 }
+                int policy = sched_getscheduler(0);
+                if (!(policy == SCHED_FIFO || policy == SCHED_RR)) {
+                    ALOGE("did not receive expected priority boost");
+                }
                 // This may be overly conservative; there could be times that the normal mixer
                 // requests such a brief cold idle that it doesn't require resetting this flag.
                 isWarm = false;
diff --git a/services/audioflinger/ISchedulingPolicyService.cpp b/services/audioflinger/ISchedulingPolicyService.cpp
index 218aa6b..0079968 100644
--- a/services/audioflinger/ISchedulingPolicyService.cpp
+++ b/services/audioflinger/ISchedulingPolicyService.cpp
@@ -37,14 +37,15 @@
     {
     }
 
-    virtual int requestPriority(int32_t pid, int32_t tid, int32_t prio)
+    virtual int requestPriority(int32_t pid, int32_t tid, int32_t prio, bool asynchronous)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISchedulingPolicyService::getInterfaceDescriptor());
         data.writeInt32(pid);
         data.writeInt32(tid);
         data.writeInt32(prio);
-        remote()->transact(REQUEST_PRIORITY_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY);
+        uint32_t flags = asynchronous ? IBinder::FLAG_ONEWAY : 0;
+        remote()->transact(REQUEST_PRIORITY_TRANSACTION, data, &reply, flags);
         // fail on exception
         if (reply.readExceptionCode() != 0) return -1;
         return reply.readInt32();
diff --git a/services/audioflinger/ISchedulingPolicyService.h b/services/audioflinger/ISchedulingPolicyService.h
index a38e67e..b94b191 100644
--- a/services/audioflinger/ISchedulingPolicyService.h
+++ b/services/audioflinger/ISchedulingPolicyService.h
@@ -27,7 +27,7 @@
     DECLARE_META_INTERFACE(SchedulingPolicyService);
 
     virtual int         requestPriority(/*pid_t*/int32_t pid, /*pid_t*/int32_t tid,
-                                                int32_t prio) = 0;
+                                                int32_t prio, bool asynchronous) = 0;
 
 };
 
diff --git a/services/audioflinger/SchedulingPolicyService.cpp b/services/audioflinger/SchedulingPolicyService.cpp
index 59cc99a..36e62e9 100644
--- a/services/audioflinger/SchedulingPolicyService.cpp
+++ b/services/audioflinger/SchedulingPolicyService.cpp
@@ -25,7 +25,7 @@
 static const String16 _scheduling_policy("scheduling_policy");
 static Mutex sMutex;
 
-int requestPriority(pid_t pid, pid_t tid, int32_t prio)
+int requestPriority(pid_t pid, pid_t tid, int32_t prio, bool asynchronous)
 {
     // FIXME merge duplicated code related to service lookup, caching, and error recovery
     sp<ISchedulingPolicyService> sps;
@@ -46,7 +46,7 @@
         }
         sleep(1);
     }
-    return sps->requestPriority(pid, tid, prio);
+    return sps->requestPriority(pid, tid, prio, asynchronous);
 }
 
 }   // namespace android
diff --git a/services/audioflinger/SchedulingPolicyService.h b/services/audioflinger/SchedulingPolicyService.h
index 7ac8454..a9870d4 100644
--- a/services/audioflinger/SchedulingPolicyService.h
+++ b/services/audioflinger/SchedulingPolicyService.h
@@ -21,7 +21,10 @@
 
 // Request elevated priority for thread tid, whose thread group leader must be pid.
 // The priority parameter is currently restricted to either 1 or 2.
-int requestPriority(pid_t pid, pid_t tid, int32_t prio);
+// The asynchronous parameter should be 'true' to return immediately,
+// after the request is enqueued but not necessarily executed.
+// The default value 'false' means to return after request has been enqueued and executed.
+int requestPriority(pid_t pid, pid_t tid, int32_t prio, bool asynchronous = false);
 
 }   // namespace android
 
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 47ca100..539bb4f 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -373,7 +373,9 @@
         switch(event->type()) {
             case CFG_EVENT_PRIO: {
                 PrioConfigEvent *prioEvent = static_cast<PrioConfigEvent *>(event);
-                int err = requestPriority(prioEvent->pid(), prioEvent->tid(), prioEvent->prio());
+                // FIXME Need to understand why this has be done asynchronously
+                int err = requestPriority(prioEvent->pid(), prioEvent->tid(), prioEvent->prio(),
+                        true /*asynchronous*/);
                 if (err != 0) {
                     ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; "
                           "error %d",
diff --git a/services/camera/libcameraservice/camera2/Parameters.cpp b/services/camera/libcameraservice/camera2/Parameters.cpp
index d02f17e..b26cd09 100644
--- a/services/camera/libcameraservice/camera2/Parameters.cpp
+++ b/services/camera/libcameraservice/camera2/Parameters.cpp
@@ -659,15 +659,13 @@
     float minFocalLength = availableFocalLengths.data.f[0];
     params.setFloat(CameraParameters::KEY_FOCAL_LENGTH, minFocalLength);
 
-    camera_metadata_ro_entry_t sensorSize =
-        staticInfo(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, 2, 2);
-    if (!sensorSize.count) return NO_INIT;
+    float horizFov, vertFov;
+    res = calculatePictureFovs(&horizFov, &vertFov);
+    if (res != OK) {
+        ALOGE("%s: Can't calculate field of views!", __FUNCTION__);
+        return res;
+    }
 
-    // The fields of view here assume infinity focus, maximum wide angle
-    float horizFov = 180 / M_PI *
-            2 * atanf(sensorSize.data.f[0] / (2 * minFocalLength));
-    float vertFov  = 180 / M_PI *
-            2 * atanf(sensorSize.data.f[1] / (2 * minFocalLength));
     params.setFloat(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, horizFov);
     params.setFloat(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, vertFov);
 
@@ -861,6 +859,10 @@
         staticInfo(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE);
     bool fixedLens = (minFocusDistance.data.f[0] == 0);
 
+    camera_metadata_ro_entry_t availableFocalLengths =
+        staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS);
+    if (!availableFocalLengths.count) return NO_INIT;
+
     if (sceneModeOverrides.count > 0) {
         // sceneModeOverrides is defined to have 3 entries for each scene mode,
         // which are AE, AWB, and AF override modes the HAL wants for that scene
@@ -928,6 +930,16 @@
     fastInfo.arrayHeight = arrayHeight;
     fastInfo.bestFaceDetectMode = bestFaceDetectMode;
     fastInfo.maxFaces = maxFaces;
+
+    // Find smallest (widest-angle) focal length to use as basis of still
+    // picture FOV reporting.
+    fastInfo.minFocalLength = availableFocalLengths.data.f[0];
+    for (size_t i = 1; i < availableFocalLengths.count; i++) {
+        if (fastInfo.minFocalLength > availableFocalLengths.data.f[i]) {
+            fastInfo.minFocalLength = availableFocalLengths.data.f[i];
+        }
+    }
+
     return OK;
 }
 
@@ -1577,6 +1589,21 @@
 
     *this = validatedParams;
 
+    /** Update external parameters calculated from the internal ones */
+
+    // HORIZONTAL/VERTICAL FIELD OF VIEW
+    float horizFov, vertFov;
+    res = calculatePictureFovs(&horizFov, &vertFov);
+    if (res != OK) {
+        ALOGE("%s: Can't calculate FOVs", __FUNCTION__);
+        // continue so parameters are at least consistent
+    }
+    newParams.setFloat(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE,
+            horizFov);
+    newParams.setFloat(CameraParameters::KEY_VERTICAL_VIEW_ANGLE,
+            vertFov);
+    ALOGV("Current still picture FOV: %f x %f deg", horizFov, vertFov);
+
     // Need to flatten again in case of overrides
     paramsFlattened = newParams.flatten();
     params = newParams;
@@ -2246,7 +2273,7 @@
 
     CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
     ALOG_ASSERT(x < previewCrop.width, "Crop-relative X coordinate = '%d' "
-                    "is out of bounds (upper = %d)", x, previewCrop.width);
+                    "is out of bounds (upper = %f)", x, previewCrop.width);
 
     int ret = x + previewCrop.left;
 
@@ -2262,7 +2289,7 @@
 
     CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
     ALOG_ASSERT(y < previewCrop.height, "Crop-relative Y coordinate = '%d' is "
-                "out of bounds (upper = %d)", y, previewCrop.height);
+                "out of bounds (upper = %f)", y, previewCrop.height);
 
     int ret = y + previewCrop.top;
 
@@ -2468,6 +2495,90 @@
     return crop;
 }
 
+status_t Parameters::calculatePictureFovs(float *horizFov, float *vertFov)
+        const {
+    camera_metadata_ro_entry_t sensorSize =
+            staticInfo(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, 2, 2);
+    if (!sensorSize.count) return NO_INIT;
+
+    camera_metadata_ro_entry_t availableFocalLengths =
+            staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS);
+    if (!availableFocalLengths.count) return NO_INIT;
+
+    float arrayAspect = static_cast<float>(fastInfo.arrayWidth) /
+            fastInfo.arrayHeight;
+    float stillAspect = static_cast<float>(pictureWidth) / pictureHeight;
+    ALOGV("Array aspect: %f, still aspect: %f", arrayAspect, stillAspect);
+
+    // The crop factors from the full sensor array to the still picture crop
+    // region
+    float horizCropFactor = 1.f;
+    float vertCropFactor = 1.f;
+
+    /**
+     * Need to calculate the still image field of view based on the total pixel
+     * array field of view, and the relative aspect ratios of the pixel array
+     * and output streams.
+     *
+     * Special treatment for quirky definition of crop region and relative
+     * stream cropping.
+     */
+    if (quirks.meteringCropRegion) {
+        /**
+         * All streams are the same in height, so narrower aspect ratios will
+         * get cropped on the sides.  First find the largest (widest) aspect
+         * ratio, then calculate the crop of the still FOV based on that.
+         */
+        float cropAspect = arrayAspect;
+        float aspects[] = {
+            stillAspect,
+            static_cast<float>(previewWidth) / previewHeight,
+            static_cast<float>(videoWidth) / videoHeight
+        };
+        for (size_t i = 0; i < sizeof(aspects)/sizeof(aspects[0]); i++) {
+            if (cropAspect < aspects[i]) cropAspect = aspects[i];
+        }
+        ALOGV("Widest crop aspect: %f", cropAspect);
+        // Horizontal crop of still is done based on fitting in the widest
+        // aspect ratio
+        horizCropFactor = stillAspect / cropAspect;
+        // Vertical crop is a function of the array aspect ratio and the
+        // widest aspect ratio.
+        vertCropFactor = arrayAspect / cropAspect;
+    } else {
+        /**
+         * Crop are just a function of just the still/array relative aspect
+         * ratios. Since each stream will maximize its area within the crop
+         * region, and for FOV we assume a full-sensor crop region, we only ever
+         * crop the FOV either vertically or horizontally, never both.
+         */
+        horizCropFactor = (arrayAspect > stillAspect) ?
+                (stillAspect / arrayAspect) : 1.f;
+        vertCropFactor = (arrayAspect < stillAspect) ?
+                (arrayAspect / stillAspect) : 1.f;
+    }
+    ALOGV("Horiz crop factor: %f, vert crop fact: %f",
+            horizCropFactor, vertCropFactor);
+    /**
+     * Basic field of view formula is:
+     *   angle of view = 2 * arctangent ( d / 2f )
+     * where d is the physical sensor dimension of interest, and f is
+     * the focal length. This only applies to rectilinear sensors, for focusing
+     * at distances >> f, etc.
+     */
+    if (horizFov != NULL) {
+        *horizFov = 180 / M_PI * 2 *
+                atanf(horizCropFactor * sensorSize.data.f[0] /
+                        (2 * fastInfo.minFocalLength));
+    }
+    if (vertFov != NULL) {
+        *vertFov = 180 / M_PI * 2 *
+                atanf(vertCropFactor * sensorSize.data.f[1] /
+                        (2 * fastInfo.minFocalLength));
+    }
+    return OK;
+}
+
 int32_t Parameters::fpsFromRange(int32_t /*min*/, int32_t max) const {
     return max;
 }
diff --git a/services/camera/libcameraservice/camera2/Parameters.h b/services/camera/libcameraservice/camera2/Parameters.h
index 696ee2f..6d85037 100644
--- a/services/camera/libcameraservice/camera2/Parameters.h
+++ b/services/camera/libcameraservice/camera2/Parameters.h
@@ -183,6 +183,7 @@
             }
         };
         DefaultKeyedVector<uint8_t, OverrideModes> sceneModeOverrides;
+        float minFocalLength;
     } fastInfo;
 
     // Quirks information; these are short-lived flags to enable workarounds for
@@ -243,6 +244,9 @@
     };
     CropRegion calculateCropRegion(CropRegion::Outputs outputs) const;
 
+    // Calculate the field of view of the high-resolution JPEG capture
+    status_t calculatePictureFovs(float *horizFov, float *vertFov) const;
+
     // Static methods for debugging and converting between camera1 and camera2
     // parameters