OSDN Git Service

android-2.1_r1 snapshot
authorThe Android Open Source Project <initial-contribution@android.com>
Tue, 12 Jan 2010 23:18:53 +0000 (15:18 -0800)
committerThe Android Open Source Project <initial-contribution@android.com>
Tue, 12 Jan 2010 23:18:53 +0000 (15:18 -0800)
19 files changed:
camera/libcameraservice/CameraService.cpp
include/ui/Surface.h
libs/audioflinger/AudioFlinger.cpp
libs/audioflinger/AudioFlinger.h
libs/binder/ProcessState.cpp
libs/surfaceflinger/Android.mk
libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
libs/surfaceflinger/Layer.cpp
libs/surfaceflinger/LayerBuffer.cpp
libs/surfaceflinger/LayerBuffer.h
libs/surfaceflinger/SurfaceFlinger.cpp
libs/surfaceflinger/SurfaceFlinger.h
libs/ui/FramebufferNativeWindow.cpp
libs/ui/Surface.cpp
libs/utils/ResourceTypes.cpp
opengl/libagl/array.cpp
opengl/libagl/copybit.cpp
opengl/libagl/egl.cpp
opengl/libagl/state.cpp

index df59dcf..6419a5c 100644 (file)
@@ -669,8 +669,14 @@ status_t CameraService::Client::startRecording()
     LOGD("startRecording (pid %d)", getCallingPid());
 
     if (mMediaPlayerBeep.get() != NULL) {
-        mMediaPlayerBeep->seekTo(0);
-        mMediaPlayerBeep->start();
+        // do not play record jingle if stream volume is 0
+        // (typically because ringer mode is silent).
+        int index;
+        AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
+        if (index != 0) {
+            mMediaPlayerBeep->seekTo(0);
+            mMediaPlayerBeep->start();
+        }
     }
 
     mHardware->enableMsgType(CAMERA_MSG_VIDEO_FRAME);
@@ -888,8 +894,14 @@ void CameraService::Client::handleShutter(
 {
     // Play shutter sound.
     if (mMediaPlayerClick.get() != NULL) {
-        mMediaPlayerClick->seekTo(0);
-        mMediaPlayerClick->start();
+        // do not play shutter sound if stream volume is 0
+        // (typically because ringer mode is silent).
+        int index;
+        AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
+        if (index != 0) {
+            mMediaPlayerClick->seekTo(0);
+            mMediaPlayerClick->start();
+        }
     }
 
     // Screen goes black after the buffer is unregistered.
index 70303cd..008c297 100644 (file)
@@ -109,7 +109,7 @@ private:
 
     ~SurfaceControl();
 
-    status_t validate(SharedClient const* cblk) const;
+    status_t validate() const;
     void destroy();
     
     sp<SurfaceComposerClient>   mClient;
@@ -190,7 +190,7 @@ private:
 
     status_t getBufferLocked(int index, int usage);
    
-           status_t validate(SharedClient const* cblk) const;
+           status_t validate() const;
 
     inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
     inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
index ebd470f..2024cc0 100644 (file)
@@ -674,32 +674,13 @@ void AudioFlinger::binderDied(const wp<IBinder>& who) {
 }
 
 // audioConfigChanged_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::audioConfigChanged_l(int event, const sp<ThreadBase>& thread, void *param2) {
-    int ioHandle = 0;
-
-    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-        if (mPlaybackThreads.valueAt(i) == thread) {
-            ioHandle = mPlaybackThreads.keyAt(i);
-            break;
-        }
-    }
-    if (ioHandle == 0) {
-        for (size_t i = 0; i < mRecordThreads.size(); i++) {
-            if (mRecordThreads.valueAt(i) == thread) {
-                ioHandle = mRecordThreads.keyAt(i);
-                break;
-            }
-        }
-    }
-
-    if (ioHandle != 0) {
-        size_t size = mNotificationClients.size();
-        for (size_t i = 0; i < size; i++) {
-            sp<IBinder> binder = mNotificationClients.itemAt(i);
-            LOGV("audioConfigChanged_l() Notifying change to client %p", binder.get());
-            sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
-            client->ioConfigChanged(event, ioHandle, param2);
-        }
+void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2) {
+    size_t size = mNotificationClients.size();
+    for (size_t i = 0; i < size; i++) {
+        sp<IBinder> binder = mNotificationClients.itemAt(i);
+        LOGV("audioConfigChanged_l() Notifying change to client %p", binder.get());
+        sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
+        client->ioConfigChanged(event, ioHandle, param2);
     }
 }
 
@@ -712,10 +693,10 @@ void AudioFlinger::removeClient_l(pid_t pid)
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger)
+AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id)
     :   Thread(false),
         mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
-        mFormat(0), mFrameSize(1), mStandby(false)
+        mFormat(0), mFrameSize(1), mStandby(false), mId(id), mExiting(false)
 {
 }
 
@@ -734,6 +715,7 @@ void AudioFlinger::ThreadBase::exit()
     LOGV("ThreadBase::exit");
     {
         AutoMutex lock(&mLock);
+        mExiting = true;
         requestExit();
         mWaitWorkCV.signal();
     }
@@ -870,8 +852,8 @@ status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output)
-    :   ThreadBase(audioFlinger),
+AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
+    :   ThreadBase(audioFlinger, id),
         mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
         mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
 {
@@ -1106,15 +1088,6 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
 {
     status_t status = ALREADY_EXISTS;
 
-    // here the track could be either new, or restarted
-    // in both cases "unstop" the track
-    if (track->isPaused()) {
-        track->mState = TrackBase::RESUMING;
-        LOGV("PAUSED => RESUMING (%d) on thread %p", track->name(), this);
-    } else {
-        track->mState = TrackBase::ACTIVE;
-        LOGV("? => ACTIVE (%d) on thread %p", track->name(), this);
-    }
     // set retry count for buffer fill
     track->mRetryCount = kMaxTrackStartupRetries;
     if (mActiveTracks.indexOf(track) < 0) {
@@ -1138,7 +1111,6 @@ void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
 {
     track->mState = TrackBase::TERMINATED;
     if (mActiveTracks.indexOf(track) < 0) {
-        LOGV("remove track (%d) and delete from mixer", track->name());
         mTracks.remove(track);
         deleteTrackName_l(track->name());
     }
@@ -1173,7 +1145,7 @@ void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) {
         break;
     }
     Mutex::Autolock _l(mAudioFlinger->mLock);
-    mAudioFlinger->audioConfigChanged_l(event, this, param2);
+    mAudioFlinger->audioConfigChanged_l(event, mId, param2);
 }
 
 void AudioFlinger::PlaybackThread::readOutputParameters()
@@ -1185,7 +1157,6 @@ void AudioFlinger::PlaybackThread::readOutputParameters()
     mFrameSize = mOutput->frameSize();
     mFrameCount = mOutput->bufferSize() / mFrameSize;
 
-    mMinBytesToWrite = (mOutput->latency() * mSampleRate * mFrameSize) / 1000;
     // FIXME - Current mixer implementation only supports stereo output: Always
     // Allocate a stereo buffer even if HW output is mono.
     if (mMixBuffer != NULL) delete mMixBuffer;
@@ -1195,8 +1166,8 @@ void AudioFlinger::PlaybackThread::readOutputParameters()
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output)
-    :   PlaybackThread(audioFlinger, output),
+AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
+    :   PlaybackThread(audioFlinger, output, id),
         mAudioMixer(0)
 {
     mType = PlaybackThread::MIXER;
@@ -1215,23 +1186,25 @@ AudioFlinger::MixerThread::~MixerThread()
 
 bool AudioFlinger::MixerThread::threadLoop()
 {
-    uint32_t sleepTime = 1000;
-    uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
     int16_t* curBuf = mMixBuffer;
     Vector< sp<Track> > tracksToRemove;
-    size_t enabledTracks = 0;
+    uint32_t mixerStatus = MIXER_IDLE;
     nsecs_t standbyTime = systemTime();
     size_t mixBufferSize = mFrameCount * mFrameSize;
     // FIXME: Relaxed timing because of a certain device that can't meet latency
     // Should be reduced to 2x after the vendor fixes the driver issue
     nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
     nsecs_t lastWarning = 0;
+    bool longStandbyExit = false;
+    uint32_t activeSleepTime = activeSleepTimeUs();
+    uint32_t idleSleepTime = idleSleepTimeUs();
+    uint32_t sleepTime = idleSleepTime;
 
     while (!exitPending())
     {
         processConfigEvents();
 
-        enabledTracks = 0;
+        mixerStatus = MIXER_IDLE;
         { // scope for mLock
 
             Mutex::Autolock _l(mLock);
@@ -1241,7 +1214,8 @@ bool AudioFlinger::MixerThread::threadLoop()
                 // FIXME: Relaxed timing because of a certain device that can't meet latency
                 // Should be reduced to 2x after the vendor fixes the driver issue
                 maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
-                maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+                activeSleepTime = activeSleepTimeUs();
+                idleSleepTime = idleSleepTimeUs();
             }
 
             const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
@@ -1277,15 +1251,15 @@ bool AudioFlinger::MixerThread::threadLoop()
                     }
 
                     standbyTime = systemTime() + kStandbyTimeInNsecs;
-                    sleepTime = 1000;
+                    sleepTime = idleSleepTime;
                     continue;
                 }
             }
 
-            enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
+            mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
        }
 
