Merge "Make AudioRecord and AudioTrack comments more similar"
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index 3e79ee0..28fc00f 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -44,8 +44,9 @@
 // Command-line parameters.
 static bool gVerbose = false;               // chatty on stdout
 static bool gRotate = false;                // rotate 90 degrees
-static uint32_t gVideoWidth = 1280;         // 720p
-static uint32_t gVideoHeight = 720;
+static bool gSizeSpecified = false;         // was size explicitly requested?
+static uint32_t gVideoWidth = 0;            // default width+height
+static uint32_t gVideoHeight = 0;
 static uint32_t gBitRate = 4000000;         // 4Mbps
 
 // Set by signal handler to stop recording.
@@ -107,6 +108,14 @@
 }
 
 /*
+ * Returns "true" if the device is rotated 90 degrees.
+ */
+static bool isDeviceRotated(int orientation) {
+    return orientation != DISPLAY_ORIENTATION_0 &&
+            orientation != DISPLAY_ORIENTATION_180;
+}
+
+/*
  * Configures and starts the MediaCodec encoder.  Obtains an input surface
  * from the codec.
  */
@@ -114,6 +123,11 @@
         sp<IGraphicBufferProducer>* pBufferProducer) {
     status_t err;
 
+    if (gVerbose) {
+        printf("Configuring recorder for %dx%d video at %.2fMbps\n",
+                gVideoWidth, gVideoHeight, gBitRate / 1000000.0);
+    }
+
     sp<AMessage> format = new AMessage;
     format->setInt32("width", gVideoWidth);
     format->setInt32("height", gVideoHeight);
@@ -152,6 +166,7 @@
         return err;
     }
 
+    ALOGV("Codec prepared");
     *pCodec = codec;
     *pBufferProducer = bufferProducer;
     return 0;
@@ -169,8 +184,7 @@
     // Set the region of the layer stack we're interested in, which in our
     // case is "all of it".  If the app is rotated (so that the width of the
     // app is based on the height of the display), reverse width/height.
-    bool deviceRotated = mainDpyInfo.orientation != DISPLAY_ORIENTATION_0 &&
-            mainDpyInfo.orientation != DISPLAY_ORIENTATION_180;
+    bool deviceRotated = isDeviceRotated(mainDpyInfo.orientation);
     uint32_t sourceWidth, sourceHeight;
     if (!deviceRotated) {
         sourceWidth = mainDpyInfo.w;
@@ -295,6 +309,12 @@
                         bufIndex, size, ptsUsec);
                 CHECK(trackIdx != -1);
 
+                // If the virtual display isn't providing us with timestamps,
+                // use the current time.
+                if (ptsUsec == 0) {
+                    ptsUsec = systemTime(SYSTEM_TIME_MONOTONIC) / 1000;
+                }
+
                 // The MediaMuxer docs are unclear, but it appears that we
                 // need to pass either the full set of BufferInfo flags, or
                 // (flags & BUFFER_FLAG_SYNCFRAME).
@@ -370,11 +390,6 @@
 static status_t recordScreen(const char* fileName) {
     status_t err;
 
-    if (gVerbose) {
-        printf("Recording %dx%d video at %.2fMbps\n",
-                gVideoWidth, gVideoHeight, gBitRate / 1000000.0);
-    }
-
     // Configure signal handler.
     err = configureSignals();
     if (err != NO_ERROR) return err;
@@ -399,11 +414,31 @@
                 mainDpyInfo.orientation);
     }
 
+    bool rotated = isDeviceRotated(mainDpyInfo.orientation);
+    if (gVideoWidth == 0) {
+        gVideoWidth = rotated ? mainDpyInfo.h : mainDpyInfo.w;
+    }
+    if (gVideoHeight == 0) {
+        gVideoHeight = rotated ? mainDpyInfo.w : mainDpyInfo.h;
+    }
+
     // Configure and start the encoder.
     sp<MediaCodec> encoder;
     sp<IGraphicBufferProducer> bufferProducer;
     err = prepareEncoder(mainDpyInfo.fps, &encoder, &bufferProducer);
-    if (err != NO_ERROR) return err;
+    if (err != NO_ERROR && !gSizeSpecified) {
+        ALOGV("Retrying with 720p");
+        if (gVideoWidth != 1280 && gVideoHeight != 720) {
+            fprintf(stderr, "WARNING: failed at %dx%d, retrying at 720p\n",
+                    gVideoWidth, gVideoHeight);
+            gVideoWidth = 1280;
+            gVideoHeight = 720;
+            err = prepareEncoder(mainDpyInfo.fps, &encoder, &bufferProducer);
+        }
+    }
+    if (err != NO_ERROR) {
+        return err;
+    }
 
     // Configure virtual display.
     sp<IBinder> dpy;
