Merge "audioflinger: fix lost offload thread resume event" into klp-dev
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index 68289a5..49999b5 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -464,12 +464,16 @@
     err = prepareEncoder(mainDpyInfo.fps, &encoder, &bufferProducer);
 
     if (err != NO_ERROR && !gSizeSpecified) {
-        if (gVideoWidth != kFallbackWidth && gVideoHeight != kFallbackHeight) {
+        // fallback is defined for landscape; swap if we're in portrait
+        bool needSwap = gVideoWidth < gVideoHeight;
+        uint32_t newWidth = needSwap ? kFallbackHeight : kFallbackWidth;
+        uint32_t newHeight = needSwap ? kFallbackWidth : kFallbackHeight;
+        if (gVideoWidth != newWidth && gVideoHeight != newHeight) {
             ALOGV("Retrying with 720p");
-            fprintf(stderr, "WARNING: failed at %dx%d, retrying at 720p\n",
-                    gVideoWidth, gVideoHeight);
-            gVideoWidth = kFallbackWidth;
-            gVideoHeight = kFallbackHeight;
+            fprintf(stderr, "WARNING: failed at %dx%d, retrying at %dx%d\n",
+                    gVideoWidth, gVideoHeight, newWidth, newHeight);
+            gVideoWidth = newWidth;
+            gVideoHeight = newHeight;
             err = prepareEncoder(mainDpyInfo.fps, &encoder, &bufferProducer);
         }
     }
diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp
index 5239b2f..37b400c 100644
--- a/media/libmedia/SoundPool.cpp
+++ b/media/libmedia/SoundPool.cpp
@@ -537,6 +537,18 @@
     mSoundPool = soundPool;
 }
 
+// This class is used to destroy a RefBase asynchronously
+class AsyncDestructThread : public Thread
+{
+public:
+    AsyncDestructThread(sp<RefBase> refBase) : mRefBase(refBase) { }
+protected:
+    virtual ~AsyncDestructThread() { }
+private:
+    virtual bool        threadLoop()    { return false; }
+    const   sp<RefBase> mRefBase;
+};
+
 // call with sound pool lock held
 void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume,
         float rightVolume, int priority, int loop, float rate)
@@ -641,6 +653,17 @@
     if (status != NO_ERROR) {
         mAudioTrack.clear();
     }
+    // FIXME AudioTrack destruction should not be slow
+    if (oldTrack != 0) {
+        // must be a raw reference to avoid a race after run()
+        AsyncDestructThread *adt = new AsyncDestructThread(oldTrack);
+        // guaranteed to not run destructor
+        oldTrack.clear();
+        // after the run(), adt thread will hold a strong reference to oldTrack,
+        // and the only strong reference to itself
+        adt->run("AsyncDestruct");
+        // do not delete adt here: adt thread destroys itself, and oldTrack if needed
+    }
 }
 
 void SoundChannel::nextEvent()
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 8fbac42..f6e4c6a 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -264,6 +264,12 @@
         }
     }
 
+    result.append("Notification Clients:\n");
+    for (size_t i = 0; i < mNotificationClients.size(); ++i) {
+        snprintf(buffer, SIZE, "  pid: %d\n", mNotificationClients.keyAt(i));
+        result.append(buffer);
+    }
+
     result.append("Global session refs:\n");
     result.append(" session pid count\n");
     for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
@@ -1850,6 +1856,16 @@
     Mutex::Autolock _l(mLock);
     pid_t caller = IPCThreadState::self()->getCallingPid();
     ALOGV("acquiring %d from %d", audioSession, caller);