-        if (LIKELY(enabledTracks)) {
+        if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
             // mix buffers...
             mAudioMixer->process(curBuf);
             sleepTime = 0;
@@ -1294,15 +1268,21 @@ bool AudioFlinger::MixerThread::threadLoop()
             // If no tracks are ready, sleep once for the duration of an output
             // buffer size, then write 0s to the output
             if (sleepTime == 0) {
-                sleepTime = maxBufferRecoveryInUsecs;
-            } else if (mBytesWritten != 0) {
+                if (mixerStatus == MIXER_TRACKS_ENABLED) {
+                    sleepTime = activeSleepTime;
+                } else {
+                    sleepTime = idleSleepTime;
+                }
+            } else if (mBytesWritten != 0 ||
+                       (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
                 memset (curBuf, 0, mixBufferSize);
                 sleepTime = 0;
+                LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
             }
         }
 
         if (mSuspended) {
-            sleepTime = maxBufferRecoveryInUsecs;
+            sleepTime = idleSleepTime;
         }
         // sleepTime == 0 means we must write to audio hardware
         if (sleepTime == 0) {
@@ -1312,7 +1292,6 @@ bool AudioFlinger::MixerThread::threadLoop()
             if (bytesWritten > 0) mBytesWritten += bytesWritten;
             mNumWrites++;
             mInWrite = false;
-            mStandby = false;
             nsecs_t now = systemTime();
             nsecs_t delta = now - mLastWriteTime;
             if (delta > maxPeriod) {
@@ -1322,7 +1301,11 @@ bool AudioFlinger::MixerThread::threadLoop()
                             ns2ms(delta), mNumDelayedWrites, this);
                     lastWarning = now;
                 }
+                if (mStandby) {
+                    longStandbyExit = true;
+                }
             }
+            mStandby = false;
         } else {
             usleep(sleepTime);
         }
@@ -1342,10 +1325,10 @@ bool AudioFlinger::MixerThread::threadLoop()
 }
 
 // prepareTracks_l() must be called with ThreadBase::mLock held
-size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
+uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
 {
 
-    size_t enabledTracks = 0;
+    uint32_t mixerStatus = MIXER_IDLE;
     // find out which tracks need to be processed
     size_t count = activeTracks.size();
     for (size_t i=0 ; i<count ; i++) {
@@ -1415,7 +1398,7 @@ size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track>
 
             // reset retry count
             track->mRetryCount = kMaxTrackRetries;
-            enabledTracks++;
+            mixerStatus = MIXER_TRACKS_READY;
         } else {
             //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
             if (track->isStopped()) {
@@ -1432,16 +1415,11 @@ size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track>
                 if (--(track->mRetryCount) <= 0) {
                     LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
                     tracksToRemove->add(track);
+                } else if (mixerStatus != MIXER_TRACKS_READY) {
+                    mixerStatus = MIXER_TRACKS_ENABLED;
                 }
-                // For tracks using static shared memory buffer, make sure that we have
-                // written enough data to audio hardware before disabling the track
-                // NOTE: this condition with arrive before track->mRetryCount <= 0 so we
-                // don't care about code removing track from active list above.
-                if ((track->mSharedBuffer == 0) || (mBytesWritten >= mMinBytesToWrite)) {
-                    mAudioMixer->disable(AudioMixer::MIXING);
-                } else {
-                    enabledTracks++;
-                }
+
+                mAudioMixer->disable(AudioMixer::MIXING);
             }
         }
     }
@@ -1459,7 +1437,7 @@ size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track>
         }
     }
 
-    return enabledTracks;
+    return mixerStatus;
 }
 
 void AudioFlinger::MixerThread::getTracks(
@@ -1532,6 +1510,7 @@ int AudioFlinger::MixerThread::getTrackName_l()
 // deleteTrackName_l() must be called with ThreadBase::mLock held
 void AudioFlinger::MixerThread::deleteTrackName_l(int name)
 {
+    LOGV("remove track (%d) and delete from mixer", name);
     mAudioMixer->deleteTrackName(name);
 }
 
@@ -1621,19 +1600,19 @@ status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>
     return NO_ERROR;
 }
 
-uint32_t AudioFlinger::MixerThread::getMaxBufferRecoveryInUsecs()
+uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
 {
-    uint32_t time = ((mFrameCount * 1000) / mSampleRate) * 1000;
-    // Add some margin with regard to scheduling precision
-    if (time > 10000) {
-        time -= 10000;
-    }
-    return time;
+    return (uint32_t)(mOutput->latency() * 1000) / 2;
+}
+
+uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
+{
+    return (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
 }
 
 // ----------------------------------------------------------------------------
-AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output)
-    :   PlaybackThread(audioFlinger, output),
+AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
+    :   PlaybackThread(audioFlinger, output, id),
     mLeftVolume (1.0), mRightVolume(1.0)
 {
     mType = PlaybackThread::DIRECT;
@@ -1646,25 +1625,31 @@ AudioFlinger::DirectOutputThread::~DirectOutputThread()
 
 bool AudioFlinger::DirectOutputThread::threadLoop()
 {
-    uint32_t sleepTime = 1000;
-    uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+    uint32_t mixerStatus = MIXER_IDLE;
     sp<Track> trackToRemove;
     sp<Track> activeTrack;
     nsecs_t standbyTime = systemTime();
     int8_t *curBuf;
     size_t mixBufferSize = mFrameCount*mFrameSize;
+    uint32_t activeSleepTime = activeSleepTimeUs();
+    uint32_t idleSleepTime = idleSleepTimeUs();
+    uint32_t sleepTime = idleSleepTime;
+
 
     while (!exitPending())
     {
         processConfigEvents();
 
+        mixerStatus = MIXER_IDLE;
+
         { // scope for the mLock
 
             Mutex::Autolock _l(mLock);
 
             if (checkForNewParameters_l()) {
                 mixBufferSize = mFrameCount*mFrameSize;
-                maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+                activeSleepTime = activeSleepTimeUs();
+                idleSleepTime = idleSleepTimeUs();
             }
 
             // put audio hardware into standby after short delay
@@ -1698,7 +1683,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
                     }
 
                     standbyTime = systemTime() + kStandbyTimeInNsecs;
-                    sleepTime = 1000;
+                    sleepTime = idleSleepTime;
                     continue;
                 }
             }
@@ -1753,6 +1738,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
                     // reset retry count
                     track->mRetryCount = kMaxTrackRetries;
                     activeTrack = t;
+                    mixerStatus = MIXER_TRACKS_READY;
                 } else {
                     //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
                     if (track->isStopped()) {
@@ -1768,16 +1754,10 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
                         if (--(track->mRetryCount) <= 0) {
                             LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
                             trackToRemove = track;
+                        } else {
+                            mixerStatus = MIXER_TRACKS_ENABLED;
                         }
-
-                        // For tracks using static shared memry buffer, make sure that we have
-                        // written enough data to audio hardware before disabling the track
-                        // NOTE: this condition with arrive before track->mRetryCount <= 0 so we
-                        // don't care about code removing track from active list above.
-                        if ((track->mSharedBuffer != 0) && (mBytesWritten < mMinBytesToWrite)) {
-                            activeTrack = t;
-                        }
-                     }
+                    }
                 }
             }
 