@@ -478,6 +513,8 @@
     fprintf(stderr,
         "Usage: screenrecord [options] <filename>\n"
         "\n"
+        "Records the device's display to a .mp4 file.\n"
+        "\n"
         "Options:\n"
         "--size WIDTHxHEIGHT\n"
         "    Set the video size, e.g. \"1280x720\".  For best results, use\n"
@@ -485,8 +522,7 @@
         "--bit-rate RATE\n"
         "    Set the video bit rate, in megabits per second.  Default 4Mbps.\n"
         "--rotate\n"
-        "    Rotate the output 90 degrees.  Useful for filling the frame\n"
-        "    when in portrait mode.\n"
+        "    Rotate the output 90 degrees.\n"
         "--verbose\n"
         "    Display interesting information on stdout.\n"
         "--help\n"
@@ -536,6 +572,7 @@
                     gVideoWidth, gVideoHeight);
                 return 2;
             }
+            gSizeSpecified = true;
             break;
         case 'b':
             gBitRate = atoi(optarg);
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 9f84ba0..8b7f20c 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -35,8 +35,6 @@
 {
 public:
 
-    static const int DEFAULT_SAMPLE_RATE = 8000;
-
     /* Events used by AudioRecord callback function (callback_t).
      * Keep in sync with frameworks/base/media/java/android/media/AudioRecord.java NATIVE_EVENT_*.
      */
@@ -482,6 +480,7 @@
 
     int                     mPreviousPriority;  // before start()
     SchedPolicy             mPreviousSchedulingGroup;
+    bool                    mAwaitBoost;    // thread should wait for priority boost before running
 
     // The proxy should only be referenced while a lock is held because the proxy isn't
     // multi-thread safe.
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 7687aae..ddb5842 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -171,9 +171,9 @@
      */
 
                         AudioTrack( audio_stream_type_t streamType,
-                                    uint32_t sampleRate  = 0,
-                                    audio_format_t format = AUDIO_FORMAT_DEFAULT,
-                                    audio_channel_mask_t channelMask = 0,
+                                    uint32_t sampleRate,
+                                    audio_format_t format,
+                                    audio_channel_mask_t,
                                     int frameCount       = 0,
                                     audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
                                     callback_t cbf       = NULL,
@@ -195,10 +195,10 @@
      */
 
                         AudioTrack( audio_stream_type_t streamType,
-                                    uint32_t sampleRate = 0,
-                                    audio_format_t format = AUDIO_FORMAT_DEFAULT,
-                                    audio_channel_mask_t channelMask = 0,
-                                    const sp<IMemory>& sharedBuffer = 0,
+                                    uint32_t sampleRate,
+                                    audio_format_t format,
+                                    audio_channel_mask_t channelMask,
+                                    const sp<IMemory>& sharedBuffer,
                                     audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
                                     callback_t cbf      = NULL,
                                     void* user          = NULL,
@@ -228,10 +228,10 @@
      *
      * threadCanCallJava:  Whether callbacks are made from an attached thread and thus can call JNI.
      */
-            status_t    set(audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT,
-                            uint32_t sampleRate = 0,
-                            audio_format_t format = AUDIO_FORMAT_DEFAULT,
-                            audio_channel_mask_t channelMask = 0,
+            status_t    set(audio_stream_type_t streamType,
+                            uint32_t sampleRate,
+                            audio_format_t format,
+                            audio_channel_mask_t channelMask,
                             int frameCount      = 0,
                             audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
                             callback_t cbf      = NULL,
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 0e7e17f..d88c1ed 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -60,10 +60,9 @@
     // We double the size of input buffer for ping pong use of record buffer.
     size <<= 1;
 
-    if (audio_is_linear_pcm(format)) {
-        uint32_t channelCount = popcount(channelMask);
-        size /= channelCount * audio_bytes_per_sample(format);
-    }
+    // Assumes audio_is_linear_pcm(format)
+    uint32_t channelCount = popcount(channelMask);
+    size /= channelCount * audio_bytes_per_sample(format);
 
     *frameCount = size;
     return NO_ERROR;
@@ -176,7 +175,8 @@
     }
 
     if (sampleRate == 0) {
-        sampleRate = DEFAULT_SAMPLE_RATE;
+        ALOGE("Invalid sample rate %u", sampleRate);
+        return BAD_VALUE;
     }
     mSampleRate = sampleRate;
 
@@ -205,11 +205,8 @@
     uint32_t channelCount = popcount(channelMask);
     mChannelCount = channelCount;
 
-    if (audio_is_linear_pcm(format)) {
-        mFrameSize = channelCount * audio_bytes_per_sample(format);
-    } else {
-        mFrameSize = sizeof(uint8_t);
-    }
+    // Assumes audio_is_linear_pcm(format), else sizeof(uint8_t)
+    mFrameSize = channelCount * audio_bytes_per_sample(format);
 
     if (sessionId == 0 ) {
         mSessionId = AudioSystem::newAudioSessionId();
@@ -665,6 +662,26 @@
 nsecs_t AudioRecord::processAudioBuffer(const sp<AudioRecordThread>& thread)
 {
     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");
+        }
+        // Run again immediately
+        return 0;
+    }
 
     // Can only reference mCblk while locked
     int32_t flags = android_atomic_and(~CBLK_OVERRUN, &mCblk->mFlags);
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index befd4cc..b082c3a 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -65,10 +65,8 @@
     // reference once the ctor ends, as that would cause the refcount of 'this'
     // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
     // that's what we create.
-    wp<BufferQueue::ConsumerListener> listener;
-    sp<BufferQueue::ConsumerListener> proxy;
-    listener = static_cast<BufferQueue::ConsumerListener*>(this);
-    proxy = new BufferQueue::ProxyConsumerListener(listener);
+    wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this);
+    sp<BufferQueue::ProxyConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
 
     status_t err = mBufferQueue->consumerConnect(proxy, false);
     if (err != NO_ERROR) {
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index d6fd95b..325ffcf 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -69,11 +69,8 @@
     // reference once the ctor ends, as that would cause the refcount of 'this'
     // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
     // that's what we create.
-    wp<BufferQueue::ConsumerListener> listener;
-    listener = static_cast<BufferQueue::ConsumerListener*>(this);
-
-    sp<BufferQueue::ConsumerListener> proxy;
-    proxy = new BufferQueue::ProxyConsumerListener(listener);
+    wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this);
+    sp<BufferQueue::ProxyConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
 
     mInitCheck = mBufferQueue->consumerConnect(proxy, false);
     if (mInitCheck != NO_ERROR) {
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index 74c4484..9432a59 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -77,6 +77,8 @@
 
     virtual size_t   getBufferCountLocked();
 
+    virtual status_t getEndpointUsage(uint32_t *usage) = 0;
+
     status_t getBufferPreconditionCheckLocked() const;
     status_t returnBufferPreconditionCheckLocked() const;
 
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index e9a9c2b..1889a11 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -234,6 +234,12 @@
     return OK;
 }
 
+status_t Camera3InputStream::getEndpointUsage(uint32_t *usage) {
+    // Per HAL3 spec, input streams have 0 for their initial usage field.
+    *usage = 0;
+    return OK;
+}
+
 }; // namespace camera3
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h
index 8adda88..91d6f16 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.h
@@ -79,6 +79,8 @@
 
     virtual status_t configureQueueLocked();
 
+    virtual status_t getEndpointUsage(uint32_t *usage);
+
 }; // class Camera3InputStream
 
 }; // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 0ec2b05..35cb5ba 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -364,6 +364,17 @@
     return OK;
 }
 
