Cleanup openRecord error handling

Bug: 10888816
Change-Id: I84897dd7d30b370640b54e928f230604b873cb68
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 49f921b..eaf7780 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -53,6 +53,9 @@
     };
     typedef uint32_t track_flags_t;
 
+    // invariant on exit for all APIs that return an sp<>:
+    //   (return value != 0) == (*status == NO_ERROR)
+
     /* create an audio track and registers it with AudioFlinger.
      * return null if the track cannot be created.
      */
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index c5a7777..666fafa 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -474,7 +474,7 @@
     ALOGE_IF(originalSessionId != 0 && mSessionId != originalSessionId,
             "session ID changed from %d to %d", originalSessionId, mSessionId);
 
-    if (record == 0) {
+    if (record == 0 || status != NO_ERROR) {
         ALOGE("AudioFlinger could not create record track, status: %d", status);
         AudioSystem::releaseInput(input);
         return status;
@@ -484,6 +484,11 @@
         ALOGE("Could not get control block");
         return NO_INIT;
     }
+    void *iMemPointer = iMem->pointer();
+    if (iMemPointer == NULL) {
+        ALOGE("Could not get control block pointer");
+        return NO_INIT;
+    }
     if (mAudioRecord != 0) {
         mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this);
         mDeathNotifier.clear();
@@ -491,7 +496,7 @@
     mInput = input;
     mAudioRecord = record;
     mCblkMemory = iMem;
-    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMem->pointer());
+    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
     mCblk = cblk;
     // FIXME missing fast track frameCount logic
     mAwaitBoost = false;
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index be818c6..2cc35c6 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -179,6 +179,17 @@
             }
             lStatus = reply.readInt32();
             record = interface_cast<IAudioRecord>(reply.readStrongBinder());
+            if (lStatus == NO_ERROR) {
+                if (record == 0) {
+                    ALOGE("openRecord should have returned an IAudioRecord");
+                    lStatus = UNKNOWN_ERROR;
+                }
+            } else {
+                if (record != 0) {
+                    ALOGE("openRecord returned an IAudioRecord but with status %d", lStatus);
+                    record.clear();
+                }
+            }
         }
         if (status) {
             *status = lStatus;
@@ -767,6 +778,7 @@
             status_t status;
             sp<IAudioRecord> record = openRecord(input,
                     sampleRate, format, channelMask, frameCount, &flags, tid, &sessionId, &status);
+            LOG_ALWAYS_FATAL_IF((record != 0) != (status == NO_ERROR));
             reply->writeInt32(flags);
             reply->writeInt32(sessionId);
             reply->writeInt32(status);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index f6e4c6a..b8f2d0d 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1242,6 +1242,7 @@
 
     // check calling permissions
     if (!recordingAllowed()) {
+        ALOGE("openRecord() permission denied: recording not allowed");
         lStatus = PERMISSION_DENIED;
         goto Exit;
     }
@@ -1257,12 +1258,14 @@
         Mutex::Autolock _l(mLock);
         thread = checkRecordThread_l(input);
         if (thread == NULL) {
+            ALOGE("openRecord() checkRecordThread_l failed");
             lStatus = BAD_VALUE;
             goto Exit;
         }
 
         if (deviceRequiresCaptureAudioOutputPermission(thread->inDevice())
                 && !captureAudioOutputAllowed()) {
+            ALOGE("openRecord() permission denied: capture not allowed");
             lStatus = PERMISSION_DENIED;
             goto Exit;
         }
@@ -1283,6 +1286,7 @@
         // The record track uses one track in mHardwareMixerThread by convention.
         recordTrack = thread->createRecordTrack_l(client, sampleRate, format, channelMask,
                                                   frameCount, lSessionId, flags, tid, &lStatus);
+        LOG_ALWAYS_FATAL_IF((recordTrack != 0) != (lStatus == NO_ERROR));
     }
     if (lStatus != NO_ERROR) {
         // remove local strong reference to Client before deleting the RecordTrack so that the
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 5f36cab..cba9ad1 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4548,7 +4548,7 @@
 
     lStatus = initCheck();
     if (lStatus != NO_ERROR) {
-        ALOGE("Audio driver not initialized.");
+        ALOGE("createRecordTrack_l() audio driver not initialized");
         goto Exit;
     }
 
@@ -4612,7 +4612,9 @@
                       format, channelMask, frameCount, sessionId);
 
         if (track->getCblk() == 0) {
+            ALOGE("createRecordTrack_l() no control block");
             lStatus = NO_MEMORY;
+            track.clear();
             goto Exit;
         }
         mTracks.add(track);