@@ -1791,7 +1771,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
             }
        }
 
-        if (activeTrack != 0) {
+        if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
             AudioBufferProvider::Buffer buffer;
             size_t frameCount = mFrameCount;
             curBuf = (int8_t *)mMixBuffer;
@@ -1812,7 +1792,11 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
             standbyTime = systemTime() + kStandbyTimeInNsecs;
         } else {
             if (sleepTime == 0) {
-                sleepTime = maxBufferRecoveryInUsecs;
+                if (mixerStatus == MIXER_TRACKS_ENABLED) {
+                    sleepTime = activeSleepTime;
+                } else {
+                    sleepTime = idleSleepTime;
+                }
             } else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) {
                 memset (mMixBuffer, 0, mFrameCount * mFrameSize);
                 sleepTime = 0;
@@ -1820,7 +1804,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
         }
 
         if (mSuspended) {
-            sleepTime = maxBufferRecoveryInUsecs;
+            sleepTime = idleSleepTime;
         }
         // sleepTime == 0 means we must write to audio hardware
         if (sleepTime == 0) {
@@ -1905,15 +1889,22 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
     return reconfig;
 }
 
-uint32_t AudioFlinger::DirectOutputThread::getMaxBufferRecoveryInUsecs()
+uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
 {
     uint32_t time;
     if (AudioSystem::isLinearPCM(mFormat)) {
-        time = ((mFrameCount * 1000) / mSampleRate) * 1000;
-        // Add some margin with regard to scheduling precision
-        if (time > 10000) {
-            time -= 10000;
-        }
+        time = (uint32_t)(mOutput->latency() * 1000) / 2;
+    } else {
+        time = 10000;
+    }
+    return time;
+}
+
+uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
+{
+    uint32_t time;
+    if (AudioSystem::isLinearPCM(mFormat)) {
+        time = (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
     } else {
         time = 10000;
     }
@@ -1922,8 +1913,8 @@ uint32_t AudioFlinger::DirectOutputThread::getMaxBufferRecoveryInUsecs()
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread)
-    :   MixerThread(audioFlinger, mainThread->getOutput())
+AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
+    :   MixerThread(audioFlinger, mainThread->getOutput(), id)
 {
     mType = PlaybackThread::DUPLICATING;
     addOutputTrack(mainThread);
@@ -1931,33 +1922,38 @@ AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audio
 
 AudioFlinger::DuplicatingThread::~DuplicatingThread()
 {
+    for (size_t i = 0; i < mOutputTracks.size(); i++) {
+        mOutputTracks[i]->destroy();
+    }
     mOutputTracks.clear();
 }
 
 bool AudioFlinger::DuplicatingThread::threadLoop()
 {
-    uint32_t sleepTime = 1000;
-    uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
     int16_t* curBuf = mMixBuffer;
     Vector< sp<Track> > tracksToRemove;
-    size_t enabledTracks = 0;
+    uint32_t mixerStatus = MIXER_IDLE;
     nsecs_t standbyTime = systemTime();
     size_t mixBufferSize = mFrameCount*mFrameSize;
     SortedVector< sp<OutputTrack> > outputTracks;
     uint32_t writeFrames = 0;
+    uint32_t activeSleepTime = activeSleepTimeUs();
+    uint32_t idleSleepTime = idleSleepTimeUs();
+    uint32_t sleepTime = idleSleepTime;
 
     while (!exitPending())
     {
         processConfigEvents();
 
-        enabledTracks = 0;
+        mixerStatus = MIXER_IDLE;
         { // scope for the mLock
 
             Mutex::Autolock _l(mLock);
 
             if (checkForNewParameters_l()) {
                 mixBufferSize = mFrameCount*mFrameSize;
-                maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+                activeSleepTime = activeSleepTimeUs();
+                idleSleepTime = idleSleepTimeUs();
             }
 
             const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
@@ -1997,22 +1993,26 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
                     }
 
                     standbyTime = systemTime() + kStandbyTimeInNsecs;
-                    sleepTime = 1000;
+                    sleepTime = idleSleepTime;
                     continue;
                 }
             }
 
-            enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
+            mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
         }
 
-        if (LIKELY(enabledTracks)) {
+        if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
             // mix buffers...
             mAudioMixer->process(curBuf);
             sleepTime = 0;
             writeFrames = mFrameCount;
         } else {
             if (sleepTime == 0) {
-                sleepTime = maxBufferRecoveryInUsecs;
+                if (mixerStatus == MIXER_TRACKS_ENABLED) {
+                    sleepTime = activeSleepTime;
+                } else {
+                    sleepTime = idleSleepTime;
+                }
             } else if (mBytesWritten != 0) {
                 // flush remaining overflow buffers in output tracks
                 for (size_t i = 0; i < outputTracks.size(); i++) {
@@ -2026,7 +2026,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
         }
 
         if (mSuspended) {
-            sleepTime = maxBufferRecoveryInUsecs;
+            sleepTime = idleSleepTime;
         }
         // sleepTime == 0 means we must write to audio hardware
         if (sleepTime == 0) {
@@ -2047,17 +2047,6 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
         outputTracks.clear();
     }
 
-    { // scope for the mLock
-
-        Mutex::Autolock _l(mLock);
-        if (!mStandby) {
-            LOGV("DuplicatingThread() exiting out of standby");
-            for (size_t i = 0; i < mOutputTracks.size(); i++) {
-                mOutputTracks[i]->destroy();
-            }
-        }
-    }
-
     return false;
 }
 
@@ -2299,6 +2288,12 @@ void AudioFlinger::PlaybackThread::Track::destroy()
     { // scope for mLock
         sp<ThreadBase> thread = mThread.promote();
         if (thread != 0) {
+            if (!isOutputTrack()) {
+                if (mState == ACTIVE || mState == RESUMING) {
+                    AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
+                }
+                AudioSystem::releaseOutput(thread->id());
+            }
             Mutex::Autolock _l(thread->mLock);
             PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
             playbackThread->destroyTrack_l(this);
@@ -2380,14 +2375,37 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const {
 
 status_t AudioFlinger::PlaybackThread::Track::start()
 {
+    status_t status = NO_ERROR;
     LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
     sp<ThreadBase> thread = mThread.promote();
     if (thread != 0) {
         Mutex::Autolock _l(thread->mLock);
-        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
-        playbackThread->addTrack_l(this);
+        int state = mState;
+        // here the track could be either new, or restarted
+        // in both cases "unstop" the track
+        if (mState == PAUSED) {
+            mState = TrackBase::RESUMING;
+            LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
+        } else {
+            mState = TrackBase::ACTIVE;
+            LOGV("? => ACTIVE (%d) on thread %p", mName, this);
+        }
+
+        if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
+            thread->mLock.unlock();
+            status = AudioSystem::startOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
+            thread->mLock.lock();
+        }
+        if (status == NO_ERROR) {
+            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+            playbackThread->addTrack_l(this);
+        } else {
+            mState = state;
+        }
+    } else {
+        status = BAD_VALUE;
     }
-    return NO_ERROR;
+    return status;
 }
 
 void AudioFlinger::PlaybackThread::Track::stop()
@@ -2396,6 +2414,7 @@ void AudioFlinger::PlaybackThread::Track::stop()
     sp<ThreadBase> thread = mThread.promote();
     if (thread != 0) {
         Mutex::Autolock _l(thread->mLock);
+        int state = mState;
         if (mState > STOPPED) {
             mState = STOPPED;
             // If the track is not active (PAUSED and buffers full), flush buffers
@@ -2405,6 +2424,11 @@ void AudioFlinger::PlaybackThread::Track::stop()
             }
             LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
         }
+        if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
+            thread->mLock.unlock();
+            AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
+            thread->mLock.lock();
+        }
     }
 }
 
@@ -2417,6 +2441,11 @@ void AudioFlinger::PlaybackThread::Track::pause()
         if (mState == ACTIVE || mState == RESUMING) {
             mState = PAUSING;
             LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
+            if (!isOutputTrack()) {
+                thread->mLock.unlock();
+                AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
+                thread->mLock.lock();
+            }
         }
     }
 }