+
+    // Ignore requests received from processes not known as notification client. The request
+    // is likely proxied by mediaserver (e.g CameraService) and releaseAudioSessionId() can be
+    // called from a different pid leaving a stale session reference.  Also we don't know how
+    // to clear this reference if the client process dies.
+    if (mNotificationClients.indexOfKey(caller) < 0) {
+        ALOGV("acquireAudioSessionId() unknown client %d for session %d", caller, audioSession);
+        return;
+    }
+
     size_t num = mAudioSessionRefs.size();
     for (size_t i = 0; i< num; i++) {
         AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
@@ -1882,7 +1898,9 @@
             return;
         }
     }
-    ALOGW("session id %d not found for pid %d", audioSession, caller);
+    // If the caller is mediaserver it is likely that the session being released was acquired
+    // on behalf of a process not in notification clients and we ignore the warning.
+    ALOGW_IF(caller != getpid_cached, "session id %d not found for pid %d", audioSession, caller);
 }
 
 void AudioFlinger::purgeStaleEffects_l() {
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 055ea12..83466cb 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -360,6 +360,26 @@
 
         ALOGV("%s: Camera %d: Successfully created a new stream ID %d",
               __FUNCTION__, mCameraId, streamId);
+
+        /**
+         * Set the stream transform flags to automatically
+         * rotate the camera stream for preview use cases.
+         */
+        int32_t transform = 0;
+        res = getRotationTransformLocked(&transform);
+
+        if (res != OK) {
+            // Error logged by getRotationTransformLocked.
+            return res;
+        }
+
+        res = mDevice->setStreamTransform(streamId, transform);
+        if (res != OK) {
+            ALOGE("%s: Failed to set stream transform (stream id %d)",
+                  __FUNCTION__, streamId);
+            return res;
+        }
+
         return streamId;
     }
 
@@ -560,4 +580,64 @@
     return true;
 }
 
+status_t CameraDeviceClient::getRotationTransformLocked(int32_t* transform) {
+    ALOGV("%s: begin", __FUNCTION__);
+
+    if (transform == NULL) {
+        ALOGW("%s: null transform", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    *transform = 0;
+
+    const CameraMetadata& staticInfo = mDevice->info();
+    camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_SENSOR_ORIENTATION);
+    if (entry.count == 0) {
+        ALOGE("%s: Camera %d: Can't find android.sensor.orientation in "
+                "static metadata!", __FUNCTION__, mCameraId);
+        return INVALID_OPERATION;
+    }
+
+    int32_t& flags = *transform;
+
+    int orientation = entry.data.i32[0];
+    switch (orientation) {
+        case 0:
+            flags = 0;
+            break;
+        case 90:
+            flags = NATIVE_WINDOW_TRANSFORM_ROT_90;
+            break;
+        case 180:
+            flags = NATIVE_WINDOW_TRANSFORM_ROT_180;
+            break;
+        case 270:
+            flags = NATIVE_WINDOW_TRANSFORM_ROT_270;
+            break;
+        default:
+            ALOGE("%s: Invalid HAL android.sensor.orientation value: %d",
+                  __FUNCTION__, orientation);
+            return INVALID_OPERATION;
+    }
+
+    /**
+     * This magic flag makes surfaceflinger un-rotate the buffers
+     * to counter the extra global device UI rotation whenever the user
+     * physically rotates the device.
+     *
+     * By doing this, the camera buffer always ends up aligned
+     * with the physical camera for a "see through" effect.
+     *
+     * In essence, the buffer only gets rotated during preview use-cases.
+     * The user is still responsible to re-create streams of the proper
+     * aspect ratio, or the preview will end up looking non-uniformly
+     * stretched.
+     */
+    flags |= NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
+
+    ALOGV("%s: final transform = 0x%x", __FUNCTION__, flags);
+
+    return OK;
+}
+
 } // namespace android
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index c6b6336..b490924 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -120,6 +120,9 @@
                                            const CameraMetadata& frame);
     virtual void          detachDevice();
 
+    // Calculate the ANativeWindow transform from android.sensor.orientation
+    status_t              getRotationTransformLocked(/*out*/int32_t* transform);
+
 private:
     /** ICameraDeviceUser interface-related private members */