+status_t Camera3OutputStream::getEndpointUsage(uint32_t *usage) {
+
+    status_t res;
+    int32_t u = 0;
+    res = mConsumer->query(mConsumer.get(),
+            NATIVE_WINDOW_CONSUMER_USAGE_BITS, &u);
+    *usage = u;
+
+    return res;
+}
+
 }; // namespace camera3
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 774fbdd..6cbb9f4 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -92,6 +92,9 @@
 
     virtual status_t configureQueueLocked();
     virtual status_t disconnectLocked();
+
+    virtual status_t getEndpointUsage(uint32_t *usage);
+
 }; // class Camera3OutputStream
 
 } // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index ab563df..a6872aa 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -77,7 +77,9 @@
 }
 
 camera3_stream* Camera3Stream::startConfiguration() {
+    ATRACE_CALL();
     Mutex::Autolock l(mLock);
+    status_t res;
 
     switch (mState) {
         case STATE_ERROR:
@@ -107,8 +109,15 @@
             return NULL;
     }
 
-    oldUsage = usage;
-    oldMaxBuffers = max_buffers;
+    oldUsage = camera3_stream::usage;
+    oldMaxBuffers = camera3_stream::max_buffers;
+
+    res = getEndpointUsage(&(camera3_stream::usage));
+    if (res != OK) {
+        ALOGE("%s: Cannot query consumer endpoint usage!",
+                __FUNCTION__);
+        return NULL;
+    }
 
     if (mState == STATE_CONSTRUCTED) {
         mState = STATE_IN_CONFIG;
@@ -125,6 +134,7 @@
 }
 
 status_t Camera3Stream::finishConfiguration(camera3_device *hal3Device) {
+    ATRACE_CALL();
     Mutex::Autolock l(mLock);
     switch (mState) {
         case STATE_ERROR:
@@ -147,8 +157,8 @@
     // Check if the stream configuration is unchanged, and skip reallocation if
     // so. As documented in hardware/camera3.h:configure_streams().
     if (mState == STATE_IN_RECONFIG &&
-            oldUsage == usage &&
-            oldMaxBuffers == max_buffers) {
+            oldUsage == camera3_stream::usage &&
+            oldMaxBuffers == camera3_stream::max_buffers) {
         mState = STATE_CONFIGURED;
         return OK;
     }
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 69d81e4..b64fd86 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -263,6 +263,10 @@
     // Get the total number of buffers in the queue
     virtual size_t   getBufferCountLocked() = 0;
 
+    // Get the usage flags for the other endpoint, or return
+    // INVALID_OPERATION if they cannot be obtained.
+    virtual status_t getEndpointUsage(uint32_t *usage) = 0;
+
   private:
     uint32_t oldUsage;
     uint32_t oldMaxBuffers;