@@ -2500,6 +2529,10 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack(
 
 AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
 {
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        AudioSystem::releaseInput(thread->id());
+    }
 }
 
 status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
@@ -2547,8 +2580,9 @@ status_t AudioFlinger::RecordThread::RecordTrack::start()
     if (thread != 0) {
         RecordThread *recordThread = (RecordThread *)thread.get();
         return recordThread->start(this);
+    } else {
+        return BAD_VALUE;
     }
-    return NO_INIT;
 }
 
 void AudioFlinger::RecordThread::RecordTrack::stop()
@@ -2985,8 +3019,8 @@ status_t AudioFlinger::RecordHandle::onTransact(
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels) :
-    ThreadBase(audioFlinger),
+AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) :
+    ThreadBase(audioFlinger, id),
     mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
 {
     mReqChannelCount = AudioSystem::popCount(channels);
@@ -3014,6 +3048,7 @@ void AudioFlinger::RecordThread::onFirstRef()
 
     run(buffer, PRIORITY_URGENT_AUDIO);
 }
+
 bool AudioFlinger::RecordThread::threadLoop()
 {
     AudioBufferProvider::Buffer buffer;
@@ -3043,22 +3078,37 @@ bool AudioFlinger::RecordThread::threadLoop()
             }
             if (mActiveTrack != 0) {
                 if (mActiveTrack->mState == TrackBase::PAUSING) {
+                    if (!mStandby) {
+                        mInput->standby();
+                        mStandby = true;
+                    }
                     mActiveTrack.clear();
                     mStartStopCond.broadcast();
                 } else if (mActiveTrack->mState == TrackBase::RESUMING) {
-                    mRsmpInIndex = mFrameCount;
                     if (mReqChannelCount != mActiveTrack->channelCount()) {
                         mActiveTrack.clear();
-                    } else {
-                        mActiveTrack->mState = TrackBase::ACTIVE;
+                        mStartStopCond.broadcast();
+                    } else if (mBytesRead != 0) {
+                        // record start succeeds only if first read from audio input
+                        // succeeds
+                        if (mBytesRead > 0) {
+                            mActiveTrack->mState = TrackBase::ACTIVE;
+                        } else {
+                            mActiveTrack.clear();
+                        }
+                        mStartStopCond.broadcast();
                     }
-                    mStartStopCond.broadcast();
+                    mStandby = false;
                 }
-                mStandby = false;
             }
         }
 
         if (mActiveTrack != 0) {
+            if (mActiveTrack->mState != TrackBase::ACTIVE &&
+                mActiveTrack->mState != TrackBase::RESUMING) {
+                usleep(5000);
+                continue;
+            }
             buffer.frameCount = mFrameCount;
             if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
                 size_t framesOut = buffer.frameCount;
@@ -3093,18 +3143,19 @@ bool AudioFlinger::RecordThread::threadLoop()
                             }
                         }
                         if (framesOut && mFrameCount == mRsmpInIndex) {
-                            ssize_t bytesRead;
                             if (framesOut == mFrameCount &&
                                 (mChannelCount == mReqChannelCount || mFormat != AudioSystem::PCM_16_BIT)) {
-                                bytesRead = mInput->read(buffer.raw, mInputBytes);
+                                mBytesRead = mInput->read(buffer.raw, mInputBytes);
                                 framesOut = 0;
                             } else {
-                                bytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
+                                mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
                                 mRsmpInIndex = 0;
                             }
-                            if (bytesRead < 0) {
+                            if (mBytesRead < 0) {
                                 LOGE("Error reading audio input");
-                                sleep(1);
+                                if (mActiveTrack->mState == TrackBase::ACTIVE) {
+                                    sleep(1);
+                                }
                                 mRsmpInIndex = mFrameCount;
                                 framesOut = 0;
                                 buffer.frameCount = 0;
@@ -3156,6 +3207,8 @@ bool AudioFlinger::RecordThread::threadLoop()
     }
     mActiveTrack.clear();
 
+    mStartStopCond.broadcast();
+
     LOGV("RecordThread %p exiting", this);
     return false;
 }
@@ -3163,37 +3216,74 @@ bool AudioFlinger::RecordThread::threadLoop()
 status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
 {
     LOGV("RecordThread::start");
-    AutoMutex lock(&mLock);
-
-    if (mActiveTrack != 0) {
-        if (recordTrack != mActiveTrack.get()) return -EBUSY;
-
-        if (mActiveTrack->mState == TrackBase::PAUSING) mActiveTrack->mState = TrackBase::RESUMING;
-
-        return NO_ERROR;
-    }
+    sp <ThreadBase> strongMe = this;
+    status_t status = NO_ERROR;
+    {
+        AutoMutex lock(&mLock);
+        if (mActiveTrack != 0) {
+            if (recordTrack != mActiveTrack.get()) {
+                status = -EBUSY;
+            } else if (mActiveTrack->mState == TrackBase::PAUSING) {
+                mActiveTrack->mState = TrackBase::ACTIVE;
+            }
+            return status;
+        }
 
-    mActiveTrack = recordTrack;
-    mActiveTrack->mState = TrackBase::RESUMING;
-    // signal thread to start
-    LOGV("Signal record thread");
-    mWaitWorkCV.signal();
-    mStartStopCond.wait(mLock);
-    if (mActiveTrack != 0) {
+        recordTrack->mState = TrackBase::IDLE;
+        mActiveTrack = recordTrack;
+        mLock.unlock();
+        status_t status = AudioSystem::startInput(mId);
+        mLock.lock();
+        if (status != NO_ERROR) {
+            mActiveTrack.clear();
+            return status;
+        }
+        mActiveTrack->mState = TrackBase::RESUMING;
+        mRsmpInIndex = mFrameCount;
+        mBytesRead = 0;
+        // signal thread to start
+        LOGV("Signal record thread");
+        mWaitWorkCV.signal();
+        // do not wait for mStartStopCond if exiting
+        if (mExiting) {
+            mActiveTrack.clear();
+            status = INVALID_OPERATION;
+            goto startError;
+        }
+        mStartStopCond.wait(mLock);
+        if (mActiveTrack == 0) {
+            LOGV("Record failed to start");
+            status = BAD_VALUE;
+            goto startError;
+        }
         LOGV("Record started OK");
-        return NO_ERROR;
-    } else {
-        LOGV("Record failed to start");
-        return BAD_VALUE;
+        return status;
     }
+startError:
+    AudioSystem::stopInput(mId);
+    return status;
 }
 
 void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
     LOGV("RecordThread::stop");
-    AutoMutex lock(&mLock);
-    if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
-        mActiveTrack->mState = TrackBase::PAUSING;
-        mStartStopCond.wait(mLock);
+    sp <ThreadBase> strongMe = this;
+    {
+        AutoMutex lock(&mLock);
+        if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
+            mActiveTrack->mState = TrackBase::PAUSING;
+            // do not wait for mStartStopCond if exiting
+            if (mExiting) {
+                return;
+            }
+            mStartStopCond.wait(mLock);
+            // if we have been restarted, recordTrack == mActiveTrack.get() here
+            if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
+                mLock.unlock();
+                AudioSystem::stopInput(mId);
+                mLock.lock();
+                LOGV("Record stopped OK");
+            }
+        }
     }
 }
 
