android-2.1_r1 snapshot
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index df59dcf..6419a5c 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -669,8 +669,14 @@
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 @@
{
// 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.
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index 70303cd..008c297 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -109,7 +109,7 @@
~SurfaceControl();
- status_t validate(SharedClient const* cblk) const;
+ status_t validate() const;
void destroy();
sp<SurfaceComposerClient> mClient;
@@ -190,7 +190,7 @@
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; }
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index ebd470f..2024cc0 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -674,32 +674,13 @@
}
// 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 @@
// ----------------------------------------------------------------------------
-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 @@
LOGV("ThreadBase::exit");
{
AutoMutex lock(&mLock);
+ mExiting = true;
requestExit();
mWaitWorkCV.signal();
}
@@ -870,8 +852,8 @@
// ----------------------------------------------------------------------------
-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 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 @@
{
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 @@
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 @@
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 @@
// ----------------------------------------------------------------------------
-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 @@
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 @@
// 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 @@
}
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 @@
// 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 @@
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 @@
ns2ms(delta), mNumDelayedWrites, this);
lastWarning = now;
}
+ if (mStandby) {
+ longStandbyExit = true;
+ }
}
+ mStandby = false;
} else {
usleep(sleepTime);
}
@@ -1342,10 +1325,10 @@
}
// 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 @@
// 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 @@
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 @@
}
}
- return enabledTracks;
+ return mixerStatus;
}
void AudioFlinger::MixerThread::getTracks(
@@ -1532,6 +1510,7 @@
// 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 @@
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 @@
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 @@
}
standbyTime = systemTime() + kStandbyTimeInNsecs;
- sleepTime = 1000;
+ sleepTime = idleSleepTime;
continue;
}
}
@@ -1753,6 +1738,7 @@
// 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 @@
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 @@
}
}
- if (activeTrack != 0) {
+ if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
AudioBufferProvider::Buffer buffer;
size_t frameCount = mFrameCount;
curBuf = (int8_t *)mMixBuffer;
@@ -1812,7 +1792,11 @@
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 @@
}
if (mSuspended) {
- sleepTime = maxBufferRecoveryInUsecs;
+ sleepTime = idleSleepTime;
}
// sleepTime == 0 means we must write to audio hardware
if (sleepTime == 0) {
@@ -1905,15 +1889,22 @@
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 @@
// ----------------------------------------------------------------------------
-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()
{
+ 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 @@
}
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 @@
}
if (mSuspended) {
- sleepTime = maxBufferRecoveryInUsecs;
+ sleepTime = idleSleepTime;
}
// sleepTime == 0 means we must write to audio hardware
if (sleepTime == 0) {
@@ -2047,17 +2047,6 @@
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 @@
{ // 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 @@
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 @@
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 @@
}
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 @@
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()
{
+ 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 @@
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 @@
// ----------------------------------------------------------------------------
-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 @@
run(buffer, PRIORITY_URGENT_AUDIO);
}
+
bool AudioFlinger::RecordThread::threadLoop()
{
AudioBufferProvider::Buffer buffer;
@@ -3043,22 +3078,37 @@
}
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 @@
}
}
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 @@
}
mActiveTrack.clear();
+ mStartStopCond.broadcast();
+
LOGV("RecordThread %p exiting", this);
return false;
}
@@ -3163,37 +3216,74 @@
status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
{
LOGV("RecordThread::start");
- AutoMutex lock(&mLock);
+ 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;
+ }
- if (mActiveTrack != 0) {
- if (recordTrack != mActiveTrack.get()) return -EBUSY;
-
- if (mActiveTrack->mState == TrackBase::PAUSING) mActiveTrack->mState = TrackBase::RESUMING;
-
- return NO_ERROR;
- }
-
- 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 @@
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 @@
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 @@
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 @@
}
- 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 @@
}
}
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 @@
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 @@
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();
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 22d15c9..8c29da8 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -213,7 +213,7 @@
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 @@
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 @@
status_t mParamStatus;
Vector<ConfigEvent *> mConfigEvents;
bool mStandby;
+ int mId;
+ bool mExiting;
};
// --- PlaybackThread ---
@@ -361,6 +364,12 @@
DUPLICATING
};
+ enum mixer_state {
+ MIXER_IDLE,
+ MIXER_TRACKS_ENABLED,
+ MIXER_TRACKS_READY
+ };
+
// playback track
class Track : public TrackBase {
public:
@@ -415,6 +424,10 @@
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 @@
}; // 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
size_t mInputBytes;
int mReqChannelCount;
uint32_t mReqSampleRate;
+ ssize_t mBytesRead;
};
class RecordHandle : public android::BnAudioRecord {
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index d7daf73..2d4e10d 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -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;
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index eb51c22..b3fed58 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -22,9 +22,6 @@
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)
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 1abfd68..d9d9bfe 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -246,10 +246,11 @@
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;
}
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index f5a5a0b..1870d3a 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -93,6 +93,7 @@
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 @@
{
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 @@
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()
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index a36304c..2ff6167 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -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 @@
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 @@
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 @@
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 @@
: 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 @@
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 @@
#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);
+ 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);
- graphicBuffer->setVerticalStride(src.img.h);
-
- err = mLayer.initializeEglImage(graphicBuffer, &mTexture);
+ }
+ } else {
+ err = INVALID_OPERATION;
+ }
}
#endif
else {
@@ -471,6 +494,72 @@
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,
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 47482f4..2ca63ac 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -130,13 +130,15 @@
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 @@
sp<Surface> mSurface;
bool mInvalidate;
bool mNeedsBlending;
+ copybit_device_t* mBlitEngine;
};
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 9694cf1..965b7dd 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -417,9 +417,9 @@
{
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,23 +429,27 @@
}
MessageList::value_type msg = mEventQueue.waitMessage(timeout);
+
+ // 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;
+ }
+ }
+
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()) {
- // we timed out and are still frozen
- LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d",
- mFreezeDisplay, mFreezeCount);
- mFreezeCount = 0;
- mFreezeDisplay = false;
- return;
- }
}
}
}
@@ -1646,6 +1650,7 @@
}
case 1007: // set mFreezeCount
mFreezeCount = data.readInt32();
+ mFreezeDisplayTime = 0;
return NO_ERROR;
case 1010: // interrogate.
reply->writeInt32(0);
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index f9bfe6c..c0ab73d 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -291,7 +291,11 @@
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 {
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index 0efba9c..c5e22e5 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -118,8 +118,6 @@
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;
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index f51ca7a..24ae27f 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -152,96 +152,85 @@
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 @@
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 @@
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 @@
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::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::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;
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 872b2bc..450af8d 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -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 @@
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 @@
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 @@
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) {
diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp
index 4878722..71825c5 100644
--- a/opengl/libagl/array.cpp
+++ b/opengl/libagl/array.cpp
@@ -1548,24 +1548,36 @@
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;
+ }
}
}
}
diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp
index a68750e..4cacc11 100644
--- a/opengl/libagl/copybit.cpp
+++ b/opengl/libagl/copybit.cpp
@@ -38,7 +38,7 @@
#include <ui/Rect.h>
-#define DEBUG_COPYBIT true
+#define DEBUG_COPYBIT false
// ----------------------------------------------------------------------------
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 673c174..781b8c3 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -876,7 +876,7 @@
#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 "
diff --git a/opengl/libagl/state.cpp b/opengl/libagl/state.cpp
index a59b3b0..0f1f27d 100644
--- a/opengl/libagl/state.cpp
+++ b/opengl/libagl/state.cpp
@@ -37,7 +37,7 @@
// ----------------------------------------------------------------------------
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