@@ -3242,10 +3332,12 @@ status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer*
     int channelCount;
 
     if (framesReady == 0) {
-        ssize_t bytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
-        if (bytesRead < 0) {
+        mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
+        if (mBytesRead < 0) {
             LOGE("RecordThread::getNextBuffer() Error reading audio input");
-            sleep(1);
+            if (mActiveTrack->mState == TrackBase::ACTIVE) {
+                sleep(1);
+            }
             buffer->raw = 0;
             buffer->frameCount = 0;
             return NOT_ENOUGH_DATA;
@@ -3363,7 +3455,7 @@ void AudioFlinger::RecordThread::audioConfigChanged(int event, int param) {
         break;
     }
     Mutex::Autolock _l(mAudioFlinger->mLock);
-    mAudioFlinger->audioConfigChanged_l(event, this, param2);
+    mAudioFlinger->audioConfigChanged_l(event, mId, param2);
 }
 
 void AudioFlinger::RecordThread::readInputParameters()
@@ -3451,21 +3543,23 @@ int AudioFlinger::openOutput(uint32_t *pDevices,
         if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
             (format != AudioSystem::PCM_16_BIT) ||
             (channels != AudioSystem::CHANNEL_OUT_STEREO)) {
-            thread = new DirectOutputThread(this, output);
-            LOGV("openOutput() created direct output: ID %d thread %p", (mNextThreadId + 1), thread);
+            thread = new DirectOutputThread(this, output, ++mNextThreadId);
+            LOGV("openOutput() created direct output: ID %d thread %p", mNextThreadId, thread);
         } else {
-            thread = new MixerThread(this, output);
-            LOGV("openOutput() created mixer output: ID %d thread %p", (mNextThreadId + 1), thread);
+            thread = new MixerThread(this, output, ++mNextThreadId);
+            LOGV("openOutput() created mixer output: ID %d thread %p", mNextThreadId, thread);
         }
-        mPlaybackThreads.add(++mNextThreadId, thread);
+        mPlaybackThreads.add(mNextThreadId, thread);
 
         if (pSamplingRate) *pSamplingRate = samplingRate;
         if (pFormat) *pFormat = format;
         if (pChannels) *pChannels = channels;
         if (pLatencyMs) *pLatencyMs = thread->latency();
+
+        return mNextThreadId;
     }
 
-    return mNextThreadId;
+    return 0;
 }
 
 int AudioFlinger::openDuplicateOutput(int output1, int output2)
@@ -3480,9 +3574,9 @@ int AudioFlinger::openDuplicateOutput(int output1, int output2)
     }
 
 
-    DuplicatingThread *thread = new DuplicatingThread(this, thread1);
+    DuplicatingThread *thread = new DuplicatingThread(this, thread1, ++mNextThreadId);
     thread->addOutputTrack(thread2);
-    mPlaybackThreads.add(++mNextThreadId, thread);
+    mPlaybackThreads.add(mNextThreadId, thread);
     return mNextThreadId;
 }
 
@@ -3509,7 +3603,7 @@ status_t AudioFlinger::closeOutput(int output)
             }
         }
         void *param2 = 0;
-        audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, thread, param2);
+        audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2);
         mPlaybackThreads.removeItem(output);
     }
     thread->exit();
@@ -3603,17 +3697,19 @@ int AudioFlinger::openInput(uint32_t *pDevices,
 
     if (input != 0) {
          // Start record thread
-        thread = new RecordThread(this, input, reqSamplingRate, reqChannels);
-        mRecordThreads.add(++mNextThreadId, thread);
+        thread = new RecordThread(this, input, reqSamplingRate, reqChannels, ++mNextThreadId);
+        mRecordThreads.add(mNextThreadId, thread);
         LOGV("openInput() created record thread: ID %d thread %p", mNextThreadId, thread);
         if (pSamplingRate) *pSamplingRate = reqSamplingRate;
         if (pFormat) *pFormat = format;
         if (pChannels) *pChannels = reqChannels;
 
         input->standby();
+
+        return mNextThreadId;
     }
 
-    return mNextThreadId;
+    return 0;
 }
 
 status_t AudioFlinger::closeInput(int input)
@@ -3630,7 +3726,7 @@ status_t AudioFlinger::closeInput(int input)
 
         LOGV("closeInput() %d", input);
         void *param2 = 0;
-        audioConfigChanged_l(AudioSystem::INPUT_CLOSED, thread, param2);
+        audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
         mRecordThreads.removeItem(input);
     }
     thread->exit();
index 22d15c9..8c29da8 100644 (file)
@@ -213,7 +213,7 @@ private:
 
     class ThreadBase : public Thread {
     public:
-        ThreadBase (const sp<AudioFlinger>& audioFlinger);
+        ThreadBase (const sp<AudioFlinger>& audioFlinger, int id);
         virtual             ~ThreadBase();
 
         status_t dumpBase(int fd, const Vector<String16>& args);
@@ -323,6 +323,7 @@ private:
                     void        sendConfigEvent(int event, int param = 0);
                     void        sendConfigEvent_l(int event, int param = 0);
                     void        processConfigEvents();
+                    int         id() const { return mId;}
 
         mutable     Mutex                   mLock;
 
@@ -349,6 +350,8 @@ private:
                     status_t                mParamStatus;
                     Vector<ConfigEvent *>   mConfigEvents;
                     bool                    mStandby;
+                    int                     mId;
+                    bool                    mExiting;
     };
 
     // --- PlaybackThread ---
@@ -361,6 +364,12 @@ private:
             DUPLICATING
         };
 
+        enum mixer_state {
+            MIXER_IDLE,
+            MIXER_TRACKS_ENABLED,
+            MIXER_TRACKS_READY
+        };
+
         // playback track
         class Track : public TrackBase {
         public:
@@ -415,6 +424,10 @@ private:
             void setPaused() { mState = PAUSED; }
             void reset();
 
+            bool isOutputTrack() const {
+                return (mStreamType == AudioSystem::NUM_STREAM_TYPES);
+            }
+
             // we don't really need a lock for these
             float               mVolume[2];
             volatile bool       mMute;
@@ -467,7 +480,7 @@ private:
 
         };  // end of OutputTrack
 
-        PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output);
+        PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id);
         virtual             ~PlaybackThread();
 
         virtual     status_t    dump(int fd, const Vector<String16>& args);
@@ -530,7 +543,8 @@ private:
 
         virtual int             getTrackName_l() = 0;
         virtual void            deleteTrackName_l(int name) = 0;
-        virtual uint32_t        getMaxBufferRecoveryInUsecs() = 0;
+        virtual uint32_t        activeSleepTimeUs() = 0;
+        virtual uint32_t        idleSleepTimeUs() = 0;
 
     private:
 
@@ -562,12 +576,11 @@ private:
         int                             mNumWrites;
         int                             mNumDelayedWrites;
         bool                            mInWrite;
-        int                             mMinBytesToWrite;
     };
 
     class MixerThread : public PlaybackThread {
     public:
-        MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output);
+        MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id);
         virtual             ~MixerThread();
 
         // Thread virtuals
@@ -582,10 +595,11 @@ private:
         virtual     status_t    dumpInternals(int fd, const Vector<String16>& args);
 
     protected:
-        size_t prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove);
+                    uint32_t    prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove);
         virtual     int         getTrackName_l();
         virtual     void        deleteTrackName_l(int name);
-        virtual     uint32_t    getMaxBufferRecoveryInUsecs();
+        virtual     uint32_t    activeSleepTimeUs();
+        virtual     uint32_t    idleSleepTimeUs();
 
         AudioMixer*                     mAudioMixer;
     };
@@ -593,7 +607,7 @@ private:
     class DirectOutputThread : public PlaybackThread {
     public:
 
-        DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output);
+        DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id);
         ~DirectOutputThread();
 
         // Thread virtuals
@@ -604,7 +618,8 @@ private:
     protected:
         virtual     int         getTrackName_l();
         virtual     void        deleteTrackName_l(int name);
-        virtual     uint32_t    getMaxBufferRecoveryInUsecs();
+        virtual     uint32_t    activeSleepTimeUs();
+        virtual     uint32_t    idleSleepTimeUs();
 
     private:
         float mLeftVolume;
@@ -613,7 +628,7 @@ private:
 
     class DuplicatingThread : public MixerThread {
     public:
-        DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread);
+        DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread, int id);
         ~DuplicatingThread();
 
         // Thread virtuals
@@ -629,7 +644,7 @@ private:
               MixerThread *checkMixerThread_l(int output) const;
               RecordThread *checkRecordThread_l(int input) const;
               float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; }
-              void audioConfigChanged_l(int event, const sp<ThreadBase>& thread, void *param2);
+              void audioConfigChanged_l(int event, int ioHandle, void *param2);
 
     friend class AudioBuffer;
 
@@ -697,7 +712,8 @@ private:
                 RecordThread(const sp<AudioFlinger>& audioFlinger,
                         AudioStreamIn *input,
                         uint32_t sampleRate,
-                        uint32_t channels);
+                        uint32_t channels,
+                        int id);
                 ~RecordThread();
 
         virtual bool        threadLoop();
@@ -728,6 +744,7 @@ private:
                 size_t                              mInputBytes;
                 int                                 mReqChannelCount;
                 uint32_t                            mReqSampleRate;
+                ssize_t                             mBytesRead;
     };
 
     class RecordHandle : public android::BnAudioRecord {
index d7daf73..2d4e10d 100644 (file)
@@ -41,7 +41,7 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 
-#define BINDER_VM_SIZE (1*1024*1024)
+#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
 
 static bool gSingleProcess = false;
 
index eb51c22..b3fed58 100644 (file)
@@ -22,9 +22,6 @@ LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 ifeq ($(TARGET_BOARD_PLATFORM), msm7k)
        LOCAL_CFLAGS += -DDIM_WITH_TEXTURE
 endif
-ifeq ($(TARGET_BOARD_PLATFORM), qsd8k)
-       LOCAL_CFLAGS += -DDIM_WITH_TEXTURE
-endif
 
 # need "-lrt" on Linux simulator to pick up clock_gettime
 ifeq ($(TARGET_SIMULATOR),true)
index 1abfd68..d9d9bfe 100644 (file)
@@ -246,10 +246,11 @@ void DisplayHardware::init(uint32_t dpy)
     LOGI("version   : %s", glGetString(GL_VERSION));
     LOGI("extensions: %s", gl_extensions);
 
-    if (strstr(gl_renderer, "PowerVR SGX 530")) {
+    if (strstr(gl_renderer, "Adreno")) {
         LOGD("Assuming uncached graphics buffers.");
         mFlags &= ~CACHED_BUFFERS;
     }
+
     if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) {
         mFlags |= NPOT_EXTENSION;
     }
index f5a5a0b..1870d3a 100644 (file)
@@ -93,6 +93,7 @@ sp<LayerBaseClient::Surface> Layer::createSurface() const
 status_t Layer::ditch()
 {
     // the layer is not on screen anymore. free as much resources as possible
+    mFreezeLock.clear();
     destroy();
     return NO_ERROR;
 }
@@ -134,7 +135,14 @@ void Layer::reloadTexture(const Region& dirty)
 {
     Mutex::Autolock _l(mLock);
     sp<GraphicBuffer> buffer(getFrontBufferLocked());
-    int index = mFrontBufferIndex;
+    if (buffer == NULL) {
+        // this situation can happen if we ran out of memory for instance.
+        // not much we can do. continue to use whatever texture was bound
+        // to this context.
+        return;
+    }
+
+    const int index = mFrontBufferIndex;
 
     // create the new texture name if needed
     if (UNLIKELY(mTextures[index].name == -1U)) {
@@ -515,6 +523,11 @@ void Layer::unlockPageFlip(
         dirtyRegion.andSelf(visibleRegionScreen);
         outDirtyRegion.orSelf(dirtyRegion);
     }
+    if (visibleRegionScreen.isEmpty()) {
+        // an invisible layer should not hold a freeze-lock
+        // (because it may never be updated and thereore never release it)
+        mFreezeLock.clear();
+    }
 }
 
 void Layer::finishPageFlip()
index a36304c..2ff6167 100644 (file)
@@ -26,6 +26,8 @@
 #include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
 #include <ui/FramebufferNativeWindow.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
 
 #include <hardware/copybit.h>
 
@@ -46,12 +48,15 @@ gralloc_module_t const* LayerBuffer::sGrallocModule = 0;
 LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
         const sp<Client>& client, int32_t i)
     : LayerBaseClient(flinger, display, client, i),
-      mNeedsBlending(false)
+      mNeedsBlending(false), mBlitEngine(0)
 {
 }
 
 LayerBuffer::~LayerBuffer()
 {
+    if (mBlitEngine) {
+        copybit_close(mBlitEngine);
+    }
 }
 
 void LayerBuffer::onFirstRef()
@@ -69,6 +74,10 @@ void LayerBuffer::onFirstRef()
             sGrallocModule = (gralloc_module_t const *)module;
         }
     }
+
+    if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
+        copybit_open(module, &mBlitEngine);
+    }
 }
 
 sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const
@@ -109,7 +118,10 @@ uint32_t LayerBuffer::doTransaction(uint32_t flags)
     sp<Source> source(getSource());
     if (source != 0)
         source->onTransaction(flags);
-    return LayerBase::doTransaction(flags);    
+    uint32_t res = LayerBase::doTransaction(flags);
+    // we always want filtering for these surfaces
+    mUseLinearFiltering = !(mFlags & DisplayHardware::SLOW_CONFIG);
+    return res;
 }
 
 void LayerBuffer::unlockPageFlip(const Transform& planeTransform,
@@ -252,7 +264,16 @@ LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset)
     : mBufferHeap(buffers)
 {
     NativeBuffer& src(mNativeBuffer);
-    src.img.handle = 0;
+    src.crop.l = 0;
+    src.crop.t = 0;
+    src.crop.r = buffers.w;
+    src.crop.b = buffers.h;
+
+    src.img.w       = buffers.hor_stride ?: buffers.w;
+    src.img.h       = buffers.ver_stride ?: buffers.h;
+    src.img.format  = buffers.format;
+    src.img.base    = (void*)(intptr_t(buffers.heap->base()) + offset);
+    src.img.handle  = 0;
 
     gralloc_module_t const * module = LayerBuffer::getGrallocModule();
     if (module && module->perform) {
@@ -262,19 +283,12 @@ LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset)
                 offset, buffers.heap->base(),
                 &src.img.handle);
 
-        if (err == NO_ERROR) {
-            src.crop.l = 0;
-            src.crop.t = 0;
-            src.crop.r = buffers.w;
-            src.crop.b = buffers.h;
-
-            src.img.w       = buffers.hor_stride ?: buffers.w;
-            src.img.h       = buffers.ver_stride ?: buffers.h;
-            src.img.format  = buffers.format;
-            src.img.base    = (void*)(intptr_t(buffers.heap->base()) + offset);
-        }
+        LOGE_IF(err, "CREATE_HANDLE_FROM_BUFFER (heapId=%d, size=%d, "
+             "offset=%ld, base=%p) failed (%s)",
+                buffers.heap->heapID(), buffers.heap->getSize(),
+                offset, buffers.heap->base(), strerror(-err));
     }
-}
+ }
 
 LayerBuffer::Buffer::~Buffer()
 {
@@ -438,15 +452,24 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const
 
 #if defined(EGL_ANDROID_image_native_buffer)
     if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) {
-         // NOTE: Assume the buffer is  allocated with the proper USAGE flags
-        sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
-                src.crop.r, src.crop.b, src.img.format, 
-                GraphicBuffer::USAGE_HW_TEXTURE,
-                src.img.w, src.img.handle, false);
-
-        graphicBuffer->setVerticalStride(src.img.h);
+        copybit_device_t* copybit = mLayer.mBlitEngine;
+        if (copybit) {
+            // create our EGLImageKHR the first time
+            err = initTempBuffer();
+            if (err == NO_ERROR) {
+                // NOTE: Assume the buffer is allocated with the proper USAGE flags
+                const NativeBuffer& dst(mTempBuffer);
+                region_iterator clip(Region(Rect(dst.crop.r, dst.crop.b)));
+                copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
+                copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
+                copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
+                err = copybit->stretch(copybit, &dst.img, &src.img,
+                        &dst.crop, &src.crop, &clip);
 
-        err = mLayer.initializeEglImage(graphicBuffer, &mTexture);
+            }
+        } else {
+            err = INVALID_OPERATION;
+        }
     }
 #endif
     else {
@@ -471,6 +494,72 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const
     mLayer.drawWithOpenGL(clip, mTexture);
 }
 
+status_t LayerBuffer::BufferSource::initTempBuffer() const
+{
+    // figure out the size we need now
+    const ISurface::BufferHeap& buffers(mBufferHeap);
+    uint32_t w = mLayer.mTransformedBounds.width();
+    uint32_t h = mLayer.mTransformedBounds.height();
+    if (buffers.w * h != buffers.h * w) {
+        int t = w; w = h; h = t;
+    }
+
+    if (mTexture.image != EGL_NO_IMAGE_KHR) {
+        // we have an EGLImage, make sure the needed size didn't change
+        if (w!=mTexture.width || h!= mTexture.height) {
+            // delete the EGLImage and texture
+            EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
+            glDeleteTextures(1, &mTexture.name);
+            eglDestroyImageKHR(dpy, mTexture.image);
+            Texture defaultTexture;
+            mTexture = defaultTexture;
+            mTempGraphicBuffer.clear();
+        } else {
+            // we're good, we have an EGLImageKHR and it's (still) the
+            // right size
+            return NO_ERROR;
+        }
+    }
+
+    // figure out if we need linear filtering
+    if (buffers.w * h == buffers.h * w) {
+        // same pixel area, don't use filtering
+        mLayer.mUseLinearFiltering = false;
+    }
+
+    // Allocate a temporary buffer and create the corresponding EGLImageKHR
+
+    status_t err;
+    mTempGraphicBuffer.clear();
+    mTempGraphicBuffer = new GraphicBuffer(
+            w, h, HAL_PIXEL_FORMAT_RGB_565,
+            GraphicBuffer::USAGE_HW_TEXTURE |
+            GraphicBuffer::USAGE_HW_2D);
+
+    err = mTempGraphicBuffer->initCheck();
+    if (err == NO_ERROR) {
+        NativeBuffer& dst(mTempBuffer);
+        dst.img.w = mTempGraphicBuffer->getStride();
+        dst.img.h = h;
+        dst.img.format = mTempGraphicBuffer->getPixelFormat();
+        dst.img.handle = (native_handle_t *)mTempGraphicBuffer->handle;
+        dst.img.base = 0;
+        dst.crop.l = 0;
+        dst.crop.t = 0;
+        dst.crop.r = w;
+        dst.crop.b = h;
+
+        err = mLayer.initializeEglImage(
+                mTempGraphicBuffer, &mTexture);
+        // once the EGLImage has been created (whether it fails
+        // or not) we don't need the graphic buffer reference
+        // anymore.
+        mTempGraphicBuffer.clear();
+    }
+
+    return err;
+}
+
 // ---------------------------------------------------------------------------
 
 LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer,
index 47482f4..2ca63ac 100644 (file)
@@ -130,13 +130,15 @@ private:
         virtual bool transformed() const;
         virtual void destroy() { }
     private:
+        status_t initTempBuffer() const;
         mutable Mutex                   mBufferSourceLock;
         sp<Buffer>                      mBuffer;
         status_t                        mStatus;
         ISurface::BufferHeap            mBufferHeap;
         size_t                          mBufferSize;
-        mutable sp<GraphicBuffer>       mTempBitmap;
         mutable LayerBase::Texture      mTexture;
+        mutable NativeBuffer            mTempBuffer;
+        mutable sp<GraphicBuffer>       mTempGraphicBuffer;
     };
     
     class OverlaySource : public Source {
@@ -205,6 +207,7 @@ private:
     sp<Surface>     mSurface;
     bool            mInvalidate;
     bool            mNeedsBlending;
+    copybit_device_t* mBlitEngine;
 };
 
 // ---------------------------------------------------------------------------
index 9694cf1..965b7dd 100644 (file)
@@ -417,9 +417,9 @@ void SurfaceFlinger::waitForEvent()
 {
     while (true) {
         nsecs_t timeout = -1;
+        const nsecs_t freezeDisplayTimeout = ms2ns(5000);
         if (UNLIKELY(isFrozen())) {
             // wait 5 seconds
-            const nsecs_t freezeDisplayTimeout = ms2ns(5000);
             const nsecs_t now = systemTime();
             if (mFreezeDisplayTime == 0) {
                 mFreezeDisplayTime = now;
@@ -429,22 +429,26 @@ void SurfaceFlinger::waitForEvent()
         }
 
         MessageList::value_type msg = mEventQueue.waitMessage(timeout);
-        if (msg != 0) {
-            mFreezeDisplayTime = 0;
-            switch (msg->what) {
-                case MessageQueue::INVALIDATE:
-                    // invalidate message, just return to the main loop
-                    return;
-            }
-        } else {
-            // we timed out
-            if (isFrozen()) {
+
+        // see if we timed out
+        if (isFrozen()) {
+            const nsecs_t now = systemTime();
+            nsecs_t frozenTime = (now - mFreezeDisplayTime);
+            if (frozenTime >= freezeDisplayTimeout) {
                 // we timed out and are still frozen
                 LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d",
                         mFreezeDisplay, mFreezeCount);
+                mFreezeDisplayTime = 0;
                 mFreezeCount = 0;
                 mFreezeDisplay = false;
-                return;
+            }
+        }
+
+        if (msg != 0) {
+            switch (msg->what) {
+                case MessageQueue::INVALIDATE:
+                    // invalidate message, just return to the main loop
+                    return;
             }
         }
     }
@@ -1646,6 +1650,7 @@ status_t SurfaceFlinger::onTransact(
             }
             case 1007: // set mFreezeCount
                 mFreezeCount = data.readInt32();
+                mFreezeDisplayTime = 0;
                 return NO_ERROR;
             case 1010:  // interrogate.
                 reply->writeInt32(0);
index f9bfe6c..c0ab73d 100644 (file)
@@ -291,7 +291,11 @@ private:
 
             friend class FreezeLock;
             sp<FreezeLock> getFreezeLock() const;
-            inline void incFreezeCount() { mFreezeCount++; }
+            inline void incFreezeCount() {
+                if (mFreezeCount == 0)
+                    mFreezeDisplayTime = 0;
+                mFreezeCount++;
+            }
             inline void decFreezeCount() { if (mFreezeCount > 0) mFreezeCount--; }
             inline bool hasFreezeRequest() const { return mFreezeDisplay; }
             inline bool isFrozen() const { 
index 0efba9c..c5e22e5 100644 (file)
@@ -118,8 +118,6 @@ FramebufferNativeWindow::FramebufferNativeWindow()
         LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s",
                 fbDev->width, fbDev->height, strerror(-err));
 
-        LOGE("xDpi %d", fbDev->xdpi);
-        LOGE("yDpi %d", fbDev->ydpi);
         const_cast<uint32_t&>(android_native_window_t::flags) = fbDev->flags; 
         const_cast<float&>(android_native_window_t::xdpi) = fbDev->xdpi;
         const_cast<float&>(android_native_window_t::ydpi) = fbDev->ydpi;
index f51ca7a..24ae27f 100644 (file)
@@ -152,96 +152,85 @@ bool SurfaceControl::isSameSurface(
 
 status_t SurfaceControl::setLayer(int32_t layer) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setLayer(mToken, layer);
 }
 status_t SurfaceControl::setPosition(int32_t x, int32_t y) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setPosition(mToken, x, y);
 }
 status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setSize(mToken, w, h);
 }
 status_t SurfaceControl::hide() {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->hide(mToken);
 }
 status_t SurfaceControl::show(int32_t layer) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->show(mToken, layer);
 }
 status_t SurfaceControl::freeze() {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->freeze(mToken);
 }
 status_t SurfaceControl::unfreeze() {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->unfreeze(mToken);
 }
 status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setFlags(mToken, flags, mask);
 }
 status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setTransparentRegionHint(mToken, transparent);
 }
 status_t SurfaceControl::setAlpha(float alpha) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setAlpha(mToken, alpha);
 }
 status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy);
 }
 status_t SurfaceControl::setFreezeTint(uint32_t tint) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setFreezeTint(mToken, tint);
 }
 
-status_t SurfaceControl::validate(SharedClient const* cblk) const
+status_t SurfaceControl::validate() const
 {
     if (mToken<0 || mClient==0) {
         LOGE("invalid token (%d, identity=%u) or client (%p)", 
                 mToken, mIdentity, mClient.get());
         return NO_INIT;
     }
+    SharedClient const* cblk = mClient->mControl;
     if (cblk == 0) {
         LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
         return NO_INIT;
@@ -394,7 +383,7 @@ bool Surface::isValid() {
     return mToken>=0 && mClient!=0;
 }
 
-status_t Surface::validate(SharedClient const* cblk) const
+status_t Surface::validate() const
 {
     sp<SurfaceComposerClient> client(getClient());
     if (mToken<0 || mClient==0) {
@@ -402,6 +391,7 @@ status_t Surface::validate(SharedClient const* cblk) const
                 mToken, mIdentity, client.get());
         return NO_INIT;
     }
+    SharedClient const* cblk = mClient->mControl;
     if (cblk == 0) {
         LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
         return NO_INIT;
@@ -488,7 +478,7 @@ status_t Surface::dequeueBuffer(sp<GraphicBuffer>* buffer) {
 int Surface::dequeueBuffer(android_native_buffer_t** buffer)
 {
     sp<SurfaceComposerClient> client(getClient());
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err != NO_ERROR)
         return err;
 
@@ -533,7 +523,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer)
 int Surface::lockBuffer(android_native_buffer_t* buffer)
 {
     sp<SurfaceComposerClient> client(getClient());
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err != NO_ERROR)
         return err;
 
@@ -546,7 +536,7 @@ int Surface::lockBuffer(android_native_buffer_t* buffer)
 int Surface::queueBuffer(android_native_buffer_t* buffer)
 {   
     sp<SurfaceComposerClient> client(getClient());
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err != NO_ERROR)
         return err;
 
index 872b2bc..450af8d 100644 (file)
@@ -42,6 +42,7 @@
 #define TABLE_GETENTRY(x) //x
 #define TABLE_SUPER_NOISY(x) //x
 #define LOAD_TABLE_NOISY(x) //x
+#define TABLE_THEME(x) //x
 
 namespace android {
 
@@ -1447,18 +1448,23 @@ ssize_t ResTable::Theme::getAttribute(uint32_t resID, Res_value* outValue,
         const uint32_t t = Res_GETTYPE(resID);
         const uint32_t e = Res_GETENTRY(resID);
 
-        TABLE_NOISY(LOGV("Looking up attr 0x%08x in theme %p", resID, this));
+        TABLE_THEME(LOGI("Looking up attr 0x%08x in theme %p", resID, this));
 
         if (p >= 0) {
             const package_info* const pi = mPackages[p];
+            TABLE_THEME(LOGI("Found package: %p", pi));
             if (pi != NULL) {
+                TABLE_THEME(LOGI("Desired type index is %ld in avail %d", t, pi->numTypes));
                 if (t < pi->numTypes) {
                     const type_info& ti = pi->types[t];
+                    TABLE_THEME(LOGI("Desired entry index is %ld in avail %d", e, ti.numEntries));
                     if (e < ti.numEntries) {
                         const theme_entry& te = ti.entries[e];
-                            if (outTypeSpecFlags != NULL) {
-                                *outTypeSpecFlags |= te.typeSpecFlags;
-                            }
+                        if (outTypeSpecFlags != NULL) {
+                            *outTypeSpecFlags |= te.typeSpecFlags;
+                        }
+                        TABLE_THEME(LOGI("Theme value: type=0x%x, data=0x%08x",
+                                te.value.dataType, te.value.data));
                         const uint8_t type = te.value.dataType;
                         if (type == Res_value::TYPE_ATTRIBUTE) {
                             if (cnt > 0) {
@@ -1492,6 +1498,8 @@ ssize_t ResTable::Theme::resolveAttributeReference(Res_value* inOutValue,
     if (inOutValue->dataType == Res_value::TYPE_ATTRIBUTE) {
         uint32_t newTypeSpecFlags;
         blockIndex = getAttribute(inOutValue->data, inOutValue, &newTypeSpecFlags);
+        TABLE_THEME(LOGI("Resolving attr reference: blockIndex=%d, type=0x%x, data=%p\n",
+             (int)blockIndex, (int)inOutValue->dataType, (void*)inOutValue->data));
         if (inoutTypeSpecFlags != NULL) *inoutTypeSpecFlags |= newTypeSpecFlags;
         //printf("Retrieved attribute new type=0x%x\n", inOutValue->dataType);
         if (blockIndex < 0) {
@@ -1911,8 +1919,8 @@ ssize_t ResTable::resolveReference(Res_value* value, ssize_t blockIndex,
         uint32_t newFlags = 0;
         const ssize_t newIndex = getResource(value->data, value, true, &newFlags,
                 outConfig);
-        //LOGI("Resolving reference d=%p: newIndex=%d, t=0x%02x, d=%p\n",
-        //     (void*)lastRef, (int)newIndex, (int)value->dataType, (void*)value->data);
+        TABLE_THEME(LOGI("Resolving reference %p: newIndex=%d, type=0x%x, data=%p\n",
+             (void*)lastRef, (int)newIndex, (int)value->dataType, (void*)value->data));
         //printf("Getting reference 0x%08x: newIndex=%d\n", value->data, newIndex);
         if (inoutTypeSpecFlags != NULL) *inoutTypeSpecFlags |= newFlags;
         if (newIndex < 0) {
index 4878722..71825c5 100644 (file)
@@ -1548,24 +1548,36 @@ void glDeleteBuffers(GLsizei n, const GLuint* buffers)
         GLuint name = buffers[i];
         if (name) {
             // unbind bound deleted buffers...
-            if (c->arrays.element_array_buffer->name == name) {
-                c->arrays.element_array_buffer = 0;
+            if (c->arrays.element_array_buffer) {
+                if (c->arrays.element_array_buffer->name == name) {
+                    c->arrays.element_array_buffer = 0;
+                }
             }
-            if (c->arrays.array_buffer->name == name) {
-                c->arrays.array_buffer = 0;
+            if (c->arrays.array_buffer) {
+                if (c->arrays.array_buffer->name == name) {
+                    c->arrays.array_buffer = 0;
+                }
             }
-            if (c->arrays.vertex.bo->name == name) {
-                c->arrays.vertex.bo = 0;
+            if (c->arrays.vertex.bo) {
+                if (c->arrays.vertex.bo->name == name) {
+                    c->arrays.vertex.bo = 0;
+                }
             }
-            if (c->arrays.normal.bo->name == name) {
-                c->arrays.normal.bo = 0;
+            if (c->arrays.normal.bo) {
+                if (c->arrays.normal.bo->name == name) {
+                    c->arrays.normal.bo = 0;
+                }
             }
-            if (c->arrays.color.bo->name == name) {
-                c->arrays.color.bo = 0;
+            if (c->arrays.color.bo) {
+                if (c->arrays.color.bo->name == name) {
+                    c->arrays.color.bo = 0;
+                }
             }
             for (int t=0 ; t<GGL_TEXTURE_UNIT_COUNT ; t++) {
-                if (c->arrays.texture[t].bo->name == name) {
-                    c->arrays.texture[t].bo = 0;
+                if (c->arrays.texture[t].bo) {
+                    if (c->arrays.texture[t].bo->name == name) {
+                        c->arrays.texture[t].bo = 0;
+                    }
                 }
             }
         }
index a68750e..4cacc11 100644 (file)
@@ -38,7 +38,7 @@
 #include <ui/Rect.h>
 
 
-#define DEBUG_COPYBIT true
+#define DEBUG_COPYBIT false
 
 // ----------------------------------------------------------------------------
 
index 673c174..781b8c3 100644 (file)
@@ -876,7 +876,7 @@ struct config_management_t {
 #define VERSION_MAJOR 1
 #define VERSION_MINOR 2
 static char const * const gVendorString     = "Google Inc.";
-static char const * const gVersionString    = "1.2 Android Driver";
+static char const * const gVersionString    = "1.2 Android Driver 1.1.0";
 static char const * const gClientApiString  = "OpenGL ES";
 static char const * const gExtensionsString =
         "EGL_KHR_image_base "
index a59b3b0..0f1f27d 100644 (file)
@@ -37,7 +37,7 @@ namespace android {
 // ----------------------------------------------------------------------------
 
 static char const * const gVendorString     = "Android";
-static char const * const gRendererString   = "Android PixelFlinger 1.1";
+static char const * const gRendererString   = "Android PixelFlinger 1.2";
 static char const * const gVersionString    = "OpenGL ES-CM 1.0";
 static char const * const gExtensionsString =
     "GL_OES_byte_coordinates "